BufferProvider: document the new design and use it for the prototype
Explored further aspects of this new design; as an aside, I tried to build a Concept to describe the policy, which howerer turned out to be much more challenging than expected. Lastly, I could now complete the prototype of `BufferProxyAdaptor`
This commit is contained in:
parent
8437710232
commit
ea627c1c7a
5 changed files with 293 additions and 77 deletions
|
|
@ -14,6 +14,58 @@
|
|||
|
||||
/** @file prop-builder.hpp
|
||||
** A builder for compile-time generation of data records with arbitrary named fields.
|
||||
** Generally speaking, a "record" in this context means just a struct or class with some
|
||||
** data fields, and can be easily defined to suit any needs. However, such a class definition
|
||||
** always incurs some _syntactical overhead_ — which is fine for spelling out some type in
|
||||
** general, but can be problematic when the data record is only used once, locally and
|
||||
** is without further significance beyond that single usage. Such a situation often
|
||||
** arises in the context of _policy based design_ and flexible configuration of
|
||||
** some generic facility, especially when part of this configuration involves
|
||||
** the definition of _callback functions._
|
||||
**
|
||||
** A common requirement that lends itself well to policy based design arises when such callbacks
|
||||
** establish a deeply interwoven link into local implementation details; this kind of interconnected
|
||||
** implementation can be expressed succinctly through Lambda functions with contextual capture, and
|
||||
** allows to setup a tight interconnection between implementation back-ends, without exposing any
|
||||
** of these implementation details at the interface / dependency-injection level. However, the task
|
||||
** to package several such specific callbacks into a policy instance and pass this configured policy
|
||||
** for creation of service instances, can be surprisingly complex, verbose, confusing and leads
|
||||
** to code that is hard to maintain. The reasons for this challenge are manifold:
|
||||
** - contextual capture works only well from directly within an implementation function
|
||||
** - such a setup can not be expressed well through types and interfaces, since the
|
||||
** generated closure is _essentially a value_ and its type can not be spelled out.
|
||||
** - a policy with several callbacks thus turns into a template with several type parameters,
|
||||
** and must be initialised through a likewise template based constructor; the resulting code
|
||||
** tends to become very technical, verbose, surprisingly tricky and hard to decipher for
|
||||
** any reader not familiar with all the intricate details of the implementation.
|
||||
**
|
||||
** The root of these difficulties of proper formulation seems to be related to the nature
|
||||
** of cohesive, closely interwoven implementation code. As long as this kind of structure
|
||||
** can be kept close together, it works surprisingly well and expresses intent clearly.
|
||||
** Yet as soon as it must be taken apart, expressed in names, types and interfaces,
|
||||
** a high conceptual burden is added, which leads to the danger of generalisation
|
||||
** and re-use beyond the very specific case, to which the original formulation
|
||||
** of the problem was well adapted and adequate.
|
||||
**
|
||||
** The solution promoted here thus aims to remove the need to define any type and interface
|
||||
** explicitly; a builder-expression is created rather, which allows to bind all callbacks
|
||||
** and further parameters directly inline, within a single constructor invocation.
|
||||
** Such a setup becomes possibly through a combination of some C++20 features, linked
|
||||
** together by lambda expressions generated from a _macro_.
|
||||
** - the PropBuilder acts as base class for the generated records, and is used to
|
||||
** initiate the build-up of the definition expression.
|
||||
** - several »layers« of derived classes are added step by step, where each such
|
||||
** layer adds one further _property_ attribute, that is initialised by a given value.
|
||||
** - the _junctor_ to combine those layer is provided by the template function
|
||||
** `PropBuilder::define(builder-λ, value)`. It uses the new _explicit object_
|
||||
** syntax introduced with C++20, to pick up the "self type" as template argument.
|
||||
** - by invoking this builder function, the current "this"-object is _moved_ into
|
||||
** the builder, where it is used to create and initialise a derived class.
|
||||
** - for each »layer« a specific lambda is generated by a macro — and it is this
|
||||
** technique that allows to accept a lexical token form the program text and
|
||||
** use this token as field name in the next derived class to generate.
|
||||
** @see PropBuilder_test for detailed explanation
|
||||
** @see OutputProxyProvider_test for a usage example
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -35,13 +87,19 @@ namespace meta{
|
|||
|
||||
/**
|
||||
* Anchor record and builder mechanics for generating data records.
|
||||
* - start a builder expression by constructing an anonymous `PropBulder()`
|
||||
* - invoke PropBuilder::define() for each further property to add
|
||||
* - pass a builder-λ as first argument, and the data value as second
|
||||
* - generate a suitable builder-λ with the macro `PROP_FIELD(fieldname)`
|
||||
* - overall, the builder expression generates a RValue, that will usually
|
||||
* be passed directly to the constructor of another class.
|
||||
* @see PropBuilder_test::simpleUsage
|
||||
*/
|
||||
struct PropBuilder
|
||||
{
|
||||
/**
|
||||
* Core builder operation: invoke a builder-λ to extend »this«
|
||||
* @param layerBilder a specially crafted invokable, that takes _this object_
|
||||
* @param layerBuilder a specially crafted invokable, that takes _this object_
|
||||
* and the given property value and creates an instance of a derived class.
|
||||
* @note the macro \ref PROP_FIELD below will generate a suitable argument.
|
||||
* @param val an arbitrary (movable) data element to be stored as property.
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ namespace engine {
|
|||
|
||||
operator HashVal() const { return subClassification_; }
|
||||
|
||||
/** convenience shortcut to start a buffer handling cycle */
|
||||
/** callback to engage buffer handling cycle */
|
||||
uint announce (uint count);
|
||||
BuffHandle lockBuffer();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
//#include "steam/play/diagnostic-output-slot.hpp"
|
||||
#include "steam/engine/buffer-proxy-adaptor.hpp"
|
||||
#include "steam/engine/test-rand-ontology.hpp"
|
||||
#include "lib/meta/prop-builder.hpp"
|
||||
#include "lib/test/diagnostic-output.hpp"
|
||||
|
||||
|
||||
|
|
@ -28,6 +29,7 @@ namespace steam {
|
|||
namespace engine{
|
||||
namespace test {
|
||||
|
||||
using lib::meta::PropBuilder;
|
||||
|
||||
|
||||
|
||||
|
|
@ -42,38 +44,44 @@ namespace test {
|
|||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
struct Callback
|
||||
{
|
||||
void on_lock() { cout << "LOCK" << endl; }
|
||||
void on_emit() { cout << "EMIT" << endl; }
|
||||
void on_release() { cout << "RELEASE" << endl; }
|
||||
};
|
||||
BufferState state{NIL};
|
||||
|
||||
// setup with notification callback
|
||||
BufferProxyAdaptor proxPro{Callback()};
|
||||
BufferProxyAdaptor proxPro{PropBuilder()
|
||||
.define (PROP_FIELD(on_lock), [&]{ state = LOCKED; })
|
||||
.define (PROP_FIELD(on_emit), [&]{ state = EMITTED;})
|
||||
.define (PROP_FIELD(on_release),[&]{ state = FREE; })
|
||||
};
|
||||
|
||||
// Assuming some data block is »given«
|
||||
seedRand();
|
||||
size_t frameNr = defaultGen.u64();
|
||||
TestFrame dataBlock (frameNr);
|
||||
CHECK ( dataBlock.isPristine());
|
||||
CHECK (dataBlock.isPristine());
|
||||
CHECK (state == NIL);
|
||||
|
||||
BuffHandle handle = proxPro.lockBuffer (dataBlock);
|
||||
CHECK (state == LOCKED);
|
||||
|
||||
// Now a »client« can do awful things to the buffer...
|
||||
CHECK (handle.isValid());
|
||||
auto& data = handle.accessAs<TestFrame>();
|
||||
uint64_t param = defaultGen.u64();
|
||||
ont::manipulateFrame (&data, &data, param);
|
||||
HashVal check = data.getChecksum();
|
||||
|
||||
// »client« is done...
|
||||
handle.emit();
|
||||
CHECK (state == EMITTED);
|
||||
|
||||
// end usage cycle
|
||||
handle.release();
|
||||
CHECK (state == FREE);
|
||||
CHECK (not handle.isValid());
|
||||
CHECK (not dataBlock.isPristine());
|
||||
CHECK ( dataBlock.isValid());
|
||||
|
||||
CHECK (check == dataBlock.getChecksum());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -21,38 +21,20 @@
|
|||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "lib/meta/prop-builder.hpp"
|
||||
//#include "lib/meta/tuple-helper.hpp"
|
||||
//#include "meta/typelist-diagnostics.hpp"
|
||||
//#include "meta/tuple-diagnostics.hpp"
|
||||
//#include "lib/format-string.hpp"
|
||||
//#include "lib/format-cout.hpp"
|
||||
//#include "lib/hetero-data.hpp"
|
||||
#include "lib/test/diagnostic-output.hpp"////////////////TODO
|
||||
#include "lib/format-string.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
using lib::test::showType;
|
||||
//using lib::test::showSizeof;
|
||||
//using util::toString;
|
||||
//using util::_Fmt;
|
||||
//using std::is_same_v;
|
||||
//using std::make_tuple;
|
||||
//using std::get;
|
||||
using util::_Fmt;
|
||||
|
||||
namespace lib {
|
||||
namespace meta {
|
||||
namespace test {
|
||||
|
||||
|
||||
|
||||
namespace { // test data
|
||||
|
||||
|
||||
} // (End) test data
|
||||
|
||||
using lib::test::showType;
|
||||
#define TYPE(_TY_) showType<decltype(_TY_)>()
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************************************//**
|
||||
|
|
@ -73,6 +55,9 @@ namespace test {
|
|||
|
||||
|
||||
/** @test show syntax and usage
|
||||
* - create from the PropBuilder
|
||||
* - add named fields with values as desired
|
||||
* - the result is a record holding the data values
|
||||
*/
|
||||
void
|
||||
simpleUsage()
|
||||
|
|
@ -115,7 +100,8 @@ namespace test {
|
|||
/** @test demonstrate and verify the language features
|
||||
* used to generate arbitrary record data types.
|
||||
* - capture self-type with C++20 _explicit object member function_
|
||||
* - use generic-λ to generate a derived class with a property field
|
||||
* - use generic-λ to generate a derived class with a property field
|
||||
* - chain-up further layers with named fields by extending self-type
|
||||
*/
|
||||
void
|
||||
explain_building_blocks()
|
||||
|
|
@ -139,12 +125,12 @@ namespace test {
|
|||
// local type can be _referred to_ only locally, within this function,
|
||||
// it is _not a hidden type_. Data elements using such a local type
|
||||
// can be returned by-value — which allows us to "drop off" such
|
||||
// a data record, and this also implicitly its type.
|
||||
// a data record, and thus also implicitly export its type.
|
||||
|
||||
// While this seems rather pointless in itself, it can be leveraged
|
||||
// with the help of C++20 explicit lambda template parameters: we can
|
||||
// move an instance of a base class into a function, thereby pick up
|
||||
// its type, and define a new derived class, and even move the given
|
||||
// its type, then define a new derived class, and even move the given
|
||||
// base class instance into the embedded base class sub-object:
|
||||
|
||||
auto dropperLambda = []<class BAS, typename VAL>(BAS&& bas, VAL&& val)
|
||||
|
|
@ -176,53 +162,106 @@ namespace test {
|
|||
|
||||
ushort evil = 55;
|
||||
auto compoundRecord = dropperLambda (SomeRecord{0.13}, evil);
|
||||
|
||||
// here SomeRecord was created transiently, moved into the dropper-λ,
|
||||
// used there as base for a derived struct DataLayer_something, which
|
||||
// features an additional property `something`, initialised with an
|
||||
// arbitrary value (and type) also passed on invocation.
|
||||
// arbitrary value (and type), also passed directly on invocation.
|
||||
// The result is a record object, which incorporates the base, together
|
||||
// with an additional "Layer" holding the new property, stored efficiently.
|
||||
|
||||
CHECK (compoundRecord.something == evil);
|
||||
CHECK (compoundRecord.someData == 0.13f);
|
||||
|
||||
using Compound = decltype(compoundRecord);
|
||||
SHOW_TYPE(decltype(compoundRecord))
|
||||
SHOW_EXPR(TYPE(compoundRecord))
|
||||
SHOW_EXPR(sizeof(SomeRecord))
|
||||
CHECK (sizeof(SomeRecord) == sizeof(float));
|
||||
SHOW_EXPR(sizeof(Compound))
|
||||
CHECK (sizeof(Compound) >= sizeof(float)+sizeof(ushort));
|
||||
SHOW_EXPR(alignof(SomeRecord))
|
||||
SHOW_EXPR(alignof(Compound))
|
||||
CHECK (alignof(Compound) == alignof(SomeRecord));
|
||||
CHECK (sizeof(Compound) == 2 * alignof(float));
|
||||
|
||||
SHOW_EXPR(std::is_class_v<Compound>)
|
||||
SHOW_EXPR(std::is_trivial_v<Compound>)
|
||||
SHOW_EXPR(std::is_trivial_v<SomeRecord>)
|
||||
SHOW_EXPR(std::is_trivially_copyable_v<SomeRecord>)
|
||||
SHOW_EXPR(std::is_trivially_copyable_v<Compound>)
|
||||
SHOW_EXPR(std::is_standard_layout_v<Compound>)
|
||||
CHECK (std::is_class_v<Compound>);
|
||||
CHECK (std::is_trivial_v<Compound>);
|
||||
CHECK (std::is_trivial_v<SomeRecord>);
|
||||
CHECK (std::is_trivially_copyable_v<Compound>);
|
||||
CHECK (std::is_trivially_copyable_v<SomeRecord>);
|
||||
|
||||
// Yet obviously it is not a POD,
|
||||
// Yet obviously the generated record is not a POD,
|
||||
// since non-static members reside at several levels
|
||||
CHECK (not std::is_standard_layout_v<Compound>);
|
||||
|
||||
SHOW_EXPR((is_Subclass_v<Compound, SomeRecord>))
|
||||
CHECK ((is_Subclass_v<Compound, SomeRecord>));
|
||||
|
||||
|
||||
// Lastly, a chain of such »property layers« can be built gradually,
|
||||
// with the help of a hook-method, that grabs the _current record_
|
||||
// and passes it to the next extension-layer-λ. As first example,
|
||||
// the dropper-λ defined above can be used here too...
|
||||
auto record1 = PropBuilder()
|
||||
.define (dropperLambda, 0.23)
|
||||
;
|
||||
using Rec1 = decltype(record1);
|
||||
CHECK ((is_Subclass_v<Rec1, PropBuilder>));
|
||||
CHECK (sizeof(Rec1) == sizeof(double));
|
||||
CHECK (TYPE(record1.something) == "double"_expect);
|
||||
CHECK (record1.something == 0.23);
|
||||
|
||||
// Note that the name of the property field, here `something`,
|
||||
// needs to be hard wired into the builder-λ, due to the nature of C++.
|
||||
// Yet this hurdle can be overcome by generating the builder-λ from a *macro*
|
||||
auto record2 = record1
|
||||
.define (PROP_FIELD(anything)
|
||||
,[&](auto val){ return val + evil; } // ◁———————————— can pass a Lambda as "value"
|
||||
);
|
||||
using Rec2 = decltype(record2);
|
||||
CHECK ((is_Subclass_v<Rec2, Rec1>));
|
||||
CHECK ((is_Subclass_v<Rec2, PropBuilder>));
|
||||
CHECK (record2.something == 0.23);
|
||||
CHECK (record2.anything(11) == 66);
|
||||
evil = 13;
|
||||
CHECK (record2.anything(42) == 55);
|
||||
// note the anything-λ is _generic_
|
||||
CHECK (record2.anything(7.77f) == 20.77f);
|
||||
|
||||
// Warning: record1 has been moved-away into record2,
|
||||
// so its content is now »undefined«
|
||||
}
|
||||
|
||||
|
||||
/** @test show how to use generated records to implement a policy.
|
||||
/** Example for demonstration of possible use-case */
|
||||
template<class POL>
|
||||
class Producer
|
||||
: POL
|
||||
{
|
||||
public:
|
||||
Producer (POL policy)
|
||||
: POL{move(policy)}
|
||||
{ }
|
||||
|
||||
decltype(auto)
|
||||
doIt()
|
||||
{
|
||||
return POL::wrap (POL::feed());
|
||||
}
|
||||
};
|
||||
|
||||
/** @test show a didactical example how generated records
|
||||
* can be used to support policy-based design.
|
||||
* - the Producer template defined above can be configured
|
||||
* with appropriate actions and operations that fit together
|
||||
* - the test features a special context-bound producer.
|
||||
*/
|
||||
void
|
||||
demonstrate_usage_scenario()
|
||||
{
|
||||
uint current{21};
|
||||
_Fmt putIt{"%s tralala"};
|
||||
|
||||
auto doer = Producer{PropBuilder()
|
||||
.define (PROP_FIELD(feed), [&]{ return current++; })
|
||||
.define (PROP_FIELD(wrap), [&](auto it)->string { return putIt % it; })
|
||||
};
|
||||
|
||||
CHECK (doer.doIt() == "21 tralala"_expect);
|
||||
CHECK (22 == current);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -58600,9 +58600,9 @@
|
|||
</node>
|
||||
</node>
|
||||
<node CREATED="1772066411633" ID="ID_50275437" MODIFIED="1772066416949" TEXT="Code-Generierung">
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1772066190351" ID="ID_940571255" MODIFIED="1772066239070" TEXT="PropBuilder : Record mit benannten Feldern generieren">
|
||||
<node BACKGROUND_COLOR="#c5ebda" COLOR="#2f6877" CREATED="1772066190351" FOLDED="true" ID="ID_940571255" MODIFIED="1772157213950" TEXT="PropBuilder : Record mit benannten Feldern generieren">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1772066253767" ID="ID_1072763198" MODIFIED="1772067242722" TEXT="Neue Metaprgramming-Technik ⟸ für Policy-based Design">
|
||||
<node COLOR="#12109f" CREATED="1772066253767" ID="ID_1072763198" MODIFIED="1772157175603" TEXT="Neue Metaprgramming-Technik ⟸ für Policy-based Design">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -58620,7 +58620,8 @@
|
|||
<linktarget COLOR="#2b57f9" DESTINATION="ID_1072763198" ENDARROW="Default" ENDINCLINATION="2965;140;" ID="Arrow_ID_198810341" SOURCE="ID_1029922863" STARTARROW="None" STARTINCLINATION="-2090;136;"/>
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1772067250896" ID="ID_1640694078" MODIFIED="1772067306544" TEXT="Aufgabe: einen »maßgeschneiderten« Daten-Record...">
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#434698" CREATED="1772067250896" ID="ID_1640694078" MODIFIED="1772074391901" TEXT="Aufgabe: einen »maßgeschneiderten« Daten-Record...">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1772067307899" ID="ID_919196456" MODIFIED="1772067410868" TEXT="kompakt und lesbar »inline« definieren">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
|
|
@ -58633,7 +58634,8 @@
|
|||
</node>
|
||||
<node CREATED="1772067418044" ID="ID_1314882599" MODIFIED="1772067438651" TEXT="und gleich mit inline-λ und Kontext-capture initialisieren"/>
|
||||
</node>
|
||||
<node CREATED="1772068221512" ID="ID_774607578" MODIFIED="1772070444439" TEXT="Bau-Technik">
|
||||
<node COLOR="#435e98" CREATED="1772068221512" ID="ID_774607578" MODIFIED="1772074416160" TEXT="Bau-Technik">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="forward"/>
|
||||
<node COLOR="#435e98" CREATED="1772068227431" ID="ID_361097452" MODIFIED="1772070455630" TEXT="ein Builder-Ausdruck"/>
|
||||
<node COLOR="#435e98" CREATED="1772068233846" ID="ID_1873632379" MODIFIED="1772070455630" TEXT="ein Lambda, das einen abgeleiteten Typ definiert">
|
||||
|
|
@ -58644,20 +58646,48 @@
|
|||
<node COLOR="#435e98" CREATED="1772068303510" ID="ID_142658280" MODIFIED="1772070460038" TEXT="Definition und Aufruf dieses Lambdas kann man in einen einzigen Ausdruck packen">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1772068327705" ID="ID_782344387" MODIFIED="1772070455629" TEXT="und diesen Ausdruck kann man dann mit einem Macro generieren">
|
||||
<node COLOR="#435e98" CREATED="1772068327705" ID="ID_782344387" MODIFIED="1772074438775" TEXT="und diesen Ausdruck wiederum kann man dann mit einem Macro generieren">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1772068339947" ID="ID_721460446" MODIFIED="1772068350577" TEXT="damit werden neue Feldnamen möglich"/>
|
||||
<node CREATED="1772068351334" ID="ID_302440640" MODIFIED="1772068360385" TEXT="und man kann auch den generierten Typ dekorieren"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1772068366233" ID="ID_858655013" MODIFIED="1772068376142" TEXT="Implementierung">
|
||||
<node COLOR="#338800" CREATED="1772068366233" ID="ID_858655013" MODIFIED="1772156709954" TEXT="Implementierung">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1772068377138" ID="ID_160543739" MODIFIED="1772068386687" TEXT="lib/meta/prop-builder.hpp"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1772068387673" ID="ID_999468145" MODIFIED="1772068449713" TEXT="PropBuilder_test">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1772068394858" ID="ID_1256049272" MODIFIED="1772068407518" TEXT="Aufruf-Syntax zeigen"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1772068408103" ID="ID_452419709" MODIFIED="1772068442634" TEXT="die verwendeten Programmiertechniken dokumentieren">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1772068387673" ID="ID_999468145" MODIFIED="1772156707171" TEXT="PropBuilder_test">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1772068394858" ID="ID_1256049272" MODIFIED="1772156702859" TEXT="Aufruf-Syntax zeigen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1772068408103" ID="ID_452419709" MODIFIED="1772156704705" TEXT="die verwendeten Programmiertechniken dokumentieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1772068421596" ID="ID_1602327531" MODIFIED="1772156705875" TEXT="Beispiel für ein Policy-based Design darststellen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#5b280f" CREATED="1772156780733" ID="ID_960855659" LINK="https://quuxplusone.github.io/blog/2020/08/10/concepts-cant-do-quantifiers/" MODIFIED="1772157138692" TEXT="auch gleich ein Concept zeigen?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Nehme davon Abstand.
|
||||
</p>
|
||||
<p>
|
||||
Da ich als Beispiel eine Struktur wie in einer Factory zeigen möchte, erweist es sich als ausgesprochen schwierig, die erwartete Struktur sauber als Concept zu repräsentieren. Das liegt darin, daß eine solche generische Factory oft implizit auf eine ∀-Quantisierung hinausläuft; d.h. man möchte etwas bauen, das <i>»für beliebige Typen funktioniert«. </i>Wenngleich auch klar ist, daß man niemals völlgig allgemeingültigen, generischen Code schreiben kann, baut man die Struktur doch dieser Idee entsprechend auf. So etwas läßt sich jedoch nicht als einfacher, formal prüfbarerer Constraint formulieren, denn das würde eine formalisierte Spezifikations-Sprache und einen Theorem-Beweis erfordern.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Die Concepts in C++ können jedoch nur <i>für einen konkret gegebenen, einzelnen Typ</i> jeweils prüfen, ob sich ein valider Ausdruck ergibt; »valide« würde sich in diesem Fall auf reine Syntax beschränken, und das rechtfertigt nicht den syntaktischen Overhead für ein Concept
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<font NAME="SansSerif" SIZE="11"/>
|
||||
<icon BUILTIN="help"/>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1772068421596" ID="ID_1602327531" MODIFIED="1772068435958" TEXT="Beispiel für ein Policy-based Design darststellen"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -114207,6 +114237,36 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1772129298282" ID="ID_1032607524" MODIFIED="1772129491113" TEXT="Implementierungs-API konsistenter gestalten">
|
||||
<linktarget COLOR="#71434f" DESTINATION="ID_1032607524" ENDARROW="Default" ENDINCLINATION="-1142;72;" ID="Arrow_ID_1327695220" SOURCE="ID_1927667326" STARTARROW="None" STARTINCLINATION="-295;-14;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1772129494743" ID="ID_797224940" MODIFIED="1772129626006" TEXT="aufgefallen beim OutputSlot / BufferProxyAdaptor">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...denn dort kommt es zu der Anforderung, bei den State-Transitions jeweils einen Callback aufzurufen; das wirft die Frage nach den Namen und den jeweils übergebenen Daten auf; die Daten wären <i>im Grunde genommen jeweils gleich.</i>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1772129627997" ID="ID_1533127720" MODIFIED="1772129874152" TEXT="weitere Analyse zeigt: die konkrtete Storage-Size weicht ab (kann größer sein)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Das ist eine Konsequenz aus der Einsicht, daß der metadata::Entry nicht nur der internen Verwaltung dient, sondern die dort aufgezeichneten Informationen auch essentiell sind für die Implementierung eines Storage-Backends. Das ist ein weithin bekanntes Pattern (und Problem) für Allokatoren: man muß die Storage-Size kennen, speziell auch zur <i>De-</i>Allokation. Wenn man diese Einsicht verbindet mit Überlegungen zum globalen Speicherblock-Management in der Engine, dann wird schnell klar, daß man bisweilen durchaus einen zu-großen-Speicherblock verwenden möchte; das bedeutet dann, daß die Size-Eintrag für den state-Key entsprechend präzise ausgefüllt sein muß.
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1772129891226" ID="ID_1405915409" MODIFIED="1772129902229" TEXT="Überlegungen zum BuffeStore-API">
|
||||
<node CREATED="1772129905244" ID="ID_545569208" MODIFIED="1772129929698" TEXT="eigentlich tritt ein charakteristisches Tupel bei jeder Transition auf"/>
|
||||
<node CREATED="1772129931304" ID="ID_1142410309" MODIFIED="1772129958147" TEXT="⟹ man könnte den »Slot«-Datentyp erweitern...">
|
||||
<node CREATED="1772129959849" ID="ID_1378157373" MODIFIED="1772130000767" TEXT="(storage, size, localTag)"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1771538366852" ID="ID_1595544111" MODIFIED="1771538575391" TEXT="saubere Fehlermeldung wenn keine Allokation möglich ist">
|
||||
<linktarget COLOR="#744d8b" DESTINATION="ID_1595544111" ENDARROW="Default" ENDINCLINATION="628;31;" ID="Arrow_ID_378933605" SOURCE="ID_27406270" STARTARROW="None" STARTINCLINATION="221;-288;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
|
|
@ -114348,8 +114408,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1771539807853" ID="ID_1455262817" MODIFIED="1771539852207" TEXT="Prototyping : OutputProxyProvider_test als Experimentierfeld">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1771616038792" ID="ID_1389235656" MODIFIED="1771809186526" TEXT="Forschung: Policy konfigurieren">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1771616038792" FOLDED="true" ID="ID_1389235656" MODIFIED="1772157520866" TEXT="Forschung: Policy konfigurieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1771616054739" ID="ID_297187964" MODIFIED="1771616315207" TEXT="hab die dunkle Erinnerung daß in so was Ähnliches schon zig mal vergeblich versucht habe">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
|
|
@ -114549,17 +114609,17 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1771893568172" ID="ID_465309080" MODIFIED="1771893720003" TEXT="Zweiter Teil der Aufgabe: named-Lambda-Tupel ">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1771893568172" ID="ID_465309080" MODIFIED="1772157313295" TEXT="Zweiter Teil der Aufgabe: named-Lambda-Tupel ">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1771893733865" ID="ID_60984394" MODIFIED="1771893764443" TEXT="ich möchte ALLES">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1771893742904" ID="ID_921712765" MODIFIED="1771893750874" TEXT="einen meta-konfigurierbaren Builder"/>
|
||||
<node CREATED="1771893769036" ID="ID_434009909" MODIFIED="1771893878715" TEXT="einzelne Layer mit einem λ-Attribut von generischem Typ ⟹ MACRO"/>
|
||||
<node CREATED="1771893845362" ID="ID_112946042" MODIFIED="1771893872082" TEXT="UND das λ soll aber noch lokal gegeben werden können ⟹ Kontext-Binding"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1771893896510" ID="ID_771196335" MODIFIED="1771895013673" TEXT="Ideen sammeln">
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1771893896510" ID="ID_771196335" MODIFIED="1772157452614" TEXT="Ideen sammeln">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1771893905186" ID="ID_1241420221" MODIFIED="1771893946302" TEXT="nicht klar ob es geht .... die Teile passen noch nicht recht zusammen (in meinem Kopf)">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1771893905186" ID="ID_1241420221" MODIFIED="1772157446312" TEXT="nicht klar ob es geht .... die Teile passen noch nicht recht zusammen (in meinem Kopf)">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1771893948001" ID="ID_898834553" MODIFIED="1771894995111" TEXT="einen Builder, der per Macro generierte nested-Classes zusammenhängt">
|
||||
|
|
@ -114572,11 +114632,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<icon BUILTIN="full-3"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1772064586741" ID="ID_1333957843" MODIFIED="1772064712945" TEXT="das Problem ist vor allem syntaktischer Natur">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1772064586741" ID="ID_1333957843" MODIFIED="1772157307555" TEXT="das Problem ist vor allem syntaktischer Natur">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1772064634844" ID="ID_1613330952" MODIFIED="1772064634844" TEXT="Typen müssen deklariert werden"/>
|
||||
<node CREATED="1772064649488" ID="ID_806205089" MODIFIED="1772064649488" TEXT="Instanzen müssen definiert werden"/>
|
||||
<node CREATED="1772064692061" ID="ID_1021370131" MODIFIED="1772064692061" TEXT="Ich will aber nur EIN Macro pro »Layer«">
|
||||
<node BACKGROUND_COLOR="#cbcff9" COLOR="#1d0194" CREATED="1772064692061" ID="ID_1021370131" MODIFIED="1772157493399" TEXT="Ich will aber nur EIN Macro pro »Layer«">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1772064787000" ID="ID_1407594054" MODIFIED="1772064921190" TEXT="eigentlich kann man in C++ keine Typen „inline“ (in einem Ausdruck) deklarieren">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -114627,15 +114687,25 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<icon BUILTIN="smiley-neutral"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1772065498436" ID="ID_1029922863" MODIFIED="1772066452619" TEXT="Neues generisches Feature: PropBuilder">
|
||||
<node COLOR="#338800" CREATED="1772065498436" ID="ID_1029922863" MODIFIED="1772157233364" TEXT="Neues generisches Feature: PropBuilder">
|
||||
<arrowlink COLOR="#2b57f9" DESTINATION="ID_1072763198" ENDARROW="Default" ENDINCLINATION="2965;140;" ID="Arrow_ID_198810341" STARTARROW="None" STARTINCLINATION="-2090;136;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1772066464826" ID="ID_534123438" MODIFIED="1772066473089" TEXT="dokumentiert in PropBuilder_test">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node COLOR="#338800" CREATED="1772066464826" ID="ID_534123438" MODIFIED="1772157242501" TEXT="dokumentiert in PropBuilder_test">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1772066474417" ID="ID_1404760011" MODIFIED="1772066498094" TEXT="dort auch direkt diesen use-Case demonstrieren">
|
||||
<node COLOR="#435e98" CREATED="1772066474417" ID="ID_1404760011" MODIFIED="1772157245259" TEXT="dort auch direkt diesen use-Case demonstrieren">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node COLOR="#3a109f" CREATED="1772157247895" ID="ID_1241263989" MODIFIED="1772157288387" TEXT="zeige ein einfaches policy-pased-Design">
|
||||
<font NAME="SansSerif" SIZE="8"/>
|
||||
</node>
|
||||
<node COLOR="#3a109f" CREATED="1772157258547" ID="ID_577340727" MODIFIED="1772157288388" TEXT="eine Factory, die ihr Produkt auch gleich noch »verpackt«">
|
||||
<font NAME="SansSerif" SIZE="8"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1772157327329" ID="ID_54487483" MODIFIED="1772157434174" TEXT="erfolgreich in den Prototyp für den OutputProxyProvider integriert">
|
||||
<arrowlink COLOR="#1d8abd" DESTINATION="ID_946959732" ENDARROW="Default" ENDINCLINATION="85;-99;" ID="Arrow_ID_1405310375" STARTARROW="None" STARTINCLINATION="189;8;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -114909,6 +114979,43 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
<node CREATED="1771719247697" ID="ID_1277905446" MODIFIED="1771719262138" TEXT="biete also für diese Skizze erst mal nur ein Spezial-API"/>
|
||||
<node CREATED="1772128789402" ID="ID_858761125" MODIFIED="1772128800353" TEXT="Interface: Callback-Funktionen">
|
||||
<node CREATED="1772128802215" ID="ID_258480503" MODIFIED="1772128808917" TEXT="werden per Policy konfiguriert"/>
|
||||
<node CREATED="1772128810953" ID="ID_1904023092" MODIFIED="1772128829194" TEXT="für jede State-Transition eine andere Funktion">
|
||||
<node CREATED="1772128834199" ID="ID_1497809945" MODIFIED="1772128839049" TEXT="on_lock"/>
|
||||
<node CREATED="1772128840151" ID="ID_430684409" MODIFIED="1772128843792" TEXT="on_emit"/>
|
||||
<node CREATED="1772128844960" ID="ID_502402565" MODIFIED="1772129182182" TEXT="on_release">
|
||||
<arrowlink COLOR="#86858e" DESTINATION="ID_373327393" ENDARROW="Default" ENDINCLINATION="-28;-43;" ID="Arrow_ID_1002798807" STARTARROW="None" STARTINCLINATION="47;11;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1772129024726" ID="ID_1695408974" MODIFIED="1772129042551" TEXT="weitergegebene Detail-Info">
|
||||
<node CREATED="1772129044383" ID="ID_1927667326" MODIFIED="1772129473327" TEXT="das interne Interface ist noch inkonsistent">
|
||||
<arrowlink COLOR="#71434f" DESTINATION="ID_1032607524" ENDARROW="Default" ENDINCLINATION="-1142;72;" ID="Arrow_ID_1327695220" STARTARROW="None" STARTINCLINATION="-295;-14;"/>
|
||||
<node CREATED="1772129080302" ID="ID_373327393" MODIFIED="1772129287183" TEXT="Namensgebung">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
leichte Uneinheitlichkeit bzgl. der jeweils erreichten States, und auch die implizite Perspektive betreffend (wer sagt wem was); »release« könnte auch »free« heißen
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<linktarget COLOR="#86858e" DESTINATION="ID_373327393" ENDARROW="Default" ENDINCLINATION="-28;-43;" ID="Arrow_ID_1002798807" SOURCE="ID_502402565" STARTARROW="None" STARTINCLINATION="47;11;"/>
|
||||
</node>
|
||||
<node CREATED="1772129084894" ID="ID_598702937" MODIFIED="1772129147835" TEXT="jeweils bereitgestellt Daten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<i>effektiv</i> sind es jeweils die gleichen Infos für jeden Transition, aber sie sind nicht eindeutig angeordnet
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1772129100438" ID="ID_255962416" MODIFIED="1772129106895" TEXT="Umgang mit der Storage-Size"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1771719274535" ID="ID_1815060462" MODIFIED="1771719385960" TEXT="Implementierung zusammenschalten...">
|
||||
<node CREATED="1771719283904" ID="ID_270233023" MODIFIED="1771719295702" TEXT="es gibt schon einen bestehenden Test, der sogar was verifiziert"/>
|
||||
|
|
@ -114974,6 +115081,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<arrowlink COLOR="#4198b7" DESTINATION="ID_251025614" ENDARROW="Default" ENDINCLINATION="280;452;" ID="Arrow_ID_1811648927" STARTARROW="None" STARTINCLINATION="230;-772;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1772157371762" ID="ID_946959732" MODIFIED="1772157434175" TEXT="...und mit λ-gebundener Policy!">
|
||||
<linktarget COLOR="#1d8abd" DESTINATION="ID_946959732" ENDARROW="Default" ENDINCLINATION="85;-99;" ID="Arrow_ID_1405310375" SOURCE="ID_54487483" STARTARROW="None" STARTINCLINATION="189;8;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue