revamp namespace func. Finish excursion on function handling

This commit is contained in:
Fischlurch 2009-07-03 14:31:52 +02:00
parent b7be61c4e6
commit d13d461a9c
5 changed files with 348 additions and 377 deletions

View file

@ -25,7 +25,8 @@
** 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 (partially or all) arguments,
** where especially the parameter values to close on are provided as a tuple.
** where especially the parameter values to close on are provided as a tuple.
** Additionally, we allow for composing (chaining) of two functions.
**
** 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.
@ -55,15 +56,14 @@
namespace lumiera {
namespace typelist{
namespace func {
using std::tr1::function;
//using std::tr1::bind;
//using std::tr1::placeholders::_1;
namespace func { ///< helpers for binding and applying a function to an argument tuple
namespace { // helpers for binding and applying a function to an argument tuple
using tuple::element;
@ -96,7 +96,7 @@ namespace typelist{
/**
* this Helper with repetitive specialisations for up to nine arguments
* is used either to apply a function to arguments given as a tuple, or
* to create the actual closure (functor) over all function arguments.
* to create the actual closure (functor) over all function arguments.
*/
template<uint n>
struct Apply;
@ -419,9 +419,7 @@ namespace typelist{
};
} // (END) impl-namespace (func)
} // (END) impl-namespace
@ -450,232 +448,15 @@ namespace typelist{
: params_(args)
{ }
BoundFunc bind (SIG& f) { return func::Apply<ARG_CNT>::template bind<BoundFunc> (f, params_); }
BoundFunc bind (function<SIG> const& f) { return func::Apply<ARG_CNT>::template bind<BoundFunc> (f, params_); }
BoundFunc bind (SIG& f) { return Apply<ARG_CNT>::template bind<BoundFunc> (f, params_); }
BoundFunc bind (function<SIG> const& f) { return Apply<ARG_CNT>::template bind<BoundFunc> (f, params_); }
Ret operator() (SIG& f) { return func::Apply<ARG_CNT>::template invoke<Ret> (f, params_); }
Ret operator() (function<SIG>& f) { return func::Apply<ARG_CNT>::template invoke<Ret> (f, params_); }
Ret operator() (SIG& f) { return Apply<ARG_CNT>::template invoke<Ret> (f, params_); }
Ret operator() (function<SIG>& f) { return Apply<ARG_CNT>::template invoke<Ret> (f, params_); }
};
/**
* Partial function application
* Takes a function and a value tuple,
* using the latter to close function arguments
* either from the front (left) or aligned to the end
* of the function argument list. Result is a "reduced" function,
* expecting only the remaining "un-closed" arguments at invocation.
*/
template<typename SIG, typename VAL>
class PApply
{
typedef typename func::_Fun<SIG>::Args Args;
typedef typename func::_Fun<SIG>::Ret Ret;
typedef typename Args::List ArgsList;
typedef typename VAL::List ValList;
enum { ARG_CNT = count<ArgsList>::value
, VAL_CNT = count<ValList> ::value
, ROFFSET = (VAL_CNT < ARG_CNT)? ARG_CNT-VAL_CNT : 0
};
// create list of the *remaining* arguments, after applying the ValList
typedef typename Splice<ArgsList, ValList>::Back LeftReduced;
typedef typename Splice<ArgsList, ValList, ROFFSET>::Front RightReduced;
// build a list, where each of the *remaining* arguments is replaced by a placeholder marker
typedef typename func::PlaceholderTuple<LeftReduced>::PlaceholderSeq::List LeftPlaceholders;
typedef typename func::PlaceholderTuple<RightReduced>::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<ArgsList, LeftPlaceholders, VAL_CNT>::List LeftReplaced;
typedef typename Splice<ArgsList, RightPlaceholders, 0 >::List RightReplaced;
typedef Tuple<LeftReplaced> TupleL;
typedef Tuple<RightReplaced> TupleR;
typedef typename Tuple<LeftReduced>::Type ArgsL;
typedef typename Tuple<RightReduced>::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<LeftReplaced, ValList> BuildL;
typedef tuple::BuildTuple<RightReplaced, ValList, ROFFSET> BuildR;
public:
typedef function<typename FunctionTypedef<Ret,ArgsL>::Sig> LeftReducedFunc;
typedef function<typename FunctionTypedef<Ret,ArgsR>::Sig> RightReducedFunc;
/** Contains the argument values, starting from left.
* Any remaining positions are occupied by binding placeholders */
struct LeftReplacedArgs
: TupleL
{
LeftReplacedArgs (Tuple<VAL> const& arg)
: TupleL ( BuildL::create(arg))
{ }
};
/** Contains the argument values, aligned to the end of the function argument list.
* Any remaining positions before are occupied by binding placeholders */
struct RightReplacedArgs
: TupleR
{
RightReplacedArgs (Tuple<VAL> const& arg)
: TupleR ( BuildR::create(arg))
{ }
};
/** do a partial function application, closing the first arguments
* f(a,b,c)->res + (a,b) yields f(c)->res
*
* @param f function, function pointer or functor
* @param arg value tuple, used to close function arguments starting from left
* @return new function object, holding copies of the values and using them at the
* closed arguments; on invocation, only the remaining arguments need to be supplied.
*/
static LeftReducedFunc
bindFront (SIG& f, Tuple<VAL> const& arg)
{
LeftReplacedArgs params (arg);
return func::Apply<ARG_CNT>::template bind<LeftReducedFunc> (f, params.tupleCast());
}
/** do a partial function application, closing the last arguments
* f(a,b,c)->res + (b,c) yields f(a)->res
*
* @param f function, function pointer or functor
* @param arg value tuple, used to close function arguments starting from right
* @return new function object, holding copies of the values and using them at the
* closed arguments; on invocation, only the remaining arguments need to be supplied.
*/
static RightReducedFunc
bindBack (SIG& f, Tuple<VAL> const& arg)
{
RightReplacedArgs params (arg);
return func::Apply<ARG_CNT>::template bind<RightReducedFunc> (f, params.tupleCast());
}
};
namespace _cmp {
using std::tr1::bind;
using std::tr1::placeholders::_1;
using std::tr1::placeholders::_2;
using std::tr1::placeholders::_3;
using std::tr1::placeholders::_4;
using std::tr1::placeholders::_5;
using std::tr1::placeholders::_6;
using std::tr1::placeholders::_7;
using std::tr1::placeholders::_8;
using std::tr1::placeholders::_9;
template<typename RES, typename F1, typename F2, uint n>
struct BuildComposed;
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 0 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1)); }
};
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 1 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1)); }
};
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 2 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2)); }
};
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 3 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3)); }
};
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 4 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4)); }
};
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 5 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5)); }
};
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 6 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6)); }
};
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 7 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6,_7)); }
};
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 8 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6,_7,_8)); }
};
template<typename RES, typename F1, typename F2>
struct BuildComposed<RES,F1,F2, 9 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6,_7,_8,_9)); }
};
}
/**
* 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<typename SIG1, typename RET>
class FunctionComposition
{
typedef typename func::_Fun<SIG1>::Args Args;
typedef typename func::_Fun<SIG1>::Ret Ret1;
typedef Types<Ret1> ArgsF2;
typedef typename FunctionTypedef<RET, ArgsF2>::Sig SigF2;
typedef typename FunctionTypedef<RET, Args>::Sig ChainedSig;
enum { ARG_CNT = count<typename Args::List>::value };
public:
static function<ChainedSig>
chain (SIG1& f1, SigF2& f2)
{
return _cmp::BuildComposed<ChainedSig,SIG1,SigF2, ARG_CNT>::func (f1,f2);
}
};
/**
* Closing a function over its arguments.
* This is a small usage example or spin-off,
@ -707,11 +488,212 @@ namespace typelist{
namespace func { // ...some convenience shortcuts
// helpers for specifying types in function declarations....
/**
* Partial function application
* Takes a function and a value tuple,
* using the latter to close function arguments
* either from the front (left) or aligned to the end
* of the function argument list. Result is a "reduced" function,
* expecting only the remaining "un-closed" arguments at invocation.
*/
template<typename SIG, typename VAL>
class PApply
{
typedef typename _Fun<SIG>::Args Args;
typedef typename _Fun<SIG>::Ret Ret;
typedef typename Args::List ArgsList;
typedef typename VAL::List ValList;
enum { ARG_CNT = count<ArgsList>::value
, VAL_CNT = count<ValList> ::value
, ROFFSET = (VAL_CNT < ARG_CNT)? ARG_CNT-VAL_CNT : 0
};
// create list of the *remaining* arguments, after applying the ValList
typedef typename Splice<ArgsList, ValList>::Back LeftReduced;
typedef typename Splice<ArgsList, ValList, ROFFSET>::Front RightReduced;
// build a list, where each of the *remaining* arguments is replaced by a placeholder marker
typedef typename func::PlaceholderTuple<LeftReduced>::PlaceholderSeq::List LeftPlaceholders;
typedef typename func::PlaceholderTuple<RightReduced>::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<ArgsList, LeftPlaceholders, VAL_CNT>::List LeftReplaced;
typedef typename Splice<ArgsList, RightPlaceholders, 0 >::List RightReplaced;
typedef typename Tuple<LeftReduced>::Type ArgsL;
typedef typename Tuple<RightReduced>::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<LeftReplaced, ValList> BuildL;
typedef tuple::BuildTuple<RightReplaced, ValList, ROFFSET> BuildR;
/** Contains the argument values, starting from left.
* Any remaining positions are occupied by binding placeholders */
typedef typename Tuple<LeftReplaced>::TupleType LeftReplacedArgs;
/** Contains the argument values, aligned to the end of the function argument list.
* Any remaining positions before are occupied by binding placeholders */
typedef typename Tuple<RightReplaced>::TupleType RightReplacedArgs;
public:
typedef function<typename FunctionTypedef<Ret,ArgsL>::Sig> LeftReducedFunc;
typedef function<typename FunctionTypedef<Ret,ArgsR>::Sig> RightReducedFunc;
/** do a partial function application, closing the first arguments
* f(a,b,c)->res + (a,b) yields f(c)->res
*
* @param f function, function pointer or functor
* @param arg value tuple, used to close function arguments starting from left
* @return new function object, holding copies of the values and using them at the
* closed arguments; on invocation, only the remaining arguments need to be supplied.
*/
static LeftReducedFunc
bindFront (SIG& f, Tuple<VAL> const& arg)
{
LeftReplacedArgs params (BuildL::create(arg));
return func::Apply<ARG_CNT>::template bind<LeftReducedFunc> (f, params);
}
/** do a partial function application, closing the last arguments
* f(a,b,c)->res + (b,c) yields f(a)->res
*
* @param f function, function pointer or functor
* @param arg value tuple, used to close function arguments starting from right
* @return new function object, holding copies of the values and using them at the
* closed arguments; on invocation, only the remaining arguments need to be supplied.
*/
static RightReducedFunc
bindBack (SIG& f, Tuple<VAL> const& arg)
{
RightReplacedArgs params (BuildR::create(arg));
return func::Apply<ARG_CNT>::template bind<RightReducedFunc> (f, params);
}
};
namespace _composed { // repetitive impl.code for function composition
using std::tr1::bind;
using std::tr1::placeholders::_1;
using std::tr1::placeholders::_2;
using std::tr1::placeholders::_3;
using std::tr1::placeholders::_4;
using std::tr1::placeholders::_5;
using std::tr1::placeholders::_6;
using std::tr1::placeholders::_7;
using std::tr1::placeholders::_8;
using std::tr1::placeholders::_9;
template<typename RES, typename F1, typename F2, uint n>
struct Build;
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 0 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1)); }
};
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 1 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1)); }
};
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 2 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2)); }
};
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 3 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3)); }
};
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 4 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4)); }
};
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 5 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5)); }
};
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 6 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6)); }
};
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 7 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6,_7)); }
};
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 8 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6,_7,_8)); }
};
template<typename RES, typename F1, typename F2>
struct Build<RES,F1,F2, 9 >
{
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6,_7,_8,_9)); }
};
} // (End) impl namespace (_composed)
/**
* 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<typename SIG1, typename RET>
class FunctionComposition
{
typedef typename func::_Fun<SIG1>::Args Args;
typedef typename func::_Fun<SIG1>::Ret Ret1;
typedef Types<Ret1> ArgsF2;
typedef typename FunctionTypedef<RET, ArgsF2>::Sig SigF2;
typedef typename FunctionTypedef<RET, Args>::Sig ChainedSig;
enum { ARG_CNT = count<typename Args::List>::value };
public:
static function<ChainedSig>
chain (SIG1& f1, SigF2& f2)
{
return _composed::Build<ChainedSig,SIG1,SigF2, ARG_CNT>::func (f1,f2);
}
};
namespace { // ...helpers for specifying types in function declarations....
template<typename RET, typename ARG>
struct _Sig
{
@ -730,8 +712,8 @@ namespace typelist{
template<typename SIG1, typename SIG2>
struct _Chain
{
typedef typename func::_Fun<SIG1>::Args Args;
typedef typename func::_Fun<SIG2>::Ret Ret;
typedef typename _Fun<SIG1>::Args Args;
typedef typename _Fun<SIG2>::Ret Ret;
typedef typename FunctionTypedef<Ret, Args>::Sig Chained;
typedef function<Chained> Function;
};
@ -758,87 +740,87 @@ namespace typelist{
typedef function<Signature> Function;
};
/* ========== function-style interface ============= */
/** build a TupleApplicator, which embodies the given
* argument tuple and can be used to apply various
* functions to them.
*/
template<typename ARG>
typename _Sig<void, ARG>::Applicator
tupleApplicator (Tuple<ARG>& args)
{
typedef typename _Sig<void,ARG>::Type Signature;
return TupleApplicator<Signature> (args);
}
/** apply the given function to the argument tuple */
template<typename SIG, typename ARG>
typename _Fun<SIG>::Ret
apply (SIG& f, Tuple<ARG>& args)
{
typedef typename _Fun<SIG>::Ret Ret; //
typedef typename _Sig<Ret,ARG>::Type Signature; // Note: deliberately re-building the Signature Type
return TupleApplicator<Signature> (args) (f); // in order to get better error messages here
}
/** close the given function over all arguments,
* using the values from the argument tuple.
* @return a closure object, which can be
* invoked later to yield the
* function result. */
template<typename SIG, typename ARG>
typename _Clo<SIG,ARG>::Type
closure (SIG& f, Tuple<ARG>& args)
{
typedef typename _Fun<SIG>::Ret Ret;
typedef typename _Sig<Ret,ARG>::Type Signature;
typedef typename _Clo<SIG,ARG>::Type Closure;
return Closure (f,args);
}
/** close the given function over the first argument */
template<typename SIG, typename ARG>
typename _PapS<SIG>::Function
applyFirst (SIG& f, ARG arg)
{
typedef typename _PapS<SIG>::Arg ArgType;
typedef Types<ArgType> ArgTypeSeq;
typedef Tuple<ArgTypeSeq> ArgTuple;
ArgTuple val(arg);
return PApply<SIG,ArgTypeSeq>::bindFront (f, val);
}
/** close the given function over the last argument */
template<typename SIG, typename ARG>
typename _PapE<SIG>::Function
applyLast (SIG& f, ARG arg)
{
typedef typename _PapE<SIG>::Arg ArgType;
typedef Types<ArgType> ArgTypeSeq;
typedef Tuple<ArgTypeSeq> ArgTuple;
ArgTuple val(arg);
return PApply<SIG,ArgTypeSeq>::bindBack (f, val);
}
/** build a functor chaining the given functions */
template<typename SIG1, typename SIG2>
typename _Chain<SIG1,SIG2>::Function
chained (SIG1& f1, SIG2& f2)
{
typedef typename _Chain<SIG1,SIG2>::Ret Ret;
return FunctionComposition<SIG1,Ret>::chain (f1, f2);
}
} // (END) namespace func
} // (End) argument type shortcuts
}} // namespace lumiera::typelist
/* ========== function-style interface ============= */
/** build a TupleApplicator, which embodies the given
* argument tuple and can be used to apply various
* functions to them.
*/
template<typename ARG>
typename _Sig<void, ARG>::Applicator
tupleApplicator (Tuple<ARG>& args)
{
typedef typename _Sig<void,ARG>::Type Signature;
return TupleApplicator<Signature> (args);
}
/** apply the given function to the argument tuple */
template<typename SIG, typename ARG>
typename _Fun<SIG>::Ret
apply (SIG& f, Tuple<ARG>& args)
{
typedef typename _Fun<SIG>::Ret Ret; //
typedef typename _Sig<Ret,ARG>::Type Signature; // Note: deliberately re-building the Signature Type
return TupleApplicator<Signature> (args) (f); // in order to get better error messages here
}
/** close the given function over all arguments,
* using the values from the argument tuple.
* @return a closure object, which can be
* invoked later to yield the
* function result. */
template<typename SIG, typename ARG>
typename _Clo<SIG,ARG>::Type
closure (SIG& f, Tuple<ARG>& args)
{
typedef typename _Fun<SIG>::Ret Ret;
typedef typename _Sig<Ret,ARG>::Type Signature;
typedef typename _Clo<SIG,ARG>::Type Closure;
return Closure (f,args);
}
/** close the given function over the first argument */
template<typename SIG, typename ARG>
typename _PapS<SIG>::Function
applyFirst (SIG& f, ARG arg)
{
typedef typename _PapS<SIG>::Arg ArgType;
typedef Types<ArgType> ArgTypeSeq;
typedef Tuple<ArgTypeSeq> ArgTuple;
ArgTuple val(arg);
return PApply<SIG,ArgTypeSeq>::bindFront (f, val);
}
/** close the given function over the last argument */
template<typename SIG, typename ARG>
typename _PapE<SIG>::Function
applyLast (SIG& f, ARG arg)
{
typedef typename _PapE<SIG>::Arg ArgType;
typedef Types<ArgType> ArgTypeSeq;
typedef Tuple<ArgTypeSeq> ArgTuple;
ArgTuple val(arg);
return PApply<SIG,ArgTypeSeq>::bindBack (f, val);
}
/** build a functor chaining the given functions */
template<typename SIG1, typename SIG2>
typename _Chain<SIG1,SIG2>::Function
chained (SIG1& f1, SIG2& f2)
{
typedef typename _Chain<SIG1,SIG2>::Ret Ret;
return FunctionComposition<SIG1,Ret>::chain (f1, f2);
}
}}} // namespace lumiera::typelist::func
#endif

View file

@ -67,7 +67,7 @@ namespace control {
using lumiera::typelist::FunctionSignature;
using lumiera::typelist::Tuple;
using lumiera::typelist::BuildTupleAccessor;
using lumiera::typelist::TupleApplicator;
using lumiera::typelist::func::TupleApplicator;
using lumiera::typelist::FunErasure;
using lumiera::typelist::StoreFunction;

View file

@ -234,7 +234,7 @@ out: dtor ~TargetObj\(12\) successful
END
TEST "closing function over its arguments" FunctionClosure_test <<END
TEST "functional closure" FunctionClosure_test <<END
out: List1 :-<1>-<2>-<3>-
out: List2 :-<5>-<6>-<7>-
out: Args :-<5>-<9>-

View file

@ -54,7 +54,7 @@ using std::endl;
namespace lumiera {
namespace typelist{
namespace test {
namespace test {
namespace { // test data
@ -87,12 +87,17 @@ namespace test {
int fun3 (int i1, int i2, int i3) { return i1+i2+i3; }
} // (End) test data
using func::Apply;
using func::TupleApplicator;
using func::FunctionClosure;
using func::closure;
using func::apply;
/*************************************************************************
* @test building a function closure for a given function or functor,
* while arguments are passed in as tuple
@ -166,20 +171,20 @@ namespace test {
DUMPVAL (tup2);
DUMPVAL (tup3);
ASSERT (-1 == func::Apply<0>::invoke<int> (fun0, tup0) );
ASSERT (11 == func::Apply<1>::invoke<int> (fun1, tup1) );
ASSERT (11+12 == func::Apply<2>::invoke<int> (fun2, tup2) );
ASSERT (11+12+13 == func::Apply<3>::invoke<int> (fun3, tup3) );
ASSERT (-1 == Apply<0>::invoke<int> (fun0, tup0) );
ASSERT (11 == Apply<1>::invoke<int> (fun1, tup1) );
ASSERT (11+12 == Apply<2>::invoke<int> (fun2, tup2) );
ASSERT (11+12+13 == Apply<3>::invoke<int> (fun3, tup3) );
ASSERT (-1 == TupleApplicator<int()> (tup0) (fun0) );
ASSERT (11 == TupleApplicator<int(int)> (tup1) (fun1) );
ASSERT (11+12 == TupleApplicator<int(int,int)> (tup2) (fun2) );
ASSERT (11+12+13 == TupleApplicator<int(int,int,int)> (tup3) (fun3) );
ASSERT (-1 == func::apply(fun0, tup0) );
ASSERT (11 == func::apply(fun1, tup1) );
ASSERT (11+12 == func::apply(fun2, tup2) );
ASSERT (11+12+13 == func::apply(fun3, tup3) );
ASSERT (-1 == apply(fun0, tup0) );
ASSERT (11 == apply(fun1, tup1) );
ASSERT (11+12 == apply(fun2, tup2) );
ASSERT (11+12+13 == apply(fun3, tup3) );
}
@ -196,20 +201,20 @@ namespace test {
function<int(int,int)> functor2 (fun2);
function<int(int,int,int)> functor3 (fun3);
ASSERT (-1 == func::Apply<0>::invoke<int> (functor0, tup0) );
ASSERT (11 == func::Apply<1>::invoke<int> (functor1, tup1) );
ASSERT (11+12 == func::Apply<2>::invoke<int> (functor2, tup2) );
ASSERT (11+12+13 == func::Apply<3>::invoke<int> (functor3, tup3) );
ASSERT (-1 == Apply<0>::invoke<int> (functor0, tup0) );
ASSERT (11 == Apply<1>::invoke<int> (functor1, tup1) );
ASSERT (11+12 == Apply<2>::invoke<int> (functor2, tup2) );
ASSERT (11+12+13 == Apply<3>::invoke<int> (functor3, tup3) );
ASSERT (-1 == TupleApplicator<int()> (tup0) (functor0) );
ASSERT (11 == TupleApplicator<int(int)> (tup1) (functor1) );
ASSERT (11+12 == TupleApplicator<int(int,int)> (tup2) (functor2) );
ASSERT (11+12+13 == TupleApplicator<int(int,int,int)> (tup3) (functor3) );
ASSERT (-1 == func::apply(functor0, tup0) );
ASSERT (11 == func::apply(functor1, tup1) );
ASSERT (11+12 == func::apply(functor2, tup2) );
ASSERT (11+12+13 == func::apply(functor3, tup3) );
ASSERT (-1 == apply(functor0, tup0) );
ASSERT (11 == apply(functor1, tup1) );
ASSERT (11+12 == apply(functor2, tup2) );
ASSERT (11+12+13 == apply(functor3, tup3) );
}
@ -226,10 +231,10 @@ namespace test {
typedef function<int()> BoundFun;
BoundFun functor0 = func::Apply<0>::bind<BoundFun> (fun0, tup0);
BoundFun functor1 = func::Apply<1>::bind<BoundFun> (fun1, tup1);
BoundFun functor2 = func::Apply<2>::bind<BoundFun> (fun2, tup3);
BoundFun functor3 = func::Apply<3>::bind<BoundFun> (fun3, tup3);
BoundFun functor0 = Apply<0>::bind<BoundFun> (fun0, tup0);
BoundFun functor1 = Apply<1>::bind<BoundFun> (fun1, tup1);
BoundFun functor2 = Apply<2>::bind<BoundFun> (fun2, tup3);
BoundFun functor3 = Apply<3>::bind<BoundFun> (fun3, tup3);
ASSERT (-1 == functor0() );
ASSERT (11 == functor1() );
@ -263,10 +268,10 @@ namespace test {
typedef function<int()> BoundFun;
BoundFun functor0 = func::Apply<0>::bind<BoundFun> (unbound_functor0, tup0);
BoundFun functor1 = func::Apply<1>::bind<BoundFun> (unbound_functor1, tup1);
BoundFun functor2 = func::Apply<2>::bind<BoundFun> (unbound_functor2, tup3);
BoundFun functor3 = func::Apply<3>::bind<BoundFun> (unbound_functor3, tup3);
BoundFun functor0 = Apply<0>::bind<BoundFun> (unbound_functor0, tup0);
BoundFun functor1 = Apply<1>::bind<BoundFun> (unbound_functor1, tup1);
BoundFun functor2 = Apply<2>::bind<BoundFun> (unbound_functor2, tup3);
BoundFun functor3 = Apply<3>::bind<BoundFun> (unbound_functor3, tup3);
ASSERT (-1 == functor0() );
ASSERT (11 == functor1() );
@ -319,15 +324,15 @@ namespace test {
ASSERT (11+12 == clo2() );
ASSERT (11+12+13 == clo3() );
ASSERT (-1 == func::closure(fun0,tup0) () );
ASSERT (11 == func::closure(fun1,tup1) () );
ASSERT (11+12 == func::closure(fun2,tup2) () );
ASSERT (11+12+13 == func::closure(fun3,tup3) () );
ASSERT (-1 == closure(fun0,tup0) () );
ASSERT (11 == closure(fun1,tup1) () );
ASSERT (11+12 == closure(fun2,tup2) () );
ASSERT (11+12+13 == closure(fun3,tup3) () );
ASSERT (-1 == func::closure(unbound_functor0,tup0) () );
ASSERT (11 == func::closure(unbound_functor1,tup1) () );
ASSERT (11+12 == func::closure(unbound_functor2,tup2) () );
ASSERT (11+12+13 == func::closure(unbound_functor3,tup3) () );
ASSERT (-1 == closure(unbound_functor0,tup0) () );
ASSERT (11 == closure(unbound_functor1,tup1) () );
ASSERT (11+12 == closure(unbound_functor2,tup2) () );
ASSERT (11+12+13 == closure(unbound_functor3,tup3) () );
// finally combine all techniques....

View file

@ -28,35 +28,19 @@
#include "lib/meta/function-closure.hpp"
#include "meta/typelist-diagnostics.hpp"
#include <iostream>
using ::test::Test;
using std::string;
using std::cout;
using std::endl;
namespace lumiera {
namespace typelist{
namespace test {
namespace test {
using ::test::Test;
using func::applyFirst;
using func::applyLast;
using func::PApply;
namespace { // test functions
typedef Types< Num<1> ////////////////////////TODO kill kill kill
, Num<2>
, Num<3>
>::List List1;
typedef Types< Num<5>
, Num<6>
, Num<7>
>::List List2;
Num<1> _1_;
Num<2> _2_;
Num<3> _3_;