Lumiera  0.pre.03
»edit your freedom«
tuple-helper.hpp
Go to the documentation of this file.
1 /*
2  TUPLE-HELPER.hpp - metaprogramming utilities for type and data tuples
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 
41 #ifndef LIB_META_TUPLE_HELPER_H
42 #define LIB_META_TUPLE_HELPER_H
43 
44 #include "lib/meta/typelist.hpp"
48 #include "lib/meta/util.hpp"
49 
50 #include <tuple>
51 #include <utility>
52 
53 
54 namespace util { // forward declaration
55 
56  template<typename TY>
57  std::string
58  toString (TY const& val) noexcept;
59 }
60 
61 
62 namespace lib {
63 namespace meta {
64 
66  template<typename T>
67  struct is_Tuple
68  : std::false_type
69  { };
70 
71  template<typename...TYPES>
72  struct is_Tuple<std::tuple<TYPES...>>
73  : std::true_type
74  { };
75 
76  template<typename...TYPES>
77  struct is_Tuple<const std::tuple<TYPES...>>
78  : std::true_type
79  { };
80 
81  template<class TUP>
83 
84  template<class TUP>
85  using disable_if_Tuple = lib::meta::disable_if<lib::meta::is_Tuple<std::remove_reference_t<TUP>>>;
86 
87 
96  template<class TUP, class FUN, typename = enable_if_Tuple<TUP>>
97  void
98  forEach (TUP&& tuple, FUN fun)
99  {
100  std::apply ([&fun](auto&&... elms)
101  {
102  (fun (std::forward<decltype(elms)> (elms)), ...);
103  }
104  ,std::forward<TUP> (tuple));
105  }
106 
121  template<class TUP, class FUN, typename = enable_if_Tuple<TUP>>
122  auto
123  mapEach (TUP&& tuple, FUN fun)
124  {
125  return std::apply ([&fun](auto&&... elms)
126  { //..construct the type explicitly (make_tuple would decay fun result types)
127  using Tuple = std::tuple<decltype(fun (std::forward<decltype(elms)> (elms))) ...>;
128  return Tuple (fun (std::forward<decltype(elms)> (elms)) ...);
129  }
130  ,std::forward<TUP> (tuple));
131  }
132 
133 
134 
135 
136 
137  namespace { // rebinding helper to create std::tuple from a type sequence
138 
139  template<typename SEQ>
141  : std::false_type
142  { };
143 
144  template<typename...TYPES>
145  struct BuildTupleType<TySeq<TYPES...>>
146  {
147  using Type = std::tuple<TYPES...>;
148  };
149 
154  template<typename...TYPES>
155  struct BuildTupleType<Types<TYPES...>>
156  {
157  using VariadicSeq = typename StripNullType<Types<TYPES...>>::Seq;
158 
159  using Type = typename BuildTupleType<VariadicSeq>::Type;
160  };
161 
162  template<class H, typename TAIL>
163  struct BuildTupleType<Node<H, TAIL>>
164  {
165  using Seq = typename Types< Node<H,TAIL>>::Seq;
166  using Type = typename BuildTupleType<Seq>::Type;
167  };
168 
169  template<>
171  {
172  using Type = typename BuildTupleType<Types<>>::Type;
173  };
174  }
175 
176 
185  template<typename TYPES>
186  using Tuple = typename BuildTupleType<TYPES>::Type;
187 
188 
189  using std::tuple_size;
190  using std::tuple_element;
191 
192 
193 
195  template<typename...TYPES>
197  {
198  using Seq = typename Types<TYPES...>::Seq;
199  using List = typename Seq::List;
200  };
201  template<typename...TYPES>
202  struct RebindTupleTypes<std::tuple<TYPES...>>
203  {
204  using Seq = typename Types<TYPES...>::Seq;
205  using List = typename Seq::List;
206  };
207 
208 
209 
210 
211 
212 
213 
235  template< typename TYPES
236  , template<class,class, size_t> class _ElmMapper_
237  >
239  : Tuple<TYPES>
240  {
242  using SequenceIterator = typename BuildIdxIter<TYPES>::Ascending;
243 
244  protected:
245  template<class SRC, size_t...idx>
246  TupleConstructor (SRC values, IndexSeq<idx...>)
247  : Tuple<TYPES> (_ElmMapper_<SRC, Tuple<TYPES>, idx>{values}...)
248  { }
249 
250 
251  public:
252  template<class SRC>
253  TupleConstructor (SRC values)
254  : TupleConstructor (values, SequenceIterator())
255  { }
256  };
257 
258 
267  template<class SRC, class TAR>
269 
270 
271  template<class SRC, class TAR, size_t i>
272  using ExtractArg = typename ElementExtractor<SRC, TAR>::template Access<i>;
273 
274 
284  template<typename TYPES, class SRC>
286  buildTuple (SRC values)
287  {
288  return TupleConstructor<TYPES, ExtractArg> (values);
289  }
290 
291 
292 
293 
294 
295 
296 
297 
316  template
317  < template<class,class,class, uint> class _X_
318  , typename TYPES
319  , class TUP =Tuple<TYPES>
320  , uint i = 0
321  >
323  {
324  // prepare recursion...
325  using Head = typename Split<TYPES>::Head;
326  using Tail = typename Split<TYPES>::Tail;
328  using NextAccessor = typename NextBuilder::Product;
329  public:
330 
333  using Product = _X_< Head // the type to use for this accessor
334  , NextAccessor // the base type to inherit from
335  , TUP // the tuple type we build upon
336  , i // current element index
337  >;
338  };
339 
340 
341  template
342  < template<class,class,class, uint> class _X_
343  , class TUP
344  , uint i
345  >
346  class BuildTupleAccessor< _X_, Types<>, TUP, i>
347  {
348  public:
349  using Product = _X_<NullType, TUP, TUP, i>; // Note: i == tuple size
350 
351  };
352 
353 
354 
361  template
362  < typename TY
363  , class BASE
364  , class TUP
365  , uint idx
366  >
368  : BASE
369  {
370  using BASE::BASE;
371 
372  std::string
373  dump (std::string const& prefix ="(") const
374  {
375  return BASE::dump (prefix + util::toString(std::get<idx>(*this))+",");
376  }
377  };
378 
379  template<class TUP, uint n>
380  struct TupleElementDisplayer<NullType, TUP, TUP, n>
381  : TUP
382  {
383  TupleElementDisplayer (TUP const& tup)
384  : TUP(tup)
385  { }
386 
387  std::string
388  dump (std::string const& prefix ="(") const
389  {
390  if (1 < prefix.length())
391  // remove the trailing comma
392  return prefix.substr (0, prefix.length()-1) +")";
393  else
394  return prefix+")";
395  }
396  };
397 
398 
407  template<typename...TYPES>
408  inline std::string
409  dump (std::tuple<TYPES...> const& tuple)
410  {
411  using BuildAccessor = BuildTupleAccessor<TupleElementDisplayer, Types<TYPES...>>;
412  using Displayer = typename BuildAccessor::Product ;
413 
414  return static_cast<Displayer const&> (tuple)
415  .dump();
416  }
417 
418 
419 
420 }} // namespace lib::meta
421 
422 
423 // add a specialisation to enable tuple string conversion
424 namespace util {
425 
426  template<typename...TYPES>
427  struct StringConv<std::tuple<TYPES...>>
428  {
429  static std::string
430  invoke (std::tuple<TYPES...> const& tuple) noexcept
431  try {
432  return "«"+typeStr(tuple)
433  + "»──" + lib::meta::dump (tuple);
434  }
435  catch(...) { return FAILURE_INDICATOR; }
436  };
437 
438 
439 } // namespace util
440 #endif /*LIB_META_TUPLE_HELPER_H*/
Hold a sequence of index numbers as template parameters.
A template metaprogramming technique for manipulating collections of types.
trait to detect tuple types
typename BuildTupleType< TYPES >::Type Tuple
Build a std::tuple from types given as type sequence.
Simple and lightweight helpers for metaprogramming and type detection.
Extensible Adapter to construct a distinct tuple from some arbitrary source type. ...
STL namespace.
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.
Generic converter to somehow extract values from the "source" type to fill and initialise a tuple of ...
_X_< Head, NextAccessor, TUP, i > Product
type of the product created by this template.
Tuple< TYPES > buildTuple(SRC values)
convenience shortcut to build a tuple from some suitable source data.
Implementation namespace for support and library code.
typename enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition: meta/util.hpp:83
temporary workaround: strip trailing NullType entries from a type sequence, to make it compatible wit...
Helper: separate parts of a type sequence.
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
Definition: format-obj.hpp:191
temporary workaround: match and rebind the type sequence from a tuple
Decorating a tuple type with auxiliary data access operations.
void forEach(TUP &&tuple, FUN fun)
Tuple iteration: perform some arbitrary operation on each element of a tuple.
typename BuildIdxIter< TYPES >::Ascending SequenceIterator
meta-sequence to drive instantiation of the ElmMapper
failsafe invocation of custom string conversion.
Definition: meta/util.hpp:390
auto mapEach(TUP &&tuple, FUN fun)
Apply some arbitrary function onto all elements of a tuple.
Metaprogramming with type sequences based on variadic template parameters.
Helper to dump tuple contents.
std::string dump(std::tuple< TYPES... > const &tuple)
convenience function to dump a given tuple&#39;s contents.