siplasplas
A library for C++ reflection and introspection
meta.hpp
1 #ifndef SIPLASPLAS_UTILITY_META_H
2 #define SIPLASPLAS_UTILITY_META_H
3 
4 #include <type_traits>
5 #include <cstdint>
6 
7 namespace cpp
8 {
9 
10 namespace meta
11 {
12  template<typename T>
13  using decay_t = typename std::decay<T>::type;
14 
15  template<typename... Bs>
16  struct assert;
17 
18  template<typename B, typename... Bs>
19  struct assert<B, Bs...> : assert<Bs...>
20  {
21  static_assert(B::value, "Assertion failed");
22  };
23 
24  template<>
25  struct assert<> {};
26 
27  template<typename T>
28  using void_t = typename std::conditional<sizeof(T) >= 0, void, T>::type;
29 
30  template<typename T>
31  struct identity
32  {
33  using type = T;
34  };
35 
36  template<typename Metafunction>
37  using type_t = typename Metafunction::type;
38 
39  template<typename MetafunctionClass, typename... Args>
40  using apply_t = type_t<typename MetafunctionClass::template apply<Args...>>;
41 
42  template<typename MetafunctionClass, typename Seq>
43  struct sequence_apply;
44 
45  template<typename MetafunctionClass,
46  template<typename...> class Seq, typename... Ts>
47  struct sequence_apply<MetafunctionClass, Seq<Ts...>>
48  {
49  using type = apply_t<MetafunctionClass, Ts...>;
50  };
51 
52  template<typename MetafunctionClass, typename Seq>
53  using sequence_apply_t = type_t<sequence_apply<MetafunctionClass, Seq>>;
54 
55  template<std::uint8_t I>
56  using uint8_t = std::integral_constant<std::uint8_t, I>;
57  template<std::uint16_t I>
58  using uint16_t = std::integral_constant<std::uint16_t, I>;
59  template<std::uint32_t I>
60  using uint32_t = std::integral_constant<std::uint32_t, I>;
61  template<std::uint64_t I>
62  using uint64_t = std::integral_constant<std::uint64_t, I>;
63 
64  template<std::int8_t I>
65  using int8_t = std::integral_constant<std::int8_t, I>;
66  template<std::int16_t I>
67  using int16_t = std::integral_constant<std::int16_t, I>;
68  template<std::int32_t I>
69  using int32_t = std::integral_constant<std::int32_t, I>;
70  template<std::int64_t I>
71  using int64_t = std::integral_constant<std::int64_t, I>;
72 
73  template<std::size_t I>
74  using size_t = std::integral_constant<std::size_t, I>;
75 
76  template<bool B>
77  using bool_ = std::integral_constant<bool, B>;
78  using true_ = bool_<true>;
79  using false_ = bool_<false>;
80 
81  template<char C>
82  using char_ = std::integral_constant<char, C>;
83 
84  template<typename T, typename = void>
85  struct is_integral : false_ {};
86  template<typename T>
87  struct is_integral<T, void_t<decltype(T::value)>> :
88  true_
89  {};
90 
91  template<typename T, typename = assert<is_integral<T>>>
92  constexpr decltype(T::value) value()
93  {
94  return T::value;
95  }
96 
97  template<template<typename...> class Function>
98  struct defer
99  {
100  template<typename... Args>
101  struct apply
102  {
103  template<typename Instance, bool = is_integral<Instance>::value>
104  struct result
105  {
106  using type = Instance;
107  };
108 
109  template<typename Instance>
110  struct result<Instance, false>
111  {
112  using type = type_t<Instance>;
113  };
114 
115  using type = type_t<result<Function<Args...>>>;
116  };
117  };
118 
119  struct and_
120  {
121  template<typename Lhs, typename Rhs>
122  struct apply : assert<
123  is_integral<Lhs>,
124  is_integral<Rhs>
125  >
126  {
127  using type = bool_<Lhs::value && Rhs::value>;
128  };
129  };
130 
131  template<typename Lhs, typename Rhs>
132  using and_t = apply_t<and_, Lhs, Rhs>;
133 
134  struct or_
135  {
136  template<typename Lhs, typename Rhs>
137  struct apply : assert<
138  is_integral<Lhs>,
139  is_integral<Rhs>
140  >
141  {
142  using type = bool_<Lhs::value || Rhs::value>;
143  };
144  };
145 
146  template<typename Lhs, typename Rhs>
147  using or_t = apply_t<or_, Lhs, Rhs>;
148 
149  struct add_
150  {
151  template<typename Lhs, typename Rhs>
152  struct apply : assert<
153  is_integral<Lhs>,
154  is_integral<Rhs>
155  >
156  {
157  using type = std::integral_constant<decltype(Lhs::value + Rhs::value), Lhs::value + Rhs::value>;
158  };
159  };
160 
161  template<typename Lhs, typename Rhs>
162  using add_t = apply_t<add_, Lhs, Rhs>;
163 
164  template<typename... Ts>
165  struct list
166  {
167  static constexpr std::size_t size = sizeof...(Ts);
168  };
169 
170  template<char... Chars>
171  using string = list<std::integral_constant<char, Chars>...>;
172 
173  template<typename Sequence>
174  class SequenceToArray;
175 
176  template<template<typename...> class Seq, typename T, T... Values>
177  class SequenceToArray<Seq<std::integral_constant<T, Values>...>>
178  {
179  public:
180  using array_t = const T[sizeof...(Values)];
181 
182  static constexpr const array_t& get()
183  {
184  return array;
185  }
186 
187  static constexpr const T get(std::size_t i)
188  {
189  return array[i];
190  }
191 
192  static constexpr std::size_t size()
193  {
194  return sizeof...(Values);
195  }
196 
197  private:
198  static constexpr const T array[] = {Values...};
199  };
200 
201  template<typename T, T... Values>
202  using PackToArray = SequenceToArray<list<std::integral_constant<T, Values>...>>;
203 
204  template<template<typename...> class Seq, typename T, T... Values>
205  constexpr const T SequenceToArray<Seq<std::integral_constant<T, Values>...>>::array[sizeof...(Values)];
206 
207  template<typename String>
208  class StringToArray;
209 
210  template<template<typename...> class Seq, char... Chars>
211  class StringToArray<Seq<std::integral_constant<char, Chars>...>> : public SequenceToArray<Seq<std::integral_constant<char, Chars>..., std::integral_constant<char, '\0'>>>
212  {
213  public:
214  static constexpr const char* c_str()
215  {
216  return SequenceToArray<Seq<std::integral_constant<char, Chars>..., std::integral_constant<char, '\0'>>>::get();
217  }
218 
219  static constexpr std::size_t length()
220  {
221  return sizeof...(Chars);
222  }
223  };
224 
225  template<char... Chars>
226  using PackStringToArray = StringToArray<list<std::integral_constant<char, Chars>...>>;
227 
228  template<typename Seq>
229  struct functor;
230 
231  template<template<typename...> class Seq, typename... Ts>
232  struct functor<Seq<Ts...>>
233  {
234  template<typename... Us>
235  struct apply
236  {
237  using type = Seq<Us...>;
238  };
239 
240  template<template<typename...> class Seq2, typename... Us>
241  struct apply<Seq2<Us...>>
242  {
243  using type = Seq<Us...>;
244  };
245  };
246 
247  template<typename Seq, typename... Ts>
248  using apply_functor = apply_t<functor<Seq>, Ts...>;
249 
250  template<typename Seq, typename... Ts>
251  using functor_t = apply_functor<Seq, Ts...>;
252 
253  template<typename Lhs, typename Rhs>
254  struct cat;
255 
256  template<template<typename...> class Seq,
257  typename... Lhs, typename... Rhs>
258  struct cat<Seq<Lhs...>, Seq<Rhs...>>
259  {
260  using type = Seq<Lhs..., Rhs...>;
261  };
262 
263  template<typename Lhs, typename Rhs>
264  using cat_t = type_t<cat<Lhs, Rhs>>;
265 
266  template<std::size_t I>
267  using index_t = std::integral_constant<std::size_t, I>;
268 
269  template<std::size_t... Is>
270  using index_sequence = list<index_t<Is>...>;
271 
272  namespace detail
273  {
274  template<typename Left, std::size_t Index, typename Right>
275  struct split;
276 
277  template<template<typename...> class Seq, std::size_t Index,
278  typename... Left, typename Head, typename... Tail>
279  struct split<Seq<Left...>, Index, Seq<Head, Tail...>>
280  {
281  using next = split<Seq<Left..., Head>, Index - 1, Seq<Tail...>>;
282 
283  using before = typename next::before;
284  using left = typename next::left;
285  using head = typename next::head;
286  using right = typename next::right;
287  using after = typename next::after;
288  };
289 
290  template<template<typename...> class Seq,
291  typename... Left, typename Head, typename... Tail>
292  struct split<Seq<Left...>, 0, Seq<Head, Tail...>>
293  {
294  using before = Seq<Left...>;
295  using left = Seq<Left..., Head>;
296  using head = Head;
297  using right = Seq<Head, Tail...>;
298  using after = Seq<Tail...>;
299  };
300  }
301 
302  template<std::size_t Index, typename... Ts>
303  using pack_split = detail::split<list<>, Index, list<Ts...>>;
304  template<std::size_t Index, typename... Ts>
305  using pack_split_left_t = typename pack_split<Index, Ts...>::left;
306  template<std::size_t Index, typename... Ts>
307  using pack_get_t = typename pack_split<Index, Ts...>::head;
308  template<std::size_t Index, typename... Ts>
309  using pack_split_right_t = typename pack_split<Index, Ts...>::right;
310  template<std::size_t Index, typename... Ts>
311  using pack_split_before_t = typename pack_split<Index, Ts...>::before;
312  template<std::size_t Index, typename... Ts>
313  using pack_split_after_t = typename pack_split<Index, Ts...>::after;
314  template<typename... Ts>
315  using pack_head_t = pack_get_t<0, Ts...>;
316  template<typename... Ts>
317  using pack_tail_t = pack_split_after_t<0, Ts...>;
318 
319  template<std::size_t Index, typename Seq>
320  struct split;
321  template<std::size_t Index, template<typename...> class Seq, typename... Ts>
322  struct split<Index, Seq<Ts...>>
323  {
324  using splitter = detail::split<Seq<>, Index, Seq<Ts...>>;
325 
326  using before = typename splitter::before;
327  using left = typename splitter::left;
328  using head = typename splitter::head;
329  using right = typename splitter::right;
330  using after = typename splitter::after;
331  };
332  template<std::size_t Index, typename Seq>
333  using split_left_t = typename split<Index, Seq>::left;
334  template<std::size_t Index, typename Seq>
335  using get_t = typename split<Index, Seq>::head;
336  template<std::size_t Index, typename Seq>
337  using split_right_t = typename split<Index, Seq>::right;
338  template<std::size_t Index, typename Seq>
339  using split_before_t = typename split<Index, Seq>::before;
340  template<std::size_t Index, typename Seq>
341  using split_after_t = typename split<Index, Seq>::after;
342  template<typename Seq>
343  using head_t = get_t<0, Seq>;
344  template<typename Seq>
345  using tail_t = split_after_t<0, Seq>;
346 
347 
348  template<typename T, typename... Ts>
349  using pack_prepend_t = list<T, Ts...>;
350  template<typename T, typename... Ts>
351  using pack_append_t = list<Ts..., T>;
352  template<typename T, std::size_t Index, typename... Ts>
353  using pack_insert_t = cat_t<pack_append_t<pack_split_left_t<Index, Ts...>, T>, pack_split_right_t<Index, Ts...>>;
354  template<typename T, std::size_t Index, typename... Ts>
355  using pack_remove_t = cat_t<pack_split_before_t<Index, Ts...>, pack_split_after_t<Index, Ts...>>;
356 
357  template<typename T, typename Seq>
358  struct prepend;
359  template<typename T, template<typename...> class Seq, typename... Ts>
360  struct prepend<T, Seq<Ts...>>
361  {
362  using type = Seq<T, Ts...>;
363  };
364  template<typename T, typename Seq>
365  struct append;
366  template<typename T, template<typename...> class Seq, typename... Ts>
367  struct append<T, Seq<Ts...>>
368  {
369  using type = Seq<Ts..., T>;
370  };
371 
372  template<typename T, typename Seq>
373  using prepend_t = type_t<prepend<T, Seq>>;
374  template<typename T, typename Seq>
375  using append_t = type_t<append<Seq, T>>;
376  template<typename T, std::size_t Index, typename Seq>
377  using insert_t = cat_t<append_t<split_left_t<Index, Seq>, T>, split_right_t<Index, Seq>>;
378  template<typename T, std::size_t Index, typename Seq>
379  using remove_t = cat_t<split_before_t<Index, Seq>, split_after_t<Index, Seq>>;
380 
381 
382  template<typename Key, typename Value>
383  struct pair
384  {
385  using key = Key;
386  using value = Value;
387  };
388 
389  template<typename Pair>
390  using key_t = typename Pair::key;
391  template<typename Pair>
392  using value_t = typename Pair::value;
393 
394  template<typename... Ts>
395  struct inherit : Ts... {};
396 
397  template<typename... Ts>
398  struct inherit<list<Ts...>> : Ts... {};
399 
400  template<typename...>
401  struct map;
402 
403  template<typename... Keys, typename... Values>
404  struct map<pair<Keys, Values>...>
405  {
406  using keys = list<Keys...>;
407  using values = list<Values...>;
408  using pairs = list<pair<Keys, Values>...>;
409 
410  template<typename Key>
411  using at_key = type_t<decltype(lookup((inherit<pairs>*)nullptr))>;
412  private:
413  template<typename Key, typename Value>
414  identity<Value> lookup(pair<Key, Value>*);
415  };
416 
417  template<typename Map>
418  using keys_t = typename Map::keys;
419  template<typename Map>
420  using values_t = typename Map::values;
421  template<typename Map>
422  using pairs_t = typename Map::pairs;
423  template<typename Map, typename Key>
424  using at_key = typename Map::template at_key<Key>;
425 
426  template<typename Function, typename... Ts>
427  struct pack_fmap
428  {
429  using type = list<apply_t<Function, Ts>...>;
430  };
431 
432  template<typename Function, typename List>
433  struct fmap;
434 
435  template<typename Function, template<typename...> class Seq, typename... Ts>
436  struct fmap<Function, Seq<Ts...>>
437  {
438  using type = Seq<apply_t<Function, Ts>...>;
439  };
440 
441  namespace detail
442  {
443  template<typename Predicate, typename FilteredSeq, typename Seq>
444  struct filter;
445 
446  template<typename Predicate,
447  template<typename...> class Seq, typename... Filtered, typename Head, typename... Tail>
448  struct filter<Predicate, Seq<Filtered...>, Seq<Head, Tail...>>
449  {
450  template<typename _Head = Head, bool = value<apply_t<Predicate, _Head>>()>
451  struct next
452  {
453  using type = Seq<Filtered..., Head>;
454  };
455 
456  template<typename _Head>
457  struct next<_Head, false>
458  {
459  using type = Seq<Filtered...>;
460  };
461 
462  using type = type_t<filter<Predicate, type_t<next<>>, Seq<Tail...>>>;
463  };
464 
465  template<typename Predicate,
466  template<typename...> class Seq, typename... Filtered>
467  struct filter<Predicate, Seq<Filtered...>, Seq<>>
468  {
469  using type = Seq<Filtered...>;
470  };
471  }
472 
473  template<typename Function, typename Seed, typename Seq>
474  struct foldl;
475 
476  template<typename Function, typename Seed,
477  template<typename...> class Seq, typename Head, typename... Tail>
478  struct foldl<Function, Seed, Seq<Head, Tail...>>
479  {
480  using type = type_t<
481  foldl<Function,
482  apply_t<Function, Seed, Head>,
483  Seq<Tail...>
484  >
485  >;
486  };
487 
488  template<typename Function, typename Seed,
489  template<typename...> class Seq>
490  struct foldl<Function, Seed, Seq<>>
491  {
492  using type = Seed;
493  };
494 
495  template<typename Function, typename Seed, typename Seq>
496  struct foldr;
497 
498  template<typename Function, typename Seed,
499  template<typename...> class Seq, typename Head, typename... Tail>
500  struct foldr<Function, Seed, Seq<Head, Tail...>>
501  {
502  using type = apply_t<
503  Function, Head,
504  type_t<foldr<Function, Seed, Seq<Tail...>>>
505  >;
506  };
507 
508  template<typename Function, typename Seed,
509  template<typename...> class Seq>
510  struct foldr<Function, Seed, Seq<>>
511  {
512  using type = Seed;
513  };
514 
515  template<typename Function, typename... Ts>
516  using pack_fmap_t = type_t<pack_fmap<Function, Ts...>>;
517  template<typename Function, typename Seq>
518  using fmap_t = type_t<fmap<Function, Seq>>;
519 
520  template<typename Function, typename Seed, typename... Seq>
521  using pack_foldl = foldl<Function, Seed, list<Seq...>>;
522  template<typename Function, typename Seed, typename... Seq>
523  using pack_foldl_t = type_t<pack_foldl<Function, Seed, Seq...>>;
524  template<typename Function, typename Seed, typename Seq>
525  using foldl_t = type_t<foldl<Function, Seed, Seq>>;
526 
527  template<typename Function, typename Seed, typename... Seq>
528  using pack_foldr = foldr<Function, Seed, list<Seq...>>;
529  template<typename Function, typename Seed, typename... Seq>
530  using pack_foldr_t = type_t<pack_foldr<Function, Seed, Seq...>>;
531  template<typename Function, typename Seed, typename Seq>
532  using foldr_t = type_t<foldr<Function, Seed, Seq>>;
533 
534  template<typename Predicate, typename Seq>
535  using filter = detail::filter<Predicate, apply_functor<Seq>, Seq>;
536  template<typename Predicate, typename Seq>
537  using filter_t = type_t<filter<Predicate, Seq>>;
538  template<typename Predicate, typename... Seq>
539  using pack_filter = detail::filter<Predicate, list<>, list<Seq...>>;
540  template<typename Predicate, typename... Seq>
541  using pack_filter_t = type_t<pack_filter<Predicate, Seq...>>;
542 
543  template<typename Bs>
544  using any_of = foldl<or_, false_, Bs>;
545  template<typename Bs>
546  using any_of_t = foldl_t<or_, false_, Bs>;
547  template<typename... Bs>
548  using pack_any_of = pack_foldl<or_, false_, Bs...>;
549  template<typename... Bs>
550  using pack_any_of_t = pack_foldl_t<or_, false_, Bs...>;
551 
552  template<typename Bs>
553  using any_of = foldl<or_, false_, Bs>;
554  template<typename Bs>
555  using any_of_t = foldl_t<or_, false_, Bs>;
556  template<typename... Bs>
557  using pack_any_of = pack_foldl<or_, false_, Bs...>;
558  template<typename... Bs>
559  using pack_any_of_t = pack_foldl_t<or_, false_, Bs...>;
560 
561  template<typename... Seqs>
562  using join = foldl<defer<cat>, apply_functor<pack_get_t<0, Seqs...>>, apply_functor<pack_get_t<0, Seqs...>, Seqs...>>;
563  template<typename... Seqs>
564  using join_t = type_t<join<Seqs...>>;
565 
566  namespace detail
567  {
568  template<template<typename...> class Seq, std::size_t N>
569  struct make_index_sequence
570  {
571  static constexpr std::size_t n = (N % 2) ? ((N - 1) / 2) : (N / 2);
572  static constexpr std::size_t m = N - n;
573 
574  struct adder
575  {
576  template<typename T>
577  struct apply
578  {
579  using type = apply_t<add_, size_t<n>, T>;
580  };
581  };
582 
583  using type = cat_t<
584  type_t<make_index_sequence<Seq, n>>,
585  fmap_t<adder, type_t<make_index_sequence<Seq, m>>>
586  >;
587  };
588 
589  template<template<typename...> class Seq>
590  struct make_index_sequence<Seq, 1>
591  {
592  using type = Seq<size_t<0>>;
593  };
594 
595  template<template<typename...> class Seq>
596  struct make_index_sequence<Seq, 0>
597  {
598  using type = Seq<>;
599  };
600  }
601 
602  template<std::size_t N, template<typename...> class Seq = list>
603  using make_index_sequence = type_t<detail::make_index_sequence<Seq, N>>;
604  template<typename... Ts>
605  using make_index_sequence_for = make_index_sequence<sizeof...(Ts)>;
606  template<typename Seq>
607  struct to_index_sequence;
608  template<template<typename...> class Seq, typename... Ts>
609  struct to_index_sequence<Seq<Ts...>>
610  {
611  using type = make_index_sequence<sizeof...(Ts), Seq>;
612  };
613  template<typename Seq>
614  using to_index_sequence_t = type_t<to_index_sequence<Seq>>;
615 
616  template<template<typename...> class Zipper, typename... Seqs>
617  struct zip
618  {
619 
620  };
621 
622  template<template<typename...> class Function, typename... Args>
623  struct bind
624  {
625  template<typename... Ts>
626  struct apply
627  {
628  using indices = make_index_sequence_for<Ts...>;
629 
630  };
631  };
632 }
633 
634 }
635 
636 #endif // SIPLASPLAS_UTILITY_META_H
Definition: canary_allocator.hpp:7
Definition: variant.hpp:500