From f452cd268d3e4b8e1936c64f3dc163bbe45fcf93 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 1 Sep 2026 20:43:12 +0200 Subject: [PATCH] Parameters: establish layered implementation order Finally able to settle upon a layering for the implementation facilities Provision:: represents the core idea of a parameter Domain:: assumes the ability to handle typed values Disposition:: complete implementation capabilities BaseDomain:: establish type conversion functionality TypedEntity:: provide a type and ID descriptor and scale configuration ParamData:: full implementation based on an embedded value buffer --- src/lib/par/disposition.hpp | 20 ++- src/lib/par/domain.hpp | 172 --------------------- src/lib/par/param-type.hpp | 194 +++++++++++++++++++++++- tests/lib/par/parameter-domain-test.cpp | 16 +- wiki/thinkPad.ichthyo.mm | 8 +- 5 files changed, 224 insertions(+), 186 deletions(-) diff --git a/src/lib/par/disposition.hpp b/src/lib/par/disposition.hpp index 8b2335fda..70319cbc4 100644 --- a/src/lib/par/disposition.hpp +++ b/src/lib/par/disposition.hpp @@ -32,7 +32,19 @@ namespace lib { namespace par { + + /** + * Implementation-Service: complete Parameter functionality. + * Includes the ability to access / set a »value«, attach automation, + * identify and convert underlying value data types and handle + * trait- and identity tags and the specifics of the value scale. + */ + class Disposition + : public Domain + { + public: + }; /** @@ -40,9 +52,13 @@ 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). */ - class Disposition - : public ParamType + template + class ParamData + : public TypedEntity { + V val_{}; + Provision* src_{nullptr}; + public: }; diff --git a/src/lib/par/domain.hpp b/src/lib/par/domain.hpp index 8d702eb15..f3622132f 100644 --- a/src/lib/par/domain.hpp +++ b/src/lib/par/domain.hpp @@ -115,177 +115,5 @@ namespace par { -// GCC > 13 warns at class definition when a new overload shadows an inherited virtual function. -// While theoretically correct, in practice any call will be dispatched through the base interface, -// which in turn is also generated by metaprogramming from a type list. -// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109740 -_Pragma("GCC diagnostic push") \ -_Pragma("GCC diagnostic ignored \"-Woverloaded-virtual\"") - - - - template - struct DomainSetup - { - - template - class TypeHandlerImpl - : public BAS - { - void extractAs (X& targetVal, ValBuff const& valBuff) override; - void conform (ValBuff& targetBuff, X const& srcVal) override; - }; - - using TypeHandlerChain = meta::InstantiateChained; - }; - - - - template - class BaseDomain - : public DomainSetup::TypeHandlerChain - { - public: - void applyLimit (ValBuff&) override; - void transferTo (ValBuff const& source, Domain& targetDomain, ValBuff& target) override; - }; - - - /* ===== type conversion details ===== */ - - /** Constraint: type \a SUB can not represent the full domain of type \a BAS - * @todo implicitly also implements a limitation to »numeric« types, - * due to the use of std::numeric_limits - */ - template - concept sub_domain = std::signed_integral != std::signed_integral - or std::numeric_limits::max() < std::numeric_limits::max() - or std::numeric_limits::lowest() > std::numeric_limits::lowest() - ; - - -_Pragma("GCC diagnostic push") \ -_Pragma("GCC diagnostic ignored \"-Wsign-compare\"") -// the following functions are specifically crafted to work around -// the ambiguities caused by automatic signed-to-unsigned promotion; -// furthermore, the automatic promotion allows to perform the comparison. - - template - inline constexpr bool - isLower_safe (X const& x, Y const& y) - { - return isNeg(x) == isNeg(y)? x < y - : isNeg(x); - } - - template - inline constexpr bool - isLarger_safe (X const& x, Y const& y) - { - return isNeg(x) == isNeg(y)? x > y - : isNeg(y); - } -_Pragma("GCC diagnostic pop") - - /** generic helper to conform into a common value domain - * @tparam SUB the implied target value domain - * @tparam BAS source data type - * @return a value in source data type, - * yet conformed into the target data range - */ - template - inline constexpr BAS - preClamp (BAS const& value) - { - return value; - } - - /** special case: clamp the source value into the target value domain. - * @remark tricky due to automatic conversions between signed/unsigned */ - template requires (sub_domain - and not same_as) - inline constexpr BAS - preClamp (BAS const& rawVal) - { - static_assert (std::is_constructible_v - ,"Value domains must overlap at least partially " - "and values must be cross-constructible within overlap"); - - auto upperBound = numeric_limits::max(); - auto lowerBound = numeric_limits::lowest(); - - return isLarger_safe(rawVal, upperBound)? BAS(upperBound) - : isLower_safe (rawVal, lowerBound)? BAS(lowerBound) - : rawVal; - } - - /** special case: trigger a bool at the 0.5 level */ - template B, floating_point F> - inline constexpr F - preClamp (F const& rawVal) - { - return 0.5 < rawVal? F{1} : F{0}; - } - - - - template - inline void - assignConverted (V& targetVal, X const& srcVal) - { - if constexpr (std::is_assignable_v) - { - targetVal = preClamp (srcVal); - } - else - if constexpr (std::is_constructible_v) - { - targetVal.~U(); - new(&targetVal) V (preClamp (srcVal)); - } - else - static_assert (!sizeof(X), "this type conversion is not supported"); - } - - - template - template - inline void - DomainSetup::TypeHandlerImpl::extractAs (X& targetVal, ValBuff const& valBuff) - { - V const& srcVal = asValue (valBuff); - assignConverted (targetVal, srcVal); - } - - - template - template - inline void - DomainSetup::TypeHandlerImpl::conform (ValBuff& targetBuff, X const& srcVal) - { - V& targetVal = asValue (targetBuff); - assignConverted (targetVal, srcVal); - } - - - template - inline void - BaseDomain::applyLimit (ValBuff& valBuff) - { - V& val{asValue (valBuff)}; - val = preClamp (val); - } - - - template - inline void - BaseDomain::transferTo (ValBuff const& source, Domain& targetDomain, ValBuff& target) - { - targetDomain.conform (target, asValue (source)); - targetDomain.applyLimit (target); - } - - - }} // namespace lib::par #endif /*LIB_PAR_DOMAIN_H*/ diff --git a/src/lib/par/param-type.hpp b/src/lib/par/param-type.hpp index 44c432f74..333dc3ede 100644 --- a/src/lib/par/param-type.hpp +++ b/src/lib/par/param-type.hpp @@ -14,8 +14,17 @@ /** @file param-type.hpp ** Specification of the value domain and scale of a parameter. - ** A ParamType descriptor implicitly also encodes the concrete value type, the - ** allowed value range, clipping behaviour and specifics of the scale (discrete, + ** The implementation of parameters is built up in layers, starting from the generic + ** interfaces \ref Provision, which describes the fundamental capabilities of a + ** parameter as conceptualised here) and \ref Domain to support type conversions. + ** + ** All extensions beyond this point can be considered implementation-level services. + ** The BaseDomain layer provides the actual type conversion services, based on internal + ** knowledge of the concrete data type handled by this parameter. + ** + ** A \ref TypedEntity descriptor adds storage to capture type properties and allow + ** for an ID registration. In addition, the concrete value type is tagged, marking + ** the allowed value range, clipping behaviour and specifics of the scale (discrete, ** stepping, continuous, logarithmic...). ** ** @todo WIP-WIP-WIP can be considered an initial draft and placeholder, as of 2026 @@ -27,22 +36,197 @@ #include "lib/par/domain.hpp" +#include "lib/meta/generator.hpp" namespace lib { namespace par { +// GCC > 13 warns at class definition when a new overload shadows an inherited virtual function. +// While theoretically correct, in practice any call will be dispatched through the base interface, +// which in turn is also generated by metaprogramming from a type list. +// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109740 +_Pragma("GCC diagnostic push") \ +_Pragma("GCC diagnostic ignored \"-Woverloaded-virtual\"") + + + template + struct DomainSetup + { + + template + class TypeHandlerImpl + : public PAR + { + void extractAs (X& targetVal, ValBuff const& valBuff) override; + void conform (ValBuff& targetBuff, X const& srcVal) override; + }; + + using TypeHandlerChain = meta::InstantiateChained; + }; + + + + template + class BaseDomain + : public DomainSetup::TypeHandlerChain + { + public: + void applyLimit (ValBuff&) override; + void transferTo (ValBuff const& source, Domain& targetDomain, ValBuff& target) override; + }; + + + /* ===== type conversion details ===== */ + + /** Constraint: type \a SUB can not represent the full domain of type \a BAS + * @todo implicitly also implements a limitation to »numeric« types, + * due to the use of std::numeric_limits + */ + template + concept sub_domain = std::signed_integral != std::signed_integral + or std::numeric_limits::max() < std::numeric_limits::max() + or std::numeric_limits::lowest() > std::numeric_limits::lowest() + ; + + +_Pragma("GCC diagnostic push") \ +_Pragma("GCC diagnostic ignored \"-Wsign-compare\"") +// the following functions are specifically crafted to work around +// the ambiguities caused by automatic signed-to-unsigned promotion; +// furthermore, the automatic promotion allows to perform the comparison. + + template + inline constexpr bool + isLower_safe (X const& x, Y const& y) + { + return isNeg(x) == isNeg(y)? x < y + : isNeg(x); + } + + template + inline constexpr bool + isLarger_safe (X const& x, Y const& y) + { + return isNeg(x) == isNeg(y)? x > y + : isNeg(y); + } +_Pragma("GCC diagnostic pop") + + + /** generic helper to conform into a common value domain + * @tparam SUB the implied target value domain + * @tparam BAS source data type + * @return a value in source data type, + * yet conformed into the target data range + */ + template + inline constexpr BAS + preClamp (BAS const& value) + { + return value; + } + + /** special case: clamp the source value into the target value domain. + * @remark tricky due to automatic conversions between signed/unsigned */ + template requires (sub_domain + and not same_as) + inline constexpr BAS + preClamp (BAS const& rawVal) + { + static_assert (std::is_constructible_v + ,"Value domains must overlap at least partially " + "and values must be cross-constructible within overlap"); + + auto upperBound = numeric_limits::max(); + auto lowerBound = numeric_limits::lowest(); + + return isLarger_safe(rawVal, upperBound)? BAS(upperBound) + : isLower_safe (rawVal, lowerBound)? BAS(lowerBound) + : rawVal; + } + + /** special case: trigger a bool at the 0.5 level */ + template B, floating_point F> + inline constexpr F + preClamp (F const& rawVal) + { + return 0.5 < rawVal? F{1} : F{0}; + } + + + + template + inline void + assignConverted (V& targetVal, X const& srcVal) + { + if constexpr (std::is_assignable_v) + { + targetVal = preClamp (srcVal); + } + else + if constexpr (std::is_constructible_v) + { + targetVal.~U(); + new(&targetVal) V (preClamp (srcVal)); + } + else + static_assert (!sizeof(X), "this type conversion is not supported"); + } + + + template + template + inline void + DomainSetup::TypeHandlerImpl::extractAs (X& targetVal, ValBuff const& valBuff) + { + VAL const& srcVal = asValue (valBuff); + assignConverted (targetVal, srcVal); + } + + + template + template + inline void + DomainSetup::TypeHandlerImpl::conform (ValBuff& targetBuff, X const& srcVal) + { + VAL& targetVal = asValue (targetBuff); + assignConverted (targetVal, srcVal); + } + + + template + inline void + BaseDomain::applyLimit (ValBuff& valBuff) + { + VAL& val{asValue (valBuff)}; + val = preClamp (val); + } + + + template + inline void + BaseDomain::transferTo (ValBuff const& source, Domain& targetDomain, ValBuff& target) + { + targetDomain.conform (target, asValue (source)); + targetDomain.applyLimit (target); + } + + + + /** - * Interface: represent a specific configuration of parameter value type, + * Service-Interface: represent a specific configuration of parameter value type, * range and scale. Every ParamType descriptor is also a _prototype_ and has * an unique identity, ensured by registration, so that it acts as a type identifier. * @todo RLY? registration?? * Furthermore, the interface exposes allowed conversion and conforming operations. */ - class ParamType - : public Domain + template + class TypedEntity + : public BaseDomain { public: }; diff --git a/tests/lib/par/parameter-domain-test.cpp b/tests/lib/par/parameter-domain-test.cpp index 27c88d784..5d01a8588 100644 --- a/tests/lib/par/parameter-domain-test.cpp +++ b/tests/lib/par/parameter-domain-test.cpp @@ -19,6 +19,7 @@ #include "test/run.hpp" //#include "test/test-helper.hpp" #include "lib/par/domain.hpp" +#include "lib/par/param-type.hpp" #include "test/diagnostic-output.hpp"////////////TODO //#include @@ -168,6 +169,9 @@ namespace test{ + template + using FullDomain = BaseDomain; + /** @test base function to access the contents of an opaque buffer * with known type, and convert into another target type. * - the base interface #Domain represents an opaque type @@ -183,8 +187,8 @@ namespace test{ void verify_valueAccess() { - BaseDomain domInt; - CHECK (sizeof(BaseDomain) <= sizeof(void*)); // only the VTable + FullDomain domInt; + CHECK (sizeof(FullDomain) <= sizeof(void*)); // only the VTable // use the generic interface for access... Domain& dom{domInt}; @@ -221,7 +225,7 @@ namespace test{ void verify_valueSetting() { - BaseDomain domInt; + FullDomain domInt; Domain& dom{domInt}; int val_in_buff = 0; @@ -259,9 +263,9 @@ namespace test{ int64_t i64_val{0}; bool boo{false}; - BaseDomain ddom; - BaseDomain idom; - BaseDomain bdom; + FullDomain ddom; + FullDomain idom; + FullDomain bdom; Domain& d1{ddom}; Domain& d3{bdom}; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index d4daa2fa9..20b8fc209 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -84451,6 +84451,11 @@ + + + + + @@ -84466,9 +84471,10 @@ + - +