From 9f19f5d895c1fd6d4c13fa382d485b8e8ced64c6 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 1 Sep 2026 23:48:01 +0200 Subject: [PATCH] Parameters: build container with in-place init turns out to be quite tricky, due to the overly convoluted implementation of PolymorphicValue (which looks quite dated, generally speaking, and could use a complete overhaul). - pass the basic value type as template parameter through the Builder - allow for the ability to define an initial value for the parameter - invoke the protected constructor of PolymorphicValue, directly passing a ''type tag'' to specify the implementation data package to be placed into the embedded data buffer --- src/lib/par/disposition.hpp | 12 +++-- src/lib/par/parameter.hpp | 40 ++++++++++------- src/lib/polymorphic-value.hpp | 2 +- wiki/thinkPad.ichthyo.mm | 85 +++++++++++++++++++++++++++++++++-- 4 files changed, 114 insertions(+), 25 deletions(-) diff --git a/src/lib/par/disposition.hpp b/src/lib/par/disposition.hpp index 70319cbc4..d870c8bd4 100644 --- a/src/lib/par/disposition.hpp +++ b/src/lib/par/disposition.hpp @@ -52,14 +52,18 @@ namespace par { * with domain and scale, and a value provision. Can be generated through a builder * notation and stored within the Parameter object (as a container). */ - template + template class ParamData - : public TypedEntity + : public TypedEntity { - V val_{}; - Provision* src_{nullptr}; + VAL val_; + Provision* src_; public: + ParamData (VAL initVal) + : val_{std::move (initVal)} + , src_{nullptr} + { } }; diff --git a/src/lib/par/parameter.hpp b/src/lib/par/parameter.hpp index 2ebe47539..cacd25897 100644 --- a/src/lib/par/parameter.hpp +++ b/src/lib/par/parameter.hpp @@ -32,6 +32,8 @@ #include "lib/par/disposition.hpp" #include "lib/polymorphic-value.hpp" +#include + namespace lib { namespace par { @@ -44,6 +46,7 @@ namespace par { } + /** * Descriptor and container to hold a generic parameter. * The value can be fixed or supplied by an automation function. @@ -52,6 +55,7 @@ namespace par { : protected ParamContainer { public: + template class Builder; template @@ -63,30 +67,32 @@ namespace par { /* === Builder API === */ template - static Builder forType(); + static Builder + forType() { return {}; } protected: - - }; - - - class Parameter::Builder - { - public: - Parameter - build() - { - UNIMPLEMENTED ("terminal builder operation: package a disposition into the Parameter"); - } + template + Parameter (IMP* typeTag, ARGS&&... args) + : PolymorphicValue (typeTag, std::forward(args)...) + { } }; template - Parameter::Builder - Parameter::forType() + class Parameter::Builder { - UNIMPLEMENTED ("how to setup the base type configuration? do we need a type parameter in the Builder class?"); - } + VAL initVal_{}; + + public: + Parameter + build() + { + using ImplPackage = ParamData; + ImplPackage* typeTag{nullptr}; + Parameter resParam{typeTag, std::move (initVal_)}; + return resParam; + } + }; template diff --git a/src/lib/polymorphic-value.hpp b/src/lib/polymorphic-value.hpp index d9ff8787f..e3fad2293 100644 --- a/src/lib/polymorphic-value.hpp +++ b/src/lib/polymorphic-value.hpp @@ -516,7 +516,7 @@ namespace lib { static PolymorphicValue build (ARGS&&... args) { - Adapter* type_to_build_in_buffer(0); + IMP* type_to_build_in_buffer; return PolymorphicValue (type_to_build_in_buffer, std::forward(args)...); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 5e8132043..6d582230e 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -64126,7 +64126,8 @@ - + + @@ -64805,7 +64806,8 @@ - + + @@ -64821,6 +64823,17 @@ + + + + +

+ ...war mir aber letztlich nicht schlüssig, in welche Richtung meine Abwägung geht; die C++-STDLIB verwendet ja zwei Funktionspointer, von denen einer auf einen generischen Instance-Manager zeigt. Meine eigenen »Freihand-Abwägungen« bezüglich generierter Assembly und Runtime-Overhead weisen aber immer wieder in die Richtung, daß eine VTable effizienter ist, als mehrere Funktionspointer, wobei im Fall von lediglich zwei Pointern vermutlich immer noch nahezu Äquivalenz besteht. Das Problem bei solchen Abwägungen im Kontext von LIbrary-Design ist, daß man die Frage eigentlich nicht empirisch entscheiden kann; Microbenchmarks sind immer nur Momentaufnahmen, und der globale Impact einer solchen Entscheidung ist extrem schwer zu fassen (und aufwendig zu untersuchen) +

+ +
+ +
@@ -64828,6 +64841,13 @@ + + + + + + +
@@ -83964,7 +83984,7 @@ - + @@ -83993,6 +84013,16 @@ + + + + + + + + + + @@ -84503,6 +84533,55 @@ + + + + + + + + + +

+ ....diese erscheint heutzutage in mehrfacher Hinsicht als unbeholfen  — wobei allerdings die Wurzeln noch in die Zeit vor C++11 zurückreichen. Im Besonderen gibt es keinen direkt nutzbaren Konstruktor, und auch keine effizienten move-Assignments (copy-and-swap-Idiom). Demzufolge würde bereits eine direkte per-Value-Initialisierung der Basisklasse sofort einen Aufruf des virtuellen-Copy-APIs nach sich ziehen.... +

+ +
+
+ + + + +

+ ...da ich dieses Konstrukt zunehmend für bedeutsam halte, und in viel größerem Umfang zu verwenden gedenke — es könnte sogar das bisherige ref-count-basiderte Memory-Management im high-level-Model ablösen.... +

+ +
+ +
+ + + + + + +

+ ....der proctcted-ctor bekommt ein marker-Tag, das definiert ist als IMP* — dadurch wird der Typ IMP kommuniziert und in einen TypeSelector<IMP> verwandelt ... der dann allerdings erneut indirekt an den eigentlichen Arbeits-ctor weitergetgeben wird. Oh (Herr)mann! +

+ +
+
+
+ + + + +

+ damit sollte laut Standard der initiale Parameter-Value tatsächlich in-place konstruiert werden, ohne Aufruf des virtuellen copy-support +

+ +
+