From 31e9d59d808e985b71dca498fcc6ca5a52ff60bb Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 1 Jul 2009 04:47:52 +0200 Subject: [PATCH] WIP draft solution for next task --- src/lib/meta/function-closure.hpp | 67 ++++++++++++++++++++ tests/lib/meta/function-composition-test.cpp | 36 ++++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/lib/meta/function-closure.hpp b/src/lib/meta/function-closure.hpp index d2fc740fd..590753c74 100644 --- a/src/lib/meta/function-closure.hpp +++ b/src/lib/meta/function-closure.hpp @@ -562,6 +562,54 @@ namespace typelist{ } }; + + + + /** + * Functional composition. Create a functor, which + * on invocation will execute two functions chained, + * i.e. fed the result of invoking the first function + * as argument into the second function. + */ + template + class FunctionComposition + { + typedef typename func::_Fun::Args Args; + typedef typename func::_Fun::Ret Ret1; + + typedef Types ArgsF2; + typedef typename FunctionTypedef::Sig SigF2; + + typedef typename FunctionTypedef::Sig ChainedSig; + typedef function ChainedFunc; + + typedef typename func::PlaceholderTuple::PlaceholderSeq PlaceholderSeq; + typedef Tuple Placeholders; + + enum { ARG_CNT = count::value }; + + struct ComposedFunc + : ChainedFunc + { + template + ComposedFunc (SIG1& f1, SigF2& f2, TUP& args) + : ChainedFunc (std::tr1::bind (f2 , + func::Apply::template bind > (f1, args) + )) + { } + }; + + public: + static ChainedFunc + chain (SIG1& f1, SigF2& f2) + { + Placeholders args; + return ComposedFunc (f1,f2,args); + } + + }; + + /** @@ -615,6 +663,15 @@ namespace typelist{ typedef FunctionClosure Type; }; + template + struct _Chain + { + typedef typename func::_Fun::Args Args; + typedef typename func::_Fun::Ret Ret; + typedef typename FunctionTypedef::Sig Chained; + typedef function Function; + }; + template struct _PapS { @@ -705,6 +762,16 @@ namespace typelist{ return PApply::bindBack (f, val); } + + /** build a functor chaining the given functions */ + template + typename _Chain::Function + chained (SIG1& f1, SIG2& f2) + { + typedef typename _Chain::Ret Ret; + return FunctionComposition::chain (f1, f2); + } + } // (END) namespace func diff --git a/tests/lib/meta/function-composition-test.cpp b/tests/lib/meta/function-composition-test.cpp index a7d3c66c8..5cfc3f7a5 100644 --- a/tests/lib/meta/function-composition-test.cpp +++ b/tests/lib/meta/function-composition-test.cpp @@ -285,6 +285,23 @@ namespace test { ASSERT ( 7+6+5 == (func::applyFirst( fun13<7,6,5>, _7_) (_6_,_5_)).o_); ASSERT ( 6+5 == (func::applyFirst( fun12<6,5>, _6_) (_5_)).o_); ASSERT ( 5 == (func::applyFirst( fun11<5>, _5_) ( )).o_); + + + + // Finally a more convoluted example + // covering the general case of partial function closure: + typedef Num<5> Sig54321(Num<5>, Num<4>, Num<3>, Num<2>, Num<1>); // Signature of the 5-argument function + typedef Num<5> Sig54 (Num<5>, Num<4>); // ...closing the last 3 arguments should yield this 2-argument function + typedef Types,Num<2>,Num<1> > Args2Close; // Tuple type to hold the 3 argument values used for the closure + + // Close the trailing 3 arguments of the 5-argument function... + function fun_54 = PApply::bindBack(fun15<5,4,3,2,1>, + tuple::make(_3_,_2_,_1_) + ); + + // apply the remaining argument values + Num<5> resN5 = fun_54 (_5_,_4_); + ASSERT (5+4+3+2+1 == resN5.o_); } @@ -292,7 +309,24 @@ namespace test { void check_functionalComposition () { -// ASSERT (1+5+9 == fun(Num<1>(), Num<5>(), Num<9>())); + typedef Num<1> Sig12(Num<1>,Num<2>); + typedef int SigF21(Num<1>); + + Sig12 &f1 = fun12<1,2>; + SigF21 &f2 = fun2 >; + + typedef function,Num<2>)> Chained; + + Chained funCh = func::chained (f1, f2 ); + ASSERT (1+2 == funCh (_1_,_2_) ); + +#if false + ASSERT (1 == func::chain(fun11<1> , fun2) (_1_) ); + ASSERT (1+2 == func::chain(fun12<1,2> , fun2 > ) (_1_,_2_) ); + ASSERT (1+2+3 == func::chain(fun13<1,2,3> , fun2) (_1_,_2_,_3_) ); + ASSERT (1+2+3+4 == func::chain(fun14<1,2,3,4> , fun2) (_1_,_2_,_3_,_4_) ); + ASSERT (1+2+3+4+5 == func::chain(fun15<1,2,3,4,5>, fun2) (_1_,_2_,_3_,_4_,_5_) ); +#endif } };