Lumiera  0.pre.03
»edit your freedom«
function-closure.hpp
Go to the documentation of this file.
1 /*
2  FUNCTION-CLOSURE.hpp - metaprogramming tools for closing a function over given arguments
3 
4  Copyright (C)
5  2009, 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_FUNCTION_CLOSURE_H
44 #define LIB_META_FUNCTION_CLOSURE_H
45 
46 #include "lib/meta/function.hpp"
48 #include "lib/util.hpp"
49 
50 #include <functional>
51 #include <utility>
52 #include <tuple>
53 
54 
55 
56 namespace lib {
57 namespace meta{
58 namespace func{
59 
60  using std::tuple;
61  using std::function;
62  using std::forward;
63  using std::move;
64 
65 
66 
67 
68  namespace { // helpers for binding and applying a function to an argument tuple
69 
70  using std::get;
71 
77  template<uint n>
78  struct Apply;
79 
80 
81  template<> //__________________________________
82  struct Apply<0>
83  {
84  template<typename RET, class FUN, class TUP>
85  static RET
86  invoke (FUN& f, TUP&)
87  {
88  return f ();
89  }
90 
91  template<typename RET, class FUN, class TUP>
92  static RET
93  bind (FUN& f, TUP&)
94  {
95  return std::bind (f);
96  }
97  };
98 
99 
100  template<> //_________________________________
101  struct Apply<1>
102  {
103  template<typename RET, class FUN, class TUP>
104  static RET
105  invoke (FUN& f, TUP & arg)
106  {
107  return f (get<0>(arg));
108  }
109 
110  template<typename RET, class FUN, class TUP>
111  static RET
112  bind (FUN& f, TUP & arg)
113  {
114  return std::bind (f, get<0>(arg));
115  }
116  };
117 
118 
119  template<> //_________________________________
120  struct Apply<2>
121  {
122  template<typename RET, class FUN, class TUP>
123  static RET
124  invoke (FUN& f, TUP & arg)
125  {
126  return f ( get<0>(arg)
127  , get<1>(arg)
128  );
129  }
130 
131  template<typename RET, class FUN, class TUP>
132  static RET
133  bind (FUN& f, TUP & arg)
134  {
135  return std::bind (f, get<0>(arg)
136  , get<1>(arg)
137  );
138  }
139  };
140 
141 
142  template<> //_________________________________
143  struct Apply<3>
144  {
145  template<typename RET, class FUN, class TUP>
146  static RET
147  invoke (FUN& f, TUP & arg)
148  {
149  return f ( get<0>(arg)
150  , get<1>(arg)
151  , get<2>(arg)
152  );
153  }
154 
155  template<typename RET, class FUN, class TUP>
156  static RET
157  bind (FUN& f, TUP & arg)
158  {
159  return std::bind (f, get<0>(arg)
160  , get<1>(arg)
161  , get<2>(arg)
162  );
163  }
164  };
165 
166 
167  template<> //_________________________________
168  struct Apply<4>
169  {
170  template<typename RET, class FUN, class TUP>
171  static RET
172  invoke (FUN& f, TUP & arg)
173  {
174  return f ( get<0>(arg)
175  , get<1>(arg)
176  , get<2>(arg)
177  , get<3>(arg)
178  );
179  }
180 
181  template<typename RET, class FUN, class TUP>
182  static RET
183  bind (FUN& f, TUP & arg)
184  {
185  return std::bind (f, get<0>(arg)
186  , get<1>(arg)
187  , get<2>(arg)
188  , get<3>(arg)
189  );
190  }
191  };
192 
193 
194  template<> //_________________________________
195  struct Apply<5>
196  {
197  template<typename RET, class FUN, class TUP>
198  static RET
199  invoke (FUN& f, TUP & arg)
200  {
201  return f ( get<0>(arg)
202  , get<1>(arg)
203  , get<2>(arg)
204  , get<3>(arg)
205  , get<4>(arg)
206  );
207  }
208 
209  template<typename RET, class FUN, class TUP>
210  static RET
211  bind (FUN& f, TUP & arg)
212  {
213  return std::bind (f, get<0>(arg)
214  , get<1>(arg)
215  , get<2>(arg)
216  , get<3>(arg)
217  , get<4>(arg)
218  );
219  }
220  };
221 
222 
223  template<> //_________________________________
224  struct Apply<6>
225  {
226  template<typename RET, class FUN, class TUP>
227  static RET
228  invoke (FUN& f, TUP & arg)
229  {
230  return f ( get<0>(arg)
231  , get<1>(arg)
232  , get<2>(arg)
233  , get<3>(arg)
234  , get<4>(arg)
235  , get<5>(arg)
236  );
237  }
238 
239  template<typename RET, class FUN, class TUP>
240  static RET
241  bind (FUN& f, TUP & arg)
242  {
243  return std::bind (f, get<0>(arg)
244  , get<1>(arg)
245  , get<2>(arg)
246  , get<3>(arg)
247  , get<4>(arg)
248  , get<5>(arg)
249  );
250  }
251  };
252 
253 
254  template<> //_________________________________
255  struct Apply<7>
256  {
257  template<typename RET, class FUN, class TUP>
258  static RET
259  invoke (FUN& f, TUP & arg)
260  {
261  return f ( get<0>(arg)
262  , get<1>(arg)
263  , get<2>(arg)
264  , get<3>(arg)
265  , get<4>(arg)
266  , get<5>(arg)
267  , get<6>(arg)
268  );
269  }
270 
271  template<typename RET, class FUN, class TUP>
272  static RET
273  bind (FUN& f, TUP & arg)
274  {
275  return std::bind (f, get<0>(arg)
276  , get<1>(arg)
277  , get<2>(arg)
278  , get<3>(arg)
279  , get<4>(arg)
280  , get<5>(arg)
281  , get<6>(arg)
282  );
283  }
284  };
285 
286 
287  template<> //_________________________________
288  struct Apply<8>
289  {
290  template<typename RET, class FUN, class TUP>
291  static RET
292  invoke (FUN& f, TUP & arg)
293  {
294  return f ( get<0>(arg)
295  , get<1>(arg)
296  , get<2>(arg)
297  , get<3>(arg)
298  , get<4>(arg)
299  , get<5>(arg)
300  , get<6>(arg)
301  , get<7>(arg)
302  );
303  }
304 
305  template<typename RET, class FUN, class TUP>
306  static RET
307  bind (FUN& f, TUP & arg)
308  {
309  return std::bind (f, get<0>(arg)
310  , get<1>(arg)
311  , get<2>(arg)
312  , get<3>(arg)
313  , get<4>(arg)
314  , get<5>(arg)
315  , get<6>(arg)
316  , get<7>(arg)
317  );
318  }
319  };
320 
321 
322  template<> //_________________________________
323  struct Apply<9>
324  {
325  template<typename RET, class FUN, class TUP>
326  static RET
327  invoke (FUN& f, TUP & arg)
328  {
329  return f ( get<0>(arg)
330  , get<1>(arg)
331  , get<2>(arg)
332  , get<3>(arg)
333  , get<4>(arg)
334  , get<5>(arg)
335  , get<6>(arg)
336  , get<7>(arg)
337  , get<8>(arg)
338  );
339  }
340 
341  template<typename RET, class FUN, class TUP>
342  static RET
343  bind (FUN& f, TUP & arg)
344  {
345  return std::bind (f, get<0>(arg)
346  , get<1>(arg)
347  , get<2>(arg)
348  , get<3>(arg)
349  , get<4>(arg)
350  , get<5>(arg)
351  , get<6>(arg)
352  , get<7>(arg)
353  , get<8>(arg)
354  );
355  }
356  };
357 
358 
359 
360 
361 
362 
363  /* ===== Helpers for partial function application ===== */
364 
367  using std::_Placeholder;
368 
369 
375  template<typename TYPES, size_t i=1>
377  : PlaceholderTuple<typename TYPES::List>
378  { };
379 
380  template<typename X, typename TAIL, size_t i>
381  struct PlaceholderTuple<Node<X,TAIL>, i>
382  {
383  using TailPlaceholders = typename PlaceholderTuple<TAIL,i+1>::List;
384 
385  using List = Node<_Placeholder<i>, TailPlaceholders>;
386  };
387 
388  template<size_t i>
390  {
391  using List = NullType;
392  };
393 
394 
395 
396  using std::tuple_element;
397  using std::tuple_size;
398  using std::get;
399 
400 
419  template<typename SRC, typename TAR, size_t start>
421  {
422  template<size_t i>
423  using DestType = typename std::tuple_element<i, TAR>::type;
424 
425 
431  static constexpr bool
432  useArg (size_t idx)
433  {
434  return (start <= idx)
435  and (idx < start + std::tuple_size<SRC>());
436  }
437 
438 
439 
440  template<size_t idx, bool doPick = PartiallyInitTuple::useArg(idx)>
441  struct IndexMapper
442  {
443  SRC const& initArgs;
444 
445  operator DestType<idx>()
446  {
447  return std::get<idx-start> (initArgs);
448  }
449  };
450 
451  template<size_t idx>
452  struct IndexMapper<idx, false>
453  {
454  SRC const& initArgs;
455 
456  operator DestType<idx>()
457  {
458  return DestType<idx>();
459  }
460  };
461  };
462 
463  } // (END) impl-namespace
464 
465 
466 
467 
468  /* ======= core operations: closures and partial application ========= */
469 
477  template<typename SIG>
479  {
480  using Args = typename _Fun<SIG>::Args;
481  using Ret = typename _Fun<SIG>::Ret;
482 
483  using BoundFunc = function<Ret()>;
484 
485  enum { ARG_CNT = count<typename Args::List>::value };
486 
487 
490 
491  public:
493  : params_(args)
494  { }
495 
496  BoundFunc bind (SIG& f) { return Apply<ARG_CNT>::template bind<BoundFunc> (f, params_); }
497  BoundFunc bind (function<SIG> const& f) { return Apply<ARG_CNT>::template bind<BoundFunc> (f, params_); }
498 
499  Ret operator() (SIG& f) { return Apply<ARG_CNT>::template invoke<Ret> (f, params_); }
500  Ret operator() (function<SIG>& f) { return Apply<ARG_CNT>::template invoke<Ret> (f, params_); }
501  };
502 
503 
504 
512  template<typename SIG>
514  {
515  typedef typename _Fun<SIG>::Args Args;
516  typedef typename _Fun<SIG>::Ret Ret;
517 
518  function<Ret(void)> closure_;
519 
520  public:
521  FunctionClosure (SIG& f, Tuple<Args>& arg)
522  : closure_(TupleApplicator<SIG>(arg).bind(f))
523  { }
524  FunctionClosure (function<SIG> const& f, Tuple<Args>& arg)
525  : closure_(TupleApplicator<SIG>(arg).bind(f))
526  { }
527 
528  Ret operator() () { return closure_(); }
529 
530  typedef Ret result_type;
531  typedef void argument_type;
532  };
533 
534 
535 
536 
557  template<typename SIG, typename VAL>
558  class PApply
559  {
560  typedef typename _Fun<SIG>::Args Args;
561  typedef typename _Fun<SIG>::Ret Ret;
562  typedef typename Args::List ArgsList;
563  typedef typename VAL::List ValList;
564  typedef typename Types<ValList>::Seq ValTypes;
565 
566  enum { ARG_CNT = count<ArgsList>::value
567  , VAL_CNT = count<ValList> ::value
568  , ROFFSET = (VAL_CNT < ARG_CNT)? ARG_CNT-VAL_CNT : 0
569  };
570 
571 
572  // create list of the *remaining* arguments, after applying the ValList
573  typedef typename Splice<ArgsList, ValList>::Back LeftReduced;
574  typedef typename Splice<ArgsList, ValList, ROFFSET>::Front RightReduced;
575 
576  typedef typename Types<LeftReduced>::Seq ArgsL;
577  typedef typename Types<RightReduced>::Seq ArgsR;
578 
579 
580  // build a list, where each of the *remaining* arguments is replaced by a placeholder marker
581  typedef typename func::PlaceholderTuple<LeftReduced>::List TrailingPlaceholders;
582  typedef typename func::PlaceholderTuple<RightReduced>::List LeadingPlaceholders;
583 
584  // ... and splice these placeholders on top of the original argument type list,
585  // thus retaining the types to be closed, but setting a placeholder for each remaining argument
586  typedef typename Splice<ArgsList, TrailingPlaceholders, VAL_CNT>::List LeftReplaced;
587  typedef typename Splice<ArgsList, LeadingPlaceholders, 0 >::List RightReplaced;
588 
591 
592  // create a "builder" helper, which accepts exactly the value tuple elements
593  // and puts them at the right location, while default-constructing the remaining
594  // (=placeholder)-arguments. Using this builder helper, we can finally set up
595  // the argument tuples (Left/RightReplacedArgs) used for the std::bind call
596  template<class SRC, class TAR, size_t i>
597  using IdxSelectorL = typename PartiallyInitTuple<SRC, TAR, 0>::template IndexMapper<i>;
598 
599  template<class SRC, class TAR, size_t i>
600  using IdxSelectorR = typename PartiallyInitTuple<SRC, TAR, ROFFSET>::template IndexMapper<i>;
601 
604 
605 
609 
613 
614 
615  public:
616  typedef function<typename BuildFunType<Ret,ArgsL>::Sig> LeftReducedFunc;
617  typedef function<typename BuildFunType<Ret,ArgsR>::Sig> RightReducedFunc;
618 
619 
628  static LeftReducedFunc
629  bindFront (SIG const& f, Tuple<ValTypes> const& arg)
630  {
631  LeftReplacedArgs params {BuildL(arg)};
632  return func::Apply<ARG_CNT>::template bind<LeftReducedFunc> (f, params);
633  }
634 
643  static RightReducedFunc
644  bindBack (SIG const& f, Tuple<ValTypes> const& arg)
645  {
646  RightReplacedArgs params {BuildR(arg)};
647  return func::Apply<ARG_CNT>::template bind<RightReducedFunc> (f, params);
648  }
649  };
650 
651 
652 
657  template<typename SIG, typename X, uint pos>
659  {
660  typedef typename _Fun<SIG>::Args Args;
661  typedef typename _Fun<SIG>::Ret Ret;
662  typedef typename Args::List ArgsList;
663  typedef typename Types<X>::List ValList;
664 
665  enum { ARG_CNT = count<ArgsList>::value };
666 
667  typedef typename Splice<ArgsList, ValList, pos>::Front RemainingFront;
668  typedef typename Splice<ArgsList, ValList, pos>::Back RemainingBack;
669  typedef typename func::PlaceholderTuple<RemainingFront>::List PlaceholdersBefore;
670  typedef typename func::PlaceholderTuple<RemainingBack,pos+1>::List PlaceholdersBehind;
671  typedef typename Append< typename Append< PlaceholdersBefore
672  , ValList >::List
673  , PlaceholdersBehind >::List PreparedArgs;
675 
676  using PreparedArgTypes = typename Types<PreparedArgs>::Seq;
677  using RemainingArgs = typename Types<ReducedArgs>::Seq;
678 
679  using ReducedSig = typename BuildFunType<Ret,RemainingArgs>::Sig;
680 
681  template<class SRC, class TAR, size_t i>
682  using IdxSelector = typename PartiallyInitTuple<SRC, TAR, pos>::template IndexMapper<i>;
683 
685 
686 
687 
688  public:
689  typedef function<ReducedSig> ReducedFunc;
690 
691  static ReducedFunc
692  reduced (SIG& f, Tuple<Types<X>> const& val)
693  {
695  return func::Apply<ARG_CNT>::template bind<ReducedFunc> (f, params);
696  }
697  };
698 
699 
700 
701  namespace { // ...helpers for specifying types in function declarations....
702 
703  using std::get;
704  using util::unConst;
705 
706 
707  template<typename RET, typename ARG>
708  struct _Sig
709  {
710  typedef typename BuildFunType<RET, ARG>::Sig Type;
712  };
713 
714  template<typename SIG, typename ARG>
715  struct _Clo
716  {
717  typedef typename _Fun<SIG>::Ret Ret;
718  typedef typename _Sig<Ret,ARG>::Type Signature;
720  };
721 
722  template<typename FUN1, typename FUN2>
723  struct _Chain
724  {
725  using Ret = typename _Fun<FUN2>::Ret;
726  using Args = typename _Fun<FUN1>::Args;
727 
728  using FunType = typename BuildFunType<Ret,Args>::Fun;
729  static auto adaptedFunType() { return FunType{}; }
730 
731 
732  template<typename F1, typename F2
733  ,typename RET, typename... ARGS>
734  static auto
735  composedFunctions (F1&& f1, F2&& f2, _Fun<RET(ARGS...)>)
736  {
737  tuple<F1,F2> binding{forward<F1> (f1)
738  ,forward<F2> (f2)
739  };
740  return [binding = move(binding)]
741  (ARGS ...args) -> RET
742  {
743  auto& functor1 = get<0>(binding);
744  auto& functor2 = get<1>(binding);
745  //
746  return functor2 (functor1 (forward<ARGS> (args)...));
747  };
748  }
749  };
750 
751  template<typename FUN>
752  struct _PapS
753  {
754  using Ret = typename _Fun<FUN>::Ret;
755  using Args = typename _Fun<FUN>::Args;
756  using Arg = typename Split<Args>::Head;
757  using Rest = typename Split<Args>::Tail;
758 
759  using FunType = typename BuildFunType<Ret,Rest>::Fun;
760  static auto adaptedFunType() { return FunType{}; }
761 
762 
763  template<typename F, typename A
764  ,typename RET, typename... ARGS>
765  static auto
766  bindFrontArg (F&& fun, A&& arg, _Fun<RET(ARGS...)>)
767  {
768  tuple<F,A> binding{forward<F> (fun)
769  ,forward<A> (arg)
770  };
771  return [binding = move(binding)]
772  (ARGS ...args) -> RET
773  {
774  auto& functor = get<0>(binding);
775  // //Warning: might corrupt ownership
776  return functor ( forward<A> (unConst (get<1>(binding)))
777  , forward<ARGS> (args)...);
778  };
779  }
780  };
781 
782  template<typename FUN>
783  struct _PapE
784  {
785  using Ret = typename _Fun<FUN>::Ret;
786  using Args = typename _Fun<FUN>::Args;
787  using Arg = typename Split<Args>::End;
788  using Rest = typename Split<Args>::Prefix;
789 
790  using FunType = typename BuildFunType<Ret,Rest>::Fun;
791  static auto adaptedFunType() { return FunType{}; }
792 
793 
794  template<typename F, typename A
795  ,typename RET, typename... ARGS>
796  static auto
797  bindBackArg (F&& fun, A&& arg, _Fun<RET(ARGS...)>)
798  {
799  tuple<F,A> binding{forward<F> (fun)
800  ,forward<A> (arg)
801  };
802  return [binding = move(binding)]
803  (ARGS ...args) -> RET
804  {
805  auto& functor = get<0>(binding);
806  //
807  return functor ( forward<ARGS> (args)...
808  , forward<A> (unConst (get<1>(binding))));
809  };
810  }
811  };
812 
813  } // (End) argument type shortcuts
814 
815 
816 
817 
818  /* ========== function-style interface ============= */
819 
824  template<typename...ARG>
825  inline
826  typename _Sig<void, Types<ARG...>>::Applicator
827  tupleApplicator (std::tuple<ARG...>& args)
828  {
829  typedef typename _Sig<void,Types<ARG...>>::Type Signature;
830  return TupleApplicator<Signature> (args);
831  }
832 
833 
836  template<typename SIG, typename...ARG>
837  inline
838  typename _Fun<SIG>::Ret
839  apply (SIG& f, std::tuple<ARG...>& args)
840  {
841  typedef typename _Fun<SIG>::Ret Ret; //
842  typedef typename _Sig<Ret,Types<ARG...>>::Type Signature; // Note: deliberately re-building the Signature Type
843  return TupleApplicator<Signature> (args) (f); // in order to get better error messages here
844  }
845 
851  template<typename SIG, typename...ARG>
852  inline
853  typename _Clo<SIG,Types<ARG...>>::Type
854  closure (SIG& f, std::tuple<ARG...>& args)
855  {
856  typedef typename _Clo<SIG,Types<ARG...>>::Type Closure;
857  return Closure (f,args);
858  }
859 
860 
863  template<typename FUN, typename ARG>
864  inline auto
865  applyFirst (FUN&& fun, ARG&& arg)
866  {
867  static_assert (_Fun<FUN>(), "expect something function-like");
868  return _PapS<FUN>::bindFrontArg (forward<FUN> (fun)
869  ,forward<ARG> (arg)
870  ,_PapS<FUN>::adaptedFunType());
871  }
872 
874  template<typename FUN, typename ARG>
875  inline auto
876  applyLast (FUN&& fun, ARG&& arg)
877  {
878  static_assert (_Fun<FUN>(), "expect something function-like");
879  return _PapE<FUN>::bindBackArg (forward<FUN> (fun)
880  ,forward<ARG> (arg)
881  ,_PapE<FUN>::adaptedFunType());
882  }
883 
884 
887  template<typename SIG, typename TERM>
888  inline
889  typename _PapE<SIG>::FunType::Functor
890  bindLast (SIG& f, TERM const& arg)
891  {
892  typedef Types<TERM> ArgTypeSeq;
893  typedef Tuple<ArgTypeSeq> ArgTuple;
894  ArgTuple argT(arg);
895  enum { LAST_POS = -1 + count<typename _Fun<SIG>::Args::List>::value };
897  }
898 
899 
903  template<typename FUN1, typename FUN2>
904  inline auto
905  chained (FUN1&& f1, FUN2&& f2)
906  {
907  static_assert (_Fun<FUN1>(), "expect something function-like for function-1");
908  static_assert (_Fun<FUN2>(), "expect something function-like for function-2");
909  using Chain = _Chain<FUN1,FUN2>;
910  return Chain::composedFunctions (forward<FUN1> (f1)
911  ,forward<FUN2> (f2)
912  ,Chain::adaptedFunType());
913  }
914 
915 
916 
917 }}} // namespace lib::meta::func
918 #endif
Build function types from given Argument types.
Definition: function.hpp:341
_Clo< SIG, Types< ARG... > >::Type closure(SIG &f, std::tuple< ARG... > &args)
close the given function over all arguments, using the values from the argument tuple.
Build a list of standard function argument placeholder types.
Bind a specific argument to an arbitrary value.
typename BuildTupleType< TYPES >::Type Tuple
Build a std::tuple from types given as type sequence.
Extensible Adapter to construct a distinct tuple from some arbitrary source type. ...
auto applyFirst(FUN &&fun, ARG &&arg)
close the given function over the first argument.
Helper for uniform access to function signature types.
Definition: function.hpp:99
static RightReducedFunc bindBack(SIG const &f, Tuple< ValTypes > const &arg)
do a partial function application, closing the last arguments f(a,b,c)->res + (b,c) yields f(a)->res
_PapE< SIG >::FunType::Functor bindLast(SIG &f, TERM const &arg)
bind the last function argument to an arbitrary term, which especially might be a (nested) binder...
static constexpr bool useArg(size_t idx)
define those index positions in the target tuple, where init arguments shall be used on construction...
Implementation namespace for support and library code.
Metaprogramming with tuples-of-types and the std::tuple record.
Partial function application Takes a function and a value tuple, using the latter to close function a...
Tuple< LeftReplacedTypes > LeftReplacedArgs
Tuple to hold all argument values, starting from left.
auto applyLast(FUN &&fun, ARG &&arg)
close the given function over the last argument
Metaprogramming tools for transforming functor types.
Tuple< Args > & params_
storing a ref to the parameter tuple
Metafunction counting the number of Types in the collection.
append lists-of-types
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Helper: separate parts of a type sequence.
splice a typelist like an overlay into an base typelist, starting at given index. ...
auto chained(FUN1 &&f1, FUN2 &&f2)
build a functor chaining the given functions: feed the result of f1 into f2.
Closing a function over its arguments.
static LeftReducedFunc bindFront(SIG const &f, Tuple< ValTypes > const &arg)
do a partial function application, closing the first arguments f(a,b,c)->res + (a,b) yields f(c)->res
_Sig< void, Types< ARG... > >::Applicator tupleApplicator(std::tuple< ARG... > &args)
build a TupleApplicator, which embodies the given argument tuple and can be used to apply them to var...
Tuple< RightReplacedTypes > RightReplacedArgs
Tuple to hold all argument values, aligned to the end of the function argument list.
this Helper with repetitive specialisations for up to nine arguments is used either to apply a functi...
Closure-creating template.
_Fun< SIG >::Ret apply(SIG &f, std::tuple< ARG... > &args)
apply the given function to the argument tuple
apply a transformation (template) to each type in the list
Builder for a tuple instance, where only some ctor parameters are supplied, while the remaining argum...