Invocation: switch WeavingBuilder to produce the result via λ

This change allows to disentangle the usages of `lib::SeveralBuilder`,
so that at any time during the build process only a single instance is
actively populated, all in one row — and thus the required storage can
either be pre-allocated, or dynamically extended and shrinked (when
filling elements into the last `SeveralBuilder` currently activated)

By packaging into a λ-closure, the building of the actual `Port`
implementation objects (≙ `Turnout` instances) is delayed until the
very end of the build process, and then unloaded into yet another
`lib::Several` in one strike. Temporarily, those building functor
objects are „hidden“ in the current stack frame, as a new `NodeBuilder`
instance is dropped off with an adapted type parameter (embedding the
λ-type produced by the last nested `PortBuilder` invocation, while
inheriting from previous ones.

However, defining a special constructor to cause this »chaining«
poses some challenge (regarding overload resolution). Moreover,
since the actual processing function shall be embedded directly
(as opposed to wrapping it into a `std::function`), further problems
can arise when this function is given as a ''function reference''
This commit is contained in:
Fischlurch 2024-10-22 03:20:50 +02:00
parent 0de7905444
commit df37fec500
5 changed files with 244 additions and 79 deletions

View file

@ -96,6 +96,7 @@
#include "steam/engine/turnout.hpp"
#include "lib/several-builder.hpp"
#include "lib/nocopy.hpp"
#include "lib/test/test-helper.hpp"/////////////////////TODO TOD-oh
#include <utility>
#include <vector>
@ -119,6 +120,7 @@ namespace engine {
}//(End) policy
/**
* A builder to collect working data.
* Implemented through a suitable configuration of lib::SeveralBuilder,
@ -127,9 +129,35 @@ namespace engine {
template<class POL, class I, class E=I>
using DataBuilder = lib::SeveralBuilder<I,E, POL::template Policy>;
template<class POL, class DAT>
class NodeBuilder;
template<class POL, class DAT>
class PortBuilderRoot;
namespace { // Metaprogramming helper to pick the proper constructor...
using lib::meta::disable_if;
using std::bool_constant;
using std::__and_;
template<typename ...ARGS>
struct ArgMatch : std::false_type { };
// template<class POL, class D, uint siz, typename...XS>
// struct ArgMatch<NodeBuilder<POL,D>&&, SizMark<siz>, XS...> : std::true_type { }; // the chaining-ctor takes a NodeBuilder and a size-mark...
template<typename X, uint siz, typename...XS>
struct ArgMatch<X, SizMark<siz> const&, XS...> : std::true_type { }; // the chaining-ctor takes a NodeBuilder and a size-mark...
/** Metaprogramming: prevent the var-args ctor from shadowing the chaining ctor */
template<typename ...ARGS>
using disable_if_Chain = disable_if<__and_<bool_constant<3 == sizeof...(ARGS)> // do not use this constructor if 3 arguments given
,ArgMatch<ARGS...> // and these match the signature for the chaining-constructor
>>;
}
template<class POL, class DAT = PatternDataAnchor>
class NodeBuilder
@ -139,30 +167,36 @@ namespace engine {
using LeadRefs = DataBuilder<POL, ProcNodeRef>;
protected:
PortData ports_; ///////////////////////////////////////OOO obsolete and replaced by patternData_
LeadRefs leads_;
DAT patternData_;
public:
template<typename...INIT>
template<typename...INIT>//, typename = disable_if_Chain<INIT...>>
NodeBuilder (INIT&& ...alloInit)
: ports_{forward<INIT> (alloInit)...} /////////////OOO obsolete and replaced by patternData_
, leads_{forward<INIT> (alloInit)...}
{ }
: leads_{forward<INIT> (alloInit)...}
{
//lib::test::TypeDebugger<lib::meta::TySeq<INIT...>> muggi;
//lib::test::TypeDebugger<disable_if_Chain<INIT...>> muggi;
// if constexpr (ArgMatch<INIT...>())
// static_assert(not sizeof(POL), "YESSS!");
// else
// static_assert(not sizeof(POL), "OH_NO");
}
template<class BUILD, uint siz, class D0>
NodeBuilder (NodeBuilder<POL,D0>&& pred, BUILD&& entryBuilder)
: ports_{} /////////////OOO obsolete and replaced by patternData_
, leads_{move (pred.leads_)}
NodeBuilder (NodeBuilder<POL,D0>&& pred, SizMark<siz>, BUILD&& entryBuilder)
: leads_{move (pred.leads_)}
, patternData_{move (pred.patternData_), forward<BUILD> (entryBuilder)}
{ }
template<class P, class D0>
friend class NodeBuilder;
NodeBuilder
addLead (ProcNode const& lead)
{
UNIMPLEMENTED ("append the given predecessor node to the sequence of leads");
leads_.append (lead);
return move(*this);
}
@ -201,12 +235,18 @@ namespace engine {
Connectivity
build()
{
return Connectivity{ports_.build()
PortData ports;
patternData_.collectEntries(ports);
return Connectivity{ports.build()
,leads_.build()
,NodeID{}}; //////////////////////////////////////OOO what's the purpose of the NodeID??
}
};
/** Deduction Guide: help the compiler with deducing follow-up NodeBuilder parameters */
template<class POL, class D0, uint siz, class BUILD>
NodeBuilder (NodeBuilder<POL,D0>&&, SizMark<siz>, BUILD&&) -> NodeBuilder<POL, PatternData<D0,BUILD,siz>>;
template<class POL, class DAT>
@ -319,14 +359,21 @@ namespace engine {
/*************************************************************//**
* Terminal: complete the Port wiring and return to the node level.
*/
NodeBuilder<POL,DAT> ////////////////////////////////////////OOO need to extend and evolve the DAT parameter here
auto
completePort()
{
//////////////////////////////////////////////////////////OOO need to provide all links to lead nodes here
weavingBuilder_.fillRemainingBufferTypes();
_Par::ports_.append(weavingBuilder_.build());
return static_cast<NodeBuilder<POL,DAT>&&> (*this);
} // slice away the subclass
using MoThi = decltype(move(*this));
// if constexpr (ArgMatch<MoThi&&, SizMark<5>, void*>())
// static_assert(not sizeof(POL), "YESSS!");
// else
// static_assert(not sizeof(POL), "OH_NO");
// lib::test::TypeDebugger<disable_if_Chain<MoThi&&, int, void*>> buggi;
return NodeBuilder{static_cast<NodeBuilder<POL,DAT>&&> (*this) //move (*this)
,weavingBuilder_.sizMark
,weavingBuilder_.build()};
} // chain to builder with extended patternData
private:
template<typename FUN>

View file

@ -218,7 +218,6 @@ namespace engine {
virtual BuffHandle
allocateBuffer (const lumiera::StreamType* ty) { return current_.allocateBuffer(ty); }
};
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
/**
@ -255,6 +254,7 @@ namespace engine {
return Strategy::step (*this);
}
};
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
/**
@ -288,11 +288,11 @@ namespace engine {
* + an array of output buffer pointers
* + `CONF::MAX_SIZ` limits both arrays
*/
template<class CONF>
template<class INVO>
struct SimpleWeavingPattern
: CONF
: INVO
{
using Feed = typename CONF::Feed;
using Feed = typename INVO::Feed;
static_assert (_verify_usable_as_InvocationAdapter<Feed>());
@ -301,19 +301,23 @@ namespace engine {
uint resultSlot{0};
//////////////////////////////////////////OOO builder must set-up those descriptors
/** forwarding-ctor to provide the detailed input/output connections */
template<typename...ARGS>
SimpleWeavingPattern(Several<PortRef>&& pr, Several<BuffDescr>&& dr, ARGS&& ...args)
: CONF{forward<ARGS>(args)...}
SimpleWeavingPattern (Several<PortRef>&& pr
,Several<BuffDescr>&& dr
,uint resultIdx
,ARGS&& ...args)
: INVO{forward<ARGS>(args)...}
, leadPort{move(pr)}
, outTypes{move(dr)}
, resultSlot{resultIdx}
{ }
Feed
mount()
{
return CONF::buildFeed();
return INVO::buildFeed();
}
void
@ -358,7 +362,7 @@ namespace engine {
if (i != resultSlot)
feed.outBuff[i].release();
}
ENSURE (resultSlot < CONF::MAX_SIZ, "invalid result buffer configured.");
ENSURE (resultSlot < INVO::MAX_SIZ, "invalid result buffer configured.");
return feed.outBuff[resultSlot];
}

View file

@ -198,7 +198,7 @@ namespace engine {
* - use a sufficiently sized FeedManifold as storage scheme
*/
template<uint N, class FUN>
struct Conf_DirectFunctionInvocation
struct DirectFunctionInvocation
: util::MoveOnly
{
using Manifold = FeedManifold<N>;
@ -208,7 +208,7 @@ namespace engine {
std::function<Feed()> buildFeed;
// template<typename INIT>
Conf_DirectFunctionInvocation(FUN fun)
DirectFunctionInvocation(FUN fun)
: buildFeed{[=]//procFun = forward<INIT> (fun)]
{
// using URGS = decltype(procFun);
@ -224,8 +224,11 @@ namespace engine {
template<class POL, class I, class E=I>
using DataBuilder = lib::SeveralBuilder<I,E, POL::template Policy>;
template<uint siz>
using SizMark = std::integral_constant<uint,siz>;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Prototyping: how to assemble a Turnout
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1371 : Prototyping: how to assemble a Turnout
/**
* Recursive functional data structure to collect weaving pattern data
@ -273,18 +276,19 @@ namespace engine {
template<uint N, class FUN>
using SimpleDirectInvoke = SimpleWeavingPattern<Conf_DirectFunctionInvocation<N,FUN>>;
using SimpleDirectInvoke = SimpleWeavingPattern<DirectFunctionInvocation<N,FUN>>;
template<class POL, uint N, class FUN>
struct WeavingBuilder
: util::MoveOnly
{
DataBuilder<POL, PortRef> leadPort;
DataBuilder<POL, BuffDescr> outTypes;
using TurnoutWeaving = Turnout<SimpleDirectInvoke<N,FUN>>;
static constexpr SizMark<sizeof(TurnoutWeaving)> sizMark{};
using TypeMarker = std::function<BuffDescr(BufferProvider&)>;
using ProviderRef = std::reference_wrapper<BufferProvider>;
DataBuilder<POL, PortRef> leadPort;
std::vector<TypeMarker> buffTypes;
std::vector<ProviderRef> providers;
@ -339,19 +343,37 @@ namespace engine {
auto
build()
{
// discard excess storage prior to allocating the output types sequence
leadPort.shrinkFit();
maybeFillDefaultProviders (buffTypes.size());
REQUIRE (providers.size() == buffTypes.size());
auto outTypes = DataBuilder<POL, BuffDescr>{}
.reserve (buffTypes.size());
uint i=0;
for (auto& typeConstructor : buffTypes)
outTypes.append (
typeConstructor (providers[i++]));
ENSURE (leadPort.size() < N);
ENSURE (outTypes.size() < N);
ENSURE (leadPort.size() <= N);
ENSURE (outTypes.size() <= N);
using Product = Turnout<SimpleDirectInvoke<N,FUN>>;
///////////////////////////////OOO need a way to prepare SeveralBuilder-instances for leadPort and outDescr --> see NodeBuilder
return Product{leadPort.build(), outTypes.build(), move(fun_)};
using PortDataBuilder = DataBuilder<POL, Port>;
// provide a free-standing functor to build a suitable Port impl (≙Turnout)
return [leads = move(leadPort.build())
,types = move(outTypes.build())
,procFun = move(fun_)
,resultIdx = resultSlot
]
(PortDataBuilder& portData) mutable -> void
{
//lib::test::TypeDebugger<decltype(procFun)> uggi;
portData.template emplace<TurnoutWeaving> (move(leads)
,move(types)
,resultIdx
,move(procFun)
);
};
}
private:

View file

@ -73,7 +73,7 @@ namespace test {
{
auto con = prepareNode()
.preparePort()
.invoke(dummyOp)
.invoke(&dummyOp)
.completePort()
.build();
CHECK (isnil (con.leads));

View file

@ -8778,9 +8778,7 @@
</node>
<node CREATED="1511455502648" ID="ID_1704619802" MODIFIED="1511455566686">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
das ist aber <i>unpraktisch</i>....
@ -8791,9 +8789,7 @@
</node>
<node CREATED="1511455513119" ID="ID_128446946" MODIFIED="1511572072789" TEXT="denn grade Iterator-Typen kennt der Benutzer typischerweise nicht">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
....also ist es gradezu nat&#252;rlich,
@ -9414,9 +9410,7 @@
<node CREATED="1512951955616" ID="ID_529939230" MODIFIED="1512951965123" TEXT="sie verleiten zu Glasperlen-Spielen"/>
<node CREATED="1512951978101" ID="ID_489027143" MODIFIED="1512952012416" TEXT="Leitlinie f&#xfc;r gutes Design">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
der Natur der Dinge folgen,
@ -10352,9 +10346,7 @@
<node CREATED="1512349367230" ID="ID_1844975610" MODIFIED="1512349379887" TEXT="IterTool braucht den Typ des Basis-Iterators"/>
<node CREATED="1512349380643" ID="ID_1515581078" MODIFIED="1512349403999">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
versehentlich wurde <i>auch der</i>&#160;an std::forward gegeben
@ -12071,9 +12063,7 @@
<icon BUILTIN="button_ok"/>
<node CREATED="1514848818421" ID="ID_26529397" MODIFIED="1515206142953" TEXT="vermutlich (fast) nix zu tun">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<ul>
<li>
@ -14417,9 +14407,7 @@
</node>
<node COLOR="#990000" CREATED="1519355201077" HGAP="31" ID="ID_539031017" MODIFIED="1529076927655" VSHIFT="13">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
wer interpretiert
@ -18748,9 +18736,7 @@
<icon BUILTIN="button_ok"/>
<node CREATED="1664027121220" ID="ID_1123910943" MODIFIED="1664027234710" TEXT="f&#xfc;r das ElementBoxWidget stets in Pixel">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
das ist eine Design/Architektur-Entscheidung; ein generisches Widget soll noch nicht mit dem speziellen Belang einer Eichung in Zeiteinheiten belastet werden; dies hat dann jeweils ins abgeleiteten Klassen zu erfolgen, so z.B im Clip-Widget
@ -48420,9 +48406,7 @@
<icon BUILTIN="button_cancel"/>
<node CREATED="1456011676086" ID="ID_1849622483" MODIFIED="1456011688340">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
und delegiert iterativ
@ -49266,9 +49250,7 @@
</node>
<node CREATED="1448683561882" ID="ID_839961131" MODIFIED="1518487921087">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
Idee: <b>context-bound</b>
@ -49774,9 +49756,7 @@
<node CREATED="1487269963098" ID="ID_723170966" MODIFIED="1518487921088" TEXT="Raum als Metapher"/>
<node CREATED="1487269990582" ID="ID_164128588" MODIFIED="1518487921088">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
Focus/Spot wird <i>mitbewegt</i>
@ -50410,9 +50390,7 @@
<node CREATED="1453590828976" ID="ID_659078492" MODIFIED="1453590855465" TEXT="eine VTable pro Zieltyp"/>
<node CREATED="1453590856220" ID="ID_376478329" MODIFIED="1453590879683">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
eine virtuelle Funktion
@ -50867,9 +50845,7 @@
<node CREATED="1492443933813" ID="ID_1185852649" MODIFIED="1492443940760" TEXT="hat eigene lokale Hashtable"/>
<node CREATED="1492443941260" ID="ID_870719620" MODIFIED="1576282357997" TEXT="unterst&#xfc;tzt einfachen Fallback">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
aufruf direkt mit Command-ID -&gt; erzeugt automatisch eine Klon-Kopie
@ -85659,6 +85635,11 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1728657599660" ID="ID_1919244666" MODIFIED="1728657606815" TEXT="mu&#xdf; einfache Node bauen k&#xf6;nnen"/>
<node CREATED="1728657607703" ID="ID_1131573155" MODIFIED="1728657612430" TEXT="mu&#xdf; Node aufrufen k&#xf6;nnen"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1729552217035" ID="ID_797574499" MODIFIED="1729552701795" TEXT="#1371 Prototyping: build and connect render nodes">
<arrowlink COLOR="#8e213e" DESTINATION="ID_495934512" ENDARROW="Default" ENDINCLINATION="548;-1633;" ID="Arrow_ID_1445467180" STARTARROW="None" STARTINCLINATION="1411;76;"/>
<arrowlink COLOR="#b60103" DESTINATION="ID_1585637379" ENDARROW="Default" ENDINCLINATION="-1157;-58;" ID="Arrow_ID_1730193164" STARTARROW="None" STARTINCLINATION="1290;69;"/>
<icon BUILTIN="pencil"/>
</node>
<node CREATED="1718845263947" ID="ID_1747091374" MODIFIED="1718845332197" TEXT="Ziel: den NodeLinkage_test aufbauen">
<arrowlink COLOR="#fe018a" DESTINATION="ID_673154392" ENDARROW="Default" ENDINCLINATION="3;-16;" ID="Arrow_ID_894402730" STARTARROW="None" STARTINCLINATION="-151;11;"/>
<icon BUILTIN="yes"/>
@ -87186,6 +87167,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1719964416438" HGAP="61" ID="ID_495934512" MODIFIED="1719967866179" TEXT="hier komme ich ohne Prototyping nicht weiter" VSHIFT="39">
<arrowlink COLOR="#5e2f3f" DESTINATION="ID_1199569608" ENDARROW="Default" ENDINCLINATION="-1226;-72;" ID="Arrow_ID_1409703862" STARTARROW="None" STARTINCLINATION="-302;19;"/>
<linktarget COLOR="#8e213e" DESTINATION="ID_495934512" ENDARROW="Default" ENDINCLINATION="548;-1633;" ID="Arrow_ID_1445467180" SOURCE="ID_797574499" STARTARROW="None" STARTINCLINATION="1411;76;"/>
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1728497991103" ID="ID_1877481634" MODIFIED="1728498077898" TEXT="Top-down Bottom-up">
<icon BUILTIN="yes"/>
@ -90005,7 +89987,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1729306885960" ID="ID_1794659252" MODIFIED="1729306913167" TEXT="leadPort und outTypes sind relativ unproblematisch"/>
<node CREATED="1729306923281" ID="ID_665043448" MODIFIED="1729306938419" TEXT="es gibt aber noch zwei Vectors mit Arbeitsdaten"/>
<node CREATED="1729307009348" ID="ID_1344032375" MODIFIED="1729307029655" TEXT="die Belegung von leadPort und outTypes findet bereits entflochten statt"/>
<node CREATED="1729307034959" ID="ID_982363236" MODIFIED="1729307066852" TEXT="man m&#xfc;&#xdf;te lediglich das Several f&#xfc;r die leadPorts in die build()-Funktion schieben"/>
<node CREATED="1729307034959" ID="ID_982363236" MODIFIED="1729555491578" TEXT="man m&#xfc;&#xdf;te lediglich das Several f&#xfc;r die outTypes in die build()-Funktion schieben">
<arrowlink COLOR="#5a758c" DESTINATION="ID_455881892" ENDARROW="Default" ENDINCLINATION="353;-366;" ID="Arrow_ID_1206334910" STARTARROW="None" STARTINCLINATION="595;21;"/>
</node>
</node>
<node CREATED="1729307297963" ID="ID_943373598" MODIFIED="1729307309144" TEXT="abschlie&#xdf;ender Schritt">
<node CREATED="1729307313017" ID="ID_1049380221" MODIFIED="1729307344813" TEXT="demnach m&#xfc;&#xdf;te das Konstruieren des Turnout auf sp&#xe4;ter verschoben werden"/>
@ -90065,6 +90049,10 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1729555599082" HGAP="21" ID="ID_466296328" MODIFIED="1729555917266" TEXT="durch &#x3bb;-closure" VSHIFT="15">
<arrowlink COLOR="#3d37ad" DESTINATION="ID_669795504" ENDARROW="Default" ENDINCLINATION="-187;-368;" ID="Arrow_ID_91190585" STARTARROW="None" STARTINCLINATION="-105;399;"/>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
</node>
@ -90250,8 +90238,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1729476213539" ID="ID_1086673999" MODIFIED="1729477907340" TEXT="Weitergabe der Pattern-Daten">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1729476230116" ID="ID_632213709" MODIFIED="1729477873527" TEXT="sie m&#xfc;ssen im NodeBuilder liegen">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1729476230116" ID="ID_632213709" MODIFIED="1729554611988" TEXT="sie m&#xfc;ssen im NodeBuilder liegen">
<icon BUILTIN="yes"/>
<node COLOR="#338800" CREATED="1729477632752" ID="ID_1978776650" MODIFIED="1729477655829" TEXT="mu&#xdf; dazu einen zweiten Typpatameter DAT &#xfc;berall durchschleifen">
<icon BUILTIN="button_ok"/>
</node>
@ -90263,15 +90251,118 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
...damit die terminale Methode des PortBuilders nun nicht mehr den originalen NodeBuilder per slice-copy extrahiert, sondern stattdessen eine angepa&#223;te Variante erzeugen kann, bei der ein &#187;Zwiebelschalen-Layer&#171; um die PatternData gelegt wird, w&#228;hrend alle weiteren Daten per move weitergeschoben werden
</p>
</body>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1729477829436" ID="ID_669795504" MODIFIED="1729555900220" TEXT="PortBuilder::build() mu&#xdf; nun Build-Funktor erzeugen">
<linktarget COLOR="#3d37ad" DESTINATION="ID_669795504" ENDARROW="Default" ENDINCLINATION="-187;-368;" ID="Arrow_ID_91190585" SOURCE="ID_466296328" STARTARROW="None" STARTINCLINATION="-105;399;"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1729555298490" ID="ID_1421832672" MODIFIED="1729555506141" TEXT="die Several-Builds komplett entflechten">
<icon BUILTIN="button_ok"/>
<node CREATED="1729555314259" ID="ID_1977364446" MODIFIED="1729555322282" TEXT="leadPort.shrink() zu Beginn"/>
<node CREATED="1729555323199" ID="ID_455881892" MODIFIED="1729555491578">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
danach &#252;berhaupt erst <font face="Monospaced" color="#5c2c20">outTypes = DataBuilder&lt;POL, BuffDescr&gt;</font>&#160; erzeugen
</p>
</body>
</html>
</richcontent>
<linktarget COLOR="#5a758c" DESTINATION="ID_455881892" ENDARROW="Default" ENDINCLINATION="353;-366;" ID="Arrow_ID_1206334910" SOURCE="ID_982363236" STARTARROW="None" STARTINCLINATION="595;21;"/>
</node>
<node CREATED="1729555947647" ID="ID_986884580" MODIFIED="1729555978307" TEXT="beim Verschieben in die &#x3bb;-closure : den Several-Build sofort ausf&#xfc;hren (fixieren)"/>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1729550672047" ID="ID_998453303" MODIFIED="1729550685246" TEXT="der Chain-Konstruktor ist problematisch">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1729550687877" ID="ID_930534741" MODIFIED="1729551189497" TEXT="er steht in Konkurrenz zum prim&#xe4;ren Konstruktor mit Var-Args">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
der prim&#228;re Konstruktor nimmt Var-Args, und reicht sie zur Initialisierung des Allokators durch (was vor allem den wichtigen Fall eines monomorphic Allocators abdeckt, der gar keine Init-Argumente nimmt)....
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1729551190813" ID="ID_1962189795" MODIFIED="1729551289714">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
der andere ctor w&#252;rde dann nur vorgezogen, wenn er <b>exakt</b>&#160;pa&#223;t
</p>
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Das sind die bekannten Regeln f&#252;r die Overload-Selection: ein exakter Match ist stets besser als ein Match mit einer impliziten Konversion. Aber ein variadic Match ist schlechter als ein exakter Match.
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1729551291039" ID="ID_506616215" MODIFIED="1729551308379" TEXT="man kann das mit enable_if aussteuern....">
<node CREATED="1729551309871" ID="ID_1474952384" MODIFIED="1729551319221" TEXT="wenn man es richtig macht">
<icon BUILTIN="smiley-oh"/>
<node CREATED="1729551427369" ID="ID_1022335541" MODIFIED="1729551544207" TEXT="ziemlich unintuitiv">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
hab jetzt zwei Stunden mit dem TypeDebugger die Instantiierungen auseinandergenommen, bis ich den Fehler gefunden hatte: die compile-time-Konstante ist eine static constexpr, wird also zu einer const&amp;, und au&#223;erdem mu&#223; man dann auch noch das Strippen der RRef ber&#252;cksichtigen, und eigentlich auch noch den Subtype match. Nee Danke!
</p>
</body>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1729477829436" ID="ID_669795504" MODIFIED="1729477870839" TEXT="PortBuilder::build() mu&#xdf; nun Build-Funktor erzeugen">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1729551321744" ID="ID_1587079876" MODIFIED="1729551424915" TEXT="und au&#xdf;erdem ist das ziemlich komplexer Code">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...mu&#223; hier zweistufig vorgehen mit einer Helper-Metafunction, die dann den genauen Match der Argumente pr&#252;ft.
</p>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1729477875734" ID="ID_1268344411" MODIFIED="1729477903179" TEXT="Datenerzeugung &#xfc;ber die Funktoren-Kette">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1729551548530" ID="ID_1970430503" MODIFIED="1729551581331" TEXT="Ha! also dann beim Aufruf einen static_cast machen &#xd83e;&#xdc32; exakter Match">
<icon BUILTIN="idea"/>
</node>
<node COLOR="#b50188" CREATED="1729551588573" ID="ID_1416053128" MODIFIED="1729551609389" TEXT="kaum macht mans richtig, schon funktionierts">
<font NAME="SansSerif" SIZE="9"/>
</node>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1729525573004" ID="ID_1595587422" MODIFIED="1729551640274" TEXT="Problem: direct Funktion-ref decays">
<icon BUILTIN="broken-line"/>
<node CREATED="1729551646837" ID="ID_797477885" MODIFIED="1729551707565" TEXT="OH-Mann!!!">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
das ewige &#196;rgenis bei Function-Referenzen, die auf einen Function-Pointer decayen. Das passiert dann irgendwo mittendrin; konkret beim Binden in die Lambda-Closure, wo ich leider &#252;berhaupt keinen Einflu&#223; nehmen kann. Grrrrrrr
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1729551710696" ID="ID_964817822" MODIFIED="1729552162079" TEXT="ich m&#xf6;chte aber die Funktion &#xbb;blank&#xab; durchgeben &#x2014; aus Performance-Gr&#xfc;nden">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...weil diese Funktion in der Praxis sehr h&#228;ufig ein Lambda sein d&#252;rfte, das dann direkt kopiert und ge-Inlined werden kann. Bekannterma&#223;en ist n&#228;mlich std::function nicht sonderlich Inline-freundlich; in meinen Experimenten hat es manchmal geklappt, manchmal nicht, und dann bleibt eine Indirektion durch einen Funktion-Pointer &#252;brig, was ich hier, auf einem Performance-kritischen Pfad gerne vermeiden m&#246;chte. Mal ganz abgesehen davon, da&#223; eine std::function auch ziemlich &#187;fett&#171; ist (bei mir 5 &#187;Slots&#171; &#8793; 40 Byte) &#8212; klar, aktuell haben wir das gleiche Problem auch in lib::Several, aber dort wei&#223; ich bereits, da&#223; es sich nahezu optimal l&#246;sen l&#228;&#223;t, wenn man nur die entsprechende Komplexit&#228;t in der Definition in Kauf nimmt (was ich auf sp&#228;ter verschoben habe, siehe Ticket #)
</p>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1729477875734" ID="ID_1268344411" MODIFIED="1729554584154" TEXT="Datenerzeugung &#xfc;ber die Funktoren-Kette">
<icon BUILTIN="pencil"/>
</node>
</node>
</node>
@ -90816,6 +90907,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1728785663035" ID="ID_1585637379" MODIFIED="1728785801243" TEXT="Integration des einfachst-m&#xf6;glichen Builder-Terms">
<linktarget COLOR="#b60103" DESTINATION="ID_1585637379" ENDARROW="Default" ENDINCLINATION="-1157;-58;" ID="Arrow_ID_1730193164" SOURCE="ID_797574499" STARTARROW="None" STARTINCLINATION="1290;69;"/>
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1728785697448" ID="ID_1129960489" MODIFIED="1728785739456" TEXT="kein Lead &#x2259; Generator-Node">
<icon BUILTIN="yes"/>