RLBox
rlbox_type_traits.hpp
1 #pragma once
2 // IWYU pragma: private, include "rlbox.hpp"
3 // IWYU pragma: friend "rlbox_.*\.hpp"
4 
5 #include <array>
6 #include <type_traits>
7 
8 namespace rlbox::detail {
9 
10 #define RLBOX_ENABLE_IF(...) std::enable_if_t<__VA_ARGS__>* = nullptr
11 
12 template<typename T>
13 constexpr bool true_v = true;
14 
15 template<typename T>
16 constexpr bool is_fundamental_or_enum_v =
17  std::is_fundamental_v<T> || std::is_enum_v<T>;
18 
19 template<typename T>
20 constexpr bool is_basic_type_v =
21  std::is_fundamental_v<T> || std::is_enum_v<T> || std::is_pointer_v<T>;
22 
23 template<typename T>
24 using valid_return_t =
25  std::conditional_t<std::is_function_v<T>, void*, std::decay_t<T>>;
26 
27 template<typename T>
28 using valid_param_t = std::conditional_t<std::is_void_v<T>, void*, T>;
29 
30 namespace func_arg_nums_v_detail {
31  template<typename T_Ret, typename... T_Args>
32  constexpr size_t helper_two(T_Ret(*)(T_Args...))
33  {
34  return sizeof...(T_Args);
35  }
36  template<typename T_Func>
37  constexpr size_t helper()
38  {
39  constexpr T_Func* ptr = nullptr;
40  return helper_two(ptr);
41  }
42 }
43 
44 template<typename T_Func>
45 constexpr size_t func_arg_nums_v = func_arg_nums_v_detail::helper<T_Func>();
46 
47 template<typename T>
48 using valid_array_el_t =
49  std::conditional_t<std::is_void_v<T> || std::is_function_v<T>, int, T>;
50 
51 template<typename T>
52 constexpr bool is_func_ptr_v = (std::is_pointer_v<T> &&
53  std::is_function_v<std::remove_pointer_t<T>>) ||
54  std::is_member_function_pointer_v<T>;
55 
56 template<typename T>
57 constexpr bool is_func_or_func_ptr = std::is_function_v<T> || is_func_ptr_v<T>;
58 
59 template<typename T>
60 constexpr bool is_one_level_ptr_v =
61  std::is_pointer_v<T> && !std::is_pointer_v<std::remove_pointer_t<T>>;
62 
63 template<typename T_This, typename T_Target>
64 using add_const_if_this_const_t =
65  std::conditional_t<std::is_const_v<std::remove_pointer_t<T_This>>,
66  std::add_const_t<T_Target>,
67  T_Target>;
68 
69 template<typename T>
70 using remove_const_from_pointer = std::conditional_t<
71  std::is_pointer_v<T>,
72  std::add_pointer_t<std::remove_const_t<std::remove_pointer_t<T>>>,
73  T>;
74 
75 template<typename T>
76 using add_const_from_pointer = std::conditional_t<
77  std::is_pointer_v<T>,
78  std::remove_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>,
79  T>;
80 
81 template<typename T>
82 using remove_cv_ref_t = std::remove_cv_t<std::remove_reference_t<T>>;
83 
84 template<typename T>
85 using c_to_std_array_t =
86  std::conditional_t<std::is_array_v<T>,
87  std::array<std::remove_extent_t<T>, std::extent_v<T>>,
88  T>;
89 
90 namespace std_array_to_c_arr_detail {
91  template<typename T>
92  struct W
93  {
94  using type = T;
95  };
96 
97  template<typename T, size_t N>
98  W<T[N]> std_array_to_c_arr_helper(std::array<T, N>);
99 
100  template<typename T>
101  W<T> std_array_to_c_arr_helper(T&&);
102 }
103 
104 template<typename T>
105 using std_array_to_c_arr_t =
106  typename decltype(std_array_to_c_arr_detail::std_array_to_c_arr_helper(
107  std::declval<T>()))::type;
108 
109 template<typename T>
110 using dereference_result_t =
111  std::conditional_t<std::is_pointer_v<T>,
112  std::remove_pointer_t<T>,
113  std::remove_extent_t<std_array_to_c_arr_t<T>> // is_array
114  >;
115 
116 template<typename T>
117 using value_type_t =
118  std::conditional_t<std::is_array_v<T>, c_to_std_array_t<T>, T>;
119 
120 template<typename T>
121 using function_ptr_t =
122  std::conditional_t<std::is_pointer_v<T> &&
123  std::is_function_v<std::remove_pointer_t<T>>,
124  T,
125  int (*)(int)>;
126 
127 namespace is_c_or_std_array_detail {
128  template<typename T, typename T_Enable = void>
130 
131  template<typename T>
132  struct is_c_or_std_array_helper<T, std::enable_if_t<std::is_array_v<T>>>
133  : std::true_type
134  {};
135 
136  template<typename T, size_t N>
137  std::true_type is_std_array_helper(std::array<T, N>*);
138 
139  template<typename T>
140  std::false_type is_std_array_helper(T*);
141 
142  template<typename T>
143  constexpr bool is_std_array_v =
144  decltype(is_std_array_helper(std::declval<std::add_pointer_t<T>>()))::value;
145 
146  template<typename T>
147  struct is_c_or_std_array_helper<T, std::enable_if_t<is_std_array_v<T>>>
148  : std::true_type
149  {};
150 
151  template<typename T>
153  T,
154  std::enable_if_t<!std::is_array_v<T> && !is_std_array_v<T>>>
155  : std::false_type
156  {};
157 }
158 
159 template<typename T>
160 constexpr bool is_std_array_v = is_c_or_std_array_detail::is_std_array_v<T>;
161 
162 template<typename T>
163 constexpr bool is_c_or_std_array_v =
165 
166 namespace std_array_el_detail {
167  template<typename T>
168  struct W
169  {
170  using type = T;
171  };
172 
173  template<typename T, size_t N>
174  W<T> is_std_array_helper(std::array<T, N>*);
175 
176  template<typename T>
177  W<void> is_std_array_helper(T*);
178 
179  template<typename T>
180  using std_array_el_t = decltype(std_array_el_detail::is_std_array_helper(
181  std::declval<std::add_pointer_t<T>>));
182 }
183 
184 template<typename T>
185 using std_array_el_t = typename std_array_el_detail::std_array_el_t<T>::type;
186 
187 namespace all_extents_same_detail {
188 
189  template<typename T1, typename T2, typename T_Enable = void>
191 
192  template<typename T1, typename T2>
194  T1,
195  T2,
196  std::enable_if_t<std::rank_v<T1> != std::rank_v<T2>>> : std::false_type
197  {};
198 
199  template<typename T1, typename T2>
201  T1,
202  T2,
203  std::enable_if_t<std::rank_v<T1> == std::rank_v<T2> &&
204  !std::is_array_v<T1> && !std::is_array_v<T2>>>
205  : std::true_type
206  {};
207 
208  template<typename T1, typename T2>
210  T1,
211  T2,
212  std::enable_if_t<std::rank_v<T1> == std::rank_v<T2> &&
213  std::is_array_v<T1> && std::is_array_v<T2> &&
214  std::extent_v<T1> != std::extent_v<T2>>> : std::false_type
215  {};
216 
217  template<typename T1, typename T2>
219  T1,
220  T2,
221  std::enable_if_t<std::rank_v<T1> == std::rank_v<T2> &&
222  std::is_array_v<T1> && std::is_array_v<T2> &&
223  std::extent_v<T1> == std::extent_v<T2>>>
224  {
225  static constexpr bool value =
227  std::remove_extent_t<T2>>::value;
228  };
229 }
230 
231 template<typename T1, typename T2>
232 constexpr bool all_extents_same =
234 
235 // remove all pointers/extent types
236 namespace remove_all_pointers_detail {
237  template<typename T>
239  {
240  typedef T type;
241  };
242 
243  template<typename T>
245  {
246  typedef typename remove_all_pointers<T>::type type;
247  };
248 }
249 
250 template<typename T>
251 using remove_all_pointers_t =
252  typename remove_all_pointers_detail::remove_all_pointers<T>::type;
253 
254 // remove all pointers/extent types
255 namespace base_type_detail {
256  template<typename T>
257  struct base_type
258  {
259  typedef T type;
260  };
261 
262  template<typename T>
263  struct base_type<T*>
264  {
265  typedef typename base_type<T>::type type;
266  };
267 
268  template<typename T>
269  struct base_type<T[]>
270  {
271  typedef typename base_type<T>::type type;
272  };
273 
274  template<typename T, std::size_t N>
275  struct base_type<T[N]>
276  {
277  typedef typename base_type<T>::type type;
278  };
279 }
280 
281 template<typename T>
282 using base_type_t = typename base_type_detail::base_type<T>::type;
283 
284 // convert types
285 namespace convert_detail {
286  template<typename T,
287  typename T_ShortType,
288  typename T_IntType,
289  typename T_LongType,
290  typename T_LongLongType,
291  typename T_PointerType,
292  typename T_Enable = void>
294 
295  template<typename T,
296  typename T_ShortType,
297  typename T_IntType,
298  typename T_LongType,
299  typename T_LongLongType,
300  typename T_PointerType>
302  T,
303  T_ShortType,
304  T_IntType,
305  T_LongType,
306  T_LongLongType,
307  T_PointerType,
308  std::enable_if_t<std::is_same_v<short, T> && !std::is_const_v<T>>>
309  {
310  using type = T_ShortType;
311  };
312 
313  template<typename T,
314  typename T_ShortType,
315  typename T_IntType,
316  typename T_LongType,
317  typename T_LongLongType,
318  typename T_PointerType>
320  T,
321  T_ShortType,
322  T_IntType,
323  T_LongType,
324  T_LongLongType,
325  T_PointerType,
326  std::enable_if_t<std::is_same_v<int, T> && !std::is_const_v<T>>>
327  {
328  using type = T_IntType;
329  };
330 
331  template<typename T,
332  typename T_ShortType,
333  typename T_IntType,
334  typename T_LongType,
335  typename T_LongLongType,
336  typename T_PointerType>
338  T,
339  T_ShortType,
340  T_IntType,
341  T_LongType,
342  T_LongLongType,
343  T_PointerType,
344  std::enable_if_t<std::is_same_v<long, T> && !std::is_const_v<T>>>
345  {
346  using type = T_LongType;
347  };
348 
349  template<typename T,
350  typename T_ShortType,
351  typename T_IntType,
352  typename T_LongType,
353  typename T_LongLongType,
354  typename T_PointerType>
356  T,
357  T_ShortType,
358  T_IntType,
359  T_LongType,
360  T_LongLongType,
361  T_PointerType,
362  std::enable_if_t<std::is_same_v<long long, T> && !std::is_const_v<T>>>
363  {
364  using type = T_LongLongType;
365  };
366 
367  template<typename T,
368  typename T_ShortType,
369  typename T_IntType,
370  typename T_LongType,
371  typename T_LongLongType,
372  typename T_PointerType>
374  T,
375  T_ShortType,
376  T_IntType,
377  T_LongType,
378  T_LongLongType,
379  T_PointerType,
380  std::enable_if_t<std::is_pointer_v<T> && !std::is_const_v<T>>>
381  {
382  using type = T_PointerType;
383  };
384 
385  template<typename T,
386  typename T_ShortType,
387  typename T_IntType,
388  typename T_LongType,
389  typename T_LongLongType,
390  typename T_PointerType>
392  T,
393  T_ShortType,
394  T_IntType,
395  T_LongType,
396  T_LongLongType,
397  T_PointerType,
398  std::enable_if_t<std::is_unsigned_v<T> && !std::is_same_v<T, bool> &&
399  !std::is_same_v<T, char> && !std::is_const_v<T> &&
400  !std::is_enum_v<T>>>
401  {
402  using type = std::make_unsigned_t<
404  T_ShortType,
405  T_IntType,
406  T_LongType,
407  T_LongLongType,
408  T_PointerType>::type>;
409  };
410 
411  template<typename T,
412  typename T_ShortType,
413  typename T_IntType,
414  typename T_LongType,
415  typename T_LongLongType,
416  typename T_PointerType>
418  T,
419  T_ShortType,
420  T_IntType,
421  T_LongType,
422  T_LongLongType,
423  T_PointerType,
424  std::enable_if_t<(
425  std::is_same_v<bool, T> || std::is_same_v<void, T> ||
426  std::is_same_v<char, T> || std::is_same_v<signed char, T> ||
427  std::is_floating_point_v<T> || std::is_enum_v<T>)&&!std::is_const_v<T>>>
428  {
429  using type = T;
430  };
431 
432  template<typename T,
433  typename T_ShortType,
434  typename T_IntType,
435  typename T_LongType,
436  typename T_LongLongType,
437  typename T_PointerType>
439  T,
440  T_ShortType,
441  T_IntType,
442  T_LongType,
443  T_LongLongType,
444  T_PointerType,
445  std::enable_if_t<std::is_array_v<T> && !std::is_const_v<T>>>
446  {
447  using type = typename convert_base_types_t_helper<
448  std::remove_extent_t<T>,
449  T_ShortType,
450  T_IntType,
451  T_LongType,
452  T_LongLongType,
453  T_PointerType>::type[std::extent_v<T>];
454  };
455 
456  template<typename T,
457  typename T_ShortType,
458  typename T_IntType,
459  typename T_LongType,
460  typename T_LongLongType,
461  typename T_PointerType>
463  T_ShortType,
464  T_IntType,
465  T_LongType,
466  T_LongLongType,
467  T_PointerType,
468  std::enable_if_t<std::is_const_v<T>>>
469  {
470  using type = std::add_const_t<
472  T_ShortType,
473  T_IntType,
474  T_LongType,
475  T_LongLongType,
476  T_PointerType>::type>;
477  };
478 }
479 
480 template<typename T,
481  typename T_ShortType,
482  typename T_IntType,
483  typename T_LongType,
484  typename T_LongLongType,
485  typename T_PointerType>
486 using convert_base_types_t =
488  T_ShortType,
489  T_IntType,
490  T_LongType,
491  T_LongLongType,
492  T_PointerType>::type;
493 
494 namespace unsigned_int_of_size_t_detail {
495  template<typename T, typename T_Enable = void>
497 
498  template<typename T>
499  struct unsigned_int_of_size_t_helper<T, std::enable_if_t<sizeof(T) == 1>>
500  {
501  using type = uint8_t;
502  };
503 
504  template<typename T>
505  struct unsigned_int_of_size_t_helper<T, std::enable_if_t<sizeof(T) == 2>>
506  {
507  using type = uint16_t;
508  };
509 
510  template<typename T>
511  struct unsigned_int_of_size_t_helper<T, std::enable_if_t<sizeof(T) == 4>>
512  {
513  using type = uint32_t;
514  };
515 
516  template<typename T>
517  struct unsigned_int_of_size_t_helper<T, std::enable_if_t<sizeof(T) == 8>>
518  {
519  using type = uint64_t;
520  };
521 }
522 
523 template<typename T>
524 using unsigned_int_of_size_t =
526  T>::type;
527 
528 }
Definition: rlbox_type_traits.hpp:258
Definition: rlbox_type_traits.hpp:169
Definition: rlbox_type_traits.hpp:93