ZeroErr
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
13 namespace std {
14 template <typename T>
15 class complex;
16 
17 template <class T, class Deleter>
18 class unique_ptr;
19 
20 template <class T>
21 class shared_ptr;
22 
23 template <class T>
24 class weak_ptr;
25 
26 } // namespace std
27 
28 
29 namespace zeroerr {
30 
31 
32 namespace detail {
33 
34 // C++11 void_t
35 template <typename... Ts>
36 using void_t = void;
37 
38 // Type dependent "true"/"false".
39 // Useful for SFINAE and static_asserts where we need a type dependent
40 // expression that happens to be constant.
41 template <typename T>
42 struct always_false {
43  static std::false_type value;
44 };
45 
46 template <typename T>
47 struct always_true {
48  static std::true_type value;
49 };
50 
51 
52 // Generate sequence of integers from 0 to N-1
53 // Usage: detail::gen_seq<N> then use <size_t... I> to match it
54 template <unsigned...>
55 struct seq {};
56 
57 template <unsigned N, unsigned... Is>
58 struct gen_seq : gen_seq<N - 1, N - 1, Is...> {};
59 
60 template <unsigned... Is>
61 struct gen_seq<0, Is...> : seq<Is...> {};
62 
63 
64 // Some utility structs to check template specialization
65 template <typename Test, template <typename...> class Ref>
66 struct is_specialization : std::false_type {};
67 
68 template <template <typename...> class Ref, typename... Args>
69 struct is_specialization<Ref<Args...>, Ref> : std::true_type {};
70 
71 
72 // Check if a type is stream writable, i.e., std::cout << foo;
73 // Usage: is_streamable<std::ostream, int>::value
74 template <typename S, typename T>
75 using has_stream_operator = void_t<decltype(std::declval<S&>() << std::declval<T>())>;
76 
77 template <typename S, typename T, typename = void>
78 struct is_streamable : std::false_type {};
79 
80 template <typename S, typename T>
81 struct is_streamable<S, T, has_stream_operator<S, T>> : std::true_type {};
82 
83 
84 // Check if a type is a container type
85 // Usage: is_container<std::vector<int>>::value
86 template <typename T>
88  void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>;
89 
90 template <typename T, typename = void>
91 struct is_container : std::false_type {};
92 
93 template <typename T>
94 struct is_container<T, has_begin_end<T>> : std::true_type {};
95 
96 
97 template <typename T>
99  void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end()),
100  decltype(std::declval<T>().find(std::declval<typename T::key_type>())),
101  decltype(std::declval<T>().insert(std::declval<typename T::value_type>()))>;
102 
103 template <typename T, typename = void>
104 struct is_associative_container : std::false_type {};
105 
106 template <typename T>
107 struct is_associative_container<T, has_begin_end_find_insert<T>> : std::true_type {};
108 
109 
110 #if ZEROERR_CXX_STANDARD >= 17
111 #define ZEROERR_STRING_VIEW std::is_same<T, std::string_view>::value
112 #else
113 #define ZEROERR_STRING_VIEW 0
114 #endif
115 
116 // Check if a type is a string type
117 template <class T>
118 struct is_string
119  : std::integral_constant<bool, std::is_same<T, std::string>::value ||
120  std::is_same<T, const char*>::value || ZEROERR_STRING_VIEW> {
121 };
122 
123 
124 // Check if a type can use arr[0] like an array
125 template <typename T, typename = void>
126 struct is_array : std::false_type {};
127 
128 template <typename T>
129 struct is_array<T, void_t<decltype(std::declval<T>()[0])>> : std::true_type {};
130 
131 
132 // Check if a type has the element type as std::pair
133 template <typename T>
136  decltype(std::declval<typename T::value_type>().second)>;
137 template <typename T, typename = void>
138 struct ele_type_is_pair : std::false_type {};
139 
140 template <typename T>
141 struct ele_type_is_pair<T, has_pair_type<T>> : std::true_type {};
142 
143 template <typename T, typename V = void>
145  using type = T;
146 };
147 
148 template <>
149 struct to_store_type<const char*> {
150  using type = std::string;
151 };
152 
153 template <>
154 struct to_store_type<const char (&)[]> {
155  using type = std::string;
156 };
157 
158 template <typename T>
159 using is_not_array = typename std::enable_if<!std::is_array<T>::value>::type;
160 template <typename T>
162  using type = T;
163 };
164 
165 template <typename T>
166 struct to_store_type<T&&> {
167  using type = T;
168 };
169 
170 template <typename T>
172 
173 
174 template <size_t I>
175 struct visit_impl {
176  template <typename T, typename F>
177  static void visit(T& tup, size_t idx, F&& fun) {
178  if (idx == I - 1)
179  fun(std::get<I - 1>(tup));
180  else
181  visit_impl<I - 1>::visit(tup, idx, std::forward<F>(fun));
182  }
183 };
184 
185 template <>
186 struct visit_impl<0> {
187  template <typename T, typename F>
188  static void visit(T&, size_t, F&&) {}
189 };
190 
191 template <typename F, typename... Ts>
192 void visit_at(const std::tuple<Ts...>& tup, size_t idx, F&& fun) {
193  visit_impl<sizeof...(Ts)>::visit(tup, idx, std::forward<F>(fun));
194 }
195 
196 template <typename F, typename... Ts>
197 void visit_at(std::tuple<Ts...>& tup, size_t idx, F&& fun) {
198  visit_impl<sizeof...(Ts)>::visit(tup, idx, std::forward<F>(fun));
199 }
200 
201 
202 template <size_t I>
203 struct visit2_impl {
204  template <typename T1, typename T2, typename F>
205  static void visit(T1 tup1, T2 tup2, size_t idx, F&& fun) {
206  if (idx == I - 1)
207  fun(std::get<I - 1>(tup1), std::get<I - 1>(tup2));
208  else
209  visit2_impl<I - 1>::visit(tup1, tup2, idx, std::forward<F>(fun));
210  }
211 };
212 
213 template <>
214 struct visit2_impl<0> {
215  template <typename T1, typename T2, typename F>
216  static void visit(T1&, T2&, size_t, F&&) {}
217 };
218 
219 template <typename F, typename... Ts, typename... T2s>
220 void visit2_at(const std::tuple<Ts...>& tup1, const std::tuple<T2s...>& tup2, size_t idx, F&& fun) {
221  visit2_impl<sizeof...(Ts)>::visit(tup1, tup2, idx, std::forward<F>(fun));
222 }
223 
224 template <typename F, typename... Ts, typename... T2s>
225 void visit2_at(std::tuple<Ts...>& tup1, std::tuple<T2s...>& tup2, size_t idx, F&& fun) {
226  visit2_impl<sizeof...(Ts)>::visit(tup1, tup2, idx, std::forward<F>(fun));
227 }
228 
229 template <typename F, typename... Ts, typename... T2s>
230 void visit2_at(const std::tuple<Ts...>& tup1, std::tuple<T2s...>& tup2, size_t idx, F&& fun) {
231  visit2_impl<sizeof...(Ts)>::visit(tup1, tup2, idx, std::forward<F>(fun));
232 }
233 
234 template <typename F, typename... Ts, typename... T2s>
235 void visit2_at(std::tuple<Ts...>& tup1, const std::tuple<T2s...>& tup2, size_t idx, F&& fun) {
236  visit2_impl<sizeof...(Ts)>::visit(tup1, tup2, idx, std::forward<F>(fun));
237 }
238 
239 #define ZEROERR_ENABLE_IF(x) \
240  template <typename T> \
241  typename std::enable_if<x, void>::type
242 #define ZEROERR_IS_INT std::is_integral<T>::value
243 #define ZEROERR_IS_FLOAT std::is_floating_point<T>::value
244 #define ZEROERR_IS_CONTAINER detail::is_container<T>::value
245 #define ZEROERR_IS_STRING detail::is_string<T>::value
246 #define ZEROERR_IS_POINTER std::is_pointer<T>::value
247 #define ZEROERR_IS_CHAR std::is_same<T, char>::value
248 #define ZEROERR_IS_WCHAR std::is_same<T, wchar_t>::value
249 #define ZEROERR_IS_CLASS std::is_class<T>::value
250 #define ZEROERR_IS_STREAMABLE detail::is_streamable<std::ostream, T>::value
251 #define ZEROERR_IS_ARRAY detail::is_array<T>::value
252 #define ZEROERR_IS_COMPLEX detail::is_specialization<T, std::complex>::value
253 #define ZEROERR_IS_BOOL std::is_same<T, bool>::value
254 #define ZEROERR_IS_AUTOPTR \
255  (detail::is_specialization<T, std::unique_ptr>::value || \
256  detail::is_specialization<T, std::shared_ptr>::value || \
257  detail::is_specialization<T, std::weak_ptr>::value)
258 #define ZEROERR_IS_MAP detail::ele_type_is_pair<T>::value
259 #define ZEROERR_IS_POD std::is_standard_layout<T>::value
260 #define ZEROERR_IS_EXT detail::has_extension<T>::value
261 
262 } // namespace detail
263 
264 } // namespace zeroerr
265 
266 
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition: config.h:265
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition: config.h:218
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:136
typename to_store_type< T >::type to_store_type_t
Definition: typetraits.h:171
void_t< decltype(std::declval< S & >()<< std::declval< T >())> has_stream_operator
Definition: typetraits.h:75
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:101
void_t< decltype(std::declval< T >().begin()), decltype(std::declval< T >().end())> has_begin_end
Definition: typetraits.h:88
void void_t
Definition: typetraits.h:36
typename std::enable_if<!std::is_array< T >::value >::type is_not_array
Definition: typetraits.h:159
void visit_at(const std::tuple< Ts... > &tup, size_t idx, F &&fun)
Definition: typetraits.h:192
void visit2_at(const std::tuple< Ts... > &tup1, const std::tuple< T2s... > &tup2, size_t idx, F &&fun)
Definition: typetraits.h:220
Definition: benchmark.cpp:17
Definition: typetraits.h:42
static std::false_type value
Definition: typetraits.h:43
Definition: typetraits.h:47
static std::true_type value
Definition: typetraits.h:48
Definition: typetraits.h:138
Definition: typetraits.h:58
Definition: typetraits.h:126
Definition: typetraits.h:104
Definition: typetraits.h:91
Definition: typetraits.h:66
Definition: typetraits.h:78
Definition: typetraits.h:120
Definition: typetraits.h:55
T type
Definition: typetraits.h:167
std::string type
Definition: typetraits.h:150
std::string type
Definition: typetraits.h:155
Definition: typetraits.h:144
T type
Definition: typetraits.h:145
static void visit(T1 &, T2 &, size_t, F &&)
Definition: typetraits.h:216
Definition: typetraits.h:203
static void visit(T1 tup1, T2 tup2, size_t idx, F &&fun)
Definition: typetraits.h:205
static void visit(T &, size_t, F &&)
Definition: typetraits.h:188
Definition: typetraits.h:175
static void visit(T &tup, size_t idx, F &&fun)
Definition: typetraits.h:177