diff --git a/src/lib/meta/function-closure.hpp b/src/lib/meta/function-closure.hpp index 77ff9145a..dedf14d70 100644 --- a/src/lib/meta/function-closure.hpp +++ b/src/lib/meta/function-closure.hpp @@ -24,8 +24,17 @@ /** @file function-closure.hpp ** Partial function application and building a complete function closure. ** This is a small addendum to (and thin wrapper for) tr1/functional, supporting - ** the case when a function should be closed over (all) arguments, where especially - ** the parameter values to close on are provided as a tuple. + ** the case when a function should be closed over (partially or all) arguments, + ** where especially the parameter values to close on are provided as a tuple. + ** + ** Because we have to deal with arbitrary functions and arbitrary parameter types, + ** we need a lot of repetitive code to "catch" functions from zero to nine arguments. + ** At the bottom of this header, you'll find a function-style interface, which + ** wraps up all these technicalities. + ** + ** @todo the implementation is able to handle partial application with N arguments, + ** but currently we need just one argument, thus only this case was wrapped + ** up into a convenient functions func::applyFirst and func::applyLast ** ** @see control::CommandDef usage example ** @see function.hpp @@ -363,23 +372,29 @@ namespace typelist{ }; + + + /* ===== Helpers for partial function application ===== */ using std::tr1::_Placeholder; // what is the "official" way to import them? + + /** + * Build a sequence of tr1 function argument placeholder types. + * For each of the elements of the provided reference sequence, + * a Placeholder is added, numbers counting up starting with 1 (!) + */ template class PlaceholderTuple { -// typedef typename Tuple::HeadType HeadType; -// typedef typename Tuple::ArgList TypeList; -// typedef typename Tuple::Tail::ArgList TailList; typedef typename Tuple::Type TypeSeq; typedef typename Tuple::TailType TailSeq; typedef typename PlaceholderTuple::PlaceholderSeq TailPlaceholderSeq; public: - typedef typename Prepend<_Placeholder, TailPlaceholderSeq>::Seq PlaceholderSeq; + typedef typename Prepend<_Placeholder, TailPlaceholderSeq>::Seq PlaceholderSeq; typedef Tuple Type; }; @@ -397,12 +412,12 @@ namespace typelist{ - - } // (END) impl-namespace (func) + /* ======= core operations: closures and partial application ========= */ + /** * Closure-creating template. * @note taking functor objects \em and parameters per reference @@ -434,6 +449,7 @@ namespace typelist{ }; + /** * Partial function application * Takes a function and a value tuple, @@ -447,28 +463,38 @@ namespace typelist{ { typedef typename func::_Fun::Args Args; typedef typename func::_Fun::Ret Ret; - - enum { ARG_CNT = count::value - , VAL_CNT = count::value - , ROFFSET = (VAL_CNT < ARG_CNT)? ARG_CNT-VAL_CNT : 0 - }; - - typedef typename func::PlaceholderTuple::PlaceholderSeq::List Placeholders; typedef typename Args::List ArgsList; typedef typename VAL::List ValList; - typedef typename Splice::List LeftReplaced; - typedef typename Splice::List RightReplaced; + enum { ARG_CNT = count::value + , VAL_CNT = count ::value + , ROFFSET = (VAL_CNT < ARG_CNT)? ARG_CNT-VAL_CNT : 0 + }; + + // create list of the *remaining* arguments, after applying the ValList typedef typename Splice::Back LeftReduced; typedef typename Splice::Front RightReduced; + // build a list, where each of the *remaining* arguments is replaced by a placeholder marker + typedef typename func::PlaceholderTuple::PlaceholderSeq::List LeftPlaceholders; + typedef typename func::PlaceholderTuple::PlaceholderSeq::List RightPlaceholders; + + // ... and splice these placeholders on top of the original argument type list, + // thus retaining the types to be closed, but setting a placeholder for each remaining argument + typedef typename Splice::List LeftReplaced; + typedef typename Splice::List RightReplaced; + typedef Tuple TupleL; typedef Tuple TupleR; typedef typename Tuple::Type ArgsL; typedef typename Tuple::Type ArgsR; + // create a "builder" helper, which accepts exactly the value tuple elements + // and puts them at the right location, while default-constructing the remaining + // (=placeholder)-arguments. Using this builder helper, we can finally set up + // the argument tuples (Left/RightReplacedArgs) used for the tr1::bind call typedef tuple::BuildTuple BuildL; typedef tuple::BuildTuple BuildR; @@ -497,7 +523,8 @@ namespace typelist{ : TupleR ( BuildR::create(arg)) { } }; - + + /** do a partial function application, closing the first arguments * f(a,b,c)->res + (a,b) yields f(c)->res * diff --git a/tests/lib/meta/function-composition-test.cpp b/tests/lib/meta/function-composition-test.cpp index aa3617744..b659c280b 100644 --- a/tests/lib/meta/function-composition-test.cpp +++ b/tests/lib/meta/function-composition-test.cpp @@ -261,7 +261,7 @@ namespace test { fun_23 = func::applyFirst (func123, Num<1>(19)); res = fun_23 (_2_,_3_).o_; ASSERT (24 == res); -#if false //////////////TODO silly bug in the Split template! + typedef function(Num<1>, Num<2>)> F12; F12 fun_12 = func::applyLast(f, Num<3>(20)); res = fun_12 (_1_,_2_).o_; @@ -270,7 +270,7 @@ namespace test { fun_12 = func::applyLast(func123, Num<3>(21)); res = fun_12 (_1_,_2_).o_; ASSERT (24 == res); -#endif + }