-
Notifications
You must be signed in to change notification settings - Fork 53
/
ioutils.h
144 lines (120 loc) · 4.13 KB
/
ioutils.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#ifndef IOUTILS_H
#define IOUTILS_H
namespace ioutils {
/*
* from:
* http://shitalshah.com/p/writing-generic-container-function-in-c11/
* https://raw.githubusercontent.com/louisdx/cxx-prettyprint/master/prettyprint.hpp
* also see https://gist.github.com/louisdx/1076849
*/
namespace detail {
// SFINAE type trait to detect whether T::const_iterator exists.
struct sfinae_base {
using yes = char;
using no = yes[2];
};
template <typename T>
struct has_const_iterator : private sfinae_base {
private:
template <typename C>
static yes& test(typename C::const_iterator*);
template <typename C>
static no& test(...);
public:
static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
using type = T;
void dummy(); // for GCC to supress -Wctor-dtor-privacy
};
template <typename T>
struct not_expression : private sfinae_base {
private:
template <typename C>
static no& test(typename C::expression_tag*);
template <typename C>
static yes& test(...);
public:
static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
using type = T;
void dummy(); // for GCC to supress -Wctor-dtor-privacy
};
template <typename T>
struct has_printable_value_type : private sfinae_base {
private:
template <typename C>
static yes& test(typename std::enable_if<
std::is_fundamental<typename C::value_type>::value>::type*);
template <typename C>
static yes& test(
typename std::enable_if<
std::is_same<typename C::value_type, std::string>::value>::type*);
template <typename C>
static yes& test(
typename std::enable_if<
std::is_same<typename C::value_type, std::wstring>::value>::type*);
template <typename C>
static yes& test(
typename std::enable_if<
std::is_same<typename C::value_type, const char*>::value>::type*);
template <typename C>
static yes& test(typename std::enable_if<
std::is_same<typename C::value_type, char*>::value>::type*);
template <typename C>
static no& test(...);
public:
static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
using type = T;
void dummy(); // for GCC to supress -Wctor-dtor-privacy
};
template <typename T>
struct has_begin_end : private sfinae_base {
private:
template <typename C>
static yes&
f(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator (C::*)()
const>(&C::begin)),
typename C::const_iterator (C::*)() const>::value>::type*);
template <typename C>
static no& f(...);
template <typename C>
static yes& g(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator (
C::*)() const>(&C::end)),
typename C::const_iterator (C::*)() const>::value,
void>::type*);
template <typename C>
static no& g(...);
public:
static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
void dummy(); // for GCC to supress -Wctor-dtor-privacy
};
} // namespace detail
template <typename T>
struct is_container : public std::integral_constant<
bool,
detail::has_const_iterator<T>::value &&
detail::has_begin_end<T>::beg_value &&
detail::has_begin_end<T>::end_value &&
detail::has_printable_value_type<T>::value &&
detail::not_expression<T>::value> {};
template <>
struct is_container<std::string> : std::false_type {};
} // namespace ioutils
template <typename C,
class = typename std::enable_if<
ioutils::is_container<typename std::decay<C>::type>::value>::type>
std::ostream& operator<<(std::ostream& out, C&& container) {
out << '{';
auto i = std::begin(container);
auto e = std::end(container);
auto l = std::prev(std::end(container));
for (; i != e; ++i) {
out << *i;
if (i != l)
out << ", ";
}
out << '}';
return out;
}
#endif // IOUTILS_H