ZeroErr
Loading...
Searching...
No Matches
typetraits.h
Go to the documentation of this file.
1#pragma once
3
4#include <ostream>
5#include <sstream>
6#include <string>
7#include <tuple> // this should be removed
8#include <type_traits>
9
11
12// those predefines can help to avoid include too many headers
13namespace std {
14template <typename T>
15class complex;
16
17template <class T, class Deleter>
18class unique_ptr;
19
20template <class T>
21class shared_ptr;
22
23template <class T>
24class weak_ptr;
25
26} // namespace std
27
28
29namespace zeroerr {
30
31
45template <unsigned N>
46struct rank : rank<N - 1> {};
47template <>
48struct rank<0> {};
49
50
51namespace detail {
52
53// C++11 void_t
54template <typename... Ts>
55using void_t = void;
56
57// Type dependent "true"/"false".
58// Useful for SFINAE and static_asserts where we need a type dependent
59// expression that happens to be constant.
60template <typename T>
62 static std::false_type value;
63};
64
65template <typename T>
67 static std::true_type value;
68};
69
70
71// Generate sequence of integers from 0 to N-1
72// Usage: detail::gen_seq<N> then use <size_t... I> to match it
73template <unsigned...>
74struct seq {};
75
76template <unsigned N, unsigned... Is>
77struct gen_seq : gen_seq<N - 1, N - 1, Is...> {};
78
79template <unsigned... Is>
80struct gen_seq<0, Is...> : seq<Is...> {};
81
82
83// Some utility structs to check template specialization
84template <typename Test, template <typename...> class Ref>
85struct is_specialization : std::false_type {};
86
87template <template <typename...> class Ref, typename... Args>
88struct is_specialization<Ref<Args...>, Ref> : std::true_type {};
89
90
91// Check if a type is stream writable, i.e., std::cout << foo;
92// Usage: is_streamable<std::ostream, int>::value
93template <typename S, typename T>
95
96template <typename S, typename T, typename = void>
97struct is_streamable : std::false_type {};
98
99template <typename S, typename T>
100struct is_streamable<S, T, has_stream_operator<S, T>> : std::true_type {};
101
102
103// Check if a type is a container type
104// Usage: is_container<std::vector<int>>::value
105template <typename T>
107 void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>;
108
109template <typename T, typename = void>
110struct is_container : std::false_type {};
111
112template <typename T>
113struct is_container<T, has_begin_end<T>> : std::true_type {};
114
115
116template <typename T>
118 void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end()),
119 decltype(std::declval<T>().find(std::declval<typename T::key_type>())),
120 decltype(std::declval<T>().insert(std::declval<typename T::value_type>()))>;
121
122template <typename T, typename = void>
123struct is_associative_container : std::false_type {};
124
125template <typename T>
126struct is_associative_container<T, has_begin_end_find_insert<T>> : std::true_type {};
127
128
129#if ZEROERR_CXX_STANDARD >= 17
130#define ZEROERR_STRING_VIEW std::is_same<T, std::string_view>::value
131#else
132#define ZEROERR_STRING_VIEW 0
133#endif
134
135// Check if a type is a string type
136template <class T>
138 : std::integral_constant<bool, std::is_same<T, std::string>::value ||
139 std::is_same<T, const char*>::value || ZEROERR_STRING_VIEW> {
140};
141
142
143// Check if a type can use arr[0] like an array
144template <typename T, typename = void>
145struct is_array : std::false_type {};
146
147template <typename T>
148struct is_array<T, void_t<decltype(std::declval<T>()[0])>> : std::true_type {};
149
150
151template <typename T, typename = void>
152struct is_modifiable : std::false_type {};
153
154template <typename T>
155struct is_modifiable<T, void_t<decltype(
156 // Iterable
157 T().begin(), T().end(), T().size(),
158 // Values are mutable
159 // This rejects associative containers, for example
160 // *T().begin() = std::declval<value_type_t<T>>(),
161 // Can insert and erase elements
162 T().insert(T().end(), std::declval<typename T::value_type>()),
163 T().erase(T().begin()), (void)0)>> : std::true_type {};
164
165
166
167// Check if a type has the element type as std::pair
168template <typename T>
171 decltype(std::declval<typename T::value_type>().second)>;
172template <typename T, typename = void>
173struct ele_type_is_pair : std::false_type {};
174
175template <typename T>
176struct ele_type_is_pair<T, has_pair_type<T>> : std::true_type {};
177
178template <typename T, typename V = void>
180 using type = T;
181};
182
183template <>
184struct to_store_type<const char*> {
185 using type = std::string;
186};
187
188template <>
189struct to_store_type<const char (&)[]> {
190 using type = std::string;
191};
192
193template <typename T>
194using is_not_array = typename std::enable_if<!std::is_array<T>::value>::type;
195template <typename T>
197 using type = T;
198};
199
200template <typename T>
201struct to_store_type<T&&> {
202 using type = T;
203};
204
205template <typename T>
207
208
209template <size_t I>
211 template <typename T, typename F>
212 static void visit(T& tup, size_t idx, F&& fun) {
213 if (idx == I - 1)
214 fun(std::get<I - 1>(tup));
215 else
216 visit_impl<I - 1>::visit(tup, idx, std::forward<F>(fun));
217 }
218};
219
220template <>
221struct visit_impl<0> {
222 template <typename T, typename F>
223 static void visit(T&, size_t, F&&) {}
224};
225
226template <typename F, typename... Ts>
227void visit_at(const std::tuple<Ts...>& tup, size_t idx, F&& fun) {
228 visit_impl<sizeof...(Ts)>::visit(tup, idx, std::forward<F>(fun));
229}
230
231template <typename F, typename... Ts>
232void visit_at(std::tuple<Ts...>& tup, size_t idx, F&& fun) {
233 visit_impl<sizeof...(Ts)>::visit(tup, idx, std::forward<F>(fun));
234}
235
236
237template <size_t I>
239 template <typename T1, typename T2, typename F>
240 static void visit(T1 tup1, T2 tup2, size_t idx, F&& fun) {
241 if (idx == I - 1)
242 fun(std::get<I - 1>(tup1), std::get<I - 1>(tup2));
243 else
244 visit2_impl<I - 1>::visit(tup1, tup2, idx, std::forward<F>(fun));
245 }
246};
247
248template <>
249struct visit2_impl<0> {
250 template <typename T1, typename T2, typename F>
251 static void visit(T1&, T2&, size_t, F&&) {}
252};
253
254template <typename F, typename... Ts, typename... T2s>
255void visit2_at(const std::tuple<Ts...>& tup1, const std::tuple<T2s...>& tup2, size_t idx, F&& fun) {
256 visit2_impl<sizeof...(Ts)>::visit(tup1, tup2, idx, std::forward<F>(fun));
257}
258
259template <typename F, typename... Ts, typename... T2s>
260void visit2_at(std::tuple<Ts...>& tup1, std::tuple<T2s...>& tup2, size_t idx, F&& fun) {
261 visit2_impl<sizeof...(Ts)>::visit(tup1, tup2, idx, std::forward<F>(fun));
262}
263
264template <typename F, typename... Ts, typename... T2s>
265void visit2_at(const std::tuple<Ts...>& tup1, std::tuple<T2s...>& tup2, size_t idx, F&& fun) {
266 visit2_impl<sizeof...(Ts)>::visit(tup1, tup2, idx, std::forward<F>(fun));
267}
268
269template <typename F, typename... Ts, typename... T2s>
270void visit2_at(std::tuple<Ts...>& tup1, const std::tuple<T2s...>& tup2, size_t idx, F&& fun) {
271 visit2_impl<sizeof...(Ts)>::visit(tup1, tup2, idx, std::forward<F>(fun));
272}
273
274#define ZEROERR_ENABLE_IF(x) \
275 template <typename T> \
276 typename std::enable_if<x, void>::type
277#define ZEROERR_IS_INT std::is_integral<T>::value
278#define ZEROERR_IS_FLOAT std::is_floating_point<T>::value
279#define ZEROERR_IS_CONTAINER detail::is_container<T>::value
280#define ZEROERR_IS_STRING detail::is_string<T>::value
281#define ZEROERR_IS_POINTER std::is_pointer<T>::value
282#define ZEROERR_IS_CHAR std::is_same<T, char>::value
283#define ZEROERR_IS_WCHAR std::is_same<T, wchar_t>::value
284#define ZEROERR_IS_CLASS std::is_class<T>::value
285#define ZEROERR_IS_STREAMABLE detail::is_streamable<std::ostream, T>::value
286#define ZEROERR_IS_ARRAY detail::is_array<T>::value
287#define ZEROERR_IS_COMPLEX detail::is_specialization<T, std::complex>::value
288#define ZEROERR_IS_BOOL std::is_same<T, bool>::value
289#define ZEROERR_IS_AUTOPTR \
290 (detail::is_specialization<T, std::unique_ptr>::value || \
291 detail::is_specialization<T, std::shared_ptr>::value || \
292 detail::is_specialization<T, std::weak_ptr>::value)
293#define ZEROERR_IS_MAP detail::ele_type_is_pair<T>::value
294#define ZEROERR_IS_POD std::is_standard_layout<T>::value
295#define ZEROERR_IS_EXT detail::has_extension<T>::value
296
297} // namespace detail
298
299} // namespace zeroerr
300
301
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:265
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:218
STL namespace.
void_t< typename T::value_type, decltype(std::declval< typename T::value_type >().first), decltype(std::declval< typename T::value_type >().second)> has_pair_type
Definition typetraits.h:171
typename to_store_type< T >::type to_store_type_t
Definition typetraits.h:206
void_t< decltype(std::declval< S & >()<< std::declval< T >())> has_stream_operator
Definition typetraits.h:94
void_t< decltype(std::declval< T >().begin()), decltype(std::declval< T >().end()), decltype(std::declval< T >().find(std::declval< typename T::key_type >())), decltype(std::declval< T >().insert(std::declval< typename T::value_type >()))> has_begin_end_find_insert
Definition typetraits.h:120
void_t< decltype(std::declval< T >().begin()), decltype(std::declval< T >().end())> has_begin_end
Definition typetraits.h:107
void void_t
Definition typetraits.h:55
typename std::enable_if<!std::is_array< T >::value >::type is_not_array
Definition typetraits.h:194
void visit_at(const std::tuple< Ts... > &tup, size_t idx, F &&fun)
Definition typetraits.h:227
void visit2_at(const std::tuple< Ts... > &tup1, const std::tuple< T2s... > &tup2, size_t idx, F &&fun)
Definition typetraits.h:255
Definition benchmark.cpp:17
Definition typetraits.h:61
static std::false_type value
Definition typetraits.h:62
Definition typetraits.h:66
static std::true_type value
Definition typetraits.h:67
Definition typetraits.h:173
Definition typetraits.h:77
Definition typetraits.h:145
Definition typetraits.h:110
Definition typetraits.h:152
Definition typetraits.h:85
Definition typetraits.h:97
Definition typetraits.h:139
Definition typetraits.h:74
T type
Definition typetraits.h:202
std::string type
Definition typetraits.h:185
std::string type
Definition typetraits.h:190
Definition typetraits.h:179
T type
Definition typetraits.h:180
static void visit(T1 &, T2 &, size_t, F &&)
Definition typetraits.h:251
Definition typetraits.h:238
static void visit(T1 tup1, T2 tup2, size_t idx, F &&fun)
Definition typetraits.h:240
static void visit(T &, size_t, F &&)
Definition typetraits.h:223
Definition typetraits.h:210
static void visit(T &tup, size_t idx, F &&fun)
Definition typetraits.h:212
rank is a helper class for Printer to define the priority of overloaded functions.
Definition typetraits.h:46