Lumiera  0.pre.03
»edit your freedom«
variadic-helper.hpp
Go to the documentation of this file.
1 /*
2  VARIADIC-HELPER.hpp - metaprogramming utilities for parameter- and type sequences
3 
4  Copyright (C)
5  2016, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
43 #ifndef LIB_META_VARIADIC_HELPER_H
44 #define LIB_META_VARIADIC_HELPER_H
45 
46 #include "lib/meta/typelist.hpp"
49 #include "lib/meta/util.hpp"
50 
51 namespace lib {
52 namespace meta {
53 
55 
67  template<typename...TYPES>
68  struct TySeq
69  {
70  using Seq = TySeq;
71  using List = typename Types<TYPES...>::List;
72  };
73 
74 
80  template<typename T, typename...TYPES>
81  struct Prepend<T, TySeq<TYPES...>>
82  {
83  using Seq = TySeq<T, TYPES...>;
84  using List = typename Types<T, TYPES...>::List;
85  };
86 
87 
96  template<typename SEQ>
97  struct StripNullType;
98 
99  template<typename T, typename...TYPES>
100  struct StripNullType<Types<T,TYPES...>>
101  {
102  using TailSeq = typename StripNullType<Types<TYPES...>>::Seq;
103 
104  using Seq = typename Prepend<T, TailSeq>::Seq;
105  };
106 
107  template<typename...TYPES>
108  struct StripNullType<Types<NullType, TYPES...>>
109  {
110  using Seq = TySeq<>; // NOTE: this causes the result to be a TySeq
111  };
113 
114 
115 
116 
117 
118 
120  template<typename X>
121  constexpr inline X const&
122  max (X const& a, X const& b)
123  {
124  return a < b? b : a;
125  }
126 
127  template<typename X>
128  constexpr inline X const&
129  min (X const& a, X const& b)
130  {
131  return b < a? b : a;
132  }
134 
135 
136 
137 
138 
139 
140 
141  /* ==== Build Variadic Sequences ==== **/
142 
143 
145  template<size_t...idx>
146  struct IndexSeq
147  {
148  template<size_t i>
149  using AppendElm = IndexSeq<idx..., i>;
150 
151  template<size_t i>
152  using PrependElm = IndexSeq<i, idx...>;
153  };
154 
159  template<size_t n>
161  {
162  using Ascending = typename BuildIndexSeq<n-1>::Ascending::template AppendElm<n-1>;
163  using Descending = typename BuildIndexSeq<n-1>::Descending::template PrependElm<n-1>;
164 
165  template<size_t d>
166  using OffsetBy = typename BuildIndexSeq<n-1>::template OffsetBy<d>::template AppendElm<n-1+d>;
167 
168  template<size_t x>
169  using FilledWith = typename BuildIndexSeq<n-1>::template FilledWith<x>::template AppendElm<x>;
170 
171  template<size_t c>
172  using First = typename BuildIndexSeq<min(c,n)>::Ascending;
173 
174  template<size_t c>
175  using After = typename BuildIndexSeq< (n>c)? n-c : 0>::template OffsetBy<c>;
176  };
177 
178  template<>
179  struct BuildIndexSeq<0>
180  {
181  using Empty = IndexSeq<>;
182 
183  using Ascending = Empty;
184  using Descending = Empty;
185 
186  template<size_t>
187  using OffsetBy = Empty;
188 
189  template<size_t>
190  using FilledWith = Empty;
191 
192  template<size_t>
193  using First = Empty;
194 
195  template<size_t>
196  using After = Empty;
197  };
198 
199 
200 
204  template<typename...TYPES>
206  {
207  enum {SIZ = sizeof...(TYPES) };
208  using Builder = BuildIndexSeq<SIZ>;
209 
210  using Ascending = typename Builder::Ascending;
211  using Descending = typename Builder::Descending;
212 
213  template<size_t d>
214  using OffsetBy = typename Builder::template OffsetBy<d>;
215 
216  template<size_t x>
217  using FilledWith = typename Builder::template FilledWith<x>;
218 
219  template<size_t c>
220  using First = typename Builder::template First<c>;
221 
222  template<size_t c>
223  using After = typename Builder::template After<c>;
224  };
225 
227  template<typename...TYPES>
228  struct BuildIdxIter<Types<TYPES...>>
229  {
231  enum {SIZ = lib::meta::count<typename Types<TYPES...>::List>::value };
232  using Builder = BuildIndexSeq<SIZ>;
233 
234  using Ascending = typename Builder::Ascending;
235  using Descending = typename Builder::Descending;
236 
237  template<size_t d>
238  using OffsetBy = typename Builder::template OffsetBy<d>;
239 
240  template<size_t x>
241  using FilledWith = typename Builder::template FilledWith<x>;
242 
243  template<size_t c>
244  using First = typename Builder::template First<c>;
245 
246  template<size_t c>
247  using After = typename Builder::template After<c>;
248  };
249 
250 
251 
252 
253 
254  /* ==== Rebinding Variadic Arguments ==== **/
255 
263  template<template<typename...> class X, typename...ARGS>
265  {
266  using Type = X<ARGS...>;
267  };
268 
269  template<template<typename...> class X
270  ,template<typename...> class U
271  ,typename...ARGS>
272  struct RebindVariadic<X, U<ARGS...>>
273  {
274  using Type = X<ARGS...>;
275  };
276 
277 
278 
279 
280 
281 
282 
283  /* ==== Manipulation of variadic arguments ==== **/
284 
285  namespace { // Implementation delegate template...
291  template<size_t i>
293  {
294  template<typename ARG, typename...ARGS>
295  static auto
296  get (ARG, ARGS&& ...args)
297  {
298  return SelectVararg<i-1>::get (std::forward<ARGS> (args)...);
299  }
300  };
301 
302  template<>
303  struct SelectVararg<0>
304  {
305  template<typename ARG, typename...ARGS>
306  static auto
307  get (ARG&& a, ARGS...)
308  {
309  return std::forward<ARG>(a);
310  }
311  };
312 
318  template<bool, typename, size_t idx>
320  : SelectVararg<idx>
321  { };
322 
323  template<typename DEFAULT, size_t idx>
324  struct SelectOrInit<false, DEFAULT, idx>
325  {
326  template<typename...ARGS>
327  static DEFAULT
328  get (ARGS&&...)
329  {
330  return DEFAULT{};
331  }
332  };
333  }//(End)Implementation
334 
335 
344  template<size_t idx, typename...ARGS>
345  constexpr inline auto
346  pickArg (ARGS&&... args)
347  {
348  static_assert (idx < sizeof...(args), "insufficient number of arguments");
349 
350  return SelectVararg<idx>::get (std::forward<ARGS> (args)...);
351  }
352 
360  template<size_t idx, typename DEFAULT, typename...ARGS>
361  constexpr inline auto
362  pickInit (ARGS&&... args)
363  {
364  return SelectOrInit<(idx < sizeof...(args)), DEFAULT, idx>::get (std::forward<ARGS> (args)...);
365  }
366 
367 
368 
369 }} // namespace lib::meta
370 #endif /*LIB_META_VARIADIC_HELPER_H*/
Hold a sequence of index numbers as template parameters.
build a sequence of index numbers based on a type sequence
A template metaprogramming technique for manipulating collections of types.
Metaprogramming helper to transfer variadic arguments.
Simple and lightweight helpers for metaprogramming and type detection.
temporary workaround: alternative definition of "type sequence", already using variadic template para...
Metaprogramming: simple helpers for working with lists-of-types.
Some basic facilities for manipulating type sequences.
Helper: prepend a type to an existing type sequence, thus shifting all elements within the sequence t...
Implementation namespace for support and library code.
temporary workaround: strip trailing NullType entries from a type sequence, to make it compatible wit...
constexpr auto pickInit(ARGS &&... args)
Helper to pick one initialisation argument from a variadic argument pack, falling back to a default c...
Metafunction counting the number of Types in the collection.
build regular sequences of index number e.g.
constexpr auto pickArg(ARGS &&... args)
Helper to single out one argument from a variadic argument pack.