Invocation: extract partial closure functionality

What emerges here, seems to be a generic helper to handle
partial closure of ''tuple-like'' data records. In any case,
this is highly technical meta-programming code and mandates
extraction into a separate header — simplifying `NodeBuilder`
This commit is contained in:
Fischlurch 2025-02-16 23:16:46 +01:00
parent fbf7a792a8
commit 769060b9dd
13 changed files with 317 additions and 145 deletions

View file

@ -100,6 +100,7 @@
#include "lib/symbol.hpp"
#include "lib/diff/gen-node.hpp"
#include "lib/diff/tree-mutator.hpp"
#include "lib/meta/typeseq-util.hpp"
#include "lib/format-string.hpp"
#include "lib/idi/entry-id.hpp"

View file

@ -103,7 +103,7 @@
#include "lib/meta/duck-detector.hpp"
#include "lib/meta/function.hpp"
#include "lib/meta/trait.hpp"
#include "lib/wrapper.hpp" ////////////TODO : could be more lightweight by splitting FunctionResult into separate header. Relevant?
#include "lib/wrapper.hpp"
#include "lib/iter-adapter.hpp"
#include "lib/iter-source.hpp" /////////////TICKET #493 : only using the IterSource base feature / interface here. Should really split the iter-source.hpp
#include "lib/iter-stack.hpp"

View file

@ -14,15 +14,17 @@
/** @file function-closure.hpp
** Partial function application and building a complete function closure.
** This is a addendum to (and thin wrapper for) `<functional>`, supporting
** the case when a function should be _closed_ over (partially or all) arguments,
** where especially the parameter values to close on are provided as a tuple.
** This is a addendum to std::bind, to support especially the case when a
** function should be _closed_ over (partially or all) arguments. This implies
** to bind some arguments immediately, while keeping other arguments open to
** be supplied on function invocation.
** Additionally, we allow for composing (chaining) of two functions.
**
** Because we have to deal with arbitrary functions and arbitrary parameter types,
** we need a lot of repetitive code to "catch" functions from zero to nine arguments.
** At the bottom of this header, you'll find a function-style interface, which
** wraps up all these technicalities.
** @warning this header is in a state of transition as of 2/2025, because functionality
** of this kind will certainly needed in future, but with full support for lambdas,
** move-only types and perfect forwarding. A gradual rework has been started, and
** will lead to a complete rewrite of the core functionality eventually, making
** better use of variadic templates and library functions like std::apply, which
** were not available at the time of the first implementation.
**
** @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
@ -38,9 +40,11 @@
** 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.
** selected argument, which handles the intricacies of storing the functor.
**
** @see control::CommandDef usage example
** @see function-closure-test.hpp
** @see function-composition-test.hpp
** @see function.hpp
**
*/
@ -543,7 +547,7 @@ namespace func{
/**
* Partial function application
* Takes a function and a value tuple,
* using the latter to close function arguments
* using the latter to close function arguments
* either from the front (left) or aligned to the end
* of the function argument list. Result is a "reduced" function,
* expecting only the remaining "un-closed" arguments at invocation.

View file

@ -0,0 +1,88 @@
/*
TUPLE-CLOSURE.hpp - metaprogramming tools for closing a function over given arguments
Copyright (C)
2025, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2 of the License, or (at your
  option) any later version. See the file COPYING for further details.
*/
/** @file tuple-closure.hpp
** Partial binding for construction of tuple-like records.
** Sometimes tuple-like structures must be created as part of library code,
** in a situation where _some of the values_ are known and should be fixed-in,
** while other values need to be supplied late. Obviously this implies creating
** a functor, and then partially to close some arguments. While seemingly simple,
** this task is often complicated by the need to support _»tuple-like«_ records,
** i.e. anything which adheres to the »C++ tuple protocol« (e.g. std::array).
** Which requires to pick up the actual container type by template pattern match
** and to rely solely on the helper functions from the STLIB for data access.
**
** A relevant use-case is the handling of invocation parameters for Render Nodes:
** typically, some parameters are of technical nature and can be configured during
** the setup-phase of the render network, while other parameters allow the user
** to exert artistic control and will be supplied later, through automation.
**
** @see weaving-pattern-builder.hpp
** @see NodeBuilder_test::build_Node_closedParam()
**
*/
#ifndef LIB_META_TUPLE_CLOSURE_H
#define LIB_META_TUPLE_CLOSURE_H
#include "lib/meta/function-closure.hpp"
#include "lib/meta/tuple-helper.hpp"
#include <utility>
#include <tuple>
namespace lib {
namespace meta{
template<class PAR>
struct TupleClosureBuilder;
template<template<typename...> class TUP, typename...PARS>
struct TupleClosureBuilder<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 RemainingParams = typename lib::meta::RebindVariadic<TUP, RemainingArgs>::Type;
return [closure = move(partialClosure)
]
(RemainingParams remPar)
{
return std::apply (closure, remPar);
};
}
};
}} // namespace lib::meta
#endif

View file

@ -0,0 +1,92 @@
/*
WRAPPER-FUNCTION-RESULT.hpp - some smart wrapping and reference managing helper templates
Copyright (C)
2009, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2 of the License, or (at your
  option) any later version. See the file COPYING for further details.
*/
/** @file wrapper-function-result.hpp
** Helper to cache the result of function invocation.
** @todo 2025 initially created by direct need, it was used for a while,
** but became largely obsoleted by the ''transforming'' functionality
** provided by iter-explorer.hpp (which is implemented by the same
** basic technique, but without the std::function baseclass).
*/
#ifndef LIB_WRAPPER_FUNCTION_RESULT_H
#define LIB_WRAPPER_FUNCTION_RESULT_H
#include "lib/wrapper.hpp"
#include "lib/meta/function.hpp"
#include "lib/meta/function-closure.hpp"
#include "lib/meta/util.hpp"
#include <functional>
namespace lib {
namespace wrapper {
using lib::meta::_Fun;
using std::function;
/**
* Extension of ItemWrapper: a function remembering the result of the
* last invocation. Initially, the "value" is bottom (undefined, NIL),
* until the function is invoked for the first time. After that, the
* result of the last invocation can be accessed by `operator* ()`
* @note deliberately non-copyable, since we capture a reference
* to `this` in order to write to the embedded ItemWrapper.
* (to alleviate, we'd have to re-link after copying/moving)
*/
template<typename SIG>
struct FunctionResult
: public function<SIG>
, util::NonCopyable
{
using Res = typename _Fun<SIG>::Ret;
using ResWrapper = ItemWrapper<Res>;
ResWrapper lastResult_;
public:
/** by default locked to _invalid state_ */
FunctionResult() = default;
/**
* Create result-remembering functor by outfitting a _copy_
* of the given function with an adaptor to _capture_ each
* produced result.
* @warning if function result is a value, it is copied.
*/
template<typename FUN>
FunctionResult (FUN&& targetFunction)
: function<SIG>{lib::meta::func::chained
( std::forward<FUN> (targetFunction)
, [this](Res res) -> Res
{
lastResult_ = res;
return std::forward<Res> (res);
})}
{ }
/** retrieve the last function result observed */
Res& operator*() const { return *lastResult_; }
bool isValid () const { return lastResult_.isValid(); }
explicit
operator bool() const { return isValid(); }
};
}} // namespace lib::wrap
#endif /*LIB_WRAPPER_FUNCTION_RESULT_H*/

View file

@ -16,16 +16,22 @@
** This is (intended to become) a loose collection of the various small helper templates
** for wrapping, containing, placing or handling a somewhat \em problematic other object.
** Mostly these are implemented to suit a specific need and then factored out later on.
** - ItemWrapper is a similar concept, but more like a smart-ptr. Moreover,
** it can be instantiated with a value type, a pointer or a reference type,
** yielding the same behaviour in all cases (useful for building templates)
** - ReturnRef is similar to std::reference_wrapper, but with a function-like usage.
** - ItemWrapper is a similar concept, but used more like a smart-ptr. Notably,
** a value-object is stored inline, into an embedded buffer.
** Furthermore, ItemWrapper can be used to level differences between values,
** references and pointers, as it can be instantiated with any of them, offering
** (almost) uniform handling in all cases (useful for building templates)
** - FunctionResult is the combination of ItemWrapper with a functor object
** to cache the function result value.
**
** to cache the function result value. It was split off into a separate
** header \ref wrapper-function-result.hpp to reduce include impact
** @remark most of this helper collection became obsolete with the evolution of the
** standard library with the exception of ItermWrapper, which turned out to be
** very effective and is now pervasively used as part of transforming functor
** pipelines, to cache the result of the transforming function invocation.
** @see lib::TransformIter
**
** @todo 2017 consider to split off the FunctionResult into a dedicated header to reduce includes
**
** @see lib::explore
**
*/
@ -34,25 +40,19 @@
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#include "lib/meta/function.hpp"
#include "lib/meta/function-closure.hpp"
#include "lib/meta/util.hpp"
#include "lib/util.hpp"
#include <functional>
#include <cstddef>
#include <utility>
#include <type_traits>
namespace lib {
namespace wrapper {
using util::unConst;
using util::isSameObject;
using lib::meta::_Fun;
using LERR_(BOTTOM_VALUE);
using std::function;
/**
@ -386,56 +386,5 @@ namespace wrapper {
}
/**
* Extension of ItemWrapper: a function remembering the result of the
* last invocation. Initially, the "value" is bottom (undefined, NIL),
* until the function is invoked for the first time. After that, the
* result of the last invocation can be accessed by `operator* ()`
* @note deliberately non-copyable, since we capture a reference
* to `this` in order to write to the embedded ItemWrapper.
* (to alleviate, we'd have to re-link after copying/moving)
*/
template<typename SIG>
struct FunctionResult
: public function<SIG>
, util::NonCopyable
{
using Res = typename _Fun<SIG>::Ret;
using ResWrapper = ItemWrapper<Res>;
ResWrapper lastResult_;
public:
/** by default locked to _invalid state_ */
FunctionResult() = default;
/**
* Create result-remembering functor by outfitting a _copy_
* of the given function with an adaptor to _capture_ each
* produced result.
* @warning if function result is a value, it is copied.
*/
template<typename FUN>
FunctionResult (FUN&& targetFunction)
: function<SIG>{lib::meta::func::chained
( std::forward<FUN> (targetFunction)
, [this](Res res) -> Res
{
lastResult_ = res;
return std::forward<Res> (res);
})}
{ }
/** retrieve the last function result observed */
Res& operator*() const { return *lastResult_; }
bool isValid () const { return lastResult_.isValid(); }
explicit
operator bool() const { return isValid(); }
};
}} // namespace lib::wrap
#endif
#endif /*LIB_WRAPPER_H*/

View file

@ -493,51 +493,15 @@ 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);
};
}
};
/** immediately close (≙ fix) some values in a parameter tuple,
* starting from left, while leaving the remaining values open
* to be supplied by automation or another parameter binding. */
template<typename PAR, typename...PARS>
auto
closeParamFront (PAR v1, PARS ...vs)
{
using Params = typename WAB::Param;
return adaptParam(
ClosureBuilder<Params>::template closeFront (v1,vs...));
WAB::ParamClosure::template closeFront (v1,vs...));
}

View file

@ -138,6 +138,7 @@
#include "steam/engine/buffer-provider.hpp"
#include "steam/engine/buffhandle-attach.hpp" /////////////////OOO why do we need to include this? we need the accessAs<TY>() template function
#include "steam/engine/media-weaving-pattern.hpp"
#include "lib/meta/tuple-closure.hpp"
#include "lib/meta/tuple-helper.hpp"
//#include "lib/test/test-helper.hpp" ////////////////////////////OOO TODO added for test
#include "lib/format-string.hpp"
@ -251,9 +252,9 @@ namespace engine {
static constexpr uint FAN_I = PROT::FAN_I;
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 ProviderRef = std::reference_wrapper<BufferProvider>;
using ParamClosure = lib::meta::TupleClosureBuilder<typename PROT::Param>;
DataBuilder<POL, PortRef> leadPorts;
std::vector<TypeMarker> buffTypes;

View file

@ -35,6 +35,7 @@
#include "lib/hash-value.h"
#include "lib/opaque-holder.hpp"
#include "lib/meta/typelist-manip.hpp"
#include "lib/meta/typelist-util.hpp"
namespace steam {

View file

@ -218,7 +218,7 @@ namespace test {
.build()};
Time timeOfEvil{5555,0};
SHOW_EXPR(invokeRenderNode(node,timeOfEvil));
CHECK (15 == invokeRenderNode(node,timeOfEvil));
}

View file

@ -24,6 +24,7 @@
#include "lib/util.hpp"
#include "lib/wrapper.hpp"
#include "lib/wrapper-function-result.hpp"
#include <functional>
#include <iostream>

View file

@ -71,6 +71,7 @@
#include "vault/gear/nop-job-functor.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/meta/variadic-rebind.hpp"
#include "lib/meta/typeseq-util.hpp"
#include "lib/meta/function.hpp"
#include "lib/wrapper.hpp"
#include "lib/format-util.hpp"

View file

@ -58540,6 +58540,61 @@
<node CREATED="1573230307678" ID="ID_1856823830" MODIFIED="1573230336518" TEXT="&#xbb;Lumiera Forward Iterator&#xab; integrieren"/>
</node>
<node CREATED="1540682664865" ID="ID_1702211999" MODIFIED="1557498707236" TEXT="Metaprogramming">
<node CREATED="1739742552923" ID="ID_606595417" MODIFIED="1739742563204" TEXT="Typsequenzen und Typlisten">
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1739742570360" ID="ID_1552300649" MODIFIED="1739743026716" TEXT="Grunds&#xe4;tzlich: die Loki-Typlisten / Sequenzen werde ich weiterhin nutzen und erhalten">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Das hat sich &#252;ber l&#228;ngere Zeit herauskristalisiert.
</p>
<ul>
<li>
zun&#228;chst war das die einzige M&#246;glichkeit, &#252;berhaupt in meta-Generierung von Typen einzusteigen
</li>
<li>
dann dachte ich, es wird durch die Variadics und Lambdas obsolet werden, und hab schon teilweise mit dem R&#252;ckbau begonnen
</li>
<li>
doch dann kam die Ern&#252;chterung: <i>f&#252;r Variadics bin ich einfach zu bl&#246;d</i>&#160;&#8212; daf&#252;r mu&#223; man andauernd r&#252;ckw&#228;rts denken.
</li>
<li>
viele Jahre habe ich nun Erfahrungen gesammelt, was mit welcher Technik am besten geht; habe Helper f&#252;r Tuples gebaut, die dann doch nicht gebraucht wurden
</li>
<li>
2025 f&#252;r die Umstellung der Render-Engine auf Tuples und strikte Typisierung war ich erneut mit den &#187;tuple-likes&#171; konfrontiert. Ich hab mir wieder durch Einschieben einer Abstraktion geholfen, welche allerdings nur mit Typ-Sequenzen einigerma&#223;en sinnvoll zu implementieren ist. Damit gibt es nun drei Systeme zusammenh&#228;ngender Metaprogramming-Helper, und alle werden wohl erhalten bleiben.
</li>
<li>
habe daraufhin begonnen, Header umzuordnen, um die Include-Linien m&#246;glichst sauber zu bekommen.
</li>
</ul>
</body>
</html></richcontent>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1739743030251" ID="ID_860677414" MODIFIED="1739743057642" TEXT="#987 : Umstellen auf variadische Typsequenzen">
<icon BUILTIN="bell"/>
<node CREATED="1739743063606" ID="ID_1126377755" MODIFIED="1739743122896" TEXT="wird dringend, da sich die Metaprogrammierung nun ausgeweitet hat">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Es ist klar, da&#223; die Loki-Typlisten und Sequenzen erhalten bleiben, und in Zukunft sogar mehr zum Einsatz kommen, da ich nun im Bereich der Render-Engine viel mit Parameter-Tupeln arbeite.
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1739743156265" ID="ID_221325784" MODIFIED="1739743198704" TEXT="&#xdc;bergang per alternativer Definition: Types&lt;...&gt; vs TySeq&lt;...&gt;"/>
<node CREATED="1739743142166" ID="ID_1562037968" MODIFIED="1739743153038" TEXT="schrittweise kompatibel machen und schwenken">
<node COLOR="#338800" CREATED="1739743226160" ID="ID_490359788" MODIFIED="1739743238719" TEXT="_Fun&lt;SIG&gt; liefert nun variadic-sequence">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1739743240214" ID="ID_1756740911" MODIFIED="1739743248263" TEXT="geplant: Namen austauschen">
<icon BUILTIN="hourglass"/>
</node>
</node>
</node>
<node CREATED="1540682674455" ID="ID_1625152878" MODIFIED="1557498707236" TEXT="Typliste filtern">
<node CREATED="1540682680286" ID="ID_1172485112" MODIFIED="1557498707236" TEXT="nach canConvert">
<node CREATED="1540682731631" ID="ID_1059841081" MODIFIED="1557498707236" TEXT="die Typen, in die man umwandeln kann">
@ -58563,6 +58618,7 @@
</node>
</node>
</node>
</node>
<node CREATED="1734472826827" ID="ID_1739669703" MODIFIED="1734472937793" TEXT="generische Iteration">
<node COLOR="#435e98" CREATED="1734473802675" FOLDED="true" ID="ID_1446921071" MODIFIED="1734473919955" TEXT="forEach / mapEach">
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
@ -58763,7 +58819,7 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700669580665" FOLDED="true" ID="ID_1852128670" MODIFIED="1739581436031" TEXT="Funktor-Manipulationen">
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700669580665" FOLDED="true" ID="ID_1852128670" MODIFIED="1739742209442" 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....">
@ -58907,8 +58963,7 @@
....durch std::apply und std::invoke
</p>
</body>
</html>
</richcontent>
</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"/>
@ -105693,8 +105748,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
das geht, weil durch das constexpr-if die Funktion jedesmal erneut instantiiert wird, mit dann jeweils anderem deduziertem auto-Returntyp
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#dcd4b8" COLOR="#435e98" CREATED="1739290178567" ID="ID_1825991532" MODIFIED="1739290223471" TEXT="aber l&#xe4;&#xdf;t sich aufrufen &#xd83e;&#xdc32; mit korrektem Ergebnis">
@ -105721,8 +105775,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
...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>
</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>
@ -105732,8 +105785,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
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>
</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>
@ -105743,8 +105795,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
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>
</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;"/>
@ -105785,8 +105836,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
denn <font face="Monospaced" color="#181086">std::make_tuple</font>&#160;ist ein Template
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1739580770558" ID="ID_1162628481" MODIFIED="1739580788692" TEXT="das sich ergebende Konstrukt">
@ -105799,8 +105849,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
...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>
</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/>
@ -105809,8 +105858,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
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>
</html></richcontent>
</node>
<node CREATED="1739580942969" ID="ID_295215421" MODIFIED="1739580955344" TEXT="ist aber vermutlich irrelevant">
<icon BUILTIN="idea"/>
@ -105824,8 +105872,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
...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>
</html></richcontent>
</node>
</node>
</node>
@ -105846,8 +105893,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
RebindVariadic geht nur f&#252;r Klassen-Templates
</p>
</body>
</html>
</richcontent>
</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"/>
@ -105859,10 +105905,10 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<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 COLOR="#338800" CREATED="1739644781371" ID="ID_1651641988" MODIFIED="1739742190964" TEXT="versuche es erst mal mit einem Tupel">
<icon BUILTIN="button_ok"/>
<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">
<node COLOR="#435e98" CREATED="1739644880768" ID="ID_1786574048" MODIFIED="1739742183258" 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"/>
@ -105958,6 +106004,30 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1739742027076" ID="ID_1345350905" MODIFIED="1739742035927" TEXT="schrittweise verallgemeinern">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1739742051151" ID="ID_240638029" MODIFIED="1739743700109" TEXT="Hindernis wegr&#xe4;umen: trailing NullType in Typsequenz der Funktions-Argumente">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e6e1bd" CREATED="1739742093416" ID="ID_74503597" LINK="#ID_490359788" MODIFIED="1739743326711" TEXT="zugleich ein wichtiger Schritt f&#xfc;r #987">
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1739743344360" ID="ID_1556745780" MODIFIED="1739743697163" TEXT="war letztlich in ein paar Stunden zu leisten">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Das war vielleicht der gr&#246;&#223;te Brocken, und ich hab mich da seit einigen Jahren nicht rangetraut, weil ich eine tagelange &#187;Big Bang&#171;-Aktion f&#252;rchtete. Nun mu&#223;te ich mir aber f&#252;r dieses Thema die function-closure-Utils genauer anschauen, und hab verstanden, wie die Definitionen zusammenh&#228;ngen. Hinzu kommt, da&#223; inzwischen schon ein gewisses Kern-&#214;kosystem steht, das gleicherma&#223;en mit den variadischen Sequenzen umgehen kann. Das hat mich auf die Idee gebracht, das Thema mit kreuzweisen Br&#252;cken zu entsch&#228;rfen &#8212; bei genauerer Betrachtung zeigt sich n&#228;mlich, da&#223; ein erheblicher Teil der eigentlichen Manipulations-Funktionen nicht explizit auf NullType angewiesen ist, sondern sich im Wesentlichen auf lib::meta::Prepend abst&#252;tzt. Und da nun klar ist, da&#223; in Zukunft einmal TySeq einfach die Rolle von Types &#252;bernehmen wird, per Umbenennung, ist es m&#246;glich, an vielen Stellen Spezialisierungen daneben zu stellen (markiert mit #987), die dann wieder &#252;ber die richtige Br&#252;cke zur&#252;ck f&#252;hren. Habe nun gute Hoffnung, da&#223; sich die explizit auf die alten Typlisten angewiesenen Verwendungen schritweise isolieren lassen
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="ksmiletris"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1739743706096" ID="ID_1310970069" MODIFIED="1739743735573" TEXT="das ist eigentlich generisch &#x27f9; umziehen in lib::meta::TupleClosureBuilder">
<icon BUILTIN="yes"/>
</node>
</node>
</node>
</node>
</node>