diff --git a/src/lib/par/disposition.hpp b/src/lib/par/disposition.hpp index 6ee6e5718..8b2335fda 100644 --- a/src/lib/par/disposition.hpp +++ b/src/lib/par/disposition.hpp @@ -26,8 +26,8 @@ #define LIB_PAR_DISPOSITION_H -#include "lib/par/domain.hpp" #include "lib/par/provision.hpp" +#include "lib/par/param-type.hpp" namespace lib { @@ -41,6 +41,7 @@ namespace par { * notation and stored within the Parameter object (as a container). */ class Disposition + : public ParamType { public: }; diff --git a/src/lib/par/domain.hpp b/src/lib/par/domain.hpp index bbfb1a846..7d2ee8a8c 100644 --- a/src/lib/par/domain.hpp +++ b/src/lib/par/domain.hpp @@ -37,6 +37,7 @@ #include "lib/meta/typelist.hpp" //#include "lib/meta/typelist-util.hpp" #include "lib/meta/generator.hpp" +#include "lib/par/provision.hpp" #include "lib/meta/trait.hpp" #include "lib/util.hpp" @@ -53,7 +54,6 @@ namespace par { using std::numeric_limits; - struct ValBuff { /*placeholder*/ }; template constexpr inline ValBuff& @@ -109,7 +109,7 @@ namespace par { ,bool >; /** build a generic visitor interface for all types in list */ - using TypeHandlerInterface = meta::InstantiateForEach; + using TypeHandlerInterface = meta::InstantiateForEach; /** diff --git a/src/lib/par/param-type.cpp b/src/lib/par/param-type.cpp index 1cef924c7..60efda1ce 100644 --- a/src/lib/par/param-type.cpp +++ b/src/lib/par/param-type.cpp @@ -21,6 +21,7 @@ #include "lib/error.hpp" #include "lib/par/parameter.hpp" +#include "lib/par/provision.hpp" #include "lib/par/param-type.hpp" namespace lib { @@ -28,8 +29,7 @@ namespace par { /* emit VTables in this translation unit... */ - - ParamType::~ParamType() { } + Provision::~Provision() { } Domain::~Domain() { } diff --git a/src/lib/par/param-type.hpp b/src/lib/par/param-type.hpp index e3326fffd..44c432f74 100644 --- a/src/lib/par/param-type.hpp +++ b/src/lib/par/param-type.hpp @@ -42,9 +42,9 @@ namespace par { * Furthermore, the interface exposes allowed conversion and conforming operations. */ class ParamType + : public Domain { public: - virtual ~ParamType(); ///< this is an interface }; diff --git a/src/lib/par/parameter.hpp b/src/lib/par/parameter.hpp index 27b604c57..608294087 100644 --- a/src/lib/par/parameter.hpp +++ b/src/lib/par/parameter.hpp @@ -43,14 +43,58 @@ namespace par { class Parameter { public: + class Builder; + template - VAL get(); + VAL getVal(); + + template + void setVal (VAL&&); + + /* === Builder API === */ + + template + static Builder forType(); protected: }; + class Parameter::Builder + { + public: + Parameter + build() + { + UNIMPLEMENTED ("terminal builder operation: package a disposition into the Parameter"); + } + }; + + + template + Parameter::Builder + Parameter::forType() + { + UNIMPLEMENTED ("how to setup the base type configuration? do we need a type parameter in the Builder class?"); + } + + + template + VAL + Parameter::getVal() + { + UNIMPLEMENTED ("extract the »value«, possibly applying suitable type conversions"); + } + + + template + void + Parameter::setVal (VAL&& changedVal) + { + UNIMPLEMENTED ("apply suitable type conversions and clamping, then transfer the new value into the Provision interface"); + } + }} // namespace lib::par #endif /*LIB_PAR_PARAMETER_H*/ diff --git a/src/lib/par/provision.hpp b/src/lib/par/provision.hpp index 405078d05..611f141f1 100644 --- a/src/lib/par/provision.hpp +++ b/src/lib/par/provision.hpp @@ -25,12 +25,15 @@ #define LIB_PAR_PROVISION_H -#include "lib/par/param-type.hpp" +#include "lib/time/timevalue.hpp" namespace lib { namespace par { + using time::Time; + + struct ValBuff { /*placeholder*/ }; /** @@ -40,11 +43,22 @@ namespace par { * and assigned, while the current time-based value is the result of evaluation. * Any parameter value is associated to a ParamType that defines the underlying * value domain and possibly a scale with range limits and metric constraints. + * @remark the value access and manipulation works _backwards_ from an implicit + * value that is conceptually located _within_ this provision towards + * an ValBuff for external access. The reason for this indirect + * formulation is that the »value« is assumed to comply to some data type, + * which however remains an opaque internal detail and is not disclosed. */ class Provision { public: virtual ~Provision(); ///< this is an interface + + virtual void retrieveInto (ValBuff&) const { /*NOP*/ } + virtual void pullAt (Time, ValBuff&) const { /*NOP*/ } + virtual void setValFrom (ValBuff const&) { /*NOP*/ } + virtual void connect (Provision&) { /*NOP*/ } + virtual void disconnnect() { /*NOP*/ } }; diff --git a/tests/16parameter.tests b/tests/16parameter.tests index 7e6ebe492..26060add7 100644 --- a/tests/16parameter.tests +++ b/tests/16parameter.tests @@ -7,6 +7,11 @@ return: 0 END -PLANNED "Parameter Domain Type" ParameterDomain_test << END +TEST "Parameter Domain Type" ParameterDomain_test << END +return: 0 +END + + +PLANNED "Parameter Provision" ParameterProvision_test << END return: 0 END diff --git a/tests/lib/par/parameter-domain-test.cpp b/tests/lib/par/parameter-domain-test.cpp index 844c5b642..57525c22e 100644 --- a/tests/lib/par/parameter-domain-test.cpp +++ b/tests/lib/par/parameter-domain-test.cpp @@ -184,6 +184,7 @@ namespace test{ verify_valueAccess() { BaseDomain domInt; +SHOW_EXPR(sizeof(BaseDomain)) ///////////////////////////////////////TODO this should be only one »slot«, but is actually quite large, due to using multiple inheritance in the Domain interface. /////OOO fix that! Domain& dom{domInt}; int val = 1 + rani (1000); diff --git a/tests/lib/par/parameter-provision-test.cpp b/tests/lib/par/parameter-provision-test.cpp index 811ee237d..40c601aa9 100644 --- a/tests/lib/par/parameter-provision-test.cpp +++ b/tests/lib/par/parameter-provision-test.cpp @@ -50,7 +50,7 @@ namespace test{ /**************************************************************************//** - * @test document behaviour of paramter value provision and automation. + * @test document behaviour of parameter value provision and automation. */ class ParameterProvision_test : public Test { diff --git a/tests/lib/par/parameter-test.cpp b/tests/lib/par/parameter-test.cpp index 29bf2f59c..070257908 100644 --- a/tests/lib/par/parameter-test.cpp +++ b/tests/lib/par/parameter-test.cpp @@ -76,6 +76,14 @@ namespace test{ void simpleUsage() { + Parameter par = Parameter::forType().build(); + CHECK (0 == par.getVal()); + + par.setVal (12.3); + CHECK (12 == par.getVal()); + CHECK (12u == par.getVal()); + CHECK (12.0 == par.getVal()); + CHECK (true == par.getVal()); } diff --git a/tests/lib/several-builder-test.cpp b/tests/lib/several-builder-test.cpp index d897e6136..e96a5b878 100644 --- a/tests/lib/several-builder-test.cpp +++ b/tests/lib/several-builder-test.cpp @@ -171,7 +171,7 @@ namespace test{ } - /** @test various ways to build an populate the container + /** @test various ways to build and populate the container * - with a defined interface type \a I, instances of arbitrary subclasses * can be added, assuming there is sufficient pre-allocated buffer space; * all these subclass instances are accessed through the common interface. diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 058d10cb7..810a5f886 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -82647,8 +82647,8 @@ - + @@ -83117,6 +83117,58 @@ + + + + + + + +

+ das heißt, meine ganzen Argumente bzgl »Slots« für die VTable sind eigentlich nicht durch den Standard gedeckt; sie sind aber insofern fundiert, da C++ keine Penalty für nicht verwendete Features  erlaubt — und insofern kann es keine Layout-»Optimierung« geben, die die VTable schlechter implementiert als durch einen einzigen Pointer +

+ +
+
+ + + + +

+ Im Einzelnen ausgeführt: +

+
    +
  • + C++ - Code wird auch auf ABI-Ebene strukturiert und zusammengefügt +
  • +
  • + Eine Basisklasse ist self-contained und wird als Ganzes eingefügt und referenziert, einschließlich ihres Implementierungs-Codes (Ausnahmen können gelten unter Optimierung, aber nur wenn der Compiler völlige Äquivalenz garantieren kann +
  • +
  • + das bedeutet: der Code der Basis-Klasse bezieht sich auf sein eigenes Layout +
  • +
  • + die virtuellen Methoden werden nicht per ID aufgelöst, sondern komplett in »Slot-Offsets« übersetzt. +
  • +
  • + wenn also Code einer Basisklasse eine virtuelle Methode aufruft, dann holt er sich seine VTable (die irgendwo im Objekt per Referenz materialisiert sein muß, was aber auch ein Funktionspointer leisten würde). Auf diese VTable wendet der Code einen festen Offset an, und springt durch den resultierenden Funktionspointer. +
  • +
  • + dieser Code wird nicht umgeschrieben, wenn er in ein abgeleitetes Objekt eingebunden ist (abgesehen von Optimierungen, die jedoch niemals garantiert sind) +
  • +
+

+ Schlußfolgerung: der Code einer Methode der Basisklasse muß immer das komplette Layout dieser Basisklasse in gleicher Weise vorfinden. Insofern ist es generell nicht möglich, VTables mehrerer eingemischter Basisklassen zusammenzulegen, ohne auch den kompletten Code der Basisklasse neu generieren zu müssen. +

+ +
+
+
+ + + + +
@@ -84252,6 +84304,124 @@ + + + + + + + +

+ ...was hier allerdings nur meint, daß auch zusätzliche normale Funktionen mit Basis-Implementierung bereits da sind, und daß es fest vorgegebene Datenstrukturen gibt, für die der Zugriff inline  ist. An der Stelle könnte auch die Fallunterscheidung ansetzen für einfache Parameter vs. Komplexe Parameter. Dennoch muß der Disposition-Typ letztlich finit und explizit definiert sein, denn er wird als »Interface«-Typ in einen PolymorphicValue gepackt. +

+ +
+
+
+ + + + +

+ es muß zwingend eine lineare Interface-Kette sein mit einer VTable +

+ +
+ + + +

+ das macht den Aufbau tricky, und nicht leicht zu entscheiden, denn alle wichtigen Interfaces müssen direkt explizit aufeinander aufbauen; es gibt keine Möglichkeit, variable Aspekte später einzumischen. +

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

+ ...unter der Vorgabe, daß wir nur eine einzige lineare Vererbungskette haben können ⟹ da Domain unter Provision liegen muß, und BaseDomain über allen Interfaces, und der Typ von BaseDomain abgeleitet sein soll. +

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

+ ich möchte daß jeder Parameter auch eine Provision sein kann +

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

+ bedeutet: es wird Kenntnis eines (opaquen) Typs in der Implementierung unterstellt, so daß man Provisions verknüpfen kann, und sich diese automatisch adaptieren. Aber das Interface selber bietet keinerlei Möglichkeit, diese implizite Information zu extrahieren (und wenn, dann nur durch ein neutrales Analyse-Prädikat, oder Zugang zu einer Domain-Referenz) +

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

+ ...das würde ausnutzen, daß die Implementierung immer oben auf der ganzen Interface-Kette sitzen muß; somit könnte man von jeder konkreten Instanz, die Provision& implementiert, auch schlußfolgern daß sie sich auf eine Domain& downcasten läßt +

+ +
+
+
+ + + + +

+ ...sonst wird es schwierig mit dem Zusammenstellen der Interface-Kette; tatsächlich lassen sich alle für dieses Interface vorgesehenen Operationen »leer« Implementieren — es passiert dann einfach gar nichts, keine Zuweisung, keine Verbindung +

+ +
+ +
+
+
+ + + + + + + @@ -84276,6 +84446,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +