clean-up: simplify function-closure -- rebuild the 'bind' case
...can now be formulated in a single function, based on the apply-to-λ technique invented by David Vandervoorde. WARNING: the rewritten version of BindToArgument<...>::reduced() does not compile in the out-of-bounds case, revealing a possibly long standing defect in the typelist-metafunction Splice
This commit is contained in:
parent
400d0eb92e
commit
415e4746a6
4 changed files with 168 additions and 24 deletions
|
|
@ -412,6 +412,20 @@ namespace func{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class FUN, class TUP, typename = enable_if_Tuple<TUP>>
|
||||||
|
auto
|
||||||
|
bindArgTuple (FUN&& fun, TUP&& tuple)
|
||||||
|
{
|
||||||
|
return std::apply ([functor = forward<FUN>(fun)]
|
||||||
|
(auto&&... args)
|
||||||
|
{
|
||||||
|
return std::bind (move(functor)
|
||||||
|
,forward<decltype(args)> (args) ...);
|
||||||
|
}
|
||||||
|
,std::forward<TUP> (tuple));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closing a function over its arguments.
|
* Closing a function over its arguments.
|
||||||
|
|
@ -429,11 +443,11 @@ namespace func{
|
||||||
function<Ret(void)> closure_;
|
function<Ret(void)> closure_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FunctionClosure (SIG& f, Tuple<Args>& arg)
|
FunctionClosure (SIG& f, Tuple<Args>& args)
|
||||||
: closure_(TupleApplicator<SIG>(arg).bind(f))
|
: closure_{bindArgTuple (f, args)}
|
||||||
{ }
|
{ }
|
||||||
FunctionClosure (function<SIG> const& f, Tuple<Args>& arg)
|
FunctionClosure (function<SIG> const& f, Tuple<Args>& args)
|
||||||
: closure_(TupleApplicator<SIG>(arg).bind(f))
|
: closure_{bindArgTuple (f, args)}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Ret operator() () { return closure_(); }
|
Ret operator() () { return closure_(); }
|
||||||
|
|
@ -535,17 +549,18 @@ namespace func{
|
||||||
* @param arg value tuple, used to close function arguments starting from left
|
* @param arg value tuple, used to close function arguments starting from left
|
||||||
* @return new function object, holding copies of the values and using them at the
|
* @return new function object, holding copies of the values and using them at the
|
||||||
* closed arguments; on invocation, only the remaining arguments need to be supplied.
|
* closed arguments; on invocation, only the remaining arguments need to be supplied.
|
||||||
* @note BuildL, and consequently TupleApplicator _must take the arguments by-value._ Any attempt
|
* @note BuildL, and consequently std::bind _must take the arguments by-value._ Any attempt
|
||||||
* towards »perfect-forwarding« would be potentially fragile and not worth the effort,
|
* towards »perfect-forwarding« would be potentially fragile and not worth the effort,
|
||||||
* since the optimiser sees the operation as a whole.
|
* since the optimiser sees the operation as a whole.
|
||||||
* @todo 2/2025 However, the LeftReplacedArgs _could_ then possibly moved into the bind function,
|
* @todo 2/2025 However, the LeftReplacedArgs _could_ then possibly moved into the bind function,
|
||||||
* as could the functor, once we replace the Apply-template by STDLIB features.
|
* as could the functor, once we replace the Apply-template by STDLIB features.
|
||||||
|
* @todo 5/2025 seems indeed we could perfect-forward everything into the binder object.
|
||||||
*/
|
*/
|
||||||
static LeftReducedFunc
|
static LeftReducedFunc
|
||||||
bindFront (SIG const& f, Tuple<ValTypes> arg)
|
bindFront (SIG const& f, Tuple<ValTypes> arg)
|
||||||
{
|
{
|
||||||
LeftReplacedArgs params {BuildL(std::move(arg))};
|
LeftReplacedArgs params {BuildL(std::move(arg))};
|
||||||
return func::Apply<ARG_CNT>::template bind<LeftReducedFunc> (f, params);
|
return bindArgTuple (f, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** do a partial function application, closing the last arguments<br/>
|
/** do a partial function application, closing the last arguments<br/>
|
||||||
|
|
@ -560,7 +575,7 @@ namespace func{
|
||||||
bindBack (SIG const& f, Tuple<ValTypes> arg)
|
bindBack (SIG const& f, Tuple<ValTypes> arg)
|
||||||
{
|
{
|
||||||
RightReplacedArgs params {BuildR(std::move(arg))};
|
RightReplacedArgs params {BuildR(std::move(arg))};
|
||||||
return func::Apply<ARG_CNT>::template bind<RightReducedFunc> (f, params);
|
return bindArgTuple (f, params);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -611,6 +626,7 @@ namespace func{
|
||||||
{
|
{
|
||||||
Tuple<PreparedArgTypes> params {BuildPreparedArgs{std::make_tuple (val)}};
|
Tuple<PreparedArgTypes> params {BuildPreparedArgs{std::make_tuple (val)}};
|
||||||
return func::Apply<ARG_CNT>::template bind<ReducedFunc> (f, params);
|
return func::Apply<ARG_CNT>::template bind<ReducedFunc> (f, params);
|
||||||
|
// return bindArgTuple (f, params); ///////////////////////////////////////////////////////OOO does not compile when pos > length of ArgList
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -622,18 +638,11 @@ namespace func{
|
||||||
using util::unConst;
|
using util::unConst;
|
||||||
|
|
||||||
|
|
||||||
template<typename RET, typename ARG>
|
|
||||||
struct _Sig
|
|
||||||
{
|
|
||||||
using Type = typename BuildFunType<RET, ARG>::Sig;
|
|
||||||
using Applicator = TupleApplicator<Type>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename SIG, typename ARG>
|
template<typename SIG, typename ARG>
|
||||||
struct _Clo
|
struct _Clo
|
||||||
{
|
{
|
||||||
using Ret = typename _Fun<SIG>::Ret;
|
using Ret = typename _Fun<SIG>::Ret;
|
||||||
using Signature = typename _Sig<Ret,ARG>::Type;
|
using Signature = typename BuildFunType<Ret, ARG>::Sig;
|
||||||
using Type = FunctionClosure<Signature>;
|
using Type = FunctionClosure<Signature>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,6 @@ namespace interact {
|
||||||
using lib::meta::Split;
|
using lib::meta::Split;
|
||||||
using lib::meta::Tuple;
|
using lib::meta::Tuple;
|
||||||
using lib::meta::TySeq;
|
using lib::meta::TySeq;
|
||||||
using lib::meta::func::_Sig;
|
|
||||||
using lib::meta::func::PApply;
|
using lib::meta::func::PApply;
|
||||||
|
|
||||||
typedef typename _Fun<FUN>::Ret Ret;
|
typedef typename _Fun<FUN>::Ret Ret;
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ namespace test {
|
||||||
|
|
||||||
using func::Apply;
|
using func::Apply;
|
||||||
using func::TupleApplicator;
|
using func::TupleApplicator;
|
||||||
|
using func::bindArgTuple;
|
||||||
using func::FunctionClosure;
|
using func::FunctionClosure;
|
||||||
using func::closure;
|
using func::closure;
|
||||||
|
|
||||||
|
|
@ -208,6 +209,10 @@ namespace test {
|
||||||
Tuple<TySeq<int>> tup1 (11);
|
Tuple<TySeq<int>> tup1 (11);
|
||||||
Tuple<TySeq<int,int>> tup2 (11,12);
|
Tuple<TySeq<int,int>> tup2 (11,12);
|
||||||
Tuple<TySeq<int,int,int>> tup3 (11,12,13);
|
Tuple<TySeq<int,int,int>> tup3 (11,12,13);
|
||||||
|
DUMPVAL (tup0);
|
||||||
|
DUMPVAL (tup1);
|
||||||
|
DUMPVAL (tup2);
|
||||||
|
DUMPVAL (tup3);
|
||||||
|
|
||||||
typedef function<int()> BoundFun;
|
typedef function<int()> BoundFun;
|
||||||
|
|
||||||
|
|
@ -221,10 +226,10 @@ namespace test {
|
||||||
CHECK (11+12 == functor2() );
|
CHECK (11+12 == functor2() );
|
||||||
CHECK (11+12+13 == functor3() );
|
CHECK (11+12+13 == functor3() );
|
||||||
|
|
||||||
functor0 = TupleApplicator<int()> (tup0).bind (fun0);
|
functor0 = bindArgTuple (fun0, tup0);
|
||||||
functor1 = TupleApplicator<int(int)> (tup1).bind (fun1);
|
functor1 = bindArgTuple (fun1, tup1);
|
||||||
functor2 = TupleApplicator<int(int,int)> (tup2).bind (fun2);
|
functor2 = bindArgTuple (fun2, tup2);
|
||||||
functor3 = TupleApplicator<int(int,int,int)> (tup3).bind (fun3);
|
functor3 = bindArgTuple (fun3, tup3);
|
||||||
|
|
||||||
CHECK (-1 == functor0() );
|
CHECK (-1 == functor0() );
|
||||||
CHECK (11 == functor1() );
|
CHECK (11 == functor1() );
|
||||||
|
|
@ -258,10 +263,10 @@ namespace test {
|
||||||
CHECK (11+12 == functor2() );
|
CHECK (11+12 == functor2() );
|
||||||
CHECK (11+12+13 == functor3() );
|
CHECK (11+12+13 == functor3() );
|
||||||
|
|
||||||
functor0 = TupleApplicator<int()> (tup0).bind (unbound_functor0);
|
functor0 = bindArgTuple (unbound_functor0, tup0);
|
||||||
functor1 = TupleApplicator<int(int)> (tup1).bind (unbound_functor1);
|
functor1 = bindArgTuple (unbound_functor1, tup1);
|
||||||
functor2 = TupleApplicator<int(int,int)> (tup2).bind (unbound_functor2);
|
functor2 = bindArgTuple (unbound_functor2, tup2);
|
||||||
functor3 = TupleApplicator<int(int,int,int)> (tup3).bind (unbound_functor3);
|
functor3 = bindArgTuple (unbound_functor3, tup3);
|
||||||
|
|
||||||
CHECK (-1 == functor0() );
|
CHECK (-1 == functor0() );
|
||||||
CHECK (11 == functor1() );
|
CHECK (11 == functor1() );
|
||||||
|
|
|
||||||
|
|
@ -164397,6 +164397,137 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
<node CREATED="1749079273770" ID="ID_579464028" MODIFIED="1749079303130" TEXT="Schritt 2: Bind-to-Arg-Tuple neu implementieren">
|
||||||
|
<node CREATED="1749079304502" ID="ID_1638673098" MODIFIED="1749079325099" TEXT="rein intuitiv: das könnte mit der tuple-for-each Technik gehen...">
|
||||||
|
<node CREATED="1749079326999" ID="ID_34944630" MODIFIED="1749079363110" TEXT="also siehe forEach (tup, fun) ini tuple-helper.hpp"/>
|
||||||
|
<node CREATED="1749079368228" ID="ID_1090818949" MODIFIED="1749081564861" TEXT="und zwar mit diesem upack-Trick nach David Vandervoorde">
|
||||||
|
<arrowlink COLOR="#5d38bc" DESTINATION="ID_667556429" ENDARROW="Default" ENDINCLINATION="23;-31;" ID="Arrow_ID_1911198692" STARTARROW="None" STARTINCLINATION="-163;8;"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1749079417426" ID="ID_25131995" MODIFIED="1749079495704" TEXT="wende std::apply auf ein Lambda an ⟶ bekommt Tupel-Elemente als Argument-Pack">
|
||||||
|
<icon BUILTIN="idea"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1749080688030" ID="ID_162973867" MODIFIED="1749080711048" TEXT="scheint zu gehen .... zumindest wird's schon mal vom Compiler akzeptiert"/>
|
||||||
|
<node CREATED="1749080712258" ID="ID_1500605099" MODIFIED="1749080733204" TEXT="und wir haben nur volles forwarding für diesen Aufruf ⟶ Kopie im Binder"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1749081475903" ID="ID_605063967" MODIFIED="1749081505836" TEXT="Zwischenschritt">
|
||||||
|
<node CREATED="1749081506641" ID="ID_667556429" MODIFIED="1749081559124" TEXT="neue Hilfsfunktion bindArgTuple">
|
||||||
|
<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 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"/>
|
||||||
|
<node CREATED="1749082393371" ID="ID_1673961372" MODIFIED="1749082436871" TEXT="das hat hinten überschüssige Tupel-Elemente stillschweigend ignoriert">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
da es auf std::get<i> mit frest verdrahtetem Index aufsetzt
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1749082438789" ID="ID_477817163" MODIFIED="1749082442014" TEXT="nun...">
|
||||||
|
<node CREATED="1749082442742" ID="ID_71863154" MODIFIED="1749082453887" TEXT="ein zu groß konstruiertes Binder-Tupel wird durchgereicht"/>
|
||||||
|
<node CREATED="1749082454586" ID="ID_1932110866" MODIFIED="1749082461397" TEXT="std::apply ist wirklich voll generisch"/>
|
||||||
|
<node CREATED="1749082466958" ID="ID_1265074650" MODIFIED="1749082473555" TEXT="⟹ Compilation-Failure im Binder"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1749082478231" ID="ID_1161415270" MODIFIED="1749082494638" TEXT="kann man das bestehende Verhalten erhalten?">
|
||||||
|
<icon BUILTIN="help"/>
|
||||||
|
<node CREATED="1749082495532" ID="ID_367606531" MODIFIED="1749082502619" TEXT="weiß zwar nicht ob das sinnvoll ist...?"/>
|
||||||
|
<node CREATED="1749082503424" ID="ID_1896561211" MODIFIED="1749082514629" TEXT="aber es gibt einen Test und es ist so dokumentiert"/>
|
||||||
|
<node CREATED="1749082714136" ID="ID_1965208394" MODIFIED="1749082734615" TEXT="also ⟹ wie kommt die Länge des Binder-Tuples in BindToArg zustande?">
|
||||||
|
<node CREATED="1749085756772" ID="ID_1774712935" MODIFIED="1749085768340" TEXT="es wird aus drei Teilen zusammengesetzt"/>
|
||||||
|
<node CREATED="1749085769610" ID="ID_1876115458" MODIFIED="1749085780773" TEXT="und Präfix/Suffix beruhen auf der angegebenen pos"/>
|
||||||
|
<node CREATED="1749085786524" ID="ID_1747871175" MODIFIED="1749085803306" TEXT="Zugriff vewendet die Splice-Metafunktion">
|
||||||
|
<node CREATED="1749086105021" ID="ID_242475174" MODIFIED="1749086116894" TEXT="Splice war explizit für diesen Zweck geschaffen worden">
|
||||||
|
<icon BUILTIN="info"/>
|
||||||
|
<node CREATED="1749086171316" ID="ID_289035698" MODIFIED="1749086179374" TEXT="der Name ist etwas irreführend"/>
|
||||||
|
<node CREATED="1749086180059" ID="ID_1000117906" MODIFIED="1749086190840" TEXT="es ist mehr wie ein »slide edit«"/>
|
||||||
|
<node CREATED="1749086192917" ID="ID_51185866" MODIFIED="1749086202659" TEXT="geprüft: es gibt nur diese eine Verwendung"/>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1749086082424" ID="ID_792762505" MODIFIED="1749086090303" TEXT="Fehler in List-Splice">
|
||||||
|
<icon BUILTIN="broken-line"/>
|
||||||
|
<node CREATED="1749086093678" ID="ID_1935542921" MODIFIED="1749086103057" TEXT="dank umgeschriebenen Test jetzt klar zu sehen">
|
||||||
|
<node CREATED="1749086219612" ID="ID_1085792366" MODIFIED="1749086248922" TEXT="OLi : -<9>-<8>-"/>
|
||||||
|
<node CREATED="1749086269399" ID="ID_878268645" MODIFIED="1749086278084" TEXT="List1: -<1>-<2>-<3>-"/>
|
||||||
|
<node CREATED="1749086340477" ID="ID_1317717416" MODIFIED="1749086342945" TEXT="Fall-1">
|
||||||
|
<node CREATED="1749086293428" ID="ID_294374445" MODIFIED="1749086474248" TEXT="Splice<List1, OLi>: -<9>-<8>-<3>-">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1749086357867" ID="ID_302844078" MODIFIED="1749086474248" TEXT="Splice<List1, OLi2, 0>::Front: "-"">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1749086380050" ID="ID_464757347" MODIFIED="1749086487758" TEXT="Splice<List1, OLi2, 0>::Back: -<2>-<3>-">
|
||||||
|
<icon BUILTIN="broken-line"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1749086394605" ID="ID_23168968" MODIFIED="1749086396476" TEXT="Fall-2">
|
||||||
|
<node CREATED="1749086407860" ID="ID_1388390572" MODIFIED="1749086474248" TEXT="Splice<List1, OLi, 1>: -<1>-<9>-<8>-">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1749086430949" ID="ID_1849113809" MODIFIED="1749086474248" TEXT="Splice<List1, OLi2, 1>::Front: -<1>-">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1749086451494" ID="ID_1435991702" MODIFIED="1749086487758" TEXT="Splice<List1, OLi2, 1>::Back: -<3>-">
|
||||||
|
<icon BUILTIN="broken-line"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#bd0711" CREATED="1749086526784" ID="ID_757037322" MODIFIED="1749086594846">
|
||||||
|
<richcontent TYPE="NODE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p style="text-align: center">
|
||||||
|
d.h.: für die Back-Berchnung
|
||||||
|
</p>
|
||||||
|
<p style="text-align: center">
|
||||||
|
wird die Länge der Overlay-Liste
|
||||||
|
</p>
|
||||||
|
<p style="text-align: center">
|
||||||
|
nicht richtig gerechnet
|
||||||
|
</p>
|
||||||
|
<p style="text-align: center">
|
||||||
|
<font size="2">» off by one «</font>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
<icon BUILTIN="broken-line"/>
|
||||||
|
<node CREATED="1749089660750" ID="ID_1758217572" MODIFIED="1749089678824" TEXT="sonderbar: dieser Fehler besteht so schon lange....">
|
||||||
|
<icon BUILTIN="clanbomber"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1749089681585" ID="ID_1206510313" MODIFIED="1749089694378" TEXT="warum wurde das nie bemerkt?">
|
||||||
|
<node CREATED="1749089706918" ID="ID_1155480413" MODIFIED="1749089728318" TEXT="Hypothese: man hat immer nur das close-last wirklich getestet"/>
|
||||||
|
<node COLOR="#5b280f" CREATED="1749090006670" ID="ID_844297972" MODIFIED="1749090022859" TEXT="das stimmt nicht! function-composition-test: check_bindToArbitraryParameter">
|
||||||
|
<icon BUILTIN="button_cancel"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1749090267058" ID="ID_541383828" MODIFIED="1749090428234" TEXT="Fokussierte Untersuchung notwendig!">
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#338800" CREATED="1749081592088" ID="ID_1143027952" MODIFIED="1749081623439" TEXT="Tests OK">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1749081604439" ID="ID_372037050" MODIFIED="1749081621876" TEXT="FunctionClosure_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>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue