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<Head, 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  template<typename... Ts>
283  using pack_head_t = pack_get_t<0, Ts...>;
284  template<typename... Ts>
285  using pack_tail_t = pack_split_after_t<0, Ts...>;
286 
287  template<std::size_t Index, typename Seq>
288  struct split;
289  template<std::size_t Index, template<typename...> class Seq, typename... Ts>
290  struct split<Index, Seq<Ts...>>
291  {
292  using splitter = detail::split<Seq<>, Index, Seq<Ts...>>;
293 
294  using before = typename splitter::before;
295  using left = typename splitter::left;
296  using head = typename splitter::head;
297  using right = typename splitter::right;
298  using after = typename splitter::after;
299  };
300  template<std::size_t Index, typename Seq>
301  using split_left_t = typename split<Index, Seq>::left;
302  template<std::size_t Index, typename Seq>
303  using get_t = typename split<Index, Seq>::head;
304  template<std::size_t Index, typename Seq>
305  using split_right_t = typename split<Index, Seq>::right;
306  template<std::size_t Index, typename Seq>
307  using split_before_t = typename split<Index, Seq>::before;
308  template<std::size_t Index, typename Seq>
309  using split_after_t = typename split<Index, Seq>::after;
310  template<typename Seq>
311  using head_t = get_t<0, Seq>;
312  template<typename Seq>
313  using tail_t = split_after_t<0, Seq>;
314 
315 
316  template<typename T, typename... Ts>
317  using pack_prepend_t = list<T, Ts...>;
318  template<typename T, typename... Ts>
319  using pack_append_t = list<Ts..., T>;
320  template<typename T, std::size_t Index, typename... Ts>
321  using pack_insert_t = cat_t<pack_append_t<pack_split_left_t<Index, Ts...>, T>, pack_split_right_t<Index, Ts...>>;
322  template<typename T, std::size_t Index, typename... Ts>
323  using pack_remove_t = cat_t<pack_split_before_t<Index, Ts...>, pack_split_after_t<Index, Ts...>>;
324 
325  template<typename T, typename Seq>
326  struct prepend;
327  template<typename T, template<typename...> class Seq, typename... Ts>
328  struct prepend<T, Seq<Ts...>>
329  {
330  using type = Seq<T, Ts...>;
331  };
332  template<typename T, typename Seq>
333  struct append;
334  template<typename T, template<typename...> class Seq, typename... Ts>
335  struct append<T, Seq<Ts...>>
336  {
337  using type = Seq<Ts..., T>;
338  };
339 
340  template<typename T, typename Seq>
341  using prepend_t = type_t<prepend<T, Seq>>;
342  template<typename T, typename Seq>
343  using append_t = type_t<append<Seq, T>>;
344  template<typename T, std::size_t Index, typename Seq>
345  using insert_t = cat_t<append_t<split_left_t<Index, Seq>, T>, split_right_t<Index, Seq>>;
346  template<typename T, std::size_t Index, typename Seq>
347  using remove_t = cat_t<split_before_t<Index, Seq>, split_after_t<Index, Seq>>;
348 
349 
350  template<typename Key, typename Value>
351  struct pair
352  {
353  using key = Key;
354  using value = Value;
355  };
356 
357  template<typename Pair>
358  using key_t = typename Pair::key;
359  template<typename Pair>
360  using value_t = typename Pair::value;
361 
362  template<typename... Ts>
363  struct inherit : Ts... {};
364 
365  template<typename... Ts>
366  struct inherit<list<Ts...>> : Ts... {};
367 
368  template<typename...>
369  struct map;
370 
371  template<typename... Keys, typename... Values>
372  struct map<pair<Keys, Values>...>
373  {
374  using keys = list<Keys...>;
375  using values = list<Values...>;
376  using pairs = list<pair<Keys, Values>...>;
377 
378  template<typename Key>
379  using at_key = type_t<decltype(lookup((inherit<pairs>*)nullptr))>;
380  private:
381  template<typename Key, typename Value>
382  identity<Value> lookup(pair<Key, Value>*);
383  };
384 
385  template<typename Map>
386  using keys_t = typename Map::keys;
387  template<typename Map>
388  using values_t = typename Map::values;
389  template<typename Map>
390  using pairs_t = typename Map::pairs;
391  template<typename Map, typename Key>
392  using at_key = typename Map::template at_key<Key>;
393 
394  template<typename Function, typename... Ts>
395  struct pack_fmap
396  {
397  using type = list<apply_t<Function, Ts>...>;
398  };
399 
400  template<typename Function, typename List>
401  struct fmap;
402 
403  template<typename Function, template<typename...> class Seq, typename... Ts>
404  struct fmap<Function, Seq<Ts...>>
405  {
406  using type = Seq<apply_t<Function, Ts>...>;
407  };
408 
409  namespace detail
410  {
411  template<typename Predicate, typename FilteredSeq, typename Seq>
412  struct filter;
413 
414  template<typename Predicate,
415  template<typename...> class Seq, typename... Filtered, typename Head, typename... Tail>
416  struct filter<Predicate, Seq<Filtered...>, Seq<Head, Tail...>>
417  {
418  template<typename _Head = Head, bool = value<apply_t<Predicate, _Head>>()>
419  struct next
420  {
421  using type = Seq<Filtered..., Head>;
422  };
423 
424  template<typename _Head>
425  struct next<_Head, false>
426  {
427  using type = Seq<Filtered...>;
428  };
429 
430  using type = type_t<filter<Predicate, type_t<next<>>, Seq<Tail...>>>;
431  };
432 
433  template<typename Predicate,
434  template<typename...> class Seq, typename... Filtered>
435  struct filter<Predicate, Seq<Filtered...>, Seq<>>
436  {
437  using type = Seq<Filtered...>;
438  };
439  }
440 
441  template<typename Function, typename Seed, typename Seq>
442  struct foldl;
443 
444  template<typename Function, typename Seed,
445  template<typename...> class Seq, typename Head, typename... Tail>
446  struct foldl<Function, Seed, Seq<Head, Tail...>>
447  {
448  using type = type_t<
449  foldl<Function,
450  apply_t<Function, Seed, Head>,
451  Seq<Tail...>
452  >
453  >;
454  };
455 
456  template<typename Function, typename Seed,
457  template<typename...> class Seq>
458  struct foldl<Function, Seed, Seq<>>
459  {
460  using type = Seed;
461  };
462 
463  template<typename Function, typename Seed, typename Seq>
464  struct foldr;
465 
466  template<typename Function, typename Seed,
467  template<typename...> class Seq, typename Head, typename... Tail>
468  struct foldr<Function, Seed, Seq<Head, Tail...>>
469  {
470  using type = apply_t<
471  Function, Head,
472  type_t<foldr<Function, Seed, Seq<Tail...>>>
473  >;
474  };
475 
476  template<typename Function, typename Seed,
477  template<typename...> class Seq>
478  struct foldr<Function, Seed, Seq<>>
479  {
480  using type = Seed;
481  };
482 
483  template<typename Function, typename... Ts>
484  using pack_fmap_t = type_t<pack_fmap<Function, Ts...>>;
485  template<typename Function, typename Seq>
486  using fmap_t = type_t<fmap<Function, Seq>>;
487 
488  template<typename Function, typename Seed, typename... Seq>
489  using pack_foldl = foldl<Function, Seed, list<Seq...>>;
490  template<typename Function, typename Seed, typename... Seq>
491  using pack_foldl_t = type_t<pack_foldl<Function, Seed, Seq...>>;
492  template<typename Function, typename Seed, typename Seq>
493  using foldl_t = type_t<foldl<Function, Seed, Seq>>;
494 
495  template<typename Function, typename Seed, typename... Seq>
496  using pack_foldr = foldr<Function, Seed, list<Seq...>>;
497  template<typename Function, typename Seed, typename... Seq>
498  using pack_foldr_t = type_t<pack_foldr<Function, Seed, Seq...>>;
499  template<typename Function, typename Seed, typename Seq>
500  using foldr_t = type_t<foldr<Function, Seed, Seq>>;
501 
502  template<typename Predicate, typename Seq>
503  using filter = detail::filter<Predicate, apply_functor<Seq>, Seq>;
504  template<typename Predicate, typename Seq>
505  using filter_t = type_t<filter<Predicate, Seq>>;
506  template<typename Predicate, typename... Seq>
507  using pack_filter = detail::filter<Predicate, list<>, list<Seq...>>;
508  template<typename Predicate, typename... Seq>
509  using pack_filter_t = type_t<pack_filter<Predicate, Seq...>>;
510 
511  template<typename Bs>
512  using any_of = foldl<or_, false_, Bs>;
513  template<typename Bs>
514  using any_of_t = foldl_t<or_, false_, Bs>;
515  template<typename... Bs>
516  using pack_any_of = pack_foldl<or_, false_, Bs...>;
517  template<typename... Bs>
518  using pack_any_of_t = pack_foldl_t<or_, false_, Bs...>;
519 
520  template<typename Bs>
521  using any_of = foldl<or_, false_, Bs>;
522  template<typename Bs>
523  using any_of_t = foldl_t<or_, false_, Bs>;
524  template<typename... Bs>
525  using pack_any_of = pack_foldl<or_, false_, Bs...>;
526  template<typename... Bs>
527  using pack_any_of_t = pack_foldl_t<or_, false_, Bs...>;
528 
529  template<typename... Seqs>
530  using join = foldl<defer<cat>, apply_functor<pack_get_t<0, Seqs...>>, apply_functor<pack_get_t<0, Seqs...>, Seqs...>>;
531  template<typename... Seqs>
532  using join_t = type_t<join<Seqs...>>;
533 
534  namespace detail
535  {
536  template<template<typename...> class Seq, std::size_t N>
537  struct make_index_sequence
538  {
539  static constexpr std::size_t n = (N % 2) ? ((N - 1) / 2) : (N / 2);
540  static constexpr std::size_t m = N - n;
541 
542  struct adder
543  {
544  template<typename T>
545  struct apply
546  {
547  using type = apply_t<add_, size_t<n>, T>;
548  };
549  };
550 
551  using type = cat_t<
552  type_t<make_index_sequence<Seq, n>>,
553  fmap_t<adder, type_t<make_index_sequence<Seq, m>>>
554  >;
555  };
556 
557  template<template<typename...> class Seq>
558  struct make_index_sequence<Seq, 1>
559  {
560  using type = Seq<size_t<0>>;
561  };
562 
563  template<template<typename...> class Seq>
564  struct make_index_sequence<Seq, 0>
565  {
566  using type = Seq<>;
567  };
568  }
569 
570  template<std::size_t N, template<typename...> class Seq = list>
571  using make_index_sequence = type_t<detail::make_index_sequence<Seq, N>>;
572  template<typename... Ts>
573  using make_index_sequence_for = make_index_sequence<sizeof...(Ts)>;
574  template<typename Seq>
575  struct to_index_sequence;
576  template<template<typename...> class Seq, typename... Ts>
577  struct to_index_sequence<Seq<Ts...>>
578  {
579  using type = make_index_sequence<sizeof...(Ts), Seq>;
580  };
581  template<typename Seq>
582  using to_index_sequence_t = type_t<to_index_sequence<Seq>>;
583 
584  template<template<typename...> class Zipper, typename... Seqs>
585  struct zip
586  {
587 
588  };
589 
590  template<template<typename...> class Function, typename... Args>
591  struct bind
592  {
593  template<typename... Ts>
594  struct apply
595  {
596  using indices = make_index_sequence_for<Ts...>;
597 
598  };
599  };
600 }
601 
602 }
603 
604 #endif // SIPLASPLAS_UTILITY_META_H
Definition: canary_allocator.hpp:7
Definition: variant.hpp:500