@@ -27,6 +27,43 @@ namespace plog
2727
2828 template <class T >
2929 struct enableIf <true , T> { typedef T type; };
30+
31+ struct No { char a[1 ]; };
32+ struct Yes { char a[2 ]; };
33+
34+ template <class From , class To >
35+ struct isConvertible
36+ {
37+ // `+ sizeof(U*)` is required for GCC 4.5-4.7
38+ template <class U >
39+ static typename enableIf<!!(sizeof (static_cast <To>(meta::declval<U>())) + sizeof (U*)), Yes>::type test (int );
40+
41+ template <class U >
42+ static No test (...);
43+
44+ enum { value = sizeof (test<From>(0 )) == sizeof (Yes) };
45+ };
46+
47+ template <class T >
48+ struct isConvertibleToNString : isConvertible<T, std::basic_string<util::nchar> > {};
49+
50+ template <class T >
51+ struct isContainer
52+ {
53+ template <class U >
54+ static typename meta::enableIf<!!(sizeof (
55+ #if defined(_MSC_VER) && _MSC_VER < 1700 // MSVC 2010 doesn't understand `typename T::const_iterator`
56+ meta::declval<U>().begin()) + sizeof (meta::declval<U>().end()
57+ #else
58+ typename U::const_iterator
59+ #endif
60+ )), Yes>::type test (int );
61+
62+ template <class U >
63+ static No test (...);
64+
65+ enum { value = sizeof (test<T>(0 )) == sizeof (Yes) };
66+ };
3067 }
3168
3269 // ////////////////////////////////////////////////////////////////////////
@@ -88,20 +125,20 @@ namespace plog
88125 }
89126
90127#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 4 // skip for GCC < 4.5 due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38600
91- // Print data that can be casted to `std::basic_string`. `+ sizeof(T*)` is required for GCC 4.5-4.7.
92- template <typename T>
93- inline typename meta::enableIf<!!( sizeof ( static_cast <std::basic_string<util::nchar> >( meta::declval <T>())) + sizeof (T*)) , void >::type operator <<(util::nostringstream& stream, const T& data)
128+ // Print data that can be casted to `std::basic_string`.
129+ template <class T >
130+ inline typename meta::enableIf<meta::isConvertibleToNString <T>::value , void >::type operator <<(util::nostringstream& stream, const T& data)
94131 {
95132 plog::detail::operator <<(stream, static_cast <std::basic_string<util::nchar> >(data));
96133 }
97134
98135 // Print std containers
99- template <class Container >
100- inline typename meta::enableIf<!!( sizeof ( typename Container::const_iterator)) , void >::type operator <<(util::nostringstream& stream, const Container & data)
136+ template <class T >
137+ inline typename meta::enableIf<meta::isContainer<T>::value && !meta::isConvertibleToNString<T>::value , void >::type operator <<(util::nostringstream& stream, const T & data)
101138 {
102139 stream << " [" ;
103140
104- for (typename Container ::const_iterator it = data.begin (); it != data.end ();)
141+ for (typename T ::const_iterator it = data.begin (); it != data.end ();)
105142 {
106143 stream << *it;
107144
@@ -129,12 +166,12 @@ namespace plog
129166 namespace meta
130167 {
131168 template <class T , class Stream >
132- inline char operator <<(Stream&, const T&);
169+ inline No operator <<(Stream&, const T&);
133170
134171 template <class T , class Stream >
135172 struct isStreamable
136173 {
137- enum { value = sizeof (operator <<(meta::declval<Stream>(), meta::declval<const T>())) != sizeof (char ) };
174+ enum { value = sizeof (operator <<(meta::declval<Stream>(), meta::declval<const T>())) != sizeof (No ) };
138175 };
139176
140177 template <class Stream >
0 commit comments