Library: RandomDraw - dynamic configuration requires partial application
Investigation in test setup reveals that the intended solution for dynamic configuration of the RandomDraw can not possibly work. The reason is: the processing function binds back into the object instance. This implies that RandomDraw must be *non-copyable*. So we have to go full circle. We need a way to pass the current instance to the configuration function. And the most obvious and clear way would be to pass it as function argument. Which however requires to *partially apply* this function. So -- again -- we have to resort to one of the functor utilities written several years ago; and while doing so, we must modernise these tools further, to support perfect forwarding and binding of reference arguments.
This commit is contained in:
parent
75cbfa8991
commit
32b740cd40
10 changed files with 683 additions and 144 deletions
|
|
@ -35,7 +35,13 @@
|
|||
**
|
||||
** @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
|
||||
** 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...
|
||||
**
|
||||
** @see control::CommandDef usage example
|
||||
** @see function.hpp
|
||||
|
|
@ -50,6 +56,7 @@
|
|||
#include "lib/meta/tuple-helper.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
|
||||
|
||||
|
|
@ -58,8 +65,10 @@ namespace lib {
|
|||
namespace meta{
|
||||
namespace func{
|
||||
|
||||
using std::function;
|
||||
using std::tuple;
|
||||
using std::function;
|
||||
using std::forward;
|
||||
using std::move;
|
||||
|
||||
|
||||
|
||||
|
|
@ -607,8 +616,8 @@ namespace func{
|
|||
|
||||
|
||||
public:
|
||||
typedef function<typename FunctionTypedef<Ret,ArgsL>::Sig> LeftReducedFunc;
|
||||
typedef function<typename FunctionTypedef<Ret,ArgsR>::Sig> RightReducedFunc;
|
||||
typedef function<typename BuildFunType<Ret,ArgsL>::Sig> LeftReducedFunc;
|
||||
typedef function<typename BuildFunType<Ret,ArgsR>::Sig> RightReducedFunc;
|
||||
|
||||
|
||||
/** do a partial function application, closing the first arguments<br/>
|
||||
|
|
@ -670,7 +679,7 @@ namespace func{
|
|||
using PreparedArgTypes = typename Types<PreparedArgs>::Seq;
|
||||
using RemainingArgs = typename Types<ReducedArgs>::Seq;
|
||||
|
||||
using ReducedSig = typename FunctionTypedef<Ret,RemainingArgs>::Sig;
|
||||
using ReducedSig = typename BuildFunType<Ret,RemainingArgs>::Sig;
|
||||
|
||||
template<class SRC, class TAR, size_t i>
|
||||
using IdxSelector = typename PartiallyInitTuple<SRC, TAR, pos>::template IndexMapper<i>;
|
||||
|
|
@ -694,10 +703,12 @@ namespace func{
|
|||
|
||||
namespace { // ...helpers for specifying types in function declarations....
|
||||
|
||||
using std::get;
|
||||
|
||||
template<typename RET, typename ARG>
|
||||
struct _Sig
|
||||
{
|
||||
typedef typename FunctionTypedef<RET, ARG>::Sig Type;
|
||||
typedef typename BuildFunType<RET, ARG>::Sig Type;
|
||||
typedef TupleApplicator<Type> Applicator;
|
||||
};
|
||||
|
||||
|
|
@ -712,32 +723,92 @@ namespace func{
|
|||
template<typename FUN1, typename FUN2>
|
||||
struct _Chain
|
||||
{
|
||||
typedef typename _Fun<FUN1>::Args Args;
|
||||
typedef typename _Fun<FUN2>::Ret Ret;
|
||||
typedef typename FunctionTypedef<Ret, Args>::Sig ChainedSig;
|
||||
typedef function<ChainedSig> Functor;
|
||||
using Ret = typename _Fun<FUN2>::Ret;
|
||||
using Args = typename _Fun<FUN1>::Args;
|
||||
|
||||
using FunType = typename BuildFunType<Ret,Args>::Fun;
|
||||
static auto adaptedFunType() { return FunType{}; }
|
||||
|
||||
|
||||
template<typename F1, typename F2
|
||||
,typename RET, typename... ARGS>
|
||||
static auto
|
||||
composedFunctions (F1&& f1, F2&& f2, _Fun<RET(ARGS...)>)
|
||||
{
|
||||
tuple<F1,F2> binding{forward<F1> (f1)
|
||||
,forward<F2> (f2)
|
||||
};
|
||||
return [binding = move(binding)]
|
||||
(ARGS ...args) mutable -> RET
|
||||
{
|
||||
auto& functor1 = get<0>(binding);
|
||||
auto& functor2 = get<1>(binding);
|
||||
//
|
||||
return functor2 (functor1 (forward<ARGS> (args)...));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename SIG>
|
||||
template<typename FUN>
|
||||
struct _PapS
|
||||
{
|
||||
typedef typename _Fun<SIG>::Ret Ret;
|
||||
typedef typename _Fun<SIG>::Args Args;
|
||||
typedef typename Split<Args>::Head Arg;
|
||||
typedef typename Split<Args>::Tail Rest;
|
||||
typedef typename _Sig<Ret,Rest>::Type Signature;
|
||||
typedef function<Signature> Function;
|
||||
using Ret = typename _Fun<FUN>::Ret;
|
||||
using Args = typename _Fun<FUN>::Args;
|
||||
using Arg = typename Split<Args>::Head;
|
||||
using Rest = typename Split<Args>::Tail;
|
||||
|
||||
using FunType = typename BuildFunType<Ret,Rest>::Fun;
|
||||
static auto adaptedFunType() { return FunType{}; }
|
||||
|
||||
|
||||
template<typename F, typename A
|
||||
,typename RET, typename... ARGS>
|
||||
static auto
|
||||
bindFrontArg (F&& fun, A&& arg, _Fun<RET(ARGS...)>)
|
||||
{
|
||||
tuple<F,A> binding{forward<F> (fun)
|
||||
,forward<A> (arg)
|
||||
};
|
||||
return [binding = move(binding)]
|
||||
(ARGS ...args) mutable -> RET
|
||||
{
|
||||
auto& functor = get<0>(binding);
|
||||
//
|
||||
return functor ( forward<A> (get<1>(binding))
|
||||
, forward<ARGS> (args)...);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename SIG>
|
||||
template<typename FUN>
|
||||
struct _PapE
|
||||
{
|
||||
typedef typename _Fun<SIG>::Ret Ret;
|
||||
typedef typename _Fun<SIG>::Args Args;
|
||||
typedef typename Split<Args>::End Arg;
|
||||
typedef typename Split<Args>::Prefix Rest;
|
||||
typedef typename _Sig<Ret,Rest>::Type Signature;
|
||||
typedef function<Signature> Function;
|
||||
using Ret = typename _Fun<FUN>::Ret;
|
||||
using Args = typename _Fun<FUN>::Args;
|
||||
using Arg = typename Split<Args>::End;
|
||||
using Rest = typename Split<Args>::Prefix;
|
||||
|
||||
using FunType = typename BuildFunType<Ret,Rest>::Fun;
|
||||
static auto adaptedFunType() { return FunType{}; }
|
||||
|
||||
|
||||
template<typename F, typename A
|
||||
,typename RET, typename... ARGS>
|
||||
static auto
|
||||
bindBackArg (F&& fun, A&& arg, _Fun<RET(ARGS...)>)
|
||||
{
|
||||
tuple<F,A> binding{forward<F> (fun)
|
||||
,forward<A> (arg)
|
||||
};
|
||||
return [binding = move(binding)]
|
||||
(ARGS ...args) mutable -> RET
|
||||
{
|
||||
auto& functor = get<0>(binding);
|
||||
//
|
||||
return functor ( forward<ARGS> (args)...
|
||||
, forward<A> (get<1>(binding)));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
} // (End) argument type shortcuts
|
||||
|
|
@ -761,7 +832,8 @@ namespace func{
|
|||
}
|
||||
|
||||
|
||||
/** apply the given function to the argument tuple */
|
||||
/** apply the given function to the argument tuple
|
||||
* @deprecated 11/23 meanwhile provided by the standard lib! */
|
||||
template<typename SIG, typename...ARG>
|
||||
inline
|
||||
typename _Fun<SIG>::Ret
|
||||
|
|
@ -774,7 +846,7 @@ namespace func{
|
|||
|
||||
/** close the given function over all arguments,
|
||||
* using the values from the argument tuple.
|
||||
* @return a closure object, which can be
|
||||
* @return a closure object, which can be
|
||||
* invoked later to yield the
|
||||
* function result. */
|
||||
template<typename SIG, typename...ARG>
|
||||
|
|
@ -788,29 +860,25 @@ namespace func{
|
|||
|
||||
|
||||
/** close the given function over the first argument */
|
||||
template<typename SIG, typename ARG>
|
||||
inline
|
||||
typename _PapS<SIG>::Function
|
||||
applyFirst (SIG& f, ARG arg)
|
||||
template<typename FUN, typename ARG>
|
||||
inline auto
|
||||
applyFirst (FUN&& fun, 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);
|
||||
static_assert (_Fun<FUN>(), "expect something function-like");
|
||||
return _PapS<FUN>::bindFrontArg (forward<FUN> (fun)
|
||||
,forward<ARG> (arg)
|
||||
,_PapS<FUN>::adaptedFunType());
|
||||
}
|
||||
|
||||
/** close the given function over the last argument */
|
||||
template<typename SIG, typename ARG>
|
||||
inline
|
||||
typename _PapE<SIG>::Function
|
||||
applyLast (SIG& f, ARG arg)
|
||||
template<typename FUN, typename ARG>
|
||||
inline auto
|
||||
applyLast (FUN&& fun, 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);
|
||||
static_assert (_Fun<FUN>(), "expect something function-like");
|
||||
return _PapE<FUN>::bindBackArg (forward<FUN> (fun)
|
||||
,forward<ARG> (arg)
|
||||
,_PapE<FUN>::adaptedFunType());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -818,7 +886,7 @@ namespace func{
|
|||
* which especially might be a (nested) binder... */
|
||||
template<typename SIG, typename TERM>
|
||||
inline
|
||||
typename _PapE<SIG>::Function
|
||||
typename _PapE<SIG>::FunType::Functor
|
||||
bindLast (SIG& f, TERM const& arg)
|
||||
{
|
||||
typedef Types<TERM> ArgTypeSeq;
|
||||
|
|
@ -836,14 +904,12 @@ namespace func{
|
|||
inline auto
|
||||
chained (FUN1&& f1, FUN2&& f2)
|
||||
{
|
||||
using Ret = typename _Chain<FUN1,FUN2>::Ret;
|
||||
|
||||
return [functor1 = std::forward<FUN1> (f1)
|
||||
,functor2 = std::forward<FUN2> (f2)]
|
||||
(auto&& ...args) -> Ret
|
||||
{
|
||||
return functor2 (functor1 (std::forward<decltype(args)> (args)...));
|
||||
};
|
||||
static_assert (_Fun<FUN1>(), "expect something function-like for function-1");
|
||||
static_assert (_Fun<FUN2>(), "expect something function-like for function-2");
|
||||
using Chain = _Chain<FUN1,FUN2>;
|
||||
return Chain::composedFunctions (forward<FUN1> (f1)
|
||||
,forward<FUN2> (f2)
|
||||
,Chain::adaptedFunType());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,29 @@ namespace meta{
|
|||
|
||||
|
||||
|
||||
/** abbreviation for referring to a function's return type */
|
||||
template<typename FUN>
|
||||
using _FunRet = typename _Fun<FUN>::Ret;
|
||||
|
||||
namespace {
|
||||
template<typename FUN>
|
||||
struct _DetectSingleArgFunction
|
||||
{
|
||||
static_assert(_Fun<FUN>() , "something funktion-like required");
|
||||
static_assert(_Fun<FUN>::ARITY == 1 , "function with exactly one argument required");
|
||||
|
||||
using Sig = typename _Fun<FUN>::Sig;
|
||||
using Arg = typename _Fun<Sig>::Args::List::Head;
|
||||
};
|
||||
}
|
||||
|
||||
/** abbreviation for referring to a function's single Argument type */
|
||||
template<typename FUN>
|
||||
using _FunArg = typename _DetectSingleArgFunction<FUN>::Arg;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Meta-function to check that some _function like_ entity
|
||||
* offers the expected signature
|
||||
|
|
@ -303,24 +326,28 @@ namespace meta{
|
|||
* @param ARGS a type sequence describing the arguments
|
||||
*/ //////////////////////////////////////////////////////////////////////TICKET #987 : make lib::meta::Types<TYPES...> variadic, then replace this by a single variadic template
|
||||
template<typename RET, typename ARGS>
|
||||
struct FunctionTypedef;
|
||||
struct BuildFunType;
|
||||
|
||||
|
||||
template< typename RET>
|
||||
struct FunctionTypedef<RET, Types<> >
|
||||
struct BuildFunType<RET, Types<> >
|
||||
{
|
||||
typedef function<RET(void)> Func;
|
||||
typedef RET Sig();
|
||||
using Sig = RET(void);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1>>
|
||||
struct BuildFunType<RET, Types<A1>>
|
||||
{
|
||||
typedef function<RET(A1)> Func;
|
||||
typedef RET Sig(A1);
|
||||
using Sig = RET(A1);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -328,10 +355,12 @@ namespace meta{
|
|||
, typename A1
|
||||
, typename A2
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2>>
|
||||
struct BuildFunType<RET, Types<A1,A2>>
|
||||
{
|
||||
typedef function<RET(A1,A2)> Func;
|
||||
typedef RET Sig(A1,A2);
|
||||
using Sig = RET(A1,A2);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -340,10 +369,12 @@ namespace meta{
|
|||
, typename A2
|
||||
, typename A3
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3>>
|
||||
struct BuildFunType<RET, Types<A1,A2,A3>>
|
||||
{
|
||||
typedef function<RET(A1,A2,A3)> Func;
|
||||
typedef RET Sig(A1,A2,A3);
|
||||
using Sig = RET(A1,A2,A3);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -353,10 +384,12 @@ namespace meta{
|
|||
, typename A3
|
||||
, typename A4
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4>>
|
||||
struct BuildFunType<RET, Types<A1,A2,A3,A4>>
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4);
|
||||
using Sig = RET(A1,A2,A3,A4);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -367,10 +400,12 @@ namespace meta{
|
|||
, typename A4
|
||||
, typename A5
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5>>
|
||||
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5>>
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4,A5);
|
||||
using Sig = RET(A1,A2,A3,A4,A5);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -382,10 +417,12 @@ namespace meta{
|
|||
, typename A5
|
||||
, typename A6
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6>>
|
||||
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6>>
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5,A6)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4,A5,A6);
|
||||
using Sig = RET(A1,A2,A3,A4,A5,A6);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -398,10 +435,12 @@ namespace meta{
|
|||
, typename A6
|
||||
, typename A7
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6,A7>>
|
||||
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7>>
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5,A6,A7)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4,A5,A6,A7);
|
||||
using Sig = RET(A1,A2,A3,A4,A5,A6,A7);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -415,10 +454,12 @@ namespace meta{
|
|||
, typename A7
|
||||
, typename A8
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8>>
|
||||
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8>>
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5,A6,A7,A8)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4,A5,A6,A7,A8);
|
||||
using Sig = RET(A1,A2,A3,A4,A5,A6,A7,A8);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -433,10 +474,12 @@ namespace meta{
|
|||
, typename A8
|
||||
, typename A9
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8,A9>>
|
||||
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8,A9>>
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5,A6,A7,A8,A9)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4,A5,A6,A7,A8,A9);
|
||||
using Sig = RET(A1,A2,A3,A4,A5,A6,A7,A8,A9);
|
||||
using Fun = _Fun<Sig>;
|
||||
using Func = function<Sig>;
|
||||
using Functor = Func;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -341,6 +341,7 @@ namespace lib {
|
|||
|
||||
using Res = typename lib::meta::_Fun<FUN>::Ret;
|
||||
using lib::meta::func::chained;
|
||||
using lib::meta::_FunRet;
|
||||
|
||||
if constexpr (std::is_same_v<Res, Tar>)// ◁──────────────────────────┨ function produces result directly
|
||||
return std::forward<FUN>(fun);
|
||||
|
|
@ -355,13 +356,13 @@ namespace lib {
|
|||
,[this](double rand){ return limited(rand); }
|
||||
);
|
||||
else
|
||||
if constexpr (std::is_same_v<Res, RandomDraw const&>)// ◁─────────────┨ function yields parametrised RandomDraw to invoke
|
||||
if constexpr (std::is_same_v<Res, RandomDraw>)// ◁────────────────────┨ function yields parametrised RandomDraw to invoke
|
||||
return [functor=std::forward<FUN>(fun), this]
|
||||
(auto&& ...inArgs)
|
||||
{ // invoke with copy
|
||||
RandomDraw const& parametricDraw = functor(inArgs...);
|
||||
(auto&& ...inArgs) -> _FunRet<RandomDraw>
|
||||
{ // invoke with copy
|
||||
RandomDraw parametricDraw = functor(inArgs...);
|
||||
return parametricDraw (forward<decltype(inArgs)> (inArgs)...);
|
||||
}; // forward arguments
|
||||
}; // forward arguments
|
||||
else
|
||||
static_assert (not sizeof(Res), "unable to adapt / handle result type");
|
||||
NOTREACHED("Handle based on return type");
|
||||
|
|
|
|||
|
|
@ -506,7 +506,7 @@ namespace control {
|
|||
{
|
||||
using Args = typename Types<TYPES...>::Seq;
|
||||
using Ret = void;
|
||||
using Sig = typename FunctionTypedef<void, Args>::Sig;
|
||||
using Sig = typename BuildFunType<void, Args>::Sig;
|
||||
using ArgTuple = std::tuple<TYPES...>;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ namespace control {
|
|||
|
||||
using std::function;
|
||||
|
||||
using lib::meta::FunctionTypedef;
|
||||
using lib::meta::BuildFunType;
|
||||
using lib::meta::_Fun;
|
||||
using lib::meta::Types;
|
||||
using lib::meta::Append;
|
||||
|
|
@ -84,9 +84,9 @@ namespace control {
|
|||
using ExtendedArgs = typename Types<ExtendedArglist>::Seq;
|
||||
|
||||
public:
|
||||
using OperateSig = typename FunctionTypedef<void, Args>::Sig;
|
||||
using CaptureSig = typename FunctionTypedef<MEM, Args>::Sig;
|
||||
using UndoOp_Sig = typename FunctionTypedef<void, ExtendedArgs>::Sig;
|
||||
using OperateSig = typename BuildFunType<void, Args>::Sig;
|
||||
using CaptureSig = typename BuildFunType<MEM, Args>::Sig;
|
||||
using UndoOp_Sig = typename BuildFunType<void, ExtendedArgs>::Sig;
|
||||
using CmdArgs = Args;
|
||||
using Memento = MEM;
|
||||
};
|
||||
|
|
@ -124,9 +124,9 @@ namespace control {
|
|||
using ExtendedArglist = typename Append<ARG, Memento>::List;
|
||||
using ExtendedArgs = typename Types<ExtendedArglist>::Seq;
|
||||
|
||||
using OperateSig = typename FunctionTypedef<void, ARG>::Sig;
|
||||
using CaptureSig = typename FunctionTypedef<Ret,ARG>::Sig;
|
||||
using UndoOp_Sig = typename FunctionTypedef<void, ExtendedArgs>::Sig;
|
||||
using OperateSig = typename BuildFunType<void, ARG>::Sig;
|
||||
using CaptureSig = typename BuildFunType<Ret,ARG>::Sig;
|
||||
using UndoOp_Sig = typename BuildFunType<void, ExtendedArgs>::Sig;
|
||||
};
|
||||
/** Case2: defining the actual Undo function */
|
||||
template<typename ARG>
|
||||
|
|
@ -138,9 +138,9 @@ namespace control {
|
|||
using OperationArglist = typename SplitLast<Args>::List;
|
||||
using OperationArgs = typename Types<OperationArglist>::Seq;
|
||||
|
||||
using OperateSig = typename FunctionTypedef<void, OperationArgs>::Sig;
|
||||
using CaptureSig = typename FunctionTypedef<Ret,OperationArgs>::Sig;
|
||||
using UndoOp_Sig = typename FunctionTypedef<void, ARG>::Sig;
|
||||
using OperateSig = typename BuildFunType<void, OperationArgs>::Sig;
|
||||
using CaptureSig = typename BuildFunType<Ret,OperationArgs>::Sig;
|
||||
using UndoOp_Sig = typename BuildFunType<void, ARG>::Sig;
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ namespace control {
|
|||
* the undo and capture function, setting up the necessary bindings and closures for
|
||||
* allowing them to cooperate behind the scenes to carry out the UNDO functionality.
|
||||
* On construction, the UndoMutation functor retrieves the wired up functions,
|
||||
* storing them into generic containers (type erasure) for later invocation.
|
||||
* storing them into generic containers (type erasure) for later invocation.
|
||||
*
|
||||
* More specifically, the \c captureFunction, which is expected to run immediately prior
|
||||
* to the actual command operation, returns a \b memento value object (of unspecific type),
|
||||
|
|
@ -143,29 +143,27 @@ namespace control {
|
|||
* @note similar to #getState(), the returned functor will throw
|
||||
* when the state capturing wasn't yet invoked
|
||||
*/
|
||||
function<SIG>
|
||||
function<SIG>
|
||||
tieUndoFunc()
|
||||
{
|
||||
using std::bind;
|
||||
|
||||
return bindLast( undo_ // getState() bound to last argument of undo(...)
|
||||
, bind (&MementoTie::getState, this)
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
/** bind the capturing function to the internal memento store within this object.
|
||||
* @return a functor, which on invocation will automatically store the return value
|
||||
* of the capturing function (= the current memento value) into the field
|
||||
* #memento_ within this object
|
||||
* #memento_ within this object
|
||||
*/
|
||||
function<SIG>
|
||||
tieCaptureFunc()
|
||||
{
|
||||
using std::placeholders::_1;
|
||||
|
||||
function<void(MEM)> doCaptureMemento = bind (&MementoTie::capture, this, _1 );
|
||||
|
||||
return chained(capture_, doCaptureMemento);
|
||||
return chained(capture_
|
||||
,[this](MEM const& mementoVal){ capture (mementoVal); }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -183,7 +181,7 @@ namespace control {
|
|||
|
||||
|
||||
/** conversion to bool() yields true
|
||||
* if all functions are usable and
|
||||
* if all functions are usable and
|
||||
* memento state has been captured
|
||||
*/
|
||||
explicit
|
||||
|
|
@ -203,7 +201,7 @@ namespace control {
|
|||
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename SIG, typename MEM>
|
||||
MementoTie<SIG,MEM>::operator std::string() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ namespace test {
|
|||
typedef Prepend<Num<1>, Args>::Seq NewArgs; // manipulate the argument type(s)
|
||||
DISPLAY (NewArgs);
|
||||
|
||||
typedef FunctionTypedef<RetType,NewArgs>::Sig NewSig; // re-build a new function signature
|
||||
typedef BuildFunType<RetType,NewArgs>::Sig NewSig; // re-build a new function signature
|
||||
|
||||
NewSig& fun = getNumberz<1,5,9>; //...which is compatible to an existing real function signature!
|
||||
|
||||
|
|
@ -337,7 +337,7 @@ namespace test {
|
|||
|
||||
// finally combine all techniques....
|
||||
using NumberzArg = Types<List2>::Seq;
|
||||
using NumberzSig = FunctionTypedef<int,NumberzArg>::Sig;
|
||||
using NumberzSig = BuildFunType<int,NumberzArg>::Sig;
|
||||
|
||||
Tuple<NumberzArg> numberzTup (Num<5>(22), Num<6>(33), Num<7>(44));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ namespace meta {
|
|||
namespace test {
|
||||
|
||||
using ::test::Test;
|
||||
using lib::test::showType;
|
||||
using lib::meta::_Fun;
|
||||
using func::applyFirst;
|
||||
using func::applyLast;
|
||||
using func::bindLast;
|
||||
|
|
@ -142,10 +144,12 @@ namespace test {
|
|||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
check_diagnostics ();
|
||||
check_partialApplication ();
|
||||
check_functionalComposition ();
|
||||
check_bindToArbitraryParameter ();
|
||||
check_diagnostics();
|
||||
check_partialApplication();
|
||||
check_functionalComposition();
|
||||
check_bindToArbitraryParameter();
|
||||
|
||||
verify_referenceHandling();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -383,6 +387,52 @@ namespace test {
|
|||
CHECK (1+2+3+4+88 == f_bound_5 (_1_,_2_,_3_,_4_ ) );
|
||||
}
|
||||
|
||||
|
||||
/** @internal static function to pass as reference for test */
|
||||
static long floorIt (float it) { return long(floor (it)); }
|
||||
|
||||
|
||||
/** @test ensure reference types and arguments are handled properly */
|
||||
void
|
||||
verify_referenceHandling()
|
||||
{
|
||||
int ii = 99;
|
||||
float ff = 88;
|
||||
auto fun = std::function{[](float& f, int& i, long l) -> double { return f + i + l; }};
|
||||
auto& f1 = fun;
|
||||
|
||||
// build chained and a partially applied functors
|
||||
auto chain = func::chained(f1,floorIt);
|
||||
auto pappl = func::applyFirst (f1, ff);
|
||||
|
||||
using Sig1 = _Fun<decltype(f1)>::Sig;
|
||||
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 (220 == f1 (ff,ii,33));
|
||||
CHECK (220 == chain(ff,ii,33));
|
||||
CHECK (220 == pappl( ii,33));
|
||||
|
||||
// change original values to prove that references were
|
||||
// passed and stored properly in the adapted functors
|
||||
ii = 22;
|
||||
ff = 42;
|
||||
|
||||
CHECK ( 97 == f1 (ff,ii,33));
|
||||
CHECK ( 97 == chain(ff,ii,33));
|
||||
CHECK ( 97 == pappl( ii,33));
|
||||
|
||||
// can even exchange the actual function, since f1 was passed as reference
|
||||
fun = [](float& f, int& i, size_t s) -> double { return f - i - s; };
|
||||
|
||||
CHECK (-13 == f1 (ff,ii,33));
|
||||
CHECK (-13 == chain(ff,ii,33));
|
||||
CHECK (-13 == pappl( ii,33));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ namespace test{
|
|||
using util::_Fmt;
|
||||
using lib::time::FSecs;
|
||||
using lib::time::TimeVar;
|
||||
using lib::meta::_FunRet;
|
||||
|
||||
|
||||
|
||||
|
|
@ -78,7 +79,7 @@ namespace test{
|
|||
build (FUN&& fun)
|
||||
{
|
||||
return [functor=std::forward<FUN>(fun)]
|
||||
(size_t hash)
|
||||
(size_t hash) -> _FunRet<FUN>
|
||||
{
|
||||
return functor(uint(hash/64), uint(hash%64));
|
||||
};
|
||||
|
|
@ -94,7 +95,7 @@ namespace test{
|
|||
build (FUN&& fun)
|
||||
{
|
||||
return [functor=std::forward<FUN>(fun)]
|
||||
(size_t hash)
|
||||
(size_t hash) -> _FunRet<FUN>
|
||||
{
|
||||
return functor(hash, ctxParameter);
|
||||
};
|
||||
|
|
@ -693,37 +694,90 @@ namespace test{
|
|||
|
||||
|
||||
|
||||
template<typename FUN, typename ARG, typename RET, typename... ARGS>
|
||||
auto
|
||||
_applyFirst (FUN&& fun, ARG&& arg, _Fun<RET(ARGS...)>)
|
||||
{
|
||||
std::tuple<FUN,ARG> binding{std::forward<FUN> (fun)
|
||||
,std::forward<ARG>(arg)
|
||||
};
|
||||
return [binding = std::move(binding)]
|
||||
(ARGS ...args) mutable -> RET
|
||||
{
|
||||
auto& functor = std::get<0> (binding);
|
||||
//
|
||||
return functor ( std::forward<ARG> (std::get<1> (binding))
|
||||
, std::forward<ARGS> (args)...);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename FUN, typename ARG>
|
||||
auto
|
||||
applyFirst (FUN&& fun, ARG&& arg)
|
||||
{
|
||||
using Ret = typename lib::meta::_Fun<FUN>::Ret;
|
||||
using AllArgs = typename lib::meta::_Fun<FUN>::Args;
|
||||
using RestArgs = typename lib::meta::Split<AllArgs>::Tail;
|
||||
using AdaptedFun = typename lib::meta::BuildFunType<Ret,RestArgs>::Fun;
|
||||
|
||||
return _applyFirst( std::forward<FUN> (fun)
|
||||
, std::forward<ARG> (arg)
|
||||
, AdaptedFun{});
|
||||
}
|
||||
|
||||
/** @test TODO change the generation profile dynamically
|
||||
* @todo WIP 11/23 🔁 define ⟶ implement
|
||||
*/
|
||||
void
|
||||
verify_dynamicChange()
|
||||
{
|
||||
UNIMPLEMENTED ("change the generation profile dynamically");
|
||||
SHOW_EXPR(int(d2( 0)));
|
||||
SHOW_EXPR(int(d2( 1)));
|
||||
SHOW_EXPR(int(d2( 2)));
|
||||
SHOW_EXPR(int(d2( 3)));
|
||||
SHOW_EXPR(int(d2( 4)));
|
||||
SHOW_EXPR(int(d2( 5)));
|
||||
SHOW_EXPR(int(d2( 6)));
|
||||
SHOW_EXPR(int(d2( 7)));
|
||||
SHOW_EXPR(int(d2( 8)));
|
||||
SHOW_EXPR(int(d2( 9)));
|
||||
SHOW_EXPR(int(d2(10)));
|
||||
SHOW_EXPR(int(d2(63)));
|
||||
SHOW_EXPR(int(d2(64)));
|
||||
SHOW_EXPR(int(d2(65)));
|
||||
SHOW_EXPR(int(d2(66)));
|
||||
SHOW_EXPR(int(d2(67)));
|
||||
SHOW_EXPR(int(d2(68)));
|
||||
SHOW_EXPR(int(d2(69)));
|
||||
SHOW_EXPR(int(d2(70)));
|
||||
SHOW_EXPR(int(d2(71)));
|
||||
SHOW_EXPR(int(d2(72)));
|
||||
SHOW_EXPR(int(d2(73)));
|
||||
SHOW_EXPR(int(d2(74)));
|
||||
SHOW_EXPR(int(d2(75)));
|
||||
// auto d1 = Draw([](Draw& draw, uint cycle, uint){
|
||||
// draw.probability(cycle*0.2);
|
||||
// });
|
||||
//
|
||||
//SHOW_EXPR(int(d1( 0)));
|
||||
//SHOW_EXPR(int(d1( 1)));
|
||||
//SHOW_EXPR(int(d1( 2)));
|
||||
//SHOW_EXPR(int(d1( 16)));
|
||||
//SHOW_EXPR(int(d1( 32)));
|
||||
//SHOW_EXPR(int(d1( 48)));
|
||||
//SHOW_EXPR(int(d1( 63)));
|
||||
//SHOW_EXPR(int(d1( 64)));
|
||||
//SHOW_EXPR(int(d1( 64 +1)));
|
||||
//SHOW_EXPR(int(d1( 64 +2)));
|
||||
//SHOW_EXPR(int(d1( 64+16)));
|
||||
//SHOW_EXPR(int(d1( 64+32)));
|
||||
//SHOW_EXPR(int(d1( 64+48)));
|
||||
//SHOW_EXPR(int(d1( 64+64)));
|
||||
//SHOW_EXPR(int(d1(128 +16)));
|
||||
//SHOW_EXPR(int(d1(128 +32)));
|
||||
//SHOW_EXPR(int(d1(128 +48)));
|
||||
//SHOW_EXPR(int(d1(128 +64)));
|
||||
//SHOW_EXPR(int(d1(128+64+16)));
|
||||
//SHOW_EXPR(int(d1(128+64+32)));
|
||||
//SHOW_EXPR(int(d1(128+64+48)));
|
||||
//SHOW_EXPR(int(d1(128+64+64)));
|
||||
int yy = 99;
|
||||
float ff = 88;
|
||||
auto fuK = std::function{[](float& f, int& i, size_t s) -> double { return f + i + s; }};
|
||||
auto& f1 = fuK;
|
||||
auto f2 = lib::meta::func::applyFirst(f1, ff);
|
||||
using lib::meta::_Fun;
|
||||
using Sig1 = _Fun<decltype(f1)>::Sig;
|
||||
using Sig2 = _Fun<decltype(f2)>::Sig;
|
||||
yy = 22;
|
||||
ff = 42;
|
||||
SHOW_TYPE(Sig1)
|
||||
SHOW_TYPE(Sig2)
|
||||
SHOW_EXPR(f1 (ff,yy,33))
|
||||
SHOW_EXPR(f2 ( yy,33))
|
||||
SHOW_TYPE(decltype(f2 ( yy,33)))
|
||||
SHOW_TYPE(decltype(f2))
|
||||
|
||||
fuK = [](float& f, int& i, size_t s) -> double { return f * i * s; };
|
||||
|
||||
SHOW_EXPR(f1 (ff,yy,33))
|
||||
SHOW_EXPR(f2 ( yy,33))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -57425,6 +57425,144 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700669580665" FOLDED="true" ID="ID_1852128670" MODIFIED="1700686547102" TEXT="Funktor-Manipulationen">
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1700669596447" ID="ID_1886923243" MODIFIED="1700669617888" TEXT="einige Werkzeuge hatte ich vor sehr langer Zeit schon gebaut....">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700669619116" ID="ID_1944223150" MODIFIED="1700669643528" TEXT="diese müßten schrittweise modernisiert werden">
|
||||
<icon BUILTIN="bell"/>
|
||||
</node>
|
||||
<node CREATED="1700669672781" ID="ID_1958398990" MODIFIED="1700669703266" TEXT="Function-composition: lib::meta::func::chained">
|
||||
<node CREATED="1700669726758" ID="ID_611933272" MODIFIED="1700669730829" TEXT="function-closure.hpp"/>
|
||||
<node CREATED="1700669750587" ID="ID_1086294542" MODIFIED="1700669760357" TEXT="Type-Binding helper _Chain<FUN1,FUN2>"/>
|
||||
<node COLOR="#338800" CREATED="1700669762041" ID="ID_1323418254" MODIFIED="1700670034955" TEXT="11/23 auf variadic-λ umgestellt">
|
||||
<linktarget COLOR="#20b763" DESTINATION="ID_1323418254" ENDARROW="Default" ENDINCLINATION="1071;87;" ID="Arrow_ID_636352614" SOURCE="ID_80963960" STARTARROW="None" STARTINCLINATION="-916;62;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700669857972" HGAP="52" ID="ID_507646276" MODIFIED="1700670005919" TEXT="Vorsicht Falle" VSHIFT="4">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
der Rückgabetyp muß explizit deklariert werden — ähnlich wie decltype(auto) — denn es kann sein, daß die zusammengesetzte Funktion eine Referenz liefert
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<edge COLOR="#528497"/>
|
||||
<font NAME="SansSerif" SIZE="10"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700670186153" ID="ID_753645097" MODIFIED="1700670190204" TEXT="partial-Application">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700670130760" ID="ID_1114511607" MODIFIED="1700686530654" TEXT="partielle Funktions-Anwendung modernisieren">
|
||||
<linktarget COLOR="#994a7b" DESTINATION="ID_1114511607" ENDARROW="Default" ENDINCLINATION="1203;76;" ID="Arrow_ID_448010949" SOURCE="ID_67786691" STARTARROW="None" STARTINCLINATION="615;22;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700672135424" ID="ID_1984801808" MODIFIED="1700672141808" TEXT="was ist daran erhaltenswert?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1700672144271" ID="ID_1090292620" MODIFIED="1700672187951" TEXT="das Funktions-Manipulations-API">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...also eine Funktion, der man andere Funktoren gibt, und diese baut einen manipulierten Funktor. Sowas ist <i>extrem nützlich...</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1700672199664" ID="ID_912990030" MODIFIED="1700672350154" TEXT="das generische bindFirst/bindLast — wenn dann aber verallgemeinert">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
also die Möglichkeit, Argumente durch Funktions-artige »Binder« zu schließen, die dann aber erst zum Aufruf-Zeitpunkt aktiviert werden. In verallgemeinterter Form könnten das beliebige passende Funktoren sein, die auch weiterhin Argumente benötigen — und es müßte ein neuer Funktionstyp synthetisiert werden (klingt schlimmer als es tatsächlich umzusetzen ist, da wir so viele Tuple-Manipulationsfunktionen haben)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1700672372605" ID="ID_980669454" MODIFIED="1700672383347" TEXT="was weg muß...">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1700672384495" ID="ID_1640467092" MODIFIED="1700672393458" TEXT="die HIlfs-Konstrukte"/>
|
||||
<node CREATED="1700672393926" ID="ID_1776633246" MODIFIED="1700672401537" TEXT="die Argument-Tupel, die gespeichert werden"/>
|
||||
<node CREATED="1700672402029" ID="ID_566925298" MODIFIED="1700672412031" TEXT="jedwede Kopie muß durch perfect-Forwarding ersetzt werden"/>
|
||||
<node CREATED="1700672479034" ID="ID_1530548191" MODIFIED="1700672699321" TEXT="nach Möglichkeit nur noch Lambdas liefern (keine std::function mehr)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
warum? weil das leichtgewichtiger und inline-freundlicher ist. Ein λ ist ja erst mal eine anonyme Klasse mit jedweder Storage direkt inline; es läßt sich per Kopie und Verschiebung handhaben. Wer damit Probleme hat, kann sich das resultierende Lambda immer in eine Funktion packen, und den dafür passenden Funktor-Typ sollten wir auch als Metafunktion anbieten. Der Nachteil (oder auch Vorteil) von std::function ist, daß das ein Objekt fester (relativ begrenzter) Größe ist, und notfalls automatisch ein Erweiterungsspeicher auf dem Heap mitgeführt wird.
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700672430249" HGAP="136" ID="ID_975422639" MODIFIED="1700686519692" TEXT="schrittweise vorgehen...." VSHIFT="-7">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1700672449602" ID="ID_1457801203" MODIFIED="1700680981796" TEXT="erst mal applyFirst neu implementieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1700680821756" ID="ID_1820837495" MODIFIED="1700680834943" TEXT="mit einem generic λ ist es einfach..."/>
|
||||
<node CREATED="1700680835467" ID="ID_1512849078" MODIFIED="1700680849404" TEXT="aber das Resultat ist keine Funktion (sondern ein Template)"/>
|
||||
<node CREATED="1700680854471" ID="ID_908786228" MODIFIED="1700680868809" TEXT="besser: die neue Argument-Liste explizit umbauen und verwenden"/>
|
||||
<node CREATED="1700680871677" ID="ID_290742590" MODIFIED="1700680955304" TEXT="Prototyp lokal im Test verifiziert: geht auch mit Referenzen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
und zwar
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Referenz irgendwo in den <i>sonstigen Argumenten</i>
|
||||
</li>
|
||||
<li>
|
||||
Referenz als das Argument, das gebunden wird (⟶ bleibt eine Referenz)
|
||||
</li>
|
||||
<li>
|
||||
den Funktor selber als Referenz übergeben (⟶ bleibt eine Referenz, man kann die konkrete Funktion austauschen)
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700680640125" ID="ID_1600167237" MODIFIED="1700680810430" TEXT="neuer Trick: _Fun<Sig> als Transporter für variadische Argument-Typen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...das bekannte leidige Problem: <i>argument packs</i> sind keine Typen; man kann sie daher nicht verarbeiten und weitergeben; stattdessen müsen wir einen Typ <i>mit varidadic parameters</i> verwenden, um am Zielort in der Argumentliste dagegen zu matchen. Da lib::meta::_Fun mehr und mehr zum Analyse-Tool für Funktions-artige Entitäten wird, bietet es sich an, diese Metafunktion selber auch als Transporter für Funktionssignaturen zu verwenden
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700680962986" ID="ID_417878820" MODIFIED="1700686489900" TEXT="applyFirst / applyLast gegen neue Implementierung austauschen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700686490730" ID="ID_270581080" MODIFIED="1700686505300" TEXT="zusätzlicher Test: auch Referenzen werden korrekt gehandhabt">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -96688,6 +96826,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700535940171" ID="ID_80963960" MODIFIED="1700535962800" TEXT="lib::meta::func::chained() modernisiert">
|
||||
<arrowlink COLOR="#20b763" DESTINATION="ID_1323418254" ENDARROW="Default" ENDINCLINATION="1071;87;" ID="Arrow_ID_636352614" STARTARROW="None" STARTINCLINATION="-916;62;"/>
|
||||
<linktarget COLOR="#1de11c" DESTINATION="ID_80963960" ENDARROW="Default" ENDINCLINATION="1061;74;" ID="Arrow_ID_868943709" SOURCE="ID_146361421" STARTARROW="None" STARTINCLINATION="-252;-591;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -96960,6 +97100,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node COLOR="#338800" CREATED="1700491985219" ID="ID_460437503" MODIFIED="1700623393034" TEXT="Adaptierung restrukturieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700667013700" ID="ID_1737653728" MODIFIED="1700667059509" TEXT="RandomDraw ◁ NonCopyable">
|
||||
<linktarget COLOR="#b1054b" DESTINATION="ID_1737653728" ENDARROW="Default" ENDINCLINATION="512;-31;" ID="Arrow_ID_685625009" SOURCE="ID_1118038273" STARTARROW="None" STARTINCLINATION="-660;37;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700577811739" ID="ID_1356052727" MODIFIED="1700623391805" TEXT="Konfigurations-DSL aufbauen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
|
|
@ -96968,6 +97112,189 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node COLOR="#435e98" CREATED="1700615809354" ID="ID_664060947" MODIFIED="1700615816506" TEXT="minVal"/>
|
||||
<node COLOR="#435e98" CREATED="1700615812738" ID="ID_1089110674" MODIFIED="1700623389853" TEXT="mapping"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700666517058" ID="ID_1164549835" MODIFIED="1700666527223" TEXT="dynamische Parametrisierung ermöglichen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700666528821" ID="ID_1733767299" MODIFIED="1700666725778">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<i>das </i>ist für den <i>aktuellen </i>Use-case unabdingbar
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...im Gegensatz zu dem ganzen weiteren Schlonz, den ich die letzten Tage eingebaut habe, „weils grad gang“; ich brauche irgende einen Mechanismus, über den ein später hinzukonfigurierter Funktor <i>in Abhängigkeit von aktuellen Parameter-Daten</i> an der Parametrisierung des RandomDraw "drehen" kann...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700666732810" ID="ID_275616933" MODIFIED="1700666762334" TEXT="Konstruktions-Problem: wie kommt der Funktor an die aktuelle Instanz?">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node COLOR="#5b280f" CREATED="1700666796282" ID="ID_400868539" MODIFIED="1700666899207" TEXT="Lösung-1: gar nicht. Er baut eine neue Instanz">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1700666822918" ID="ID_1578832431" MODIFIED="1700666830593" TEXT="auf die Lösung bin ich zunächst verfallen"/>
|
||||
<node CREATED="1700666831243" ID="ID_273291815" MODIFIED="1700666840360" TEXT="sie ist zwar etwas komisch zu verdrahten"/>
|
||||
<node CREATED="1700666841204" ID="ID_1310803138" MODIFIED="1700666848911" TEXT="aber geht schon mal durch den Compiler"/>
|
||||
<node CREATED="1700666849995" ID="ID_252787073" MODIFIED="1700666893728">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<i><font color="#f22e6c">dangling Reference</font></i> ⟹ CRASH
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
<node CREATED="1700666909779" ID="ID_1903074332" MODIFIED="1700666917400" TEXT="wa-rum?">
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
</node>
|
||||
<node CREATED="1700666919681" ID="ID_1841792558" MODIFIED="1700666945613" TEXT="weil die huckepack-Funktion in RandomDraw auf *this bindet">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
<node CREATED="1700666957387" ID="ID_1118038273" MODIFIED="1700667065677" TEXT="Konsequenz: RandomDraw muß NonCopyable sein">
|
||||
<arrowlink COLOR="#b1054b" DESTINATION="ID_1737653728" ENDARROW="Default" ENDINCLINATION="512;-31;" ID="Arrow_ID_685625009" STARTARROW="None" STARTINCLINATION="-660;37;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700667123763" ID="ID_360972195" MODIFIED="1700667721958">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Lösung-2: er bindet <i>irgendwie </i>eine Referenz darauf
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node CREATED="1700667152325" ID="ID_291951431" MODIFIED="1700667161608" TEXT="ja ... mähh">
|
||||
<icon BUILTIN="smiley-neutral"/>
|
||||
</node>
|
||||
<node CREATED="1700667168921" ID="ID_277893933" MODIFIED="1700667204912" TEXT="...also entweder der User muß das beim Setup machen (⟹ setzt bestehende Instanz voraus)"/>
|
||||
<node CREATED="1700667209643" ID="ID_497670078" MODIFIED="1700667262488" TEXT="...oder man bietet ein spezielles Builder-Setup ⟶ Funktor 2.Ordnung">
|
||||
<node CREATED="1700667287164" ID="ID_9300229" MODIFIED="1700667301028" TEXT="wäre durchaus machbar — aber nicht leicht zu vestehen">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1700667564352" ID="ID_662111218" MODIFIED="1700667663542" TEXT="in drei Schritten">
|
||||
<node CREATED="1700667568604" ID="ID_1050199497" MODIFIED="1700667666028" TEXT="Builder-λ : bekommt RandomDraw& ⟼ liefert Manipulator-λ">
|
||||
<icon BUILTIN="full-1"/>
|
||||
</node>
|
||||
<node CREATED="1700667618957" ID="ID_162376172" MODIFIED="1700667668131" TEXT="Manipulator-λ: bekommt Input, manipuliert RandomDraw&">
|
||||
<icon BUILTIN="full-2"/>
|
||||
</node>
|
||||
<node CREATED="1700667642374" ID="ID_629040008" MODIFIED="1700667670894" TEXT="Invocation: RandomDraw selber auf die Argumente anwenden">
|
||||
<icon BUILTIN="full-3"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700667685604" ID="ID_462101752" MODIFIED="1700667704470" TEXT="Muuuh!">
|
||||
<icon BUILTIN="smiley-angry"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700667315966" ID="ID_336303173" MODIFIED="1700667341006" TEXT="⟹ der letztlich operierende Funktor hätte Res-type void (Seiteneffekt)"/>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700667728894" ID="ID_1647643633" MODIFIED="1700667762597" TEXT="Plan-B">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="13"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700667358039" ID="ID_1159388516" MODIFIED="1700667382024" TEXT="Lösung:3 er nimmt diese als Ref-Argument">
|
||||
<node CREATED="1700667395811" ID="ID_1168097310" MODIFIED="1700667512459">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
das wäre schön sauber — <font size="6">ABER</font> ...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="smiley-oh"/>
|
||||
<node CREATED="1700667426327" ID="ID_1988791757" MODIFIED="1700667443550" TEXT="woher bekommt er dann den Input für die Parametrisierung?"/>
|
||||
<node CREATED="1700667444188" ID="ID_495817814" MODIFIED="1700667455851" TEXT="weitere Argumente? welche?"/>
|
||||
<node CREATED="1700667456602" ID="ID_1963198981" MODIFIED="1700667463789" TEXT="und wie bindet man das??"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700667812723" ID="ID_1483170838" MODIFIED="1700667830059" TEXT="Variadic-Args + rekursiver Aufruf">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1700668497744" ID="ID_1487967876" MODIFIED="1700668593578" TEXT="das muß der adaptIn(fun)-Schritt auflösen">
|
||||
<node CREATED="1700668538836" ID="ID_1747416563" MODIFIED="1700668552053" TEXT="er muß dazu aber irgendwie die restlichen Argumente zu Greifen bekommen"/>
|
||||
<node CREATED="1700668553545" ID="ID_1272264893" MODIFIED="1700668561180" TEXT="...und diese rekursiv an sich selber übergeben"/>
|
||||
</node>
|
||||
<node CREATED="1700669255396" ID="ID_1754735258" MODIFIED="1700669300783">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
läuft auf eine <b>partielle Anwendung</b> der Funktion hinaus
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1700669349834" ID="ID_1795148710" MODIFIED="1700669452457" TEXT="auch dafür gabs bereits eine LIbrary-Lösung">
|
||||
<node CREATED="1700669462313" ID="ID_146361421" MODIFIED="1700669512820" TEXT="genau die Geliche, die ich vor ein paar Tagen schon modernisiert habe...">
|
||||
<arrowlink COLOR="#1de11c" DESTINATION="ID_80963960" ENDARROW="Default" ENDINCLINATION="1061;74;" ID="Arrow_ID_868943709" STARTARROW="None" STARTINCLINATION="-252;-591;"/>
|
||||
</node>
|
||||
<node CREATED="1700670079863" ID="ID_931371524" MODIFIED="1700670102061" TEXT="im Grunde ist auch das heutzutage leicht als generisches Lambda zu schreiben"/>
|
||||
<node COLOR="#435e98" CREATED="1700670049963" ID="ID_67786691" MODIFIED="1700686592758" TEXT="kann man die partielle-Anwendung auch modernisieren? (und dann verwenden)">
|
||||
<arrowlink COLOR="#994a7b" DESTINATION="ID_1114511607" ENDARROW="Default" ENDINCLINATION="1203;76;" ID="Arrow_ID_448010949" STARTARROW="None" STARTINCLINATION="615;22;"/>
|
||||
<icon BUILTIN="help"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700672717763" HGAP="32" ID="ID_1710135688" MODIFIED="1700672756403" TEXT="nicht ganz so einfach wie bei der Funktions-Komposition" VSHIFT="9">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1700672739896" HGAP="26" ID="ID_1441194651" MODIFIED="1700686571025" TEXT="ein Teilschritt wäre denkbar" VSHIFT="1">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700686572329" HGAP="43" ID="ID_1067874422" MODIFIED="1700686591140" TEXT="(gesägt, getan)" VSHIFT="1">
|
||||
<font NAME="SansSerif" SIZE="11"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686650589" ID="ID_1320986357" MODIFIED="1700686659027" TEXT="adaptIn">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686611506" ID="ID_1055056344" MODIFIED="1700686621481" TEXT="partielle Anwendung anwenden">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686662293" ID="ID_473080725" MODIFIED="1700686674078" TEXT="sich selbst damit rekursiv aufrufen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686675275" ID="ID_1836010727" MODIFIED="1700686690830" TEXT="adaptOut">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686680324" ID="ID_1784901789" MODIFIED="1700686688050" TEXT="neuer Zweig für void-Funktionen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686695792" ID="ID_1003013120" MODIFIED="1700686699584" TEXT="beide integriert">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686712454" ID="ID_194082456" MODIFIED="1700686717365" TEXT="im Test verifizieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700491877926" ID="ID_1958310493" MODIFIED="1700502021655" TEXT="Test zur Dokumentation">
|
||||
<icon BUILTIN="pencil"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue