Skip to content

Commit e2650b8

Browse files
Fix compilation on VS2010 (#207)
1 parent 130801c commit e2650b8

File tree

1 file changed

+45
-8
lines changed

1 file changed

+45
-8
lines changed

include/plog/Record.h

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)