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:
parent
fbf7a792a8
commit
769060b9dd
13 changed files with 317 additions and 145 deletions
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -41,6 +43,8 @@
|
|||
** 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
|
||||
**
|
||||
*/
|
||||
|
|
|
|||
88
src/lib/meta/tuple-closure.hpp
Normal file
88
src/lib/meta/tuple-closure.hpp
Normal 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
|
||||
92
src/lib/wrapper-function-result.hpp
Normal file
92
src/lib/wrapper-function-result.hpp
Normal 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*/
|
||||
|
|
@ -16,15 +16,21 @@
|
|||
** 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*/
|
||||
|
|
|
|||
|
|
@ -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...));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ namespace test {
|
|||
.build()};
|
||||
|
||||
Time timeOfEvil{5555,0};
|
||||
SHOW_EXPR(invokeRenderNode(node,timeOfEvil));
|
||||
CHECK (15 == invokeRenderNode(node,timeOfEvil));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "lib/util.hpp"
|
||||
|
||||
#include "lib/wrapper.hpp"
|
||||
#include "lib/wrapper-function-result.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -58540,6 +58540,61 @@
|
|||
<node CREATED="1573230307678" ID="ID_1856823830" MODIFIED="1573230336518" TEXT="»Lumiera Forward Iterator« 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ätzlich: die Loki-Typlisten / Sequenzen werde ich weiterhin nutzen und erhalten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Das hat sich über längere Zeit herauskristalisiert.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
zunächst war das die einzige Möglichkeit, ü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ückbau begonnen
|
||||
</li>
|
||||
<li>
|
||||
doch dann kam die Ernüchterung: <i>für Variadics bin ich einfach zu blöd</i> — dafür muß man andauernd rückwärts denken.
|
||||
</li>
|
||||
<li>
|
||||
viele Jahre habe ich nun Erfahrungen gesammelt, was mit welcher Technik am besten geht; habe Helper für Tuples gebaut, die dann doch nicht gebraucht wurden
|
||||
</li>
|
||||
<li>
|
||||
2025 für die Umstellung der Render-Engine auf Tuples und strikte Typisierung war ich erneut mit den »tuple-likes« konfrontiert. Ich hab mir wieder durch Einschieben einer Abstraktion geholfen, welche allerdings nur mit Typ-Sequenzen einigermaßen sinnvoll zu implementieren ist. Damit gibt es nun drei Systeme zusammenhängender Metaprogramming-Helper, und alle werden wohl erhalten bleiben.
|
||||
</li>
|
||||
<li>
|
||||
habe daraufhin begonnen, Header umzuordnen, um die Include-Linien mö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ß 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="Übergang per alternativer Definition: Types<...> vs TySeq<...>"/>
|
||||
<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<SIG> 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<R1> b1, Extension<R1,R2> 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äßt sich aufrufen �� mit korrektem Ergebnis">
|
||||
|
|
@ -105721,8 +105775,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
...denn im Grunde sind alle diese Bindings mit Lambdas relativ banal zu formulieren — es ist halt bloß relativ technisch, versaut den Code und erfordert vom Benutzer viel Präzision und Beachten von feinen Punkten. Da »der Benutzer« auf absehbare Zeit ich selbst bin, ist das — Määh. Ja ich kann das. Wääh
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1739549074693" ID="ID_189358758" MODIFIED="1739549443676" TEXT="direkt definiertes Template-λ für bind-to-first in NodeBuilder einbauen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -105732,8 +105785,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
Das klingt nach einer Lösung, die <i>billig zu haben wäre.</i> Es sind ein paar Zeilen recht technischer Code im Node-Builder, der ohnehin in diesem Bereich „nicht mehr schön“ ist. Kann man also in jedem Fall mal einbauen — mein <i>einziger Zweifel betrifft die Nützlichkeit und Relevanz;</i> warum man ausgerechnet ein einziges erstes Argument schließen wollte, will sich mir nicht recht erschließen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1739549457748" ID="ID_1160952116" MODIFIED="1739581633828" TEXT="auf die alten function-closure-Utils zurückgreifen und einen Wrapper dafür anbieten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -105743,8 +105795,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
Das ist pre-C++11-Code, nur oberflächlich modernisiert, und bisher nur in einem Bereich testhalber verwendet (für Proc-Commands). Grundsätzlich möchte ich diesen Code aber erhalten, nicht loswerden. <b>Risiko</b>: es gibt wohl einige »Untiefen« — 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> — und dann seither doch nicht mehr benutzt (bestätigt die Zweifel bezü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äre die Beschrä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<R1> b1, Extension<R1,R2> extension)
|
|||
denn <font face="Monospaced" color="#181086">std::make_tuple</font> 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<R1> b1, Extension<R1,R2> 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äßt sich bei diesem Design kaum vermeiden">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
|
|
@ -105809,8 +105858,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
zwar könnte man auf die Idee kommen, den Adapter <i>hinter den Parameter-Functor</i> zu setzen. Das läßt sich aber in dem hier gewählten cross-Builder-API nicht realisieren, da der Parameter-Functor sofort auf Kompatibilität mit dem Parameter-Tuple-Typ geprüft wird, und obendrein auch sofort dahingehend festglegt wird, daß er ein TurnoutSystem& als Argument bekommt. Ein schrittweises Aufbauen einer Funktor-Kette ist also nur beim Processing-Functor möglich. Es sei denn, man würde eine wesentlich elaboriertere Darstellung finden können, bei der ein Gesamt-Functor-Typ fü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<R1> b1, Extension<R1,R2> extension)
|
|||
...da wir durch das Anwenden auf einen umgebauten Processing-Functor schwenken; deshalb kann auf diesen sodann erneut eine Adaptierung angewendet werden — selbst wenn diese dann schließlich das Parameter-Tupel complett schließt (denn ohne Parameter-Functor erfolgt der Aufruf implizit mit einem default-konstruierbaren Parameter-Tupel, und das leere Tupel ist uneingeschräntk default-konstruierbar)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -105846,8 +105893,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
RebindVariadic geht nur für Klassen-Templates
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1739644580928" ID="ID_298080445" MODIFIED="1739644600474" TEXT="muß Metafunktion für die Sequenz der Parameter-Typen einbauen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
|
|
@ -105859,10 +105905,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> 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ü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 ⟸ so geht das nicht"/>
|
||||
|
|
@ -105958,6 +106004,30 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> 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ä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ü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ößte Brocken, und ich hab mich da seit einigen Jahren nicht rangetraut, weil ich eine tagelange »Big Bang«-Aktion fürchtete. Nun mußte ich mir aber für dieses Thema die function-closure-Utils genauer anschauen, und hab verstanden, wie die Definitionen zusammenhängen. Hinzu kommt, daß inzwischen schon ein gewisses Kern-Ökosystem steht, das gleichermaßen mit den variadischen Sequenzen umgehen kann. Das hat mich auf die Idee gebracht, das Thema mit kreuzweisen Brücken zu entschärfen — bei genauerer Betrachtung zeigt sich nämlich, daß ein erheblicher Teil der eigentlichen Manipulations-Funktionen nicht explizit auf NullType angewiesen ist, sondern sich im Wesentlichen auf lib::meta::Prepend abstützt. Und da nun klar ist, daß in Zukunft einmal TySeq einfach die Rolle von Types übernehmen wird, per Umbenennung, ist es möglich, an vielen Stellen Spezialisierungen daneben zu stellen (markiert mit #987), die dann wieder über die richtige Brücke zurück führen. Habe nun gute Hoffnung, daß 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 ⟹ umziehen in lib::meta::TupleClosureBuilder">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue