Invocation: investigate ways to provide partial application

...on top of the parameter-decorating functionality developed thus far.
The idea is to allow in the `NodeBuilder` to supply ''some parameters''
directly, while the remaining parameters will be drawn from automation.

Several years ago, I developed some helpers for partial function closure.
Unfortunately these utils are somewhat limited, and rely on some pre-C++11
constructs, yet seem to be usable for the task at hand, since parameters
are always expected as value objects by definition.

This changeset shows a working proof-of concept for left-closing a
parameter tuple with 5 elements; this turns out to surprisingly difficult
due to the full genericity of the acceptable parameter-aggregates...
This commit is contained in:
Fischlurch 2025-02-15 23:47:21 +01:00
parent 79b45601c0
commit 3611bc94ee
8 changed files with 464 additions and 15 deletions

View file

@ -33,6 +33,12 @@
** Providing a one-shot function-style interface for this kind of manipulations ** Providing a one-shot function-style interface for this kind of manipulations
** is still considered beneficial, and thus we should gradually modernise ** is still considered beneficial, and thus we should gradually modernise
** the tools we want to retain... ** the tools we want to retain...
** @todo 2/25 note that there is a bind_front in C++20 and C++23 will provide a bind_back
** helper, which would provide the implementation fully in accordance with current
** expectations (including move, constexpr); if we choose to retain a generic
** function-style front-end, it should be aligned with these standard facilities.
** We might want to retain a simple generic interface especially for binding some
** selected argument, which handles the intricacies of storing the functor.
** **
** @see control::CommandDef usage example ** @see control::CommandDef usage example
** @see function.hpp ** @see function.hpp
@ -412,7 +418,7 @@ namespace func{
* @tparam TAR full target tuple type. Some oft the elements within this tuple will * @tparam TAR full target tuple type. Some oft the elements within this tuple will
* be default constructed, some will be initialised from the SRC tuple * be default constructed, some will be initialised from the SRC tuple
* @tparam SRC argument tuple type, for the values _actually to be initialised_ here. * @tparam SRC argument tuple type, for the values _actually to be initialised_ here.
* @tparam start position within TYPES, at which the sequence of init-arguments starts; * @tparam start position within \a SRC, at which the sequence of init-arguments starts;
* all other positions will just be default initialised * all other positions will just be default initialised
* @see lib::meta::TupleConstructor * @see lib::meta::TupleConstructor
*/ */

View file

@ -141,11 +141,11 @@ namespace meta {
using Penult = typename _Vari<L,XS...>::Penult; using Penult = typename _Vari<L,XS...>::Penult;
using Ultima = typename _Vari<L,XS...>::Ultima; using Ultima = typename _Vari<L,XS...>::Ultima;
using _Tail_Pre_ = typename _Vari<L, XS...>::Prefix; using _Tail_Pre_ = typename _Vari<L,XS...>::Prefix;
using _Tail_Rev_ = typename _Vari<L,XS...>::Revers; using _Tail_Rev_ = typename _Vari<L,XS...>::Revers;
using Remain = L<XS...>; using Remain = L<XS...>;
using Prefix = typename _Vari<L, X, _Tail_Pre_>::Prepend; using Prefix = typename _Vari<L, X, _Tail_Pre_>::Prepend;
using Revers = typename _Vari<L, Ultima, _Tail_Rev_>::Prepend; using Revers = typename _Vari<L, Ultima, _Tail_Rev_>::Prepend;
}; };

View file

@ -360,7 +360,6 @@ namespace lib {
auto auto
adaptIn (FUN&& fun) adaptIn (FUN&& fun)
{ {
using lib::meta::func::applyFirst;
using _Fun = lib::meta::_Fun<FUN>; using _Fun = lib::meta::_Fun<FUN>;
static_assert (_Fun(), "Need something function-like."); static_assert (_Fun(), "Need something function-like.");

View file

@ -102,6 +102,7 @@ namespace engine {
using lib::meta::ElmTypes; using lib::meta::ElmTypes;
using lib::meta::NullType; using lib::meta::NullType;
using lib::meta::Tagged; using lib::meta::Tagged;
using lib::meta::TySeq;
using std::is_pointer; using std::is_pointer;
using std::is_reference; using std::is_reference;
using std::is_convertible; using std::is_convertible;
@ -110,6 +111,7 @@ namespace engine {
using std::remove_pointer_t; using std::remove_pointer_t;
using std::tuple_element_t; using std::tuple_element_t;
using std::add_pointer_t; using std::add_pointer_t;
using std::conditional_t;
using std::__and_; using std::__and_;
using std::__not_; using std::__not_;
@ -248,7 +250,7 @@ namespace engine {
static constexpr bool hasParam() { return _Proc::hasParam(); } static constexpr bool hasParam() { return _Proc::hasParam(); }
using Param = std::conditional_t<hasParam(), typename _Proc::SigP, std::tuple<>>; using Param = conditional_t<hasParam(), typename _Proc::SigP, std::tuple<>>;
template<class PF> template<class PF>
using Res = typename _Fun<PF>::Ret; using Res = typename _Fun<PF>::Ret;
@ -332,8 +334,8 @@ namespace engine {
using BuffI = BuffS<FAN_I>; using BuffI = BuffS<FAN_I>;
using BuffO = BuffS<FAN_O>; using BuffO = BuffS<FAN_O>;
using Param = std::conditional_t<hasParam(), typename _Trait::SigP, std::tuple<>>; using Param = conditional_t<hasParam(), typename _Trait::SigP, std::tuple<>>;
using ArgI = std::conditional_t<hasInput(), typename _Trait::SigI, std::tuple<>>; using ArgI = conditional_t<hasInput(), typename _Trait::SigI, std::tuple<>>;
using ArgO = typename _Trait::SigO; using ArgO = typename _Trait::SigO;
@ -373,7 +375,7 @@ namespace engine {
using NotProvided = Tagged<NullType, X>; using NotProvided = Tagged<NullType, X>;
template<bool yes, class B> template<bool yes, class B>
using Provide_if = std::conditional_t<yes, B, NotProvided<B>>; using Provide_if = conditional_t<yes, B, NotProvided<B>>;
using FeedOutput = BufferSlot_Output; using FeedOutput = BufferSlot_Output;
using FeedInput = Provide_if<hasInput(), BufferSlot_Input>; using FeedInput = Provide_if<hasInput(), BufferSlot_Input>;
@ -561,6 +563,8 @@ namespace engine {
}; };
using ElmsI = typename _Proc::ElmsI; using ElmsI = typename _Proc::ElmsI;
using ElmsO = typename _Proc::ElmsO; using ElmsO = typename _Proc::ElmsO;
using ElmsP = conditional_t<_Trait::hasParam(), typename _Proc::ArgP, TySeq<>>;
using Param = typename _Proc::SigP; ///////////////////////////////////////////////////////////////////OOO qualify?
template<template<class> class META> template<template<class> class META>
using OutTypesApply = typename ElmsO::template Apply<META>; using OutTypesApply = typename ElmsO::template Apply<META>;

View file

@ -493,6 +493,53 @@ namespace engine {
}; };
} }
template<class PAR>
struct ClosureBuilder;
template<template<typename...> class TUP, typename...PARS>
struct ClosureBuilder<TUP<PARS...>>
{
using Params = TUP<PARS...>;
static Params
buildParam (PARS ...params)
{
return {params...};
}
template<typename...VALS>
static auto
closeFront (VALS ...vs)
{
using lib::meta::_Fun;
using lib::meta::TySeq;
using lib::meta::func::PApply;
using ClosedTypes = TySeq<VALS...>;
using ParamBuilderSig = Params(PARS...);
auto partialClosure = PApply<ParamBuilderSig, ClosedTypes>::bindFront (buildParam, std::make_tuple(vs...));
using RemainingArgs = typename _Fun<decltype(partialClosure)>::Args;
using RemStripped = typename lib::meta::StripNullType<RemainingArgs>::Seq;
using RemainingParams = typename lib::meta::RebindVariadic<TUP, RemStripped>::Type;
// using idx = std::make_index_sequence<sizeof...(VALS)>;
// auto& makeParamAggregate = buildParam;
return [closure = move(partialClosure)
]
(RemainingParams remPar)
{
return std::apply (closure, remPar);
};
}
};
template<typename PAR, typename...PARS>
auto
closeParamFront (PAR v1, PARS ...vs)
{
using Params = typename WAB::Param;
return adaptParam(
ClosureBuilder<Params>::template closeFront (v1,vs...));
}
/*************************************************************//** /*************************************************************//**

View file

@ -250,8 +250,8 @@ namespace engine {
static constexpr SizMark<sizeof(TurnoutWeaving)> sizMark{}; static constexpr SizMark<sizeof(TurnoutWeaving)> sizMark{};
static constexpr uint FAN_I = PROT::FAN_I; static constexpr uint FAN_I = PROT::FAN_I;
static constexpr uint FAN_O = PROT::FAN_O; static constexpr uint FAN_O = PROT::FAN_O;
using Param = typename PROT::Param; ///////////////////////////OOO integrate here a partial-closure-helper
using TypeMarker = std::function<BuffDescr(BufferProvider&)>; using TypeMarker = std::function<BuffDescr(BufferProvider&)>;
using ProviderRef = std::reference_wrapper<BufferProvider>; using ProviderRef = std::reference_wrapper<BufferProvider>;

View file

@ -23,6 +23,7 @@
#include "lib/test/diagnostic-output.hpp" #include "lib/test/diagnostic-output.hpp"
#include "lib/time/timequant.hpp" #include "lib/time/timequant.hpp"
#include "lib/time/timecode.hpp" #include "lib/time/timecode.hpp"
#include "lib/iter-explorer.hpp"
#include "lib/symbol.hpp" #include "lib/symbol.hpp"
#include <array> #include <array>
@ -31,6 +32,7 @@
using lib::Symbol; using lib::Symbol;
using std::string; using std::string;
using std::array; using std::array;
using lib::explore;
using lib::time::Time; using lib::time::Time;
using lib::time::QuTime; using lib::time::QuTime;
using lib::time::FrameNr; using lib::time::FrameNr;
@ -62,6 +64,7 @@ namespace test {
build_Node_fixedParam(); build_Node_fixedParam();
build_Node_dynamicParam(); build_Node_dynamicParam();
build_Node_adaptedParam(); build_Node_adaptedParam();
build_Node_closedParam();
build_connectedNodes(); build_connectedNodes();
build_ParamNode(); build_ParamNode();
} }
@ -190,6 +193,35 @@ namespace test {
} }
/** @test build a node and partially close (≙ predefine) some parameters,
* while leaving other parameters open to be set on invocation
* through a parameter-functor.
* @remark it is quite common that processing functionality provided by an
* external library exposes both technical and artistic parameters, which
* leads to the situation that technical parameters can be predetermined
* and configured to a fixed value, while artistic parameters remain open
* for control by the user, either as a fixed setting (e.g. colour balance)
* or even a dynamic control by an automation function).
*/
void
build_Node_closedParam()
{
using Params = std::tuple<uint,uint,uint,uint,uint>;//array<uint, 5>;
auto procFun = [](Params params, uint* out) { auto [v1,v2,v3,v4,v5] = params; *out = v1+v2+v3+v4+v5; };//explore(params).resultSum(); };
auto autoFun = [](Time nomTime){ return FrameNr::quant (nomTime, SECONDS_GRID); };
ProcNode node{prepareNode("Test")
.preparePort()
.invoke ("fun()", procFun)
.closeParamFront (1,2,3,4)
.attachAutomation (autoFun)
.completePort()
.build()};
Time timeOfEvil{5555,0};
SHOW_EXPR(invokeRenderNode(node,timeOfEvil));
}
/** @test build a chain with three connected Nodes /** @test build a chain with three connected Nodes
* - have two source nodes, which accept a parameter * - have two source nodes, which accept a parameter
* - but configure them differently: one gets a constant, * - but configure them differently: one gets a constant,

View file

@ -58763,7 +58763,7 @@
</node> </node>
</node> </node>
</node> </node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700669580665" FOLDED="true" ID="ID_1852128670" MODIFIED="1700703920205" TEXT="Funktor-Manipulationen"> <node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700669580665" FOLDED="true" ID="ID_1852128670" MODIFIED="1739581436031" TEXT="Funktor-Manipulationen">
<icon BUILTIN="hourglass"/> <icon BUILTIN="hourglass"/>
<icon BUILTIN="pencil"/> <icon BUILTIN="pencil"/>
<node CREATED="1700669596447" ID="ID_1886923243" MODIFIED="1700669617888" TEXT="einige Werkzeuge hatte ich vor sehr langer Zeit schon gebaut...."> <node CREATED="1700669596447" ID="ID_1886923243" MODIFIED="1700669617888" TEXT="einige Werkzeuge hatte ich vor sehr langer Zeit schon gebaut....">
@ -58793,7 +58793,8 @@
</node> </node>
</node> </node>
</node> </node>
<node CREATED="1700670186153" ID="ID_753645097" MODIFIED="1700670190204" TEXT="partial-Application"> <node CREATED="1700670186153" ID="ID_753645097" MODIFIED="1739581625708" TEXT="partial-Application">
<linktarget COLOR="#8a2963" DESTINATION="ID_753645097" ENDARROW="Default" ENDINCLINATION="-424;2942;" ID="Arrow_ID_621726759" SOURCE="ID_1160952116" STARTARROW="None" STARTINCLINATION="-1012;-37;"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700670130760" ID="ID_1114511607" MODIFIED="1700686530654" TEXT="partielle Funktions-Anwendung modernisieren"> <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;"/> <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"/> <icon BUILTIN="pencil"/>
@ -58836,6 +58837,86 @@
</html></richcontent> </html></richcontent>
</node> </node>
</node> </node>
<node CREATED="1739577090376" ID="ID_1072629570" MODIFIED="1739577099267" TEXT="Einsichten / moderne Tools">
<icon BUILTIN="idea"/>
<node CREATED="1739577101558" ID="ID_1975024377" MODIFIED="1739577112033" TEXT="baut im Grunde auf std::bind auf"/>
<node CREATED="1739577112711" ID="ID_1192118535" MODIFIED="1739581980174" TEXT="std::bind ist inzwischen minimalistisch und flexibel">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
definiert in &lt;functional&gt;, ca. Zeile 280
</p>
</body>
</html></richcontent>
<icon BUILTIN="info"/>
<node CREATED="1739577144358" ID="ID_956185646" MODIFIED="1739577152295" TEXT="es ist ein erweitertes Tupel"/>
<node CREATED="1739577152968" ID="ID_1330566005" MODIFIED="1739577161667" TEXT="der Funktor wird selber inline gespeichert"/>
<node CREATED="1739577164343" ID="ID_359566395" MODIFIED="1739577197158" TEXT="die gebundenen Argumente sind als Tupel ebenfalls inline gespeichert"/>
<node CREATED="1739577198169" ID="ID_21496399" MODIFIED="1739577217680">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
alle Initialiser werden per <i>perfect-forwarding</i>&#160;genommen
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1739577253995" FOLDED="true" ID="ID_1700090604" MODIFIED="1739582013463" TEXT="der eigentliche Aufruf erfolgt per std::invoke">
<node CREATED="1739577295927" ID="ID_1757581587" MODIFIED="1739577310681" TEXT="dieses bekommt den funktor per Referenz"/>
<node CREATED="1739577319595" ID="ID_1026084367" MODIFIED="1739577337604" TEXT="sowie die Argumente als fold-Expression durch einen Remapper"/>
<node CREATED="1739577549397" ID="ID_203730942" MODIFIED="1739582002169" TEXT="dieser bekommt">
<linktarget COLOR="#397bac" DESTINATION="ID_203730942" ENDARROW="Default" ENDINCLINATION="-126;19;" ID="Arrow_ID_770856500" SOURCE="ID_660361642" STARTARROW="None" STARTINCLINATION="167;7;"/>
<node CREATED="1739577707304" ID="ID_753171948" MODIFIED="1739577715424" TEXT="eine Referenz auf das aktuelle Argument"/>
<node CREATED="1739577716144" ID="ID_357978652" MODIFIED="1739577748127" TEXT="ein Tupel-&amp; f&#xfc;r die sonstigen (freien) Argumente"/>
<node CREATED="1739577749403" ID="ID_218757629" MODIFIED="1739577757630" TEXT="er reicht entweder die Referenz durch"/>
<node CREATED="1739577758242" ID="ID_1818088093" MODIFIED="1739577824087" TEXT="oder wenn sie ein Placeholder ist, remappt der die sonstigen Argumente">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
im Placeholder-Typ wird die Index-Position gespeichert
</p>
</body>
</html></richcontent>
</node>
</node>
<node CREATED="1739577825329" ID="ID_173412302" MODIFIED="1739578029896" TEXT="das bedeutet: im Typ des Binders stecken Arg-Typen, plus remapping-Info">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
und zwar als Signatur Fun(Arg....);
</p>
<p>
dabei sind die Arg entweder exakt die Typen, wie sie gebunden und damit im Binder gespeichert sind, oder die Placeholder, die in ihrem Typ die Position aus dem verbleibenden Arg-Tupel codiert halten.
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1739578153245" ID="ID_1925401409" MODIFIED="1739578180409" TEXT="&#x27f9; die gebundenen Argumente kommen als Referenz aus dem intern gespeicherten Tupel"/>
<node CREATED="1739578181249" ID="ID_1870061994" MODIFIED="1739578195091" TEXT="&#x27f9; die sonstigen Argumente werden per perfect-forwarding durchgereicht"/>
</node>
</node>
<node CREATED="1739578237489" ID="ID_843718662" MODIFIED="1739578271506" TEXT="die Hilfsklasse TupleApplicator und Apply&lt;N&gt; sind komplett ersetzbar">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
....durch std::apply und std::invoke
</p>
</body>
</html>
</richcontent>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1739578334244" ID="ID_277606452" MODIFIED="1739578338702" TEXT="Vorgaben">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
<node CREATED="1739578282176" ID="ID_1393053020" MODIFIED="1739578297573" TEXT="Hauptfokus beim Umbau sollte das perfect-Forwarding sein"/>
<node CREATED="1739578299345" ID="ID_1545493795" MODIFIED="1739578332823" TEXT="dagegen die Positions-Steuerung sollte weiterhin per Typ-Sequenz-Manipulation erfolgen"/>
</node>
</node>
<node COLOR="#338800" CREATED="1700672430249" HGAP="136" ID="ID_975422639" MODIFIED="1700686519692" TEXT="schrittweise vorgehen...." VSHIFT="-7"> <node COLOR="#338800" CREATED="1700672430249" HGAP="136" ID="ID_975422639" MODIFIED="1700686519692" TEXT="schrittweise vorgehen...." VSHIFT="-7">
<icon BUILTIN="pencil"/> <icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1700672449602" ID="ID_1457801203" MODIFIED="1700680981796" TEXT="erst mal applyFirst neu implementieren"> <node COLOR="#338800" CREATED="1700672449602" ID="ID_1457801203" MODIFIED="1700680981796" TEXT="erst mal applyFirst neu implementieren">
@ -58892,11 +58973,45 @@
<head/> <head/>
<body> <body>
<p> <p>
wenn man ein Objekt wie einen unique_ptr oder einen vector <b>per value</b>&#160; an den partial-application-Functor &#252;bergibt, dann wandert die Ownership zu der Kopie, die in der Closure gespeichert ist. Mit dem ersten Aufruf der Funktion wander die Ownership weiter zum jeweils gebunden Funktions-Argument, und hinterl&#228;&#223;t in der Closure ein &#187;verbrauchtes Objekt&#171;. Weitere Aufrufe der gleichen Funktion bekommen dann dieses potentiell invalidierte Objekt. wenn man ein Objekt wie einen unique_ptr oder einen vector <b>per value</b> an den partial-application-Functor &#252;bergibt, dann wandert die Ownership zu der Kopie, die in der Closure gespeichert ist. Mit dem ersten Aufruf der Funktion wander die Ownership weiter zum jeweils gebunden Funktions-Argument, und hinterl&#228;&#223;t in der Closure ein &#187;verbrauchtes Objekt&#171;. Weitere Aufrufe der gleichen Funktion bekommen dann dieses potentiell invalidierte Objekt.
</p> </p>
</body> </body>
</html></richcontent> </html></richcontent>
<icon BUILTIN="clanbomber"/> <icon BUILTIN="clanbomber"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1739581690561" HGAP="49" ID="ID_1293782408" MODIFIED="1739581965371" TEXT="ich glaube das ist gar nicht m&#xf6;glich" VSHIFT="-2">
<font NAME="SansSerif" SIZE="11"/>
<icon BUILTIN="idea"/>
<icon BUILTIN="help"/>
<node CREATED="1739581745905" ID="ID_660361642" MODIFIED="1739582009913">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
<font face="Monospaced" color="#1b0a9b">std::bind</font>&#160;funktioniert nur mit <b>copy-konstruierbaren</b>&#160; Objekten
</p>
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
nur die frei-bleibenden Argumente k&#246;nnen move-Semantik haben. Und wenn man <i>definitiv eine Referenz</i>&#160;im Binder speichern m&#246;chte, so <i>mu&#223; man</i>&#160;einen <font face="Monospaced">std::reference_wrapper</font>&#160;abliefern.
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#397bac" DESTINATION="ID_203730942" ENDARROW="Default" ENDINCLINATION="-126;19;" ID="Arrow_ID_770856500" STARTARROW="None" STARTINCLINATION="167;7;"/>
</node>
<node CREATED="1739581759744" ID="ID_319570731" MODIFIED="1739581856408" TEXT="es mu&#xdf; eine Kopie im Binder speichern, und von dieser das Funktions-Argument initialisieren">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
std::bind wendet intern ganz ausdr&#252;cklich <font face="Monospaced"><b>std::decay_t</b></font>&#160; an, und speichert das sich ergebende Value-artige Objekt
</p>
</body>
</html></richcontent>
</node>
</node>
</node> </node>
<node CREATED="1700695355441" ID="ID_689943340" MODIFIED="1700695375247" TEXT="den Fall kann man nicht generisch ausschlie&#xdf;en"/> <node CREATED="1700695355441" ID="ID_689943340" MODIFIED="1700695375247" TEXT="den Fall kann man nicht generisch ausschlie&#xdf;en"/>
<node CREATED="1700695395388" ID="ID_1350839643" MODIFIED="1700695411652" TEXT="...denn er ist ununterscheidbar von einfacher Value-Semantik"/> <node CREATED="1700695395388" ID="ID_1350839643" MODIFIED="1700695411652" TEXT="...denn er ist ununterscheidbar von einfacher Value-Semantik"/>
@ -105572,9 +105687,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<node CREATED="1739467898031" ID="ID_1231552769" MODIFIED="1739467920604" TEXT="man kann die Reihenfolge geschickter anordnen"/> <node CREATED="1739467898031" ID="ID_1231552769" MODIFIED="1739467920604" TEXT="man kann die Reihenfolge geschickter anordnen"/>
<node CREATED="1739467941421" ID="ID_1175438960" MODIFIED="1739467985473" TEXT="und damit den Typ von der Builder-Funktion abnehmen"> <node CREATED="1739467941421" ID="ID_1175438960" MODIFIED="1739467985473" TEXT="und damit den Typ von der Builder-Funktion abnehmen">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
das geht, weil durch das constexpr-if die Funktion jedesmal erneut instantiiert wird, mit dann jeweils anderem deduziertem auto-Returntyp das geht, weil durch das constexpr-if die Funktion jedesmal erneut instantiiert wird, mit dann jeweils anderem deduziertem auto-Returntyp
@ -105599,6 +105712,254 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</node> </node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1739242327059" ID="ID_1669934372" MODIFIED="1739242373123" TEXT="Adapter zum Binden bestimmter Argumente im Node-Builder generieren"> <node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1739242327059" ID="ID_1669934372" MODIFIED="1739242373123" TEXT="Adapter zum Binden bestimmter Argumente im Node-Builder generieren">
<icon BUILTIN="full-3"/> <icon BUILTIN="full-3"/>
<node CREATED="1739549014719" ID="ID_1456986239" MODIFIED="1739549029021" TEXT="Design-Frage: wie weit ausarbeiten?">
<node CREATED="1739549031081" ID="ID_1258607359" MODIFIED="1739549281465" TEXT="minimal-L&#xf6;sung: gar nix bieten &#x2014; User soll &#x3bb; bauen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...denn im Grunde sind alle diese Bindings mit Lambdas relativ banal zu formulieren &#8212; es ist halt blo&#223; relativ technisch, versaut den Code und erfordert vom Benutzer viel Pr&#228;zision und Beachten von feinen Punkten. Da &#187;der Benutzer&#171; auf absehbare Zeit ich selbst bin, ist das &#8212; M&#228;&#228;h. Ja ich kann das. W&#228;&#228;h
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1739549074693" ID="ID_189358758" MODIFIED="1739549443676" TEXT="direkt definiertes Template-&#x3bb; f&#xfc;r bind-to-first in NodeBuilder einbauen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Das klingt nach einer L&#246;sung, die <i>billig zu haben w&#228;re.</i>&#160;Es sind ein paar Zeilen recht technischer Code im Node-Builder, der ohnehin in diesem Bereich &#8222;nicht mehr sch&#246;n&#8220; ist. Kann man also in jedem Fall mal einbauen &#8212; mein <i>einziger Zweifel betrifft die N&#252;tzlichkeit und Relevanz;</i>&#160;warum man ausgerechnet ein einziges erstes Argument schlie&#223;en wollte, will sich mir nicht recht erschlie&#223;en
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1739549457748" ID="ID_1160952116" MODIFIED="1739581633828" TEXT="auf die alten function-closure-Utils zur&#xfc;ckgreifen und einen Wrapper daf&#xfc;r anbieten">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Das ist pre-C++11-Code, nur oberfl&#228;chlich modernisiert, und bisher nur in einem Bereich testhalber verwendet (f&#252;r Proc-Commands). Grunds&#228;tzlich m&#246;chte ich diesen Code aber erhalten, nicht loswerden. <b>Risiko</b>: es gibt wohl einige &#187;Untiefen&#171; &#8212; es ist nicht klar, wo Heap-Allokationen stattfinden, und auch der Umgang mit non-copyable oder move-only-Typen ist nicht wirklich ausgeleuchtet. <i>Wahrscheinlich deshalb habe ich vor wenigen Jahren die beiden convenience-Wrapper vom alten Implementierungs-Framework abgekoppelt und direkt per Lambda implementiert</i>&#160;&#8212; und dann seither doch nicht mehr benutzt (best&#228;tigt die Zweifel bez&#252;glich partieller Applikation nur eines Arguments, das ist dann doch ehr so ein Haskell-Ding)
</p>
</body>
</html>
</richcontent>
<arrowlink COLOR="#8a2963" DESTINATION="ID_753645097" ENDARROW="Default" ENDINCLINATION="-424;2942;" ID="Arrow_ID_621726759" STARTARROW="None" STARTINCLINATION="-1012;-37;"/>
<node CREATED="1739556113890" ID="ID_1805875630" MODIFIED="1739580594120" TEXT="im konkreten Fall w&#xe4;re die Beschr&#xe4;nkung dieser Utils wohl tragbar">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_1805875630" ENDARROW="Default" ENDINCLINATION="331;15;" ID="Arrow_ID_275367387" SOURCE="ID_1748409648" STARTARROW="None" STARTINCLINATION="290;15;"/>
</node>
<node CREATED="1739557170512" ID="ID_1709833697" MODIFIED="1739582115569" TEXT="zu bietende Funktionalit&#xe4;t">
<arrowlink COLOR="#4936b3" DESTINATION="ID_1634640852" ENDARROW="Default" ENDINCLINATION="82;-233;" ID="Arrow_ID_40372708" STARTARROW="None" STARTINCLINATION="-287;31;"/>
<node CREATED="1739557219738" ID="ID_791362936" MODIFIED="1739557246161" TEXT="closeFront"/>
<node CREATED="1739557224737" ID="ID_881913989" MODIFIED="1739557250783" TEXT="closeBack"/>
<node CREATED="1739557252012" ID="ID_82088219" MODIFIED="1739557259143" TEXT="closeArg&lt;i&gt;"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1739578460187" ID="ID_550537240" MODIFIED="1739580673731" TEXT="Analyse">
<icon BUILTIN="info"/>
<node CREATED="1739578467409" ID="ID_1619628833" MODIFIED="1739580420196" TEXT="die zu bindende &#xbb;Funktion&#xab; ist std::make_tuple">
<font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="idea"/>
<node CREATED="1739580437643" ID="ID_408862933" MODIFIED="1739580470011" TEXT="denn schlie&#xdf;lich soll der Adapter ein Parameter-Tuple produzieren"/>
<node CREATED="1739580471143" ID="ID_1631683007" MODIFIED="1739580480982" TEXT="aber einige der Elemente dieses Tuples sind vorgebunden"/>
<node CREATED="1739580500099" ID="ID_509055645" MODIFIED="1739580505677" TEXT="das bedeutet">
<node CREATED="1739580507514" ID="ID_298884871" MODIFIED="1739580521068" TEXT="std::make_tuple ist ohnehin eine Funktions-Referenz"/>
<node CREATED="1739580522488" ID="ID_1144023619" MODIFIED="1739580549280" TEXT="die vor-gebundenen Werte m&#xfc;ssen per-Value vorliegen und copy-constructible sein"/>
</node>
<node CREATED="1739580556302" ID="ID_1748409648" MODIFIED="1739580594120" TEXT="somit kein grunds&#xe4;tzliches Problem mit dem alten Tooling">
<arrowlink DESTINATION="ID_1805875630" ENDARROW="Default" ENDINCLINATION="331;15;" ID="Arrow_ID_275367387" STARTARROW="None" STARTINCLINATION="290;15;"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1739663114472" HGAP="61" ID="ID_154602686" MODIFIED="1739663139464" TEXT="aber Ticket!!" VSHIFT="21">
<icon BUILTIN="yes"/>
</node>
</node>
</node>
<node CREATED="1739580597277" ID="ID_1887120885" MODIFIED="1739580647330">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
die Arit&#228;t mu&#223; ermittelt werden,
</p>
<p>
denn <font face="Monospaced" color="#181086">std::make_tuple</font>&#160;ist ein Template
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1739580770558" ID="ID_1162628481" MODIFIED="1739580788692" TEXT="das sich ergebende Konstrukt">
<node CREATED="1739580792958" ID="ID_1753283976" MODIFIED="1739580812227" TEXT="packt die gebundenen Elemente in den processing-funktor"/>
<node CREATED="1739580816968" ID="ID_823161940" MODIFIED="1739580925274" TEXT="jedes Argument wird also 2-Mal kopiert">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...weil wir den Processing-Functor jeweils aus dem Prototypen kopieren, dann aber in der Anwendung des Binders nochmal das gespeicherte Element ins Ergebnis kopieren
</p>
</body>
</html>
</richcontent>
<node CREATED="1739580930611" ID="ID_67861361" MODIFIED="1739581229610" TEXT="l&#xe4;&#xdf;t sich bei diesem Design kaum vermeiden">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
zwar k&#246;nnte man auf die Idee kommen, den Adapter <i>hinter den Parameter-Functor</i>&#160;zu setzen. Das l&#228;&#223;t sich aber in dem hier gew&#228;hlten cross-Builder-API nicht realisieren, da der Parameter-Functor sofort auf Kompatibilit&#228;t mit dem Parameter-Tuple-Typ gepr&#252;ft wird, und obendrein auch sofort dahingehend festglegt wird, da&#223; er ein TurnoutSystem&amp; als Argument bekommt. Ein schrittweises Aufbauen einer Funktor-Kette ist also nur beim Processing-Functor m&#246;glich. Es sei denn, man w&#252;rde eine wesentlich elaboriertere Darstellung finden k&#246;nnen, bei der ein Gesamt-Functor-Typ f&#252;r die Parameter irgendwo in den Template-Argumenten aufgebaut wird.
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1739580942969" ID="ID_295215421" MODIFIED="1739580955344" TEXT="ist aber vermutlich irrelevant">
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1739581235335" ID="ID_519521171" MODIFIED="1739581413120" TEXT="insgesammt sollte das Adaptieren ohne Weiteres beliebig repetitiv wiederholbar sein">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...da wir durch das Anwenden auf einen umgebauten Processing-Functor schwenken; deshalb kann auf diesen sodann erneut eine Adaptierung angewendet werden &#8212; selbst wenn diese dann schlie&#223;lich das Parameter-Tupel complett schlie&#223;t (denn ohne Parameter-Functor erfolgt der Aufruf implizit mit einem default-konstruierbaren Parameter-Tupel, und das leere Tupel ist uneingeschr&#228;ntk default-konstruierbar)
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1739582050928" ID="ID_1634640852" MODIFIED="1739582115569" TEXT="also mal im Test-Setup beispielhaft ausarbeiten">
<linktarget COLOR="#4936b3" DESTINATION="ID_1634640852" ENDARROW="Default" ENDINCLINATION="82;-233;" ID="Arrow_ID_40372708" SOURCE="ID_1709833697" STARTARROW="None" STARTINCLINATION="-287;31;"/>
<icon BUILTIN="yes"/>
<node CREATED="1739644403194" ID="ID_1724825463" MODIFIED="1739644431815" TEXT="Beispiel-Funktion nimmt ein Array mit 5 Parametern"/>
<node CREATED="1739644449843" ID="ID_189342580" MODIFIED="1739644468604" TEXT="davon sollen vier left-closed werden"/>
<node CREATED="1739644471400" ID="ID_1478886238" MODIFIED="1739644492368" TEXT="baue direkt einen Aufruf von PApply auf">
<node CREATED="1739644494212" ID="ID_100745879" MODIFIED="1739644498623" TEXT="m&#xfc;hsam..."/>
<node CREATED="1739644499673" ID="ID_410792417" MODIFIED="1739644514421" TEXT="mu&#xdf; den Typ der Zielfunktion konstruieren"/>
<node CREATED="1739644535072" ID="ID_1351505709" MODIFIED="1739644579376" TEXT="brauche dazu ein re-Binding von Variadics &#x27f9; geht nur mit Hilfsfunktion">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
RebindVariadic geht nur f&#252;r Klassen-Templates
</p>
</body>
</html>
</richcontent>
</node>
<node COLOR="#338800" CREATED="1739644580928" ID="ID_298080445" MODIFIED="1739644600474" TEXT="mu&#xdf; Metafunktion f&#xfc;r die Sequenz der Parameter-Typen einbauen">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1739644602379" ID="ID_1041155759" MODIFIED="1739644621556" TEXT="AUA. make_tuple kann kein Array bauen">
<icon BUILTIN="broken-line"/>
<node CREATED="1739644626954" ID="ID_630391744" MODIFIED="1739644634662" TEXT="tja...">
<icon BUILTIN="ksmiletris"/>
<node CREATED="1739644638716" ID="ID_1827688303" MODIFIED="1739644656314" TEXT="verf***tes Tuple-Protocol"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1739644781371" ID="ID_1651641988" MODIFIED="1739644789354" TEXT="versuche es erst mal mit einem Tupel">
<icon BUILTIN="pencil"/>
<node CREATED="1739644799697" ID="ID_719341889" MODIFIED="1739644804862" TEXT="fehler&#xfc;berfehler...">
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1739644880768" ID="ID_1786574048" MODIFIED="1739644892308" TEXT="lvalue-ref to rvalue-ref">
<icon BUILTIN="broken-line"/>
</node>
<node CREATED="1739661361209" ID="ID_1964857830" MODIFIED="1739661386823" TEXT="das ist nur die Spitze des Eisbergs &#x27f8; so geht das nicht"/>
</node>
<node CREATED="1739661467231" ID="ID_289562589" MODIFIED="1739661490167" TEXT="Parameter ist ein Value (ggfs Tupel)"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1739661519815" ID="ID_903309601" MODIFIED="1739661845721" TEXT="Anforderungen an einen Param-Transformer">
<icon BUILTIN="yes"/>
<node CREATED="1739661533781" ID="ID_772896721" MODIFIED="1739661545552" TEXT="mu&#xdf; ausgabeseitig den exakt erwarteten Typ liefern">
<node COLOR="#5b280f" CREATED="1739661547624" ID="ID_719316826" MODIFIED="1739661611083" TEXT="nicht blo&#xdf; ein Tupel">
<icon BUILTIN="stop-sign"/>
</node>
<node CREATED="1739661554290" ID="ID_1635861854" MODIFIED="1739661598785" TEXT="es sind n&#xe4;mlich &#xbb;tuple-like&#xab;-Typen erlaubt">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1739661573672" ID="ID_1418932711" MODIFIED="1739661593977" TEXT="man kann dann fordern, da&#xdf; diese Aggregat-initialisierbar sind">
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1739661731934" ID="ID_1693124446" MODIFIED="1739661810189">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
mu&#223; eingangsseitig Einzel<b>wert</b>&#160;<font color="#bd0c0c">oder</font>&#160;Aggregat<b>wert </b>entgegennehmen
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1739662062321" ID="ID_1123911136" MODIFIED="1739662217602" TEXT="brauche daf&#xfc;r einen dedizierten Wrapper-Funktor">
<node CREATED="1739662219842" ID="ID_1768074670" MODIFIED="1739662261937" TEXT="es mu&#xdf; ein Funktor-Objekt sein">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...denn wir m&#252;ssen den generierten Binder in diesem Funktor speichern
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1739662263448" ID="ID_1742291585" MODIFIED="1739662282200" TEXT="k&#xf6;nnte aber geschickterweise als Lambda definiert sein"/>
<node CREATED="1739662318601" ID="ID_1335080767" LINK="https://en.cppreference.com/w/cpp/utility/make_from_tuple" MODIFIED="1739662342035" TEXT="Implementierungs-Kern: std::make_from_tuple">
<node CREATED="1739662938136" ID="ID_998628856" MODIFIED="1739662953832" TEXT="st&#xfc;tzt sich nur auf das &#xbb;tuple-protocoll&#xab; ab"/>
<node CREATED="1739662954934" ID="ID_1885530605" MODIFIED="1739662977583" TEXT="das gilt aber auch f&#xfc;r das alte Apply&lt;CNT&gt;::bind(f, tup)">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1739662987026" ID="ID_233342003" MODIFIED="1739663074294" TEXT="d.h. man k&#xf6;nnte diesen partiellen Applikator als Kern verwenden">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
wenngleich er auch eine std::function liefert &#8212; das w&#252;rde ich tempor&#228;r akzeptieren, bis die function-closure-Tools umgebaut sind (<font color="#d20c0c">&#10233; Ticket!</font>)
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1739663479935" ID="ID_1499952743" MODIFIED="1739664337382" TEXT="dann brauchen wir aber eingangsseitig variadische Argumente">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
das hei&#223;t, doch auch die Builder-Funktion selber schreiben &#8212; vermutlich eingebettet in ein Builder-Konfigurator-Template
</p>
</body>
</html></richcontent>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1739664341156" ID="ID_557298566" MODIFIED="1739664369471" TEXT="mu&#xdf; es in einem Anlauf schaffen...">
<icon BUILTIN="yes"/>
<node CREATED="1739664371521" ID="ID_1608394291" MODIFIED="1739664384340" TEXT="brauche ein umschlie&#xdf;endes Konstruktor-Template">
<node CREATED="1739664387432" ID="ID_326201311" MODIFIED="1739664417960" TEXT="Zielvorgabe">
<node CREATED="1739664419614" ID="ID_1229418497" MODIFIED="1739664419614" TEXT="wandert letztlich in den Weaving-Builder"/>
<node CREATED="1739664421315" ID="ID_1529597389" MODIFIED="1739664441690" TEXT="soll die drei partial-closure-Primitive als Funktions-Templates bieten"/>
</node>
<node CREATED="1739664449146" ID="ID_1274028526" MODIFIED="1739664470061" TEXT="bekommt daher lediglich das Parameter-Aggregat als Template-Argument"/>
<node COLOR="#338800" CREATED="1739664483904" ID="ID_756152120" MODIFIED="1739669641386" TEXT="Implementierungs-Skizze">
<icon BUILTIN="button_ok"/>
<node CREATED="1739669408564" ID="ID_118009551" MODIFIED="1739669423470" TEXT="verwende einen ClosureBuilder als lokales Template in NodeBuilder"/>
<node CREATED="1739669424670" ID="ID_1318292818" MODIFIED="1739669454271" TEXT="dieser bietet eine statische Funktion ClosureBuilder::closeFront"/>
<node CREATED="1739669461469" ID="ID_1222242546" MODIFIED="1739669479950" TEXT="welche wiederum PApply verwendet, um eine closure zu konstruieren"/>
<node CREATED="1739669481090" ID="ID_1001502220" MODIFIED="1739669495780" TEXT="und diese in ein Lambda einwickelt und dort per std::apply aufruft"/>
<node CREATED="1739669497080" ID="ID_975584802" MODIFIED="1739669511367" TEXT="v&#xf6;llig generisch im konkreten Tupel-Typ"/>
<node BACKGROUND_COLOR="#bdf8db" COLOR="#338800" CREATED="1739669518141" ID="ID_260919432" MODIFIED="1739669639062" STYLE="fork" TEXT="funktionert">
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1739669530247" ID="ID_1438322146" MODIFIED="1739669555839" TEXT="fehlt noch">
<icon BUILTIN="bell"/>
<node CREATED="1739669562919" ID="ID_330946433" MODIFIED="1739669583079" TEXT="Ausschlu&#xdf; von Aufrufen ohne Parameter"/>
<node CREATED="1739669585924" ID="ID_211735922" MODIFIED="1739669597954" TEXT="Spezialbehandlung wenn die Closure nur noch ein Argument nimmt"/>
</node>
</node>
</node>
</node>
</node>
</node> </node>
</node> </node>
</node> </node>