ZeroErr
载入中...
搜索中...
未找到
typetraits.h
浏览该文件的文档.
1#pragma once
2
3// libc++ offers compatibility-only transitive includes through C++20.
4// Suppress those while loading our explicit dependencies, then restore the
5// caller's setting. This does not change standard-library types or ABI.
6#pragma push_macro("_LIBCPP_REMOVE_TRANSITIVE_INCLUDES")
7#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
8#define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
9#endif
10
12
13
14
15#include "zeroerr/string.h"
16#include <tuple> // this should be removed
17#include <type_traits>
18
19#include <memory>
20#include <cstddef>
21#include <utility>
22
24
25
26namespace zeroerr {
27
28
42template <unsigned N>
43struct rank : rank<N - 1> {};
44template <>
45struct rank<0> {};
46
47
48class StringBuffer;
49namespace detail {
50
51
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...> { using type = 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>
94using has_stream_operator = void_t<decltype(std::declval<S&>() << std::declval<const 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>
108 decltype(std::declval<const T&>().end()),
109 decltype(*std::declval<decltype(std::declval<const T&>().begin())&>()),
110 decltype(++std::declval<decltype(std::declval<const T&>().begin())&>()),
111 decltype(std::declval<const T&>().begin() != std::declval<const T&>().end()),
112 decltype(std::declval<const T&>().begin() == std::declval<const T&>().end())>;
113
114template <typename T, typename = void>
115struct is_container : std::false_type {};
116
117template <typename T>
118struct is_container<T, has_begin_end<T>> : std::true_type {};
119
120
121template <typename T>
123 void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end()),
124 decltype(std::declval<T>().find(std::declval<typename T::key_type>())),
125 decltype(std::declval<T>().insert(std::declval<typename T::value_type>()))>;
126
127template <typename T, typename = void>
128struct is_associative_container : std::false_type {};
129
130template <typename T>
131struct is_associative_container<T, has_begin_end_find_insert<T>> : std::true_type {};
132
133
134template <typename T, typename = void>
135struct is_string_like : std::false_type {};
136
137template <typename T>
138struct is_string_like<T, void_t<typename T::traits_type::char_type,
139 decltype(std::declval<const T&>().data()),
140 decltype(std::declval<const T&>().size())>>
141 : std::integral_constant<bool,
142 std::is_same<typename T::traits_type::char_type, char>::value &&
143 std::is_convertible<decltype(std::declval<const T&>().data()), const char*>::value &&
144 std::is_convertible<decltype(std::declval<const T&>().size()), std::size_t>::value> {};
145
146template<> struct is_string_like<zeroerr::String> : std::true_type {};
147
148template <class T>
149struct is_string : std::integral_constant<bool,
150 is_string_like<T>::value ||
151 (std::is_convertible<const T&, const char*>::value && !std::is_same<T, std::nullptr_t>::value)> {};
152
153template <typename T, typename = void>
154struct is_complex : std::false_type {};
155
156template <typename T>
157struct is_complex<T, void_t<decltype(std::declval<const T&>().real()),
158 decltype(std::declval<const T&>().imag())>>
159 : std::integral_constant<bool,
160 std::is_arithmetic<decltype(std::declval<const T&>().real())>::value &&
161 std::is_arithmetic<decltype(std::declval<const T&>().imag())>::value> {};
162
163template <typename T, typename = void>
164struct is_pointer_like : std::false_type {};
165
166template <typename T>
167struct is_pointer_like<T, void_t<decltype(std::declval<const T&>().get())>>
168 : std::is_convertible<decltype(std::declval<const T&>().get()), const void*> {};
169
170template <typename T, typename = void>
171struct is_weak_pointer_like : std::false_type {};
172
173template <typename T>
174struct is_weak_pointer_like<T, void_t<decltype(std::declval<const T&>().lock())>>
175 : is_pointer_like<decltype(std::declval<const T&>().lock())> {};
176
177// Unqualified, dependent lookup finds get in the value's associated namespace,
178// including declarations introduced after this header. Never declare in std.
179template <std::size_t I>
180void get() = delete;
181template <std::size_t I, typename T>
182auto tuple_get(T&& value) -> decltype(get<I>(std::forward<T>(value))) {
183 return get<I>(std::forward<T>(value));
184}
185
186template <typename T, typename Sequence, typename = void>
187struct has_tuple_get : std::false_type {};
188
189template <typename T, unsigned... I>
190struct has_tuple_get<T, seq<I...>, void_t<decltype(tuple_get<I>(std::declval<const T&>()))...>>
191 : std::true_type {};
192
193template <typename T, typename = void>
194struct is_tuple_like : std::false_type {};
195
196template <typename T>
197struct is_tuple_like<T, void_t<decltype(std::tuple_size<T>::value)>>
198 : has_tuple_get<T, typename gen_seq<std::tuple_size<T>::value>::type> {};
199
200// Completeness check that SFINAE-fails for incomplete T.
201template <typename T, typename = void>
202struct is_complete_type : std::false_type {};
203template <typename T>
204struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
205
206// Non-pointer [0] detection. Must not be instantiated for pointer-to-incomplete:
207// GCC treats that subscript as a hard error inside void_t, not SFINAE.
208template <typename T, typename = void>
209struct is_indexable_non_pointer : std::false_type {};
210template <typename T>
211struct is_indexable_non_pointer<T, void_t<decltype(std::declval<const T&>()[0])>> : std::true_type {};
212
213// Dispatch on is_pointer first so pointer-to-incomplete never reaches [0].
214template <typename T,
215 bool = std::is_pointer<
216 typename std::remove_cv<typename std::remove_reference<T>::type>::type>::value>
218
219template <typename T>
220struct is_array_dispatch<T, true>
221 : is_complete_type<typename std::remove_pointer<
222 typename std::remove_cv<typename std::remove_reference<T>::type>::type>::type> {};
223
224// Check if a type can use arr[0] like an array.
225template <typename T>
227
228
229template <typename T, typename = void>
230struct is_modifiable : std::false_type {};
231
232template <typename T>
233struct is_modifiable<T, void_t<decltype(
234 // Iterable
235 T().begin(), T().end(), T().size(),
236 // Values are mutable
237 // This rejects associative containers, for example
238 // *T().begin() = std::declval<value_type_t<T>>(),
239 // Can insert and erase elements
240 T().insert(T().end(), std::declval<typename T::value_type>()),
241 T().erase(T().begin()), (void)0)>> : std::true_type {};
242
243
244
245// Check if a type has the element type as std::pair
246template <typename T>
249 decltype((*std::declval<const T&>().begin()).second)>;
250
251template <typename T, typename = void>
252struct ele_type_is_pair : std::false_type {};
253
254template <typename T>
255struct ele_type_is_pair<T, has_pair_type<T>> : std::true_type {};
256
257template <typename T, typename V = void>
259 using type = T;
260};
261
262template <>
263struct to_store_type<const char*> {
265};
266
267template <>
268struct to_store_type<const char (&)[]> {
270};
271
272template <typename T>
273using is_not_array = typename std::enable_if<!std::is_array<T>::value>::type;
274template <typename T>
276 using type = T;
277};
278
279template <typename T>
280struct to_store_type<T&&> {
281 using type = T;
282};
283
284template <typename T>
286
287
288template <size_t I>
290 template <typename T, typename F>
291 static void visit(T& tup, size_t idx, F&& fun) {
292 if (idx == I - 1)
293 fun(tuple_get<I - 1>(tup));
294 else
295 visit_impl<I - 1>::visit(tup, idx, std::forward<F>(fun));
296 }
297};
298
299template <>
300struct visit_impl<0> {
301 template <typename T, typename F>
302 static void visit(T&, size_t, F&&) {}
303};
304
305template <typename F, typename T>
306void visit_at(T& tup, size_t idx, F&& fun) {
308 tup, idx, std::forward<F>(fun));
309}
310
311template <size_t I>
313 template <typename T1, typename T2, typename F>
314 static void visit(T1& tup1, T2& tup2, size_t idx, F&& fun) {
315 if (idx == I - 1)
316 fun(tuple_get<I - 1>(tup1), tuple_get<I - 1>(tup2));
317 else
318 visit2_impl<I - 1>::visit(tup1, tup2, idx, std::forward<F>(fun));
319 }
320};
321
322template <>
323struct visit2_impl<0> {
324 template <typename T1, typename T2, typename F>
325 static void visit(T1&, T2&, size_t, F&&) {}
326};
327
328template <typename F, typename T1, typename T2>
329void visit2_at(T1& tup1, T2& tup2, size_t idx, F&& fun) {
331 tup1, tup2, idx, std::forward<F>(fun));
332}
333
334#define ZEROERR_ENABLE_IF(x) \
335 template <typename T> \
336 typename std::enable_if<x, void>::type
337#define ZEROERR_IS_INT std::is_integral<T>::value
338#define ZEROERR_IS_FLOAT std::is_floating_point<T>::value
339#define ZEROERR_IS_ENUM std::is_enum<T>::value
340#define ZEROERR_IS_CONTAINER detail::is_container<T>::value
341#define ZEROERR_IS_STRING detail::is_string<T>::value
342#define ZEROERR_IS_POINTER (std::is_pointer<T>::value || std::is_same<T, std::nullptr_t>::value)
343#define ZEROERR_IS_CHAR std::is_same<T, char>::value
344#define ZEROERR_IS_WCHAR std::is_same<T, wchar_t>::value
345#define ZEROERR_IS_CLASS std::is_class<T>::value
346#define ZEROERR_IS_STREAMABLE detail::is_streamable<zeroerr::StringBuffer, T>::value
347#define ZEROERR_IS_ARRAY detail::is_array<T>::value
348#define ZEROERR_IS_COMPLEX detail::is_complex<T>::value
349#define ZEROERR_IS_BOOL std::is_same<T, bool>::value
350#define ZEROERR_IS_AUTOPTR detail::is_pointer_like<T>::value
351#define ZEROERR_IS_MAP detail::ele_type_is_pair<T>::value
352#define ZEROERR_IS_POD std::is_standard_layout<T>::value
353#define ZEROERR_IS_EXT detail::has_extension<T>::value
354
355} // namespace detail
356
357} // namespace zeroerr
358
359
361#pragma pop_macro("_LIBCPP_REMOVE_TRANSITIVE_INCLUDES")
Definition buffer.h:7
Definition string.h:41
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:283
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:235
STL namespace
typename to_store_type< T >::type to_store_type_t
Definition typetraits.h:285
auto tuple_get(T &&value) -> decltype(get< I >(std::forward< T >(value)))
Definition typetraits.h:182
void get()=delete
void_t< decltype(std::declval< S & >()<< std::declval< const 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:125
void void_t
Definition typetraits.h:55
void visit2_at(T1 &tup1, T2 &tup2, size_t idx, F &&fun)
Definition typetraits.h:329
typename std::enable_if<!std::is_array< T >::value >::type is_not_array
Definition typetraits.h:273
void visit_at(T &tup, size_t idx, F &&fun)
Definition typetraits.h:306
void_t< decltype((*std::declval< const T & >().begin()).first), decltype((*std::declval< const T & >().begin()).second)> has_pair_type
Definition typetraits.h:249
void_t< decltype(std::declval< const T & >().begin()), decltype(std::declval< const T & >().end()), decltype(*std::declval< decltype(std::declval< const T & >().begin())& >()), decltype(++std::declval< decltype(std::declval< const T & >().begin())& >()), decltype(std::declval< const T & >().begin() !=std::declval< const T & >().end()), decltype(std::declval< const T & >().begin()==std::declval< const T & >().end())> has_begin_end
Definition typetraits.h:112
Definition assert_text.cpp:5
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:252
Definition typetraits.h:77
Definition typetraits.h:187
Definition typetraits.h:217
Definition typetraits.h:226
Definition typetraits.h:202
Definition typetraits.h:154
Definition typetraits.h:115
Definition typetraits.h:230
Definition typetraits.h:164
Definition typetraits.h:85
Definition typetraits.h:97
Definition typetraits.h:135
Definition typetraits.h:151
Definition typetraits.h:194
Definition typetraits.h:171
Definition typetraits.h:74
T type
Definition typetraits.h:281
Definition typetraits.h:258
T type
Definition typetraits.h:259
static void visit(T1 &, T2 &, size_t, F &&)
Definition typetraits.h:325
Definition typetraits.h:312
static void visit(T1 &tup1, T2 &tup2, size_t idx, F &&fun)
Definition typetraits.h:314
static void visit(T &, size_t, F &&)
Definition typetraits.h:302
Definition typetraits.h:289
static void visit(T &tup, size_t idx, F &&fun)
Definition typetraits.h:291
rank is a helper class for Printer to define the priority of overloaded functions.
Definition typetraits.h:43