Empirical
TypePack.h
Go to the documentation of this file.
1 
63 #ifndef EMP_TYPE_PACK_H
64 #define EMP_TYPE_PACK_H
65 
66 #include "meta.h"
67 
68 namespace emp {
69 
70  // Pre-declaration of TypePack
71  template <typename... Ts> struct TypePack;
72 
73  // Create a null type for padding.
74  struct null_t {};
75 
76  // Anonymous helpers for TypePack
77  namespace {
78  // Create add N copies of the same type to the end of a TypePack.
79  template <typename START, typename T, int N>
80  struct tp_pad { using type = typename tp_pad<START,T,N-1>::type::template add<T>; };
81  template <typename START, typename T>
82  struct tp_pad<START, T,0> { using type = START; };
83 
87  template <int S, typename T1, typename T2>
88  struct tp_shift {
89  using move_t = typename T2::first_t;
90  using inc_t = typename T1::template add<move_t>;
91  using dec_t = typename T2::pop;
92  using type1 = typename tp_shift<S-1, inc_t, dec_t>::type1;
93  using type2 = typename tp_shift<S-1, inc_t, dec_t>::type2;
94  };
95  template <typename T1, typename T2>
96  struct tp_shift<0, T1, T2> {
97  using type1 = T1;
98  using type2 = T2;
99  };
100 
101  // Filters create a TypePack with the element if the filter is true, empty if false.
102  template <typename T, bool> struct tp_filter1 { using type=TypePack<T>; };
103  template <typename T> struct tp_filter1<T,false> { using type=TypePack<>; };
104 
106  template <typename T, template <typename...> class FILTER, int N>
107  struct tp_filter {
108  using cur_t = typename T::first_t; // Isolate the first type
109  using other_tp = typename T::pop; // Isolate remaining types
110  constexpr static bool cur_result = test_type<FILTER,cur_t>(); // Run filter of cur type
111  using cur_ftp = typename tp_filter1<cur_t, cur_result>::type; // Use cur type if true
112  using other_ftp = typename tp_filter<other_tp, FILTER, N-1>::type; // Recurse
113  using type = typename cur_ftp::template merge< other_ftp >; // Merge
114  };
115  template <typename T, template <typename...> class FILTER>
116  struct tp_filter<T,FILTER,0> { using type = TypePack<>; };
117 
118  template <typename T, template <typename...> class FILTER>
119  using tp_filter_t = typename tp_filter<T,FILTER,T::SIZE>::type;
120 
121  // Wrappers create a TypePack with the wrapped element if the filter is true, empty if false.
122  template <typename T, template <typename...> class W, bool> struct tp_wrap1
123  { using type=TypePack<W<T>>; };
124  template <typename T, template <typename...> class W> struct tp_wrap1<T,W,false>
125  { using type=TypePack<>; };
126 
128  template <typename T, template <typename...> class W, int N> struct tp_wrap {
129  using cur_t = typename T::first_t; // Isolate the first type
130  using other_tp = typename T::pop; // Isolate remaining types
131  constexpr static bool cur_result = test_type<W,cur_t>(); // Use wrap to filter cur type
132  using cur_ftp = typename tp_wrap1<cur_t, W, cur_result>::type; // Use cur type if true
133  using other_ftp = typename tp_wrap<other_tp, W, N-1>::type; // Recurse
134  using type = typename cur_ftp::template merge< other_ftp >; // Merge
135  };
136  template <typename T, template <typename...> class W>
137  struct tp_wrap<T,W,0> { using type = TypePack<>; };
138 
139  template <typename T, template <typename...> class W>
140  using tp_wrap_t = typename tp_wrap<T,W,T::SIZE>::type;
141  }
142 
143  template <typename T, int N> using TypePackFill = typename tp_pad<TypePack<>,T,N>::type;
144 
145  // Specialized TypePack with at least one type.
146  template <typename T1, typename... Ts>
147  struct TypePack<T1, Ts...> {
149  template <typename T> constexpr static bool Has() { return has_type<T,T1,Ts...>(); }
150 
152  template <typename T> constexpr static size_t Count() { return count_type<T,T1,Ts...>(); }
153 
155  template <typename T> constexpr static int GetID() { return get_type_index<T,T1,Ts...>(); }
156 
158  template <typename T> constexpr static int GetID(const T &) { return get_type_index<T,T1,Ts...>(); }
159 
161  constexpr static int SIZE = 1+sizeof...(Ts);
162 
164  constexpr static int GetSize() { return SIZE; }
165 
167  constexpr static bool IsEmpty() { return false; }
168 
170  constexpr static bool IsUnique() { return has_unique_types<T1,Ts...>(); }
171 
173  template <int POS> using get = pack_id<POS, T1, Ts...>;
174 
175  // Other type lookups
176 
178  // (mostly a helper for the code below)
179  using this_t = TypePack<T1, Ts...>;
180 
182  using first_t = T1;
183 
185  using last_t = last_type<T1,Ts...>;
186 
187  // Modifications
188 
190  template <typename... T> using push_front = TypePack<T...,T1,Ts...>;
191 
193  template <typename... T> using push_back = TypePack<T1,Ts...,T...>;
194 
196  template <typename... T> using add = TypePack<T1,Ts...,T...>; // Same as push_back_t...
197 
199  using pop = TypePack<Ts...>;
200  template <int N> using popN = typename tp_shift<N, TypePack<>, this_t>::type2;
201 
203  template <int N> using shrink = typename tp_shift<N, TypePack<>, this_t>::type1;
204 
206  template <typename T, int N=1> using pad = typename tp_pad<this_t,T,N>::type;
207 
209  template <int N, typename DEFAULT=null_t>
210  using resize = typename pad<DEFAULT,(N>SIZE)?(N-SIZE):0>::template shrink<N>;
211 
213  template <typename IN> using merge = typename tp_shift<IN::SIZE, this_t, IN>::type1;
214 
216  using reverse = typename pop::reverse::template push_back<T1>;
217 
219  using rotate = typename pop::template push_back<T1>;
220 
222  template <int ID, typename T>
224 
226  template <int... Ps> using select = TypePack< get<Ps>... >;
227 
229  template <typename RETURN_T> using to_function_t = RETURN_T(T1,Ts...);
230 
232  template <template <typename...> class TEMPLATE> using apply = TEMPLATE<T1, Ts...>;
233 
235  template <template <typename...> class FILTER> using filter = tp_filter_t<this_t, FILTER>;
236 
238  template <template <typename...> class FILTER>
239  using find_t = typename tp_filter_t<this_t, FILTER>::first_t;
240 
242  template <template <typename...> class WRAPPER> using wrap = tp_wrap_t<this_t, WRAPPER>;
243  };
244 
245  // Specialized TypePack with no types.
246  template <>
247  struct TypePack<> {
248  template <typename T> constexpr static bool Has() { return false; }
249  template <typename T> constexpr static size_t Count() { return 0; }
250 
251  // GetID() NOT IMPLEMENTED since no ID's are available.
252  constexpr static int SIZE = 0;
253  constexpr static int GetSize() { return 0; }
254  constexpr static bool IsEmpty() { return true; }
255  constexpr static bool IsUnique() { return true; }
256 
257  // pop_t not implemented, since no types are available.
258 
260  using first_t = null_t;
261  using last_t = null_t;
262 
263  template <typename... T> using push_front = TypePack<T...>;
264  template <typename... T> using push_back = TypePack<T...>;
265  template <typename... T> using add = TypePack<T...>;
266 
267  // In both of these cases, N had better be zero... but no easy way to assert.
268  template <int N> using popN = this_t;
269  template <int N> using shrink = this_t;
270 
271  template <typename T, int N=1> using pad = typename tp_pad<this_t,T,N>::type;
272  template <int N, typename DEFAULT=null_t> using resize = pad<DEFAULT,N>;
273 
274  template <typename IN> using merge = IN;
275  using reverse = this_t;
276  using rotate = this_t;
277 
278  template <typename RETURN_T> using to_function_t = RETURN_T();
279 
280  template <template <typename...> class TEMPLATE> using apply = TEMPLATE<>;
281 
282  // There's nothing to filter, so return this_t (TypePack<>) or null_t
283  template <template <typename...> class FILTER> using filter = this_t;
284  template <template <typename...> class FILTER> using find_t = null_t;
285  template <template <typename...> class WRAPPER> using wrap = this_t;
286  };
287 }
288 
289 #endif
typename tp_pad< this_t, T, N >::type pad
Add N new entries onto TypePack, all of provided type T.
Definition: TypePack.h:206
static constexpr bool IsUnique()
Return bool indicating if all types in this pack are different from each other.
Definition: TypePack.h:170
static constexpr bool IsEmpty()
Definition: TypePack.h:254
static constexpr int GetSize()
Definition: TypePack.h:253
tp_filter_t< this_t, FILTER > filter
Remove all types that cannot pass a filter. Return as new TypePack.
Definition: TypePack.h:235
typename tp_shift< N, TypePack<>, this_t >::type2 popN
Definition: TypePack.h:200
static constexpr bool Has()
Return a bool indicating whether the specified type is present.
Definition: TypePack.h:149
typename tp_shift< N, TypePack<>, this_t >::type1 shrink
Reduce the size of this TypePack down to N.
Definition: TypePack.h:203
TEMPLATE<> apply
Definition: TypePack.h:280
pad< DEFAULT, N > resize
Definition: TypePack.h:272
typename pad< DEFAULT,(N >SIZE)?(N-SIZE):0 >::template shrink< N > resize
Make this TypePack the specified size, padding with provided type T.
Definition: TypePack.h:210
Definition: TypePack.h:147
typename pop::template push_back< T1 > rotate
Rotate types through typepack by the specified number of steps.
Definition: TypePack.h:219
static constexpr int GetSize()
Return the number of types in this pack.
Definition: TypePack.h:164
static constexpr size_t Count()
Count the number of instances of the specified type.
Definition: TypePack.h:152
static constexpr bool Has()
Definition: TypePack.h:248
typename internal::pack_id_impl< ID, Ts... >::type pack_id
Definition: meta.h:40
typename tp_shift< IN::SIZE, this_t, IN >::type1 merge
Join this TypePack with another TypePack.
Definition: TypePack.h:213
pack_id< sizeof...(Ts)-1, Ts... > last_type
Definition: meta.h:43
typename pop::reverse::template push_back< T1 > reverse
Rearrange types in TypePack into reverse order.
Definition: TypePack.h:216
static constexpr bool IsUnique()
Definition: TypePack.h:255
last_type< T1, Ts... > last_t
What is the final type in this TypePack?
Definition: TypePack.h:185
Definition: TypePack.h:247
static constexpr int GetID()
Return the position of the specified type.
Definition: TypePack.h:155
constexpr bool has_unique_types()
Definition: meta.h:77
TEMPLATE< T1, Ts... > apply
Apply to a specified template with TypePack as template arguments.
Definition: TypePack.h:232
Definition: TypePack.h:74
If we are in emscripten, make sure to include the header.
Definition: array.h:37
static constexpr int GetID(const T &)
Return the position of the type of owner.
Definition: TypePack.h:158
tp_wrap_t< this_t, WRAPPER > wrap
Wrap all types in a specified wrapper template.
Definition: TypePack.h:242
typename tp_pad< this_t, T, N >::type pad
Definition: TypePack.h:271
constexpr int get_type_index()
Definition: meta.h:70
typename tp_pad< TypePack<>, T, N >::type TypePackFill
Definition: TypePack.h:143
T1 first_t
What is the first type in this TypePack?
Definition: TypePack.h:182
static constexpr bool cur_result
Definition: TypePack.h:110
IN merge
Definition: TypePack.h:274
constexpr size_t count_type()
Definition: meta.h:54
typename tp_filter_t< this_t, FILTER >::first_t find_t
Return the first type that satisfies a filter.
Definition: TypePack.h:239
static constexpr bool IsEmpty()
Return bool indicating if there are any types in this pack.
Definition: TypePack.h:167
static constexpr size_t Count()
Definition: TypePack.h:249
Definition: TypePack.h:71
constexpr bool has_type()
Definition: meta.h:49
RETURN_T(T1, Ts...) to_function_t
Convert to a function signature with a specified return type.
Definition: TypePack.h:229