diff --git a/src/lib/meta/function-closure.hpp b/src/lib/meta/function-closure.hpp index 74149ab40..bb4350410 100644 --- a/src/lib/meta/function-closure.hpp +++ b/src/lib/meta/function-closure.hpp @@ -692,6 +692,46 @@ namespace func { + /** + * Bind a specific argument to an arbitrary value. + * Especially, this "value" might be another binder. + */ + template + class BindToArgument + { + typedef typename _Fun::Args Args; + typedef typename _Fun::Ret Ret; + typedef typename Args::List ArgsList; + typedef typename Types::List ValList; + + enum { ARG_CNT = count::value }; + + typedef typename Splice::Front RemainingFront; + typedef typename Splice::Back RemainingBack; + typedef typename func::PlaceholderTuple::PlaceholderSeq::List PlaceholdersBefore; + typedef typename func::PlaceholderTuple::PlaceholderSeq::List PlaceholdersBehind; + typedef typename Append::List + ,PlaceholdersBehind + >::List PreparedArgs; + typedef typename Append::List ReducedArgs; + + typedef tuple::BuildTuple BuildPreparedArgs; + typedef typename Tuple::TupleType PreparedArgTuple; + + + public: + typedef function::Sig> ReducedFunc; + + static ReducedFunc + reduced (SIG& f, Tuple const& val) + { + PreparedArgTuple params (BuildPreparedArgs::create(val)); + return func::Apply::template bind (f, params); + } + }; + + + namespace { // ...helpers for specifying types in function declarations.... template @@ -798,16 +838,18 @@ namespace func { return PApply::bindFront (f, val); } - /** close the given function over the last argument */ - template + + /** bind the last function argument to an arbitrary term, + * which especially might be a (nested) binder... */ + template typename _PapE::Function - applyLast (SIG& f, ARG arg) + bindLast (SIG& f, TERM arg) { - typedef typename _PapE::Arg ArgType; - typedef Types ArgTypeSeq; - typedef Tuple ArgTuple; - ArgTuple val(arg); - return PApply::bindBack (f, val); + typedef Types ArgTypeSeq; + typedef Tuple ArgTuple; + ArgTuple argT(arg); + const int LAST_POS = count::Args>::value; + return BindToArgument::reduced (f, argT); } diff --git a/tests/lib/meta/function-composition-test.cpp b/tests/lib/meta/function-composition-test.cpp index cfeb26539..3ce70af52 100644 --- a/tests/lib/meta/function-composition-test.cpp +++ b/tests/lib/meta/function-composition-test.cpp @@ -135,6 +135,7 @@ namespace test { check_diagnostics (); check_partialApplication (); check_functionalComposition (); + check_bindToArbitraryParameter (); } @@ -315,6 +316,40 @@ namespace test { ASSERT (1+2+3+4+5 == func::chained(f5, ff) (_1_,_2_,_3_,_4_,_5_) ); } + + + void + check_bindToArbitraryParameter () + { + typedef Num<1> Sig15(Num<1>,Num<2>,Num<3>,Num<4>,Num<5>); + typedef Num<1> SigR1( Num<2>,Num<3>,Num<4>,Num<5>); + typedef Num<1> SigR2(Num<1>, Num<3>,Num<4>,Num<5>); + typedef Num<1> SigR3(Num<1>,Num<2>, Num<4>,Num<5>); + typedef Num<1> SigR4(Num<1>,Num<2>,Num<3>, Num<5>); + typedef Num<1> SigR5(Num<1>,Num<2>,Num<3>,Num<4> ); + + typedef Num<5> SigI5(Num<5>); + + Sig15& f = fun15<1,2,3,4,5>; + SigI5& f5 = fun11<5>; + Tuple > argT(55); + + SigR1& f_red1 = BindToArgument::reduced (f, argT); + SigR2& f_red2 = BindToArgument::reduced (f, argT); + SigR3& f_red3 = BindToArgument::reduced (f, argT); + SigR4& f_red4 = BindToArgument::reduced (f, argT); + SigR5& f_red5 = BindToArgument::reduced (f, argT); + + ASSERT (55+2+3+4+5 == f_red1 ( _2_,_3_,_4_,_5_) ); + ASSERT (1+55+3+4+5 == f_red1 (_1_, _3_,_4_,_5_) ); + ASSERT (1+2+55+4+5 == f_red1 (_1_,_2_, _4_,_5_) ); + ASSERT (1+2+3+55+5 == f_red1 (_1_,_2_,_3_, _5_) ); + ASSERT (1+2+3+4+55 == f_red1 (_1_,_2_,_3_,_4_ ) ); + + SigR5& f_2bind = bindLast (f, bind(f5, Num<5>(99))); + ASSERT (1+2+3+4+99 == f_2bind (_1_,_2_,_3_,_4_ ) ); + } + };