Empirical
type_traits.h
Go to the documentation of this file.
1 
11 #ifndef EMP_TYPE_TRAITS_H
12 #define EMP_TYPE_TRAITS_H
13 
14 #include <functional>
15 #include <tuple>
16 #include <utility>
17 
18 #include "../base/Ptr.h"
19 
20 namespace emp {
21 
22  // Customized type traits
23  template <typename T> struct is_ptr_type { enum { value = false }; };
24  template <typename T> struct is_ptr_type<T*> { enum { value = true }; };
25  template <typename T> struct is_ptr_type<T* const> { enum { value = true }; };
26  template <typename T> struct is_ptr_type<Ptr<T>> { enum { value = true }; };
27  template <typename T>
28  constexpr bool is_ptr_type_v(const T&) { return is_ptr_type<T>::value; }
29 
30  template <typename T> struct remove_ptr_type { using type = T; };
31  template <typename T> struct remove_ptr_type<T*> { using type = T; };
32  template <typename T> struct remove_ptr_type<Ptr<T>> { using type = T; };
33  template <typename T>
35  // @CAO: Make sure we are dealing with const and volitile pointers correctly.
36 
37  // Can we convert the first pointer into the second?
38  template <typename T1, typename T2> struct ptr_pair {
39  static constexpr bool Same() { return false; }
40  static constexpr bool SameBase() { return false; }
41  static bool ConvertOK(T1 * ptr) { return dynamic_cast<T2*>(ptr); }
42  };
43  template <typename T> struct ptr_pair<T,T> {
44  static constexpr bool Same() { return true; }
45  static constexpr bool SameBase() { return true; }
46  static constexpr bool ConvertOK(T *) { return true; }
47  };
48  template <typename T> struct ptr_pair<T, const T> {
49  static constexpr bool Same() { return false; }
50  static constexpr bool SameBase() { return true; }
51  static constexpr bool ConvertOK(T *) { return true; }
52  };
53  template <typename T> struct ptr_pair<const T, T> {
54  static constexpr bool Same() { return false; }
55  static constexpr bool SameBase() { return true; }
56  static constexpr bool ConvertOK(T *) { return false; }
57  };
58 
59  namespace detail {
60  template <typename Fn, typename... Args>
62  private:
63  // If U can be invoked with Args... for arguments, then it will have some
64  // return value, and we try to create a pointer to it. Note the use of
65  // decay_t. This will remove any references from the return value, which
66  // would cause SFINAE to fail, since C++ does not allow pointers to
67  // references
68  template <typename U>
69  static std::true_type check(
70  U &&,
71  std::decay_t<decltype(std::declval<U>()(std::declval<Args>()...))> * =
72  nullptr) {
73  return {};
74  }
75 
76  // Catchall which handles the cases where U is not callable with Args
77  // arguments
78  template <typename U>
79  static std::false_type check(...) {
80  return {};
81  }
82 
83  public:
84  static constexpr decltype(check<Fn>(std::declval<Fn>())) value() {
85  return {};
86  }
87  };
88  } // namespace detail
89 
90  template <typename Fn, typename... Args>
91  struct is_invocable
92  : decltype(detail::is_invocable_helper<Fn, Args...>::value()) {};
93 
94  // @todo: It might be a good idea to move these to a separate file
95  // @todo: should these be using the std naming convention?
96 
97  namespace __impl_variadics_type_traits {
98  // General container type which represents a parameter pack
99  template <typename...>
100  struct pack {};
101  template <template <typename...> class Variadic, typename Pack>
102  struct FromPack;
103 
104  template <template <typename...> class Variadic, typename Pack>
106 
107  template <template <typename...> class Variadic, typename... U>
108  struct FromPack<Variadic, pack<U...>> {
109  using type = Variadic<U...>;
110  };
111 
112  template <template <typename...> class Variadic, typename Pack>
113  struct ToPack;
114 
115  template <template <typename...> class Variadic, typename Pack>
117 
118  template <template <typename...> class Variadic, typename... U>
119  struct ToPack<Variadic, Variadic<U...>> {
120  using type = pack<U...>;
121  };
122 
123  template <bool, typename Needle, typename Haystack,
124  template <typename, typename> class Cmp>
126 
127  template <typename Needle, typename Haystack,
128  template <typename, typename> class Cmp>
130 
131  // Base case where pack<U...> == pack<>
132  template <typename Needle, template <typename, typename> class Cmp>
133  struct variadic_contains<Needle, __impl_variadics_type_traits::pack<>, Cmp>
134  : std::false_type {};
135 
136  // Base case where Variadic<A...> == Variadic<>
137  template <typename Needle, typename U0, typename... U,
138  template <typename, typename> class Cmp>
139  struct variadic_contains<Needle,
140  __impl_variadics_type_traits::pack<U0, U...>, Cmp>
142  Cmp<Needle, U0>::value, Needle,
143  __impl_variadics_type_traits::pack<U...>, Cmp> {};
144 
145  template <typename Needle, typename Haystack,
146  template <typename, typename> class Cmp>
147  struct variadic_contains_switch<true, Needle, Haystack, Cmp>
148  : std::true_type {};
149 
150  template <typename Needle, typename Haystack,
151  template <typename, typename> class Cmp>
152  struct variadic_contains_switch<false, Needle, Haystack, Cmp>
153  : variadic_contains<Needle, Haystack, Cmp> {};
154 
155  } // namespace __impl_variadics_type_traits
156 
157  // -- variadic_contains --
158  // A utility for checking if any template class X<A0, A1, ..., An> has one of
159  // its template parameters such that Ak == Needle
160 
161  template <typename Needle, typename Haystack,
162  template <typename, typename> class Cmp = std::is_same>
164 
165  // Base case where Variadic<A...> == Variadic<>
166  template <typename Needle, template <typename...> class Variadic,
167  typename... U, template <typename, typename> class Cmp>
168  struct variadic_contains<Needle, Variadic<U...>, Cmp>
170  Needle, __impl_variadics_type_traits::pack<U...>, Cmp> {};
171 
172  template <typename Needle, typename Haystack,
173  template <typename, typename> class... Cmp>
174  constexpr bool variadic_contains_v{
175  variadic_contains<Needle, Haystack, Cmp...>::value};
176 
177  // -- variadic_concat --
178  template <typename... Variadics>
180  template <typename... Variadics>
181  using variadic_concat_t = typename variadic_concat<Variadics...>::type;
182 
183  namespace __impl_variadics_type_traits {
184 
185  template <template <typename...> class Variadic, typename Pack>
187 
188  template <template <typename...> class Variadic, class... U>
189  struct variadic_concat<Variadic, pack<pack<U...>>> {
190  using type = pack<U...>;
191  };
192 
193  template <template <typename...> class Variadic, class... A, class... B,
194  class... Rest>
195  struct variadic_concat<Variadic,
196  pack<pack<A...>, Variadic<B...>, Rest...>> {
197  using type =
198  typename variadic_concat<Variadic,
199  pack<pack<A..., B...>, Rest...>>::type;
200  };
201  } // namespace __impl_variadics_type_traits
202 
203  template <template <typename...> class Variadic, class... A, class... Rest>
204  struct variadic_concat<Variadic<A...>, Rest...> {
206  Variadic,
210  };
211 
212  // -- variadic_remove_duplicates --
213  template <typename Variadic, template <typename> class Filter>
215 
216  template <typename Variadic, template <typename> class Filter>
218 
219  namespace __impl_variadics_type_traits {
220 
221  template <typename Filtered, typename Unfiltered,
222  template <typename> class Filter>
224 
225  template <bool, typename Filtered, typename Unfiltered,
226  template <typename> class Filter>
228 
229  template <typename Filtered, typename... Unfiltered,
230  template <typename> class Filter>
231  struct variadic_filter<Filtered, pack<Unfiltered...>, Filter> {
232  using type = Filtered;
233  };
234 
235  template <typename... Filtered, typename R0, typename... Rest,
236  template <typename> class Filter>
237  struct variadic_filter<pack<Filtered...>, pack<R0, Rest...>, Filter>
238  : variadic_filter_switch<Filter<R0>::value, pack<Filtered...>,
239  pack<R0, Rest...>, Filter> {};
240 
241  template <typename... Filtered, typename R0, typename... Rest,
242  template <typename> class Filter>
243  struct variadic_filter_switch<false, pack<Filtered...>, pack<R0, Rest...>,
244  Filter> {
245  using type = typename variadic_filter<pack<Filtered...>, pack<Rest...>,
246  Filter>::type;
247  };
248 
249  template <typename... Filtered, typename R0, typename... Rest,
250  template <typename> class Filter>
251  struct variadic_filter_switch<true, pack<Filtered...>, pack<R0, Rest...>,
252  Filter> {
253  using type = typename variadic_filter<pack<Filtered..., R0>,
254  pack<Rest...>, Filter>::type;
255  };
256  } // namespace __impl_variadics_type_traits
257 
258  template <template <typename...> class Variadic, typename... U,
259  template <typename> class Filter>
260  struct variadic_filter<Variadic<U...>, Filter> {
265  };
266 
267  // -- variadic_remove_duplicates --
268  template <typename Variadic,
269  template <typename, typename> class Cmp = std::is_same>
271 
272  template <typename Variadic, template <typename, typename> class... Cmp>
274  typename variadic_remove_duplicates<Variadic, Cmp...>::type;
275 
276  namespace __impl_variadics_type_traits {
277 
278  template <typename Unique, typename Remaining,
279  template <typename, typename> class Cmp>
281 
282  template <bool, typename Unique, typename Remaining,
283  template <typename, typename> class Cmp>
285 
286  template <typename Unique, typename... Rest,
287  template <typename, typename> class Cmp>
288  struct variadic_remove_duplicates<Unique, pack<Rest...>, Cmp> {
289  using type = Unique;
290  };
291 
292  template <typename... Unique, typename R0, typename... Rest,
293  template <typename, typename> class Cmp>
294  struct variadic_remove_duplicates<pack<Unique...>, pack<R0, Rest...>, Cmp>
296  variadic_contains_v<R0, pack<Unique...>, Cmp>, pack<Unique...>,
297  pack<R0, Rest...>, Cmp> {};
298 
299  template <typename... Unique, typename R0, typename... Rest,
300  template <typename, typename> class Cmp>
301  struct variadic_remove_duplicates_switch<false, pack<Unique...>,
302  pack<R0, Rest...>, Cmp> {
303  using type =
304  typename variadic_remove_duplicates<pack<Unique..., R0>, pack<Rest...>,
305  Cmp>::type;
306  };
307 
308  template <typename... Unique, typename R0, typename... Rest,
309  template <typename, typename> class Cmp>
310  struct variadic_remove_duplicates_switch<true, pack<Unique...>,
311  pack<R0, Rest...>, Cmp> {
312  using type =
313  typename variadic_remove_duplicates<pack<Unique...>, pack<Rest...>,
314  Cmp>::type;
315  };
316  } // namespace __impl_variadics_type_traits
317 
318  template <template <typename...> class Variadic, typename... U,
319  template <typename, typename> class Cmp>
320  struct variadic_remove_duplicates<Variadic<U...>, Cmp> {
322  Variadic,
326  };
327 
328  // -- variadic_union --
329  // Given X<A0, A1, ... An> and X<B0, B1, ... Bm>, this gives X<Union of
330  // A and B>. Note that this will also remove any duplicates in A and B.
331  // Also, the ordering of the elements in the union is undefined.
332  template <template <typename, typename> class Cmp, typename...>
334 
335  template <template <typename, typename> class Cmp, typename... U>
336  using variadic_union_t = typename variadic_union<Cmp, U...>::type;
337 
338  namespace __impl_variadics_type_traits {
339  template <template <typename, typename> class Cmp, typename...>
341 
342  template <template <typename, typename> class Cmp, typename U>
343  struct variadic_union<Cmp, U> {
344  using type = U;
345  };
346 
347  template <template <typename, typename> class Cmp, typename U0, typename U1,
348  typename... U>
349  struct variadic_union<Cmp, U0, U1, U...> {
350  private:
352  using second_t = variadic_remove_duplicates_t<U1, Cmp>;
353 
354  template <typename T>
355  struct not_in_first
356  : std::integral_constant<bool, !variadic_contains_v<T, first_t, Cmp>> {
357  };
358 
359  using filtered_second_t = variadic_filter_t<second_t, not_in_first>;
360 
362 
363  public:
364  // @todo: There are more efficient ways to do this
365  using type = typename variadic_union<Cmp, head_t, U...>::type;
366  };
367  } // namespace __impl_variadics_type_traits
368 
369  template <template <typename...> class Variadic,
370  template <typename, typename> class Cmp, typename... U>
371  struct variadic_union<Cmp, Variadic<U...>> {
373  Variadic, variadic_remove_duplicates_t<
375  };
376 
377  template <template <typename...> class Variadic,
378  template <typename, typename> class Cmp, typename... U0,
379  typename U1, typename... U>
380  struct variadic_union<Cmp, Variadic<U0...>, U1, U...> {
382  Variadic,
387  };
388 
389  // -- variadic_intersection --
390  // Given X<A0, A1, ... An> and X<B0, B1, ... Bm>, this gives X<Intersection
391  // of A and B>
392  template <template <typename, typename> class Cmp, typename...>
394 
395  template <template <typename, typename> class Cmp, typename... U>
397  typename variadic_intersection<Cmp, U...>::type;
398 
399  namespace __impl_variadics_type_traits {
400 
401  template <template <typename, typename> class Cmp, typename...>
403  template <template <typename, typename> class Cmp, typename U>
404  struct variadic_intersection<Cmp, U> {
405  using type = U;
406  };
407 
408  template <template <typename, typename> class Cmp, typename U0, typename U1,
409  typename... U>
410  struct variadic_intersection<Cmp, U0, U1, U...> {
411  private:
413  using second_t = variadic_remove_duplicates_t<U1, Cmp>;
414 
415  template <typename T>
416  struct in_second
417  : std::integral_constant<bool, variadic_contains_v<T, second_t, Cmp>> {
418  };
419 
420  // Remove everything from first_t that is not also in second_t
421  using intersection_t = variadic_filter_t<first_t, in_second>;
422 
423  public:
424  // Remove that everything in intersection_t that is not also in U...
425  using type =
426  typename variadic_intersection<Cmp, intersection_t, U...>::type;
427  };
428  } // namespace __impl_variadics_type_traits
429 
430  template <template <typename...> class Variadic,
431  template <typename, typename> class Cmp, typename... U>
432  struct variadic_intersection<Cmp, Variadic<U...>> {
434  Variadic, variadic_remove_duplicates_t<
436  };
437 
438  template <template <typename...> class Variadic,
439  template <typename, typename> class Cmp, typename... U0,
440  typename U1, typename... U>
441  struct variadic_intersection<Cmp, Variadic<U0...>, U1, U...> {
443  Variadic,
448  };
449 
450  // variadic_index_of
451 
452  template <typename Needle, typename Haystack,
453  template <typename, typename> class Cmp = std::is_same>
455 
456  template <typename Needle, typename Haystack,
457  template <typename, typename> class... Cmp>
458  static constexpr auto variadic_index_of_v = {
459  variadic_index_of<Needle, Haystack, Cmp...>::value};
460 
461  namespace __impl_variadics_type_traits {
462 
463  template <size_t I, typename Needle, typename Haystack,
464  template <typename, typename> class Cmp>
466 
467  template <bool, size_t, typename Needle, typename Haystack,
468  template <typename, typename> class Cmp>
470 
471  template <size_t I, typename Needle, typename... U,
472  template <typename, typename> class Cmp>
473  struct variadic_index_ofSwitch<true, I, Needle, pack<U...>, Cmp>
474  : std::integral_constant<size_t, I> {};
475 
476  template <size_t I, typename Needle, typename... U,
477  template <typename, typename> class Cmp>
478  struct variadic_index_ofSwitch<false, I, Needle, pack<U...>, Cmp>
479  : variadic_index_of<I + 1, Needle, pack<U...>, Cmp> {};
480 
481  template <size_t I, typename Needle, typename U0, typename... U,
482  template <typename, typename> class Cmp>
483  struct variadic_index_of<I, Needle, pack<U0, U...>, Cmp>
484  : variadic_index_ofSwitch<Cmp<Needle, U0>::value, I, Needle, pack<U...>,
485  Cmp> {};
486 
487  } // namespace __impl_variadics_type_traits
488 
489  template <typename Needle, template <typename...> class Haystack,
490  typename... U, template <typename, typename> class Cmp>
491  struct variadic_index_of<Needle, Haystack<U...>, Cmp>
493  0, Needle, __impl_variadics_type_traits::pack<U...>, Cmp> {};
494 
495 } // namespace emp
496 
497 #endif
Definition: type_traits.h:454
Definition: type_traits.h:100
Definition: type_traits.h:163
Definition: type_traits.h:179
Definition: type_traits.h:91
__impl_variadics_type_traits::FromPackType< Variadic, typename __impl_variadics_type_traits::variadic_union< Cmp, __impl_variadics_type_traits::pack< U0... >, __impl_variadics_type_traits::ToPackType< Variadic, U1 >, __impl_variadics_type_traits::ToPackType< Variadic, U >... >::type > type
Definition: type_traits.h:386
typename variadic_concat< Variadic, pack< pack< A..., B... >, Rest... >>::type type
Definition: type_traits.h:199
typename ToPack< Variadic, Pack >::type ToPackType
Definition: type_traits.h:116
__impl_variadics_type_traits::FromPackType< Variadic, variadic_remove_duplicates_t< __impl_variadics_type_traits::pack< U... >, Cmp >> type
Definition: type_traits.h:374
typename FromPack< Variadic, Pack >::type FromPackType
Definition: type_traits.h:105
static constexpr bool SameBase()
Definition: type_traits.h:55
typename variadic_remove_duplicates< Variadic, Cmp... >::type variadic_remove_duplicates_t
Definition: type_traits.h:274
Definition: type_traits.h:61
typename remove_ptr_type< T >::type remove_ptr_type_t
Definition: type_traits.h:34
Definition: type_traits.h:38
static constexpr bool Same()
Definition: type_traits.h:39
typename variadic_remove_duplicates< pack< Unique..., R0 >, pack< Rest... >, Cmp >::type type
Definition: type_traits.h:305
T type
Definition: type_traits.h:31
Definition: type_traits.h:113
typename variadic_intersection< Cmp, U... >::type variadic_intersection_t
Definition: type_traits.h:397
Variadic< U... > type
Definition: type_traits.h:109
typename variadic_intersection< Cmp, intersection_t, U... >::type type
Definition: type_traits.h:426
static constexpr bool Same()
Definition: type_traits.h:44
T type
Definition: type_traits.h:32
typename variadic_filter< Variadic, Filter >::type variadic_filter_t
Definition: type_traits.h:217
static constexpr bool Same()
Definition: type_traits.h:54
__impl_variadics_type_traits::FromPackType< Variadic, variadic_remove_duplicates_t< __impl_variadics_type_traits::pack< U... >, Cmp >> type
Definition: type_traits.h:435
Definition: type_traits.h:270
Definition: type_traits.h:393
typename variadic_union< Cmp, U... >::type variadic_union_t
Definition: type_traits.h:336
static constexpr bool ConvertOK(T *)
Definition: type_traits.h:46
static constexpr bool Same()
Definition: type_traits.h:49
static bool ConvertOK(T1 *ptr)
Definition: type_traits.h:41
static constexpr bool ConvertOK(T *)
Definition: type_traits.h:51
Definition: type_traits.h:214
static constexpr bool SameBase()
Definition: type_traits.h:40
typename variadic_concat< Variadics... >::type variadic_concat_t
Definition: type_traits.h:181
constexpr bool variadic_contains_v
Definition: type_traits.h:174
static constexpr bool SameBase()
Definition: type_traits.h:45
T type
Definition: type_traits.h:30
Definition: type_traits.h:23
__impl_variadics_type_traits::FromPackType< Variadic, typename __impl_variadics_type_traits::variadic_intersection< Cmp, __impl_variadics_type_traits::pack< U0... >, __impl_variadics_type_traits::ToPackType< Variadic, U1 >, __impl_variadics_type_traits::ToPackType< Variadic, U >... >::type > type
Definition: type_traits.h:447
If we are in emscripten, make sure to include the header.
Definition: array.h:37
Definition: type_traits.h:333
Definition: Ptr.h:711
__impl_variadics_type_traits::FromPackType< Variadic, typename __impl_variadics_type_traits::variadic_filter< __impl_variadics_type_traits::pack<>, __impl_variadics_type_traits::pack< U... >, Filter >::type > type
Definition: type_traits.h:264
__impl_variadics_type_traits::FromPackType< Variadic, typename __impl_variadics_type_traits::variadic_concat< Variadic, __impl_variadics_type_traits::pack< __impl_variadics_type_traits::pack< A... >, Rest... >>::type > type
Definition: type_traits.h:209
typename variadic_remove_duplicates< pack< Unique... >, pack< Rest... >, Cmp >::type type
Definition: type_traits.h:314
typename variadic_union< Cmp, head_t, U... >::type type
Definition: type_traits.h:365
typename variadic_filter< pack< Filtered..., R0 >, pack< Rest... >, Filter >::type type
Definition: type_traits.h:254
Definition: type_traits.h:23
Definition: type_traits.h:30
static constexpr bool ConvertOK(T *)
Definition: type_traits.h:56
typename variadic_filter< pack< Filtered... >, pack< Rest... >, Filter >::type type
Definition: type_traits.h:246
constexpr bool is_ptr_type_v(const T &)
Definition: type_traits.h:28
Definition: type_traits.h:102
__impl_variadics_type_traits::FromPackType< Variadic, typename __impl_variadics_type_traits::variadic_remove_duplicates< __impl_variadics_type_traits::pack<>, __impl_variadics_type_traits::pack< U... >, Cmp >::type > type
Definition: type_traits.h:325
static constexpr bool SameBase()
Definition: type_traits.h:50
static constexpr auto variadic_index_of_v
Definition: type_traits.h:458