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,
|
** @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
|
** but currently we need just one argument, thus only this case was wrapped
|
||||||
** up into a convenient functions func::applyFirst and func::applyLast
|
** 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
|
** @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
|
** helper, which would provide the implementation fully in accordance with current
|
||||||
** expectations (including move, constexpr); if we choose to retain a generic
|
** 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
|
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
|
/** @note relying on the implementation type
|
||||||
* since we need to _build_ placeholders */
|
* since we need to _build_ placeholders */
|
||||||
using std::_Placeholder;
|
using std::_Placeholder;
|
||||||
|
|
@ -371,47 +180,23 @@ namespace func{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ======= core operations: closures and partial application ========= */
|
/* ======= core operations: closures and partial application ========= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closure-creating template.
|
* Base technique: build a binder with arguments from a tuple.
|
||||||
* The instance is linked (reference) to a given concrete argument tuple.
|
* @remark based on the apply-λ-trick by David Vandervoorde
|
||||||
* A functor with a matching signature may then either be _closed_ over
|
* to unpack the tuple elements as argument pack
|
||||||
* this argument values, or even be invoked right away with theses arguments.
|
* @note both the functor and the arguments can be passed
|
||||||
* @warning we take functor objects _and parameters_ by reference
|
* 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>>
|
template<class FUN, class TUP, typename = enable_if_Tuple<TUP>>
|
||||||
auto
|
auto
|
||||||
bindArgTuple (FUN&& fun, TUP&& tuple)
|
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
|
* Partial function application
|
||||||
|
|
@ -638,14 +392,6 @@ namespace func{
|
||||||
using util::unConst;
|
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>
|
template<typename FUN1, typename FUN2>
|
||||||
struct _Chain
|
struct _Chain
|
||||||
{
|
{
|
||||||
|
|
@ -744,21 +490,6 @@ namespace func{
|
||||||
|
|
||||||
/* ========== function-style interface ============= */
|
/* ========== 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.
|
/** close the given function over the first argument.
|
||||||
* @warning never tie an ownership-managing object by-value! */
|
* @warning never tie an ownership-managing object by-value! */
|
||||||
template<typename FUN, typename ARG>
|
template<typename FUN, typename ARG>
|
||||||
|
|
|
||||||
|
|
@ -109,13 +109,11 @@ out-lit: List2 :-<5>-<6>-<7>-
|
||||||
out-lit: Args :-<5>-<9>-
|
out-lit: Args :-<5>-<9>-
|
||||||
out-lit: NewArgs :-<1>-<5>-<9>-
|
out-lit: NewArgs :-<1>-<5>-<9>-
|
||||||
out-lit: :
|
out-lit: :
|
||||||
out-lit: : ---Apply---
|
out-lit: : ---Bind----
|
||||||
out-lit: tup0 :«tuple<>»──()
|
out-lit: tup0 :«tuple<>»──()
|
||||||
out-lit: tup1 :«tuple<int>»──(11)
|
out-lit: tup1 :«tuple<int>»──(11)
|
||||||
out-lit: tup2 :«tuple<int, int>»──(11,12)
|
out-lit: tup2 :«tuple<int, int>»──(11,12)
|
||||||
out-lit: tup3 :«tuple<int, int, int>»──(11,12,13)
|
out-lit: tup3 :«tuple<int, int, int>»──(11,12,13)
|
||||||
out-lit: :
|
|
||||||
out-lit: : ---Bind----
|
|
||||||
return: 0
|
return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,16 +50,8 @@ namespace test {
|
||||||
|
|
||||||
namespace { // test data
|
namespace { // test data
|
||||||
|
|
||||||
|
using List1 = TySeq<Num<1>, Num<2>, Num<3> >::List;
|
||||||
|
using List2 = TySeq<Num<5>, Num<6>, Num<7> >::List;
|
||||||
typedef TySeq< Num<1>
|
|
||||||
, Num<2>
|
|
||||||
, Num<3>
|
|
||||||
>::List List1;
|
|
||||||
typedef TySeq< Num<5>
|
|
||||||
, Num<6>
|
|
||||||
, Num<7>
|
|
||||||
>::List List2;
|
|
||||||
|
|
||||||
|
|
||||||
/** special test fun
|
/** special test fun
|
||||||
|
|
@ -82,24 +74,24 @@ namespace test {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using func::Apply;
|
|
||||||
using func::TupleApplicator;
|
|
||||||
using func::bindArgTuple;
|
using func::bindArgTuple;
|
||||||
using func::FunctionClosure;
|
|
||||||
using func::closure;
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
* @test building a function closure for a given function or functor,
|
* @test building a function closure for a given function or functor,
|
||||||
* while arguments are passed in as tuple
|
* while arguments are passed in as tuple
|
||||||
* - accessing signatures as typelists
|
* - accessing signatures as typelists
|
||||||
* - apply free function to tuple
|
|
||||||
* - apply functor to tuple
|
|
||||||
* - bind free function to tuple
|
* - bind free function to tuple
|
||||||
* - bind functor to tuple
|
* - bind functor to tuple
|
||||||
* - build a simple "tuple closure"
|
|
||||||
* @remark this test is _rather low-level_ and documents the construction
|
* @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
|
class FunctionClosure_test : public Test
|
||||||
{
|
{
|
||||||
|
|
@ -108,11 +100,8 @@ namespace test {
|
||||||
{
|
{
|
||||||
verify_setup();
|
verify_setup();
|
||||||
check_signatureTypeManip();
|
check_signatureTypeManip();
|
||||||
check_applyFree();
|
|
||||||
check_applyFunc();
|
|
||||||
check_bindFree();
|
check_bindFree();
|
||||||
check_bindFunc();
|
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
|
void
|
||||||
check_bindFree ()
|
check_bindFree ()
|
||||||
{
|
{
|
||||||
|
|
@ -214,22 +153,12 @@ namespace test {
|
||||||
DUMPVAL (tup2);
|
DUMPVAL (tup2);
|
||||||
DUMPVAL (tup3);
|
DUMPVAL (tup3);
|
||||||
|
|
||||||
typedef function<int()> BoundFun;
|
using BoundFun = function<int()>;
|
||||||
|
|
||||||
BoundFun functor0 = Apply<0>::bind<BoundFun> (fun0, tup0);
|
BoundFun functor0 = bindArgTuple (fun0, tup0);
|
||||||
BoundFun functor1 = Apply<1>::bind<BoundFun> (fun1, tup1);
|
BoundFun functor1 = bindArgTuple (fun1, tup1);
|
||||||
BoundFun functor2 = Apply<2>::bind<BoundFun> (fun2, tup3);
|
BoundFun functor2 = bindArgTuple (fun2, tup2);
|
||||||
BoundFun functor3 = Apply<3>::bind<BoundFun> (fun3, tup3);
|
BoundFun functor3 = bindArgTuple (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);
|
|
||||||
|
|
||||||
CHECK (-1 == functor0() );
|
CHECK (-1 == functor0() );
|
||||||
CHECK (11 == functor1() );
|
CHECK (11 == functor1() );
|
||||||
|
|
@ -251,84 +180,18 @@ namespace test {
|
||||||
function<int(int,int)> unbound_functor2 (fun2);
|
function<int(int,int)> unbound_functor2 (fun2);
|
||||||
function<int(int,int,int)> unbound_functor3 (fun3);
|
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 functor0 = bindArgTuple (unbound_functor0, tup0);
|
||||||
BoundFun functor1 = Apply<1>::bind<BoundFun> (unbound_functor1, tup1);
|
BoundFun functor1 = bindArgTuple (unbound_functor1, tup1);
|
||||||
BoundFun functor2 = Apply<2>::bind<BoundFun> (unbound_functor2, tup3);
|
BoundFun functor2 = bindArgTuple (unbound_functor2, tup2);
|
||||||
BoundFun functor3 = Apply<3>::bind<BoundFun> (unbound_functor3, tup3);
|
BoundFun functor3 = bindArgTuple (unbound_functor3, tup3);
|
||||||
|
|
||||||
CHECK (-1 == functor0() );
|
CHECK (-1 == functor0() );
|
||||||
CHECK (11 == functor1() );
|
CHECK (11 == functor1() );
|
||||||
CHECK (11+12 == functor2() );
|
CHECK (11+12 == functor2() );
|
||||||
CHECK (11+12+13 == functor3() );
|
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 {
|
namespace test {
|
||||||
|
|
||||||
using ::test::Test;
|
using ::test::Test;
|
||||||
// using lib::test::showType;
|
using lib::test::showType;
|
||||||
using lib::meta::_Fun;
|
using lib::meta::_Fun;
|
||||||
using func::applyFirst;
|
using func::applyFirst;
|
||||||
using func::applyLast;
|
using func::applyLast;
|
||||||
|
|
@ -236,7 +236,6 @@ namespace test {
|
||||||
|
|
||||||
// Version4: as you'd typically do it in real life-------- //
|
// 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
|
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...
|
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 ( 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 ( 6+5 == (func::applyFirst( fun12<6,5>, _6_ ) (_5_)).o_);
|
||||||
CHECK ( 5 == (func::applyFirst( fun11<5>, _5_ ) ( )).o_);
|
CHECK ( 5 == (func::applyFirst( fun11<5>, _5_ ) ( )).o_);
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -403,9 +401,9 @@ namespace test {
|
||||||
using SigC = _Fun<decltype(chain)>::Sig;
|
using SigC = _Fun<decltype(chain)>::Sig;
|
||||||
using SigP = _Fun<decltype(pappl)>::Sig;
|
using SigP = _Fun<decltype(pappl)>::Sig;
|
||||||
|
|
||||||
// CHECK (showType<Sig1>() == "double (float&, int&, long)"_expect);
|
CHECK (showType<Sig1>() == "double (float&, int&, long)"_expect);
|
||||||
// CHECK (showType<SigC>() == "long (float&, int&, long)"_expect);
|
CHECK (showType<SigC>() == "long (float&, int&, long)"_expect);
|
||||||
// CHECK (showType<SigP>() == "double (int&, long)"_expect);
|
CHECK (showType<SigP>() == "double (int&, long)"_expect);
|
||||||
|
|
||||||
CHECK (220 == f1 (ff,ii,33));
|
CHECK (220 == f1 (ff,ii,33));
|
||||||
CHECK (220 == chain(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;"/>
|
<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>
|
||||||
<node CREATED="1749081571461" ID="ID_1222760176" MODIFIED="1749081586647" TEXT="dann Verwendungen des TupleApplicators eliminieren"/>
|
<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="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="1749082386028" ID="ID_1571223641" MODIFIED="1749082388299" TEXT="bisher...">
|
||||||
<node CREATED="1749082348881" ID="ID_1539878278" MODIFIED="1749082385036" TEXT="es wurde Apply<ARG_CNT> ausgewählt"/>
|
<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="1749081613141" ID="ID_126616986" MODIFIED="1749081621876" TEXT="FunctionComposition_test"/>
|
||||||
<node COLOR="#435e98" CREATED="1749081619255" ID="ID_945095728" MODIFIED="1749081621876" TEXT="TupleClosure_test"/>
|
<node COLOR="#435e98" CREATED="1749081619255" ID="ID_945095728" MODIFIED="1749081621876" TEXT="TupleClosure_test"/>
|
||||||
</node>
|
</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>
|
||||||
</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>
|
</node>
|
||||||
<node COLOR="#435e98" CREATED="1748829133428" ID="ID_266502224" MODIFIED="1748884086384" TEXT="Tuple">
|
<node COLOR="#435e98" CREATED="1748829133428" ID="ID_266502224" MODIFIED="1748884086384" TEXT="Tuple">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue