1 /*******************************************************************************
2  * tlx/logger/wrap_unprintable.hpp
3  *
4  * Part of tlx - http://panthema.net/tlx
5  *
6  * Copyright (C) 2019 Timo Bingmann <tb@panthema.net>
7  *
8  * All rights reserved. Published under the Boost Software License, Version 1.0
9  ******************************************************************************/
10 
11 #ifndef TLX_LOGGER_WRAP_UNPRINTABLE_HEADER
12 #define TLX_LOGGER_WRAP_UNPRINTABLE_HEADER
13 
14 #include <tlx/meta/enable_if.hpp>
15 
16 #include <ostream>
17 #include <utility>
18 
19 namespace tlx {
20 
21 //! SFINAE magic helper for wrap_unprintable()
22 template <typename, typename = void>
23 struct has_ostream_operator
24 { static constexpr bool value = false; };
25 
26 template <typename Type>
27 struct has_ostream_operator<
28     Type, decltype(
29         std::declval<std::ostream&>() << std::declval<Type const&>(), void())>
30 { static constexpr bool value = true; };
31 
32 //! SFINAE magic to return "<unprintable>" instead if the value HAS NO ostream
33 //! operator << available.  Identical to shorter wrap_unp().
34 template <typename Type>
35 typename enable_if<!has_ostream_operator<Type>::value, const char*>::type
wrap_unprintable(Type,const char * instead="<unprintable>")36 wrap_unprintable(Type, const char* instead = "<unprintable>") {
37     return instead;
38 }
39 
40 //! SFINAE magic to return the value if the value HAS a ostream operator <<
41 //! available.  Identical to shorter wrap_unp().
42 template <typename Type>
43 typename enable_if<has_ostream_operator<Type>::value, Type>::type
wrap_unprintable(Type value,const char * =nullptr)44 wrap_unprintable(Type value, const char* = nullptr) {
45     return value;
46 }
47 
48 //! SFINAE magic to return "<unprintable>" instead if the value HAS NO ostream
49 //! operator << available.  Shortened name of wrap_unprintable()
50 template <typename Type>
51 typename enable_if<!has_ostream_operator<Type>::value, const char*>::type
wrap_unp(Type,const char * instead="<unprintable>")52 wrap_unp(Type, const char* instead = "<unprintable>") {
53     return instead;
54 }
55 
56 //! SFINAE magic to return the value if the value HAS a ostream operator <<
57 //! available.  Shortened name of wrap_unprintable()
58 template <typename Type>
59 typename enable_if<has_ostream_operator<Type>::value, Type>::type
wrap_unp(Type value,const char * =nullptr)60 wrap_unp(Type value, const char* = nullptr) {
61     return value;
62 }
63 
64 } // namespace tlx
65 
66 #endif // !TLX_LOGGER_WRAP_UNPRINTABLE_HEADER
67 
68 /******************************************************************************/
69