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