clean-up: simplify function-closure -- can now remove obsoleted impl
A lot of repetitive, pre C++11 metaprogramming code can now be removed, and several helper constructs, which were needed to handle generic function application and passing a tuple of values to create a binder. Note however, the highly complex and technical core of this header still remains intact; which is to create a ''partial closure'' over some arguments of a function, while keeping the remaining arguments open as parameters for invocation. TODO: Even in the remaining code there is a lot of redundancy and helper construct which are no longer necessary
This commit is contained in:
parent
738d9e5b67
commit
f6f8220fbe
5 changed files with 52 additions and 449 deletions
|
|
@ -33,12 +33,6 @@
|
|||
** @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
|
||||
** @todo 11/23 these functor-utils were written at a time when support for handling
|
||||
** generic functions in C++ was woefully inadequate; at that time, we neither
|
||||
** had Lambda-support in the language, nor the ability to use variadic arguments.
|
||||
** Providing a one-shot function-style interface for this kind of manipulations
|
||||
** is still considered beneficial, and thus we should gradually modernise
|
||||
** the tools we want to retain...
|
||||
** @todo 2/25 note that there is a bind_front in C++20 and C++23 will provide a bind_back
|
||||
** helper, which would provide the implementation fully in accordance with current
|
||||
** expectations (including move, constexpr); if we choose to retain a generic
|
||||
|
|
@ -83,191 +77,6 @@ namespace func{
|
|||
|
||||
namespace { // helpers for binding and applying a function to an argument tuple
|
||||
|
||||
using std::get;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @todo 2/2025 should be replaced by a single variadic template, and
|
||||
* implemented using std::apply. Note also that std::bind would
|
||||
* support perfect-forwarding, especially also for the functor;
|
||||
* the latter would allow to use move-only functors.
|
||||
*/
|
||||
template<uint n>
|
||||
struct Apply;
|
||||
|
||||
|
||||
template<> //__________________________________
|
||||
struct Apply<0> ///< Apply function without Arguments
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP&)
|
||||
{
|
||||
return std::bind (f);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<1> ///< Apply function with 1 Argument
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP & arg)
|
||||
{
|
||||
return std::bind (f, get<0>(arg));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<2> ///< Apply function with 2 Arguments
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP & arg)
|
||||
{
|
||||
return std::bind (f, get<0>(arg)
|
||||
, get<1>(arg)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<3> ///< Apply function with 3 Arguments
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP & arg)
|
||||
{
|
||||
return std::bind (f, get<0>(arg)
|
||||
, get<1>(arg)
|
||||
, get<2>(arg)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<4> ///< Apply function with 4 Arguments
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP & arg)
|
||||
{
|
||||
return std::bind (f, get<0>(arg)
|
||||
, get<1>(arg)
|
||||
, get<2>(arg)
|
||||
, get<3>(arg)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<5> ///< Apply function with 5 Arguments
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP & arg)
|
||||
{
|
||||
return std::bind (f, get<0>(arg)
|
||||
, get<1>(arg)
|
||||
, get<2>(arg)
|
||||
, get<3>(arg)
|
||||
, get<4>(arg)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<6> ///< Apply function with 6 Arguments
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP & arg)
|
||||
{
|
||||
return std::bind (f, get<0>(arg)
|
||||
, get<1>(arg)
|
||||
, get<2>(arg)
|
||||
, get<3>(arg)
|
||||
, get<4>(arg)
|
||||
, get<5>(arg)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<7> ///< Apply function with 7 Arguments
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP & arg)
|
||||
{
|
||||
return std::bind (f, get<0>(arg)
|
||||
, get<1>(arg)
|
||||
, get<2>(arg)
|
||||
, get<3>(arg)
|
||||
, get<4>(arg)
|
||||
, get<5>(arg)
|
||||
, get<6>(arg)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<8> ///< Apply function with 8 Arguments
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP & arg)
|
||||
{
|
||||
return std::bind (f, get<0>(arg)
|
||||
, get<1>(arg)
|
||||
, get<2>(arg)
|
||||
, get<3>(arg)
|
||||
, get<4>(arg)
|
||||
, get<5>(arg)
|
||||
, get<6>(arg)
|
||||
, get<7>(arg)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<9> ///< Apply function with 9 Arguments
|
||||
{
|
||||
template<typename RET, class FUN, class TUP>
|
||||
static RET
|
||||
bind (FUN& f, TUP & arg)
|
||||
{
|
||||
return std::bind (f, get<0>(arg)
|
||||
, get<1>(arg)
|
||||
, get<2>(arg)
|
||||
, get<3>(arg)
|
||||
, get<4>(arg)
|
||||
, get<5>(arg)
|
||||
, get<6>(arg)
|
||||
, get<7>(arg)
|
||||
, get<8>(arg)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ===== Helpers for partial function application ===== */
|
||||
|
||||
/** @note relying on the implementation type
|
||||
* since we need to _build_ placeholders */
|
||||
using std::_Placeholder;
|
||||
|
|
@ -371,47 +180,23 @@ namespace func{
|
|||
|
||||
|
||||
|
||||
|
||||
/* ======= core operations: closures and partial application ========= */
|
||||
|
||||
/**
|
||||
* Closure-creating template.
|
||||
* The instance is linked (reference) to a given concrete argument tuple.
|
||||
* A functor with a matching signature may then either be _closed_ over
|
||||
* this argument values, or even be invoked right away with theses arguments.
|
||||
* @warning we take functor objects _and parameters_ by reference
|
||||
* Base technique: build a binder with arguments from a tuple.
|
||||
* @remark based on the apply-λ-trick by David Vandervoorde
|
||||
* to unpack the tuple elements as argument pack
|
||||
* @note both the functor and the arguments can be passed
|
||||
* by _perfect forwarding_, yet both will be **copied**
|
||||
* into the resulting binder
|
||||
* @param fun anything »invocable«
|
||||
* @param tuple a suitable set of arguments, or std binding placeholders
|
||||
* @return a _binder functor_, as generated by `std::bind`; all arguments
|
||||
* supplied with explicitly given values will be _closed_, while
|
||||
* argument positions marked with `std::_Placeholder<N>` instances
|
||||
* will remain _open_ to accept arguments on the resulting function.
|
||||
*/
|
||||
template<typename SIG>
|
||||
class TupleApplicator
|
||||
{
|
||||
using Args = typename _Fun<SIG>::Args;
|
||||
using Ret = typename _Fun<SIG>::Ret;
|
||||
|
||||
using BoundFunc = function<Ret()>;
|
||||
|
||||
enum { ARG_CNT = count<typename Args::List>() };
|
||||
|
||||
|
||||
/** storing a ref to the parameter tuple */
|
||||
Tuple<Args>& params_;
|
||||
|
||||
public:
|
||||
TupleApplicator (Tuple<Args>& args)
|
||||
: params_(args)
|
||||
{ }
|
||||
|
||||
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_); }
|
||||
|
||||
template<class FUN>
|
||||
Ret
|
||||
operator() (FUN&& f)
|
||||
{
|
||||
ASSERT_VALID_SIGNATURE (FUN,SIG);
|
||||
return std::apply (forward<FUN> (f), params_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class FUN, class TUP, typename = enable_if_Tuple<TUP>>
|
||||
auto
|
||||
bindArgTuple (FUN&& fun, TUP&& tuple)
|
||||
|
|
@ -427,37 +212,6 @@ namespace func{
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* Closing a function over its arguments.
|
||||
* This is a small usage example or spin-off,
|
||||
* having almost the same effect than invoking `std::bind()`.
|
||||
* The notable difference is that the function arguments for
|
||||
* creating the closure are passed in as one tuple compound.
|
||||
*/
|
||||
template<typename SIG>
|
||||
class FunctionClosure
|
||||
{
|
||||
typedef typename _Fun<SIG>::Args Args;
|
||||
typedef typename _Fun<SIG>::Ret Ret;
|
||||
|
||||
function<Ret(void)> closure_;
|
||||
|
||||
public:
|
||||
FunctionClosure (SIG& f, Tuple<Args>& args)
|
||||
: closure_{bindArgTuple (f, args)}
|
||||
{ }
|
||||
FunctionClosure (function<SIG> const& f, Tuple<Args>& args)
|
||||
: closure_{bindArgTuple (f, args)}
|
||||
{ }
|
||||
|
||||
Ret operator() () { return closure_(); }
|
||||
|
||||
typedef Ret result_type; ///< for STL use
|
||||
typedef void argument_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Partial function application
|
||||
|
|
@ -638,14 +392,6 @@ namespace func{
|
|||
using util::unConst;
|
||||
|
||||
|
||||
template<typename SIG, typename ARG>
|
||||
struct _Clo
|
||||
{
|
||||
using Ret = typename _Fun<SIG>::Ret;
|
||||
using Signature = typename BuildFunType<Ret, ARG>::Sig;
|
||||
using Type = FunctionClosure<Signature>;
|
||||
};
|
||||
|
||||
template<typename FUN1, typename FUN2>
|
||||
struct _Chain
|
||||
{
|
||||
|
|
@ -744,21 +490,6 @@ namespace func{
|
|||
|
||||
/* ========== function-style interface ============= */
|
||||
|
||||
/** 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>
|
||||
inline
|
||||
typename _Clo<SIG,TySeq<ARG...>>::Type
|
||||
closure (SIG& f, std::tuple<ARG...>& args)
|
||||
{
|
||||
using Closure = typename _Clo<SIG,TySeq<ARG...>>::Type;
|
||||
return Closure (f,args);
|
||||
}
|
||||
|
||||
|
||||
/** close the given function over the first argument.
|
||||
* @warning never tie an ownership-managing object by-value! */
|
||||
template<typename FUN, typename ARG>
|
||||
|
|
|
|||
|
|
@ -109,13 +109,11 @@ out-lit: List2 :-<5>-<6>-<7>-
|
|||
out-lit: Args :-<5>-<9>-
|
||||
out-lit: NewArgs :-<1>-<5>-<9>-
|
||||
out-lit: :
|
||||
out-lit: : ---Apply---
|
||||
out-lit: : ---Bind----
|
||||
out-lit: tup0 :«tuple<>»──()
|
||||
out-lit: tup1 :«tuple<int>»──(11)
|
||||
out-lit: tup2 :«tuple<int, int>»──(11,12)
|
||||
out-lit: tup3 :«tuple<int, int, int>»──(11,12,13)
|
||||
out-lit: :
|
||||
out-lit: : ---Bind----
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -50,16 +50,8 @@ namespace test {
|
|||
|
||||
namespace { // test data
|
||||
|
||||
|
||||
|
||||
typedef TySeq< Num<1>
|
||||
, Num<2>
|
||||
, Num<3>
|
||||
>::List List1;
|
||||
typedef TySeq< Num<5>
|
||||
, Num<6>
|
||||
, Num<7>
|
||||
>::List List2;
|
||||
using List1 = TySeq<Num<1>, Num<2>, Num<3> >::List;
|
||||
using List2 = TySeq<Num<5>, Num<6>, Num<7> >::List;
|
||||
|
||||
|
||||
/** special test fun
|
||||
|
|
@ -82,24 +74,24 @@ namespace test {
|
|||
|
||||
|
||||
|
||||
using func::Apply;
|
||||
using func::TupleApplicator;
|
||||
using func::bindArgTuple;
|
||||
using func::FunctionClosure;
|
||||
using func::closure;
|
||||
|
||||
|
||||
/*********************************************************************//**
|
||||
* @test building a function closure for a given function or functor,
|
||||
* while arguments are passed in as tuple
|
||||
* - accessing signatures as typelists
|
||||
* - apply free function to tuple
|
||||
* - apply functor to tuple
|
||||
* - bind free function to tuple
|
||||
* - bind functor to tuple
|
||||
* - build a simple "tuple closure"
|
||||
* @remark this test is _rather low-level_ and documents the construction
|
||||
* of the implementation
|
||||
* of the implementation; furthermore, most of this construction
|
||||
* was obsoleted by newer language features, notably std::apply
|
||||
* and the technique to unpack variadic-λ arguments.
|
||||
* What remains, is now largely a definition how to handle
|
||||
* function argument list signatures, to build suitable
|
||||
* argument tuple types by metaprogramming, and finally
|
||||
* to pass them to construct a binder.
|
||||
* @see function-composition-test.cpp (advanced features like partial application)
|
||||
*/
|
||||
class FunctionClosure_test : public Test
|
||||
{
|
||||
|
|
@ -108,11 +100,8 @@ namespace test {
|
|||
{
|
||||
verify_setup();
|
||||
check_signatureTypeManip();
|
||||
check_applyFree();
|
||||
check_applyFunc();
|
||||
check_bindFree();
|
||||
check_bindFunc();
|
||||
build_closure();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -150,56 +139,6 @@ namespace test {
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
check_applyFree ()
|
||||
{
|
||||
cout << "\t:\n\t: ---Apply---\n";
|
||||
|
||||
Tuple<TySeq<>> tup0 ;
|
||||
Tuple<TySeq<int>> tup1 (11);
|
||||
Tuple<TySeq<int,int>> tup2 (11,12);
|
||||
Tuple<TySeq<int,int,int>> tup3 (11,12,13);
|
||||
DUMPVAL (tup0);
|
||||
DUMPVAL (tup1);
|
||||
DUMPVAL (tup2);
|
||||
DUMPVAL (tup3);
|
||||
|
||||
CHECK (-1 == TupleApplicator<int()> (tup0) (fun0) );
|
||||
CHECK (11 == TupleApplicator<int(int)> (tup1) (fun1) );
|
||||
CHECK (11+12 == TupleApplicator<int(int,int)> (tup2) (fun2) );
|
||||
CHECK (11+12+13 == TupleApplicator<int(int,int,int)> (tup3) (fun3) );
|
||||
|
||||
CHECK (-1 == std::apply(fun0, tup0) );
|
||||
CHECK (11 == std::apply(fun1, tup1) );
|
||||
CHECK (11+12 == std::apply(fun2, tup2) );
|
||||
CHECK (11+12+13 == std::apply(fun3, tup3) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
check_applyFunc ()
|
||||
{
|
||||
Tuple<TySeq<>> tup0 ;
|
||||
Tuple<TySeq<int>> tup1 (11);
|
||||
Tuple<TySeq<int,int>> tup2 (11,12);
|
||||
Tuple<TySeq<int,int,int>> tup3 (11,12,13);
|
||||
function<int()> functor0 (fun0);
|
||||
function<int(int)> functor1 (fun1);
|
||||
function<int(int,int)> functor2 (fun2);
|
||||
function<int(int,int,int)> functor3 (fun3);
|
||||
|
||||
CHECK (-1 == TupleApplicator<int()> (tup0) (functor0) );
|
||||
CHECK (11 == TupleApplicator<int(int)> (tup1) (functor1) );
|
||||
CHECK (11+12 == TupleApplicator<int(int,int)> (tup2) (functor2) );
|
||||
CHECK (11+12+13 == TupleApplicator<int(int,int,int)> (tup3) (functor3) );
|
||||
|
||||
CHECK (-1 == std::apply(functor0, tup0) );
|
||||
CHECK (11 == std::apply(functor1, tup1) );
|
||||
CHECK (11+12 == std::apply(functor2, tup2) );
|
||||
CHECK (11+12+13 == std::apply(functor3, tup3) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
check_bindFree ()
|
||||
{
|
||||
|
|
@ -214,22 +153,12 @@ namespace test {
|
|||
DUMPVAL (tup2);
|
||||
DUMPVAL (tup3);
|
||||
|
||||
typedef function<int()> BoundFun;
|
||||
using BoundFun = function<int()>;
|
||||
|
||||
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);
|
||||
|
||||
CHECK (-1 == functor0() );
|
||||
CHECK (11 == functor1() );
|
||||
CHECK (11+12 == functor2() );
|
||||
CHECK (11+12+13 == functor3() );
|
||||
|
||||
functor0 = bindArgTuple (fun0, tup0);
|
||||
functor1 = bindArgTuple (fun1, tup1);
|
||||
functor2 = bindArgTuple (fun2, tup2);
|
||||
functor3 = bindArgTuple (fun3, tup3);
|
||||
BoundFun functor0 = bindArgTuple (fun0, tup0);
|
||||
BoundFun functor1 = bindArgTuple (fun1, tup1);
|
||||
BoundFun functor2 = bindArgTuple (fun2, tup2);
|
||||
BoundFun functor3 = bindArgTuple (fun3, tup3);
|
||||
|
||||
CHECK (-1 == functor0() );
|
||||
CHECK (11 == functor1() );
|
||||
|
|
@ -251,84 +180,18 @@ namespace test {
|
|||
function<int(int,int)> unbound_functor2 (fun2);
|
||||
function<int(int,int,int)> unbound_functor3 (fun3);
|
||||
|
||||
typedef function<int()> BoundFun;
|
||||
using BoundFun = function<int()>;
|
||||
|
||||
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);
|
||||
BoundFun functor0 = bindArgTuple (unbound_functor0, tup0);
|
||||
BoundFun functor1 = bindArgTuple (unbound_functor1, tup1);
|
||||
BoundFun functor2 = bindArgTuple (unbound_functor2, tup2);
|
||||
BoundFun functor3 = bindArgTuple (unbound_functor3, tup3);
|
||||
|
||||
CHECK (-1 == functor0() );
|
||||
CHECK (11 == functor1() );
|
||||
CHECK (11+12 == functor2() );
|
||||
CHECK (11+12+13 == functor3() );
|
||||
|
||||
functor0 = bindArgTuple (unbound_functor0, tup0);
|
||||
functor1 = bindArgTuple (unbound_functor1, tup1);
|
||||
functor2 = bindArgTuple (unbound_functor2, tup2);
|
||||
functor3 = bindArgTuple (unbound_functor3, tup3);
|
||||
|
||||
CHECK (-1 == functor0() );
|
||||
CHECK (11 == functor1() );
|
||||
CHECK (11+12 == functor2() );
|
||||
CHECK (11+12+13 == functor3() );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
build_closure ()
|
||||
{
|
||||
Tuple<TySeq<>> tup0 ;
|
||||
Tuple<TySeq<int>> tup1 (11);
|
||||
Tuple<TySeq<int,int>> tup2 (11,12);
|
||||
Tuple<TySeq<int,int,int>> tup3 (11,12,13);
|
||||
|
||||
FunctionClosure<int()> clo0 (fun0,tup0);
|
||||
FunctionClosure<int(int)> clo1 (fun1,tup1);
|
||||
FunctionClosure<int(int,int)> clo2 (fun2,tup2);
|
||||
FunctionClosure<int(int,int,int)> clo3 (fun3,tup3);
|
||||
|
||||
CHECK (-1 == clo0() );
|
||||
CHECK (11 == clo1() );
|
||||
CHECK (11+12 == clo2() );
|
||||
CHECK (11+12+13 == clo3() );
|
||||
|
||||
function<int()> unbound_functor0 (fun0);
|
||||
function<int(int)> unbound_functor1 (fun1);
|
||||
function<int(int,int)> unbound_functor2 (fun2);
|
||||
function<int(int,int,int)> unbound_functor3 (fun3);
|
||||
|
||||
clo0 = FunctionClosure<int()> (unbound_functor0,tup0);
|
||||
clo1 = FunctionClosure<int(int)> (unbound_functor1,tup1);
|
||||
clo2 = FunctionClosure<int(int,int)> (unbound_functor2,tup2);
|
||||
clo3 = FunctionClosure<int(int,int,int)> (unbound_functor3,tup3);
|
||||
|
||||
CHECK (-1 == clo0() );
|
||||
CHECK (11 == clo1() );
|
||||
CHECK (11+12 == clo2() );
|
||||
CHECK (11+12+13 == clo3() );
|
||||
|
||||
CHECK (-1 == closure(fun0,tup0) () );
|
||||
CHECK (11 == closure(fun1,tup1) () );
|
||||
CHECK (11+12 == closure(fun2,tup2) () );
|
||||
CHECK (11+12+13 == closure(fun3,tup3) () );
|
||||
|
||||
CHECK (-1 == closure(unbound_functor0,tup0) () );
|
||||
CHECK (11 == closure(unbound_functor1,tup1) () );
|
||||
CHECK (11+12 == closure(unbound_functor2,tup2) () );
|
||||
CHECK (11+12+13 == closure(unbound_functor3,tup3) () );
|
||||
|
||||
|
||||
// finally combine all techniques....
|
||||
using NumberzArg = TySeq<List2>::Seq;
|
||||
using NumberzSig = BuildFunType<int,NumberzArg>::Sig;
|
||||
|
||||
Tuple<NumberzArg> numberzTup (Num<5>(22), Num<6>(33), Num<7>(44));
|
||||
|
||||
FunctionClosure<NumberzSig> numClo (getNumberz<5,6,7>, numberzTup );
|
||||
|
||||
CHECK (22+33+44 == numClo() );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace meta {
|
|||
namespace test {
|
||||
|
||||
using ::test::Test;
|
||||
// using lib::test::showType;
|
||||
using lib::test::showType;
|
||||
using lib::meta::_Fun;
|
||||
using func::applyFirst;
|
||||
using func::applyLast;
|
||||
|
|
@ -236,7 +236,6 @@ namespace test {
|
|||
|
||||
// Version4: as you'd typically do it in real life-------- //
|
||||
|
||||
/*
|
||||
fun_23 = func::applyFirst (f, Num<1>(18)); // use the convenience function API to close over a single value
|
||||
|
||||
int r5 = fun_23(_2_,_3_).o_; // invoke the resulting functor...
|
||||
|
|
@ -276,7 +275,6 @@ namespace test {
|
|||
CHECK ( 7+6+5 == (func::applyFirst( fun13<7,6,5>, _7_ ) (_6_,_5_)).o_);
|
||||
CHECK ( 6+5 == (func::applyFirst( fun12<6,5>, _6_ ) (_5_)).o_);
|
||||
CHECK ( 5 == (func::applyFirst( fun11<5>, _5_ ) ( )).o_);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
|
@ -403,9 +401,9 @@ namespace test {
|
|||
using SigC = _Fun<decltype(chain)>::Sig;
|
||||
using SigP = _Fun<decltype(pappl)>::Sig;
|
||||
|
||||
// CHECK (showType<Sig1>() == "double (float&, int&, long)"_expect);
|
||||
// CHECK (showType<SigC>() == "long (float&, int&, long)"_expect);
|
||||
// CHECK (showType<SigP>() == "double (int&, long)"_expect);
|
||||
CHECK (showType<Sig1>() == "double (float&, int&, long)"_expect);
|
||||
CHECK (showType<SigC>() == "long (float&, int&, long)"_expect);
|
||||
CHECK (showType<SigP>() == "double (int&, long)"_expect);
|
||||
|
||||
CHECK (220 == f1 (ff,ii,33));
|
||||
CHECK (220 == chain(ff,ii,33));
|
||||
|
|
|
|||
|
|
@ -164414,7 +164414,8 @@ Since then others have made contributions, see the log for the history.</font></
|
|||
<linktarget COLOR="#5d38bc" DESTINATION="ID_667556429" ENDARROW="Default" ENDINCLINATION="23;-31;" ID="Arrow_ID_1911198692" SOURCE="ID_1090818949" STARTARROW="None" STARTINCLINATION="-163;8;"/>
|
||||
</node>
|
||||
<node CREATED="1749081571461" ID="ID_1222760176" MODIFIED="1749081586647" TEXT="dann Verwendungen des TupleApplicators eliminieren"/>
|
||||
<node CREATED="1749082302350" ID="ID_1914498797" MODIFIED="1749082308154" TEXT="BindToArgument umstellen">
|
||||
<node COLOR="#338800" CREATED="1749082302350" FOLDED="true" ID="ID_1914498797" MODIFIED="1749141642747" TEXT="BindToArgument umstellen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1749082310090" ID="ID_618843730" MODIFIED="1749082348031" TEXT="Problem: out-of-bounds Index jetzt anders behandelt">
|
||||
<node CREATED="1749082386028" ID="ID_1571223641" MODIFIED="1749082388299" TEXT="bisher...">
|
||||
<node CREATED="1749082348881" ID="ID_1539878278" MODIFIED="1749082385036" TEXT="es wurde Apply<ARG_CNT> ausgewählt"/>
|
||||
|
|
@ -164675,9 +164676,21 @@ Since then others have made contributions, see the log for the history.</font></
|
|||
<node COLOR="#435e98" CREATED="1749081613141" ID="ID_126616986" MODIFIED="1749081621876" TEXT="FunctionComposition_test"/>
|
||||
<node COLOR="#435e98" CREATED="1749081619255" ID="ID_945095728" MODIFIED="1749081621876" TEXT="TupleClosure_test"/>
|
||||
</node>
|
||||
<node CREATED="1749141651868" ID="ID_1929986459" MODIFIED="1749141664903" TEXT="Hilfskonstrukte entfernen">
|
||||
<node CREATED="1749141665773" ID="ID_1270373632" MODIFIED="1749141670880" TEXT="Apply-Spezialisierungen"/>
|
||||
<node CREATED="1749141689698" ID="ID_865992669" MODIFIED="1749141693005" TEXT="TupleApplicator"/>
|
||||
<node CREATED="1749141693742" ID="ID_1131353514" MODIFIED="1749141699732" TEXT="FunctionClosure"/>
|
||||
<node CREATED="1749141700512" ID="ID_10137882" MODIFIED="1749141707469" TEXT="func::closure()"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1749142101434" ID="ID_1381240660" MODIFIED="1749142108466" TEXT="verbleibende Konstrukte">
|
||||
<node CREATED="1749142116785" ID="ID_1310351984" MODIFIED="1749142126238" TEXT="func::bindArgTuple"/>
|
||||
<node CREATED="1749142164570" ID="ID_779039468" MODIFIED="1749142166210" TEXT="func::bindLast"/>
|
||||
<node CREATED="1749142129186" ID="ID_1530717251" MODIFIED="1749142133129" TEXT="func::chained"/>
|
||||
<node CREATED="1749142208397" ID="ID_1965271283" MODIFIED="1749142210078" TEXT="func::PApply"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1748829133428" ID="ID_266502224" MODIFIED="1748884086384" TEXT="Tuple">
|
||||
|
|
|
|||
Loading…
Reference in a new issue