uTL
micro Template library
typelist.h
Go to the documentation of this file.
1 
20 #ifndef __utl_meta_typelist_h__
21 #define __utl_meta_typelist_h__
22 
23 #include <utl/core/impl.h>
24 #include <utl/meta/integral.h>
25 #include <utl/meta/detection.h>
26 #include <utl/meta/invoke.h>
27 #include <utl/meta/sfinae.h>
32 
34 namespace utl {
35 namespace meta {
36 
64  template <typename... Ts>
65  struct typelist {
66  using type = typelist;
67 
69  static constexpr size_t size() noexcept {
70  return sizeof...(Ts);
71  }
73  static constexpr bool empty() noexcept {
74  return (sizeof...(Ts) == 0);
75  }
76  // ======= times utility =======
77  private:
78  template <typename... > struct cat_ { };
79  template <typename... L1, typename... L2>
80  struct cat_<typelist<L1...>, typelist<L2...>> {
81  using type = typelist<L1..., L2...>;
82  };
83 
84  template <size_t N, typename ...T>
85  struct times_ {
86  //static_assert( N >= 0, "Cannot make typelist of negative length" );
87  using type = eval<
88  cat_<
89  eval<times_<N/2, T...>>,
90  eval<times_<N - N/2, T...>>
91  >
92  >;
93  };
94  template <typename ...T>
95  struct times_<1, T...> {
96  using type = typelist<T...>;
97  };
98  template <typename ...T>
99  struct times_<0, T...> {
100  using type = typelist<>;
101  };
102  public:
114  template<size_t N>
115  using times = eval<
116  times_<N, Ts...>
117  >;
118  };
119 
128  template <typename List>
130 
139  template <typename List>
141 
144  template <typename T1, typename T2>
146 
147 
150 
154  template <size_t N, typename ...Ts>
155  using repeat_c = typename typelist<Ts...>::template times<N>;
156 
160  template <typename N, typename ...Ts>
161  using repeat = repeat_c<N::type::value, Ts...>;
163 
169  namespace apply_impl {
171  template <typename Fn, typename Seq>
172  struct apply_ { };
173 
175  template<typename Fn, typename ...List>
176  struct apply_<Fn, typelist<List...>> {
177  using type = invoke<Fn, List...>;
178  };
180  template <typename Fn, typename T, T... Is>
181  struct apply_<Fn, integer_sequence<T, Is...>> {
183  };
184  }
185 
196  template <typename Fn, typename Seq>
198 
199  template <typename Fn, typename Seq>
201 
203 
204  /*
205  * ========= element access ========
206  */
209  namespace at_impl {
210 
211  template <typename T> struct _add_pointer { using type = T*; };
212  template <typename T> using add_pointer = eval < _add_pointer <T> >;
213 
214  template <typename ...>
215  struct at_head_ { };
216 
217  template <typename... voids>
218  struct at_head_ <typelist<voids...>> {
219  // successful selection N voids, one T* and the rest
220  template <typename T> static constexpr T select(voids..., T*, ...);
221  // selection on error
222  static constexpr nil_ select (...);
223  };
224 
225  template<typename List, index_t N>
226  struct at_ { };
227 
228  template<typename... List, index_t N>
229  struct at_<typelist<List...>, N> {
230  using head_ = at_head_<typelist<void*>::times<N>>; //< make at_head_<> with N void*
231  using type = decltype(
232  head_::select(static_cast<add_pointer<List>>(nullptr)...) //< pass all as List*...
233  );
234  };
235  }
236 
242  template <typename List, index_t N>
243  using at_c = eval<
245  >;
246 
252  template <typename List, typename N>
255 
256 
259  namespace front_impl {
260  template <typename L>
261  struct front_ { };
262 
263  template <typename Head, typename... Tail>
264  struct front_<typelist<Head, Tail...>> {
265  using type = Head;
266  };
267  }
268 
271  template <typename List>
272  using front = eval<
274  >;
276 
279  namespace back_impl {
280  template <typename List>
281  struct back_ { };
282 
283  template <typename Head, typename... Tail>
284  struct back_<typelist<Head, Tail...>> {
285  using type = at_c <
286  typelist<Head, Tail...>, sizeof...(Tail)
287  >;
288  };
289  }
290 
293  template <typename List>
294  using back = eval<
296  >;
298  /*
299  * ========= typelist operations =========
300  */
301 
304  namespace cat_impl {
305  template <typename... Lists>
306  struct cat_ { };
307 
308  template <>
309  struct cat_<> {
310  using type = typelist<>;
311  };
312 
313  template <typename... L1>
314  struct cat_<typelist<L1...>> {
315  using type = typelist<L1...>;
316  };
317 
318  template <typename... L1, typename... L2>
319  struct cat_<typelist<L1...>, typelist<L2...>> {
320  using type = typelist<L1..., L2...>;
321  };
322 
323  template <typename... L1, typename... L2, typename... Ln>
324  struct cat_<typelist<L1...>, typelist<L2...>, Ln...>
325  : cat_ <typelist<L1..., L2...>, Ln...> { };
326 
327  }
328 
335  template <typename... Lists>
336  using cat = eval<
337  cat_impl::cat_<Lists...>
338  >;
340 
341 
344  namespace fold_impl {
345  // fold<<T1, T2, T3>, V, F> == F<F<F<V, T1>, T2>, T3>
346  template<typename, typename, typename>
347  struct fold_ { }; // ill formed
348 
349  // recursive call
350  template<typename Head, typename... Tail,
351  typename V,
352  typename Fn>
353  struct fold_<typelist<Head, Tail...>, V, Fn> {
354  // recursive call of fold_ by consuming typelist and invoking Fn
355  using type = eval<
356  fold_<
357  typelist<Tail...>,
359  Fn
360  >
361  >;
362  };
363  // termination call
364  template<typename V0, typename Fn>
365  struct fold_<typelist<>, V0, Fn> {
366  using type = V0;
367  };
368  }
369 
382  template <typename List, typename V, typename Fn>
384 
386  template <typename List, typename V, typename Fn>
388 
389  namespace rev_fold_impl {
390 
391  // rev_fold<<T1, T2, T3>, V, F> == F<T1, F<T2, F<T3, V>>>
392  template<typename, typename, typename>
393  struct rev_fold_ { }; // ill formed
394 
395  // recursive call
396  template<typename Head, typename... Tail,
397  typename V,
398  typename Fn>
399  struct rev_fold_<typelist<Head, Tail...>, V, Fn> {
400  // recursive call inside invoke. This way the 2nd argument of Fn
401  // becoming the recursive "thing", inside Fn<>
402  using type = invoke <
403  Fn, Head, eval<
404  rev_fold_ <
405  typelist<Tail...>,
406  V,
407  Fn
408  >>
409  >;
410  };
411  // pre-termination call
412  template<typename Tail, typename V, typename Fn>
413  struct rev_fold_ <typelist<Tail>, V, Fn> {
415  };
416  // termination call
417  template<typename V, typename Fn>
418  struct rev_fold_ <typelist<>, V, Fn> {
419  using type = V;
420  };
421  }
422 
435  template <typename List, typename V, typename Fn>
436  using rev_fold = eval<
438  >;
440 
445  template <typename List, typename... Ts>
446  using push_front = eval<
447  apply <
448  bind_front<quote<typelist>, Ts...>, List
449  >
450  >;
451 
456  template <typename List, typename... Ts>
457  using push_back = eval<
458  apply <
459  bind_back<quote<typelist>, Ts...>, List
460  >
461  >;
462 
465  namespace reverse_impl {
466  template <typename List, typename V = typelist<>>
467  struct reverse_ {
469  };
470  }
471 
476  template <typename List>
477  using reverse = eval<
479  >;
481 
484  namespace pop_front_impl {
485  template <typename List>
486  struct pop_front_ { };
487 
488  template <typename Head, typename... Tail>
489  struct pop_front_<typelist <Head, Tail...>> {
490  using type = typelist<Tail...>;
491  };
492  }
493 
499  template <typename List>
500  using pop_front = eval<
502  >;
504 
507  namespace pop_back_impl {
508  template <typename List>
509  struct pop_back_ {
510  using type = reverse<
512  >;
513  };
514  }
515 
523  template <typename List>
524  using pop_back = eval <
526  >;
528 
531  namespace transform_impl {
532  template <typename, typename = void>
533  struct transform_ { };
534 
535  template <typename... Ts, typename Fn>
536  struct transform_<typelist<typelist<Ts...>, Fn>,
537  void_t<invoke<Fn, Ts>...> > /* SFINAE check */ {
538  using type = typelist<
540  >;
541  };
542 
543  template <typename... Ts0, typename... Ts1, typename Fn>
544  struct transform_<typelist<typelist<Ts0...>, typelist<Ts1...>, Fn>,
545  void_t<invoke<Fn, Ts0, Ts1>...>> /* SFINAE check */ {
546  using type = typelist<
548  >;
549  };
550  }
551 
565  template <typename... Args>
566  using transform = eval<
568  >;
570 
573  namespace transform_lazy_impl {
574  template <typename, typename = void>
575  struct transform_lazy_ { };
576 
577  // Match for Unary Fn with one typelist
578  template <typename... Ts, typename Fn>
579  struct transform_lazy_<typelist<typelist<Ts...>, Fn>,
580  void_t<invoke<Fn, Ts>...> > /* SFINAE check */ {
581  using type = typelist<
582  invoke<Fn, Ts>...
583  >;
584  };
585 
586  // Match for Binary Fn with two typelists
587  template <typename... Ts0, typename... Ts1, typename Fn>
588  struct transform_lazy_<typelist<typelist<Ts0...>, typelist<Ts1...>, Fn>,
589  void_t<invoke<Fn, Ts0, Ts1>...>> /* SFINAE check */ {
590  using type = typelist<
592  >;
593  };
594  }
595 
611  template <typename... Args>
612  using transform_lazy = eval<
614  >;
616 
617 
620  namespace find_if_impl {
621  template <typename, typename, index_t>
622  struct find_if_ { };
623 
624  template<typename Head, typename... Tail, typename Fn, index_t N>
625  struct find_if_<typelist<Head, Tail...>, Fn, N> {
626  // Recursive call to find_if_ until Fn returns true_
627  using type = if_ <
629  index_<N>, // done, return current index
630  eval<find_if_< // not done, re-call find_if_ with the Tail...
631  typelist<Tail...>, Fn, N+1>
632  >
633  >;
634  };
635 
636  // When empty or when we are one place after the last item return Npos
637  template<typename Fn, index_t N>
638  struct find_if_<typelist<>, Fn, N> {
639  using type = Npos;
640  };
641  }
642 
654  template<typename List, typename Pred>
655  using find_if = eval<
657  >;
658 
662  template <typename List, typename T>
665 
668  namespace seek_if_impl {
669  template <typename, typename, index_t>
670  struct seek_if_ { };
671 
672  template<typename Head, typename... Tail, typename Fn, index_t N>
673  struct seek_if_<typelist<Head, Tail...>, Fn, N> {
674  // recursive call to seek_if_ until Fn returns true_
675  using type = if_ <
677  typelist<Head, Tail...>, // done, return the typelist starting from here
678  eval<seek_if_< // not done, re-call seek_if_ with the Tail...
679  typelist<Tail...>, Fn, N+1>
680  >
681  >;
682  };
683 
684  // When empty or when we are one place after the last item return empty typelist
685  template<typename Fn, index_t N>
686  struct seek_if_<typelist<>, Fn, N> {
687  using type = typelist<>;
688  };
689  }
690 
702  template <typename List, typename Pred>
703  using seek_if = eval<
705  >;
710  template <typename List, typename T>
713 
716  namespace count_if_impl {
717  template <typename, typename, size_t>
718  struct count_if_ { };
719 
720  template<typename Head, typename... Tail, typename Fn, size_t N>
721  struct count_if_<typelist<Head, Tail...>, Fn, N> {
722  // Recursive call to count_if_ up to the end of List, counting all invokes of Fn
723  // returning true_
724  using type = if_ <
726  eval<
727  count_if_<typelist<Tail...>, Fn, N+1> // increase and re-call
728  >,
729  eval<
730  count_if_<typelist<Tail...>, Fn, N> // re-call without increasing
731  >
732  >;
733  };
734 
735  // At the end of the List return the counter
736  template<typename Fn, size_t N>
737  struct count_if_<typelist<>, Fn, N> {
738  using type = size_<N>;
739  };
740  }
741 
752  template <typename List, typename Pred>
753  using count_if = eval<
755  >;
756 
760  template <typename List, typename T>
763 
766  namespace filter_impl {
767  template <typename, typename, typename>
768  struct filter_ { };
769 
770  template<typename Head, typename... Tail, typename Fn, typename L>
771  struct filter_<typelist<Head, Tail...>, Fn, L> {
772  // Recursive call to filter_ up to the end of the List, creating a new list
773  // of items for which the invoke of Fn returns true_
774  using type = if_ <
776  eval<filter_<typelist<Tail...>, Fn, cat<L, typelist<Head>>>>, // Add the element and re-call
777  eval<filter_<typelist<Tail...>, Fn, L>> // re-call with the same list
778  >;
779  };
780 
781  // At the end return the produced list
782  template<typename Fn, typename L>
783  struct filter_<typelist<>, Fn, L> {
784  using type = L;
785  };
786  }
787 
797  template <typename List, typename Pred>
798  using filter = eval<
800  >;
802 
805  namespace replace_if_impl {
806  template <typename, typename, typename, typename>
807  struct replace_if_ { };
808 
809  template <typename Head, typename... Tail, typename Fn, typename T, typename Ret>
810  struct replace_if_<typelist<Head, Tail...>, Fn, T, Ret> {
811  // Recursive call to replace_if_ up to the end of the List, creating a new list
812  // of items based on invocation of Fn
813  using type = if_ <
815  eval<replace_if_<typelist<Tail...>, Fn, T, cat<Ret, typelist<T>>>>, // re-call with change to T
816  eval<replace_if_<typelist<Tail...>, Fn, T, cat<Ret, typelist<Head>>>> // re-call with no change
817  >;
818  };
819 
820  // At the end return the produced list
821  template <typename Fn, typename T, typename Ret>
822  struct replace_if_ <typelist<>, Fn, T, Ret> {
823  using type = Ret;
824  };
825  }
826 
838  template<typename List, typename Pred, typename T>
839  using replace_if = eval<
841  >;
842 
845  template <typename List, typename T, typename U>
846  using replace = eval <
848  >;
850 
851 
854  template <typename List, typename Pred>
855  using all_of = if_ <
856  empty <List>,
857  false_,
858  empty <
860  >
861  >;
862 
865  template <typename List, typename Pred>
866  using any_of = not_<
868  >;
869 
872  template <typename List, typename Pred>
873  using none_of = empty<
875  >;
876 
877 }}
878 
880 
881 #endif /* __utl_meta_typelist_h__ */
fold< List, V, Fn > accumulate
accumulate is an stl name for fold
Definition: typelist.h:387
empty< filter< List, Pred > > none_of
Definition: typelist.h:875
if_c< If::type::value, Args... > if_
Select one type or another depending on a compile-time Boolean type.
Definition: selection.h:66
void void_t
void_t type alias
Definition: detection.h:55
eval< count_if_impl::count_if_< List, Pred, 0 > > count_if
Definition: typelist.h:755
eval< filter_impl::filter_< List, Pred, typelist<> > > filter
Definition: typelist.h:800
eval< at_impl::at_< List, N > > at_c
Definition: typelist.h:245
eval< cat_< eval< times_< N/2, T... > >, eval< times_< N - N/2, T... > > > > type
Definition: typelist.h:92
eval< _add_pointer< T > > add_pointer
Definition: typelist.h:212
eval< replace_if_impl::replace_if_< List, Pred, T, typelist<> > > replace_if
Definition: typelist.h:841
if_< invoke_t< Fn, Head >, eval< replace_if_< typelist< Tail... >, Fn, T, cat< Ret, typelist< T > >> >, eval< replace_if_< typelist< Tail... >, Fn, T, cat< Ret, typelist< Head > >> > > type
Definition: typelist.h:817
size_< List::size()> size
Definition: typelist.h:129
eval< apply< bind_back< quote< typelist >, Ts... >, List > > push_back
Definition: typelist.h:461
eval< back_impl::back_< List > > back
Definition: typelist.h:296
eval< fold_< typelist< Tail... >, invoke< Fn, V, Head >, Fn > > type
Definition: typelist.h:361
static constexpr size_t size() noexcept
Definition: typelist.h:69
at_c< List, N::type::value > at
Definition: typelist.h:253
eval< reverse_impl::reverse_< List > > reverse
Definition: typelist.h:479
repeat_c< N::type::value, Ts... > repeat
Definition: typelist.h:161
integral_< size_t, v > size_
size_ type: integral constant wrapper for size_t a.k.a std::size_t
Definition: integral.h:110
if_< invoke_t< Fn, Head >, eval< filter_< typelist< Tail... >, Fn, cat< L, typelist< Head > >> >, eval< filter_< typelist< Tail... >, Fn, L > > > type
Definition: typelist.h:778
eval< replace_if< List, same_as< T >, U > > replace
Definition: typelist.h:848
invoke< Fn, Head, eval< rev_fold_< typelist< Tail... >, V, Fn > > > type
Definition: typelist.h:409
find_if< List, same_as< T > > find
Definition: typelist.h:663
count_if< List, same_as< T > > count
Definition: typelist.h:761
if_< invoke_t< Fn, Head >, eval< count_if_< typelist< Tail... >, Fn, N+1 > >, eval< count_if_< typelist< Tail... >, Fn, N > > > type
Definition: typelist.h:732
size_< index_t(-1)> Npos
The last position we can express for indexing.
Definition: integral.h:124
if_< invoke_t< Fn, Head >, typelist< Head, Tail... >, eval< seek_if_< typelist< Tail... >, Fn, N+1 > > > type
Definition: typelist.h:681
eval< cat_impl::cat_< Lists... > > cat
Definition: typelist.h:338
static constexpr bool empty() noexcept
Definition: typelist.h:73
bool_< false > false_
The type used as a compile-time boolean with false value.
Definition: integral.h:69
eval< seek_if_impl::seek_if_< List, Pred, 0 > > seek_if
Definition: typelist.h:705
eval< rev_fold_impl::rev_fold_< List, V, Fn > > rev_fold
Definition: typelist.h:438
eval< fold_impl::fold_< List, V, Fn > > fold
Definition: typelist.h:383
typename Tp::type eval
Type alias for Tp::type. Used to evaluate/extract return type of metafunctions.
Definition: integral.h:49
fold< List, V, quote< push_front > > type
Definition: typelist.h:468
Detection idiom based on WG21&#39;s N4502 [n4502 1] from Walter E. Brown.
not_< empty< filter< List, Pred > > > any_of
Definition: typelist.h:868
STL&#39;s core language concepts.
Definition: _1wire.h:30
if_< empty< List >, false_, empty< filter< List, compose< quote< not_ >, Pred > > > > all_of
Definition: typelist.h:861
at_c< typelist< Head, Tail... >, sizeof...(Tail) > type
Definition: typelist.h:287
eval< pop_back_impl::pop_back_< List > > pop_back
Definition: typelist.h:526
eval< apply< bind_front< quote< typelist >, Ts... >, List > > push_front
Definition: typelist.h:450
Template meta-programming SFINAE helpers.
decltype(head_::select(static_cast< add_pointer< List > >(nullptr)...)) type
Definition: typelist.h:233
eval< pop_front_impl::pop_front_< List > > pop_front
Definition: typelist.h:502
integral_< index_t, v > index_
index_ type: integral constant wrapper for index_t a.k.a std::size_t
Definition: integral.h:106
eval< times_< N, Ts... > > times
Definition: typelist.h:117
if_< invoke_t< Fn, Head >, index_< N >, eval< find_if_< typelist< Tail... >, Fn, N+1 > > > type
Definition: typelist.h:633
integral_< bool, v > bool_
bool_ type: integral constant wrapper for bool
Definition: integral.h:66
size_t index_t
index_t and size_t mend to be interchangeable
Definition: types.h:38
eval< front_impl::front_< List > > front
Definition: typelist.h:274
eval< find_if_impl::find_if_< List, Pred, 0 > > find_if
Definition: typelist.h:657
typename typelist< Ts... >::template times< N > repeat_c
Definition: typelist.h:155
std::integer_sequence< Tp, Ints... > integer_sequence
Definition: integral.h:129
reverse< pop_front< reverse< List > > > type
Definition: typelist.h:512
eval< transform_impl::transform_< typelist< Args... > > > transform
Definition: typelist.h:568
eval< invoke< Fn, Args... > > invoke_t
Definition: invoke.h:88
eval< apply< Fn, Seq > > apply_t
Definition: typelist.h:200
typename Fn::template apply< Args... > invoke
Definition: invoke.h:81
not_c< _Tp::type::value > not_
not
Definition: operations.h:47
seek_if< List, same_as< T > > seek
Definition: typelist.h:711
bool_< List::empty()> empty
Definition: typelist.h:140
Implementation detail main forward header.
eval< transform_lazy_impl::transform_lazy_< typelist< Args... > > > transform_lazy
Definition: typelist.h:614