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) Lumiera.org
5  2016, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
52 #ifndef LIB_META_VARIADIC_HELPER_H
53 #define LIB_META_VARIADIC_HELPER_H
54 
55 #include "lib/meta/typelist.hpp"
58 #include "lib/meta/util.hpp"
59 
60 namespace lib {
61 namespace meta {
62 
64 
76  template<typename...TYPES>
77  struct TySeq
78  {
79  using Seq = TySeq;
80  using List = typename Types<TYPES...>::List;
81  };
82 
83 
89  template<typename T, typename...TYPES>
90  struct Prepend<T, TySeq<TYPES...>>
91  {
92  using Seq = TySeq<T, TYPES...>;
93  using List = typename Types<T, TYPES...>::List;
94  };
95 
96 
105  template<typename SEQ>
107 
108  template<typename T, typename...TYPES>
109  struct StripNullType<Types<T,TYPES...>>
110  {
111  using TailSeq = typename StripNullType<Types<TYPES...>>::Seq;
112 
113  using Seq = typename Prepend<T, TailSeq>::Seq;
114  };
115 
116  template<typename...TYPES>
117  struct StripNullType<Types<NullType, TYPES...>>
118  {
119  using Seq = TySeq<>; // NOTE: this causes the result to be a TySeq
120  };
122 
123 
124 
125 
126 
127 
129  template<typename X>
130  constexpr inline X const&
131  max (X const& a, X const& b)
132  {
133  return a < b? b : a;
134  }
135 
136  template<typename X>
137  constexpr inline X const&
138  min (X const& a, X const& b)
139  {
140  return b < a? b : a;
141  }
143 
144 
145 
146 
147 
148 
149 
150  /* ==== Build Variadic Sequences ==== **/
151 
152 
154  template<size_t...idx>
155  struct IndexSeq
156  {
157  template<size_t i>
158  using AppendElm = IndexSeq<idx..., i>;
159 
160  template<size_t i>
161  using PrependElm = IndexSeq<i, idx...>;
162  };
163 
168  template<size_t n>
170  {
171  using Ascending = typename BuildIndexSeq<n-1>::Ascending::template AppendElm<n-1>;
172  using Descending = typename BuildIndexSeq<n-1>::Descending::template PrependElm<n-1>;
173 
174  template<size_t d>
175  using OffsetBy = typename BuildIndexSeq<n-1>::template OffsetBy<d>::template AppendElm<n-1+d>;
176 
177  template<size_t x>
178  using FilledWith = typename BuildIndexSeq<n-1>::template FilledWith<x>::template AppendElm<x>;
179 
180  template<size_t c>
181  using First = typename BuildIndexSeq<min(c,n)>::Ascending;
182 
183  template<size_t c>
184  using After = typename BuildIndexSeq< (n>c)? n-c : 0>::template OffsetBy<c>;
185  };
186 
187  template<>
188  struct BuildIndexSeq<0>
189  {
190  using Empty = IndexSeq<>;
191 
192  using Ascending = Empty;
193  using Descending = Empty;
194 
195  template<size_t>
196  using OffsetBy = Empty;
197 
198  template<size_t>
199  using FilledWith = Empty;
200 
201  template<size_t>
202  using First = Empty;
203 
204  template<size_t>
205  using After = Empty;
206  };
207 
208 
209 
213  template<typename...TYPES>
215  {
216  enum {SIZ = sizeof...(TYPES) };
217  using Builder = BuildIndexSeq<SIZ>;
218 
219  using Ascending = typename Builder::Ascending;
220  using Descending = typename Builder::Descending;
221 
222  template<size_t d>
223  using OffsetBy = typename Builder::template OffsetBy<d>;
224 
225  template<size_t x>
226  using FilledWith = typename Builder::template FilledWith<x>;
227 
228  template<size_t c>
229  using First = typename Builder::template First<c>;
230 
231  template<size_t c>
232  using After = typename Builder::template After<c>;
233  };
234 
236  template<typename...TYPES>
237  struct BuildIdxIter<Types<TYPES...>>
238  {
240  enum {SIZ = lib::meta::count<typename Types<TYPES...>::List>::value };
241  using Builder = BuildIndexSeq<SIZ>;
242 
243  using Ascending = typename Builder::Ascending;
244  using Descending = typename Builder::Descending;
245 
246  template<size_t d>
247  using OffsetBy = typename Builder::template OffsetBy<d>;
248 
249  template<size_t x>
250  using FilledWith = typename Builder::template FilledWith<x>;
251 
252  template<size_t c>
253  using First = typename Builder::template First<c>;
254 
255  template<size_t c>
256  using After = typename Builder::template After<c>;
257  };
258 
259 
260 
261 
262 
263  /* ==== Rebinding Variadic Arguments ==== **/
264 
272  template<template<typename...> class X, typename...ARGS>
274  {
275  using Type = X<ARGS...>;
276  };
277 
278  template<template<typename...> class X
279  ,template<typename...> class U
280  ,typename...ARGS>
281  struct RebindVariadic<X, U<ARGS...>>
282  {
283  using Type = X<ARGS...>;
284  };
285 
286 
287 
288 
289 
290 
291 
292  /* ==== Manipulation of variadic arguments ==== **/
293 
294  namespace { // Implementation delegate template...
300  template<size_t i>
302  {
303  template<typename ARG, typename...ARGS>
304  static auto
305  get (ARG, ARGS&& ...args)
306  {
307  return SelectVararg<i-1>::get (std::forward<ARGS> (args)...);
308  }
309  };
310 
311  template<>
312  struct SelectVararg<0>
313  {
314  template<typename ARG, typename...ARGS>
315  static auto
316  get (ARG&& a, ARGS...)
317  {
318  return std::forward<ARG>(a);
319  }
320  };
321 
327  template<bool, typename, size_t idx>
329  : SelectVararg<idx>
330  { };
331 
332  template<typename DEFAULT, size_t idx>
333  struct SelectOrInit<false, DEFAULT, idx>
334  {
335  template<typename...ARGS>
336  static DEFAULT
337  get (ARGS&&...)
338  {
339  return DEFAULT{};
340  }
341  };
342  }//(End)Implementation
343 
344 
353  template<size_t idx, typename...ARGS>
354  constexpr inline auto
355  pickArg (ARGS&&... args)
356  {
357  static_assert (idx < sizeof...(args), "insufficient number of arguments");
358 
359  return SelectVararg<idx>::get (std::forward<ARGS> (args)...);
360  }
361 
369  template<size_t idx, typename DEFAULT, typename...ARGS>
370  constexpr inline auto
371  pickInit (ARGS&&... args)
372  {
373  return SelectOrInit<(idx < sizeof...(args)), DEFAULT, idx>::get (std::forward<ARGS> (args)...);
374  }
375 
376 
377 
378 }} // namespace lib::meta
379 #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.