-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprettyprint.hpp
135 lines (111 loc) · 4.81 KB
/
prettyprint.hpp
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
#ifndef PRETTYPRINT_HPP_INCLUDE
#define PRETTYPRINT_HPP_INCLUDE
#include <iterator> // std::begin std::end
#include <ostream> // std::basic_ostream
#include <tuple> // std::tuple std::get
#include <type_traits> // metafunctions
#include <utility> // std::pair std::index_sequence(c++14)
namespace pprint {
namespace detail {
#if __cplusplus >= 201703L
using std::void_t;
using std::disjunction;
#else
template <class...>
using void_t = void;
template <class...>
struct disjunction : std::false_type {};
template <class T>
struct disjunction<T> : T {};
template <class T, class... Rest>
struct disjunction<T, Rest...> : std::conditional<(bool)T::value, T, disjunction<Rest...>>::type {};
#endif
template <class T, class... Args>
using is_any_of = disjunction<std::is_same<T, Args>...>;
template <class T>
using is_character = is_any_of<typename std::decay<T>::type,
#if __cplusplus >= 202002L
char, wchar_t, char16_t, char32_t, char8_t>;
#else
char, wchar_t, char16_t, char32_t>;
#endif
template <class T, class = void>
struct is_basic_string_or_view : std::false_type {};
template <class T>
struct is_basic_string_or_view<T, void_t<typename T::value_type,
typename T::const_iterator,
typename T::traits_type>> : std::true_type {};
template <class T, class = void, class = void>
struct is_container : std::false_type {};
template <class T>
struct is_container<T, void_t<typename T::value_type,
typename T::const_iterator,
decltype(std::begin(std::declval<T>())),
decltype(std::end(std::declval<T>()))>,
typename std::enable_if<!is_basic_string_or_view<T>::value>::type> : std::true_type {};
template <class T>
using remove_all = std::remove_cv<
typename std::remove_pointer<
typename std::remove_reference<
typename std::remove_all_extents<T>::type>::type>::type>;
template <class T>
using is_array = std::integral_constant<bool, std::is_array<T>::value &&
!is_character<typename remove_all<T>::type>::value>;
// ostream operator<< for array of characters is overloaded in std.
} // namespace detail
namespace ptuple {
#if __cplusplus >= 201402L
using std::index_sequence;
using std::make_index_sequence;
using std::index_sequence_for;
#else
template <std::size_t...>
struct index_sequence {};
template <std::size_t N, std::size_t... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {};
template <std::size_t... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
template <class... T>
using index_sequence_for = make_index_sequence<sizeof...(T)>;
#endif
template <class CharT, class Traits, class Tuple, std::size_t... Is>
inline void print(std::basic_ostream<CharT, Traits>& os, const Tuple& tuple, index_sequence<Is...>) {
#if __cplusplus >= 201703L
((void)(os << (Is == 0 ? "" : ", ") << std::get<Is>(tuple)), ...);
#else
using swallow = char[];
(void)swallow {'\0', ((void)(os << (Is == 0 ? "" : ", ") << std::get<Is>(tuple)), '\0')...};
#endif
}
} // namespace ptuple
} // namespace pprint
template <class CharT, class Traits, class Container,
class = typename std::enable_if<pprint::detail::is_container<Container>::value ||
pprint::detail::is_array<Container>::value>::type>
inline std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const Container& container) {
auto itr = std::begin(container);
const auto end = std::end(container);
os << static_cast<CharT>('[');
if (itr != end) {
while (true) {
os << *itr;
if (++itr == end) break;
os << ", ";
}
}
return os << static_cast<CharT>(']');
}
template <class CharT, class Traits, class T, class U>
inline std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const std::pair<T, U>& pair) {
return os << static_cast<CharT>('(') << pair.first << ", " << pair.second << static_cast<CharT>(')');
}
template <class CharT, class Traits, class... Args>
inline std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const std::tuple<Args...>& tuple) {
os << static_cast<CharT>('(');
pprint::ptuple::print(os, tuple, pprint::ptuple::index_sequence_for<Args...> {});
return os << static_cast<CharT>(')');
}
#endif // PRETTYPRINT_HPP_INCLUDE