From af3d8f5b58fefd15d5f2e4f819bfcd69a69ba0c2 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 18 Oct 2026 17:10:34 +0200 Subject: [PATCH] Parameters: tentatively require explicit typing on prototype-build In-depth analysis indicated that an ''opaque solution'' would be possible, yet complex to implement in detail - a Builder interface would be required - this interface needs to package all given param values as ValBuff - furthermore, each such value must be accompanied with a BaseTypeID - the actual builder would then become ''a PImpl'' - it could be either implemented as heap-allocated with unique_ptr - or be a `PolymorphicValue` itself (in which case the builder front-end should be non-copyable and used by reference, inline in a builder expression - in any case, the front-End builder would proxy all calls to the actual builder - and the latter would return an opaque parameter at the end This setup would even allow to use ''full type erasure'' on the Parameter front-end, and might reduce the ''header inclusion tax'' BUT -- that being said, if we just require the user to specify the desired type explicitly, not only when building a new parameter, but also when cloning a parameter from a prototype, then the actual implementation could use one simple builder object and all the complexities outlined above could be skipped. So the latter is what we do for now -- since this whole effort is rather a design draft and should enable to explore actual usages of the parameter framework. At a later point, the elaborate version could still be implemented --- src/lib/par/disposition.hpp | 21 +++- src/lib/par/parameter.hpp | 50 +++----- tests/lib/par/parameter-test.cpp | 5 +- wiki/thinkPad.ichthyo.mm | 210 ++++++++++++++++++++++++++++--- 4 files changed, 230 insertions(+), 56 deletions(-) diff --git a/src/lib/par/disposition.hpp b/src/lib/par/disposition.hpp index ae96f11e8..67ab7a958 100644 --- a/src/lib/par/disposition.hpp +++ b/src/lib/par/disposition.hpp @@ -57,6 +57,12 @@ namespace par { template void setVal (X); + uint + getScaleID() const + { + return idr_.scaleID; + } + protected: template bool @@ -72,12 +78,6 @@ namespace par { idr_.baseTypeID = BaseTypeID(); } - uint - getScaleID() const - { - return idr_.scaleID; - } - void activateScale (uint scaleID) { @@ -112,6 +112,15 @@ namespace par { TypedEntity::registerScale (std::move (scale)); } + ParamData (VAL const& initVal, uint scaleID) + : val_{} + , src_{nullptr} + { + Disposition::markBaseDomain(); + Disposition::activateScale (scaleID); + val_ = this->conformScale (initVal); + } + /* === Provision Interface === */ void retrieveInto (ValBuff&) const override final; ///< @note is sometimes invoked non-virtually for sake of optimisation void setValFrom (ValBuff const&) override final; diff --git a/src/lib/par/parameter.hpp b/src/lib/par/parameter.hpp index 95c778839..35f595183 100644 --- a/src/lib/par/parameter.hpp +++ b/src/lib/par/parameter.hpp @@ -83,8 +83,13 @@ namespace par { .withValue (std::forward (initVal)); } - class ProtoBuilder; - static ProtoBuilder from (Parameter const& prototype); + template + static Builder + from (Parameter const& prototype) + { + return {prototype.getVal() // note: may convert value type + ,unConst(prototype).getPayload().getScaleID()}; + } protected: template @@ -98,16 +103,24 @@ namespace par { class Parameter::Builder { VAL initVal_{}; + uint scaleID_{0}; Scale scale_{}; public: + Builder() = default; + Builder (VAL initVal, uint scaleID) + : initVal_{initVal} + , scaleID_{scaleID} + { } + // default copy operations + Parameter build() { using ImplPackage = ParamData; //////////////////////////////////////////TICKET #1197 : remove the necessity to inject the CopySupportMarker ImplPackage* typeTag{nullptr}; - Parameter resParam{typeTag, initVal_, std::move (scale_)}; - return resParam; + return scaleID_? Parameter{typeTag, initVal_, scaleID_} // pass-through scale unmodified + : Parameter{typeTag, initVal_, std::move (scale_)}; } template @@ -127,36 +140,7 @@ namespace par { }; - class Parameter::ProtoBuilder - { - Parameter ref_; - - public: - ProtoBuilder (Parameter const& prototype) - : ref_{prototype} - { } - - Parameter - build() - { - return ref_; - } - - template - ProtoBuilder&& - maxVal (X&& upperBound) - { - /////////////////////////////////////////////OOO how to remould a scale? - return std::move(*this); - } - }; - inline Parameter::ProtoBuilder - Parameter::from (Parameter const& prototype) - { - return ProtoBuilder{prototype}; - } - template diff --git a/tests/lib/par/parameter-test.cpp b/tests/lib/par/parameter-test.cpp index c8cbabd50..3b7b32e4a 100644 --- a/tests/lib/par/parameter-test.cpp +++ b/tests/lib/par/parameter-test.cpp @@ -106,10 +106,13 @@ namespace test{ CHECK (roughEQ (23.0 , ps.getVal())); /////////////////////////////////////////////////////////////////////////////OOO (End) Prototyping 10/2026 - Parameter p2 = Parameter::from(p1) + Parameter p2 = Parameter::from(p1) .maxVal (sqrt(2)) .build(); SHOW_EXPR(p2.getVal()); +SHOW_EXPR(p2.getVal()); + CHECK (sqrt(2) == p2.getVal()); + CHECK (roughEQ (1.41421, p2.getVal())); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 14bcaa558..e24aff405 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -88095,17 +88095,33 @@ Prop.1: dist%3 1 2 0 1 2 0 - + - + + +

...den man nur includieren muß, wenn man tatsächlich neue Parameter(typen) definiert

-
+ +
+ + + + + + + + + + + + +
@@ -88155,8 +88171,8 @@ Prop.1: dist%3 1 2 0 1 2 0 - - + +
@@ -88232,11 +88248,11 @@ Prop.1: dist%3 1 2 0 1 2 0
- + - + - + @@ -88246,7 +88262,7 @@ Prop.1: dist%3 1 2 0 1 2 0 - + @@ -88256,8 +88272,8 @@ Prop.1: dist%3 1 2 0 1 2 0 - - + + @@ -88265,12 +88281,18 @@ Prop.1: dist%3 1 2 0 1 2 0 - + + + + + + + - + @@ -88282,7 +88304,7 @@ Prop.1: dist%3 1 2 0 1 2 0 - + @@ -88293,11 +88315,16 @@ Prop.1: dist%3 1 2 0 1 2 0 - + - + + + + + + @@ -88328,6 +88355,140 @@ Prop.1: dist%3 1 2 0 1 2 0 + + + + + + +

+ ...besonders gefallen tut mir das nicht, aber es ist die einzige Möglichkeit, die ich im Moment sehe +

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

+ ...also das klassische Builder-Pattern: man erzeugt ein "schwebendes" Builder-Objekt, und die Builder-Methoden geben eine Referenz darauf zurück, bis schließlich die terminale build()-Operation das Resultat by-value liefert. +

+

+ +

+

+ Der andere Ansatz, move-Build, würde nämlich in jedem Schrit einen Dispatch durch den VirtualCopySupport machen, und damit den entscheidenden Vorteil eines move-Build negieren +

+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ man könnte damit den konkreten Typ tatsächlich vom Parameter-front-End löschen, und danach eine Reorganisation der Implementierungs-Hierarchie machen, so daß Teile der Implementierung tatsächlich verborgen bleiben, da ja setets eine Indirektion dazwischen liegt +

+ + +
+
+
+ + +
+ + + + + + +
@@ -88748,6 +88909,23 @@ Prop.1: dist%3 1 2 0 1 2 0
+ + + + + + + +

+ aus Performance-Gründen wurde alles auf Inlining hin ausgelegt — und die (noch im Entstehen befindlichen) Header sind bereits ziemlich komplex geworden +

+ + +
+ + +
+