Invocation: complete helper for chained inline tuples

- complete documentation
- add extensive test coverage for use of the accessors
- demonstrate a more contrieved example, including the dangers
This commit is contained in:
Fischlurch 2024-12-12 23:27:10 +01:00
parent e6403cbc7e
commit fea2bfde7a
5 changed files with 252 additions and 67 deletions

View file

@ -45,13 +45,13 @@
** auto h1 = Front::build (1,2.3);
** using Cons1 = Front::Chain<bool,string>;
** auto b2 = Cons1::build (true, "Ψ");
** b2.linkInto(c1);
** b2.linkInto(h1);
** auto& [d1,d2,d3,d4] = Cons1::recast(h1);
** CHECK (d1 == 1);
** CHECK (d2 == 2.3);
** CHECK (d3 == true);
** CHECK (d4 == "Ψ");
** Cons1::Accessor<string> get4;
** Cons1::AccessorFor<string> get4;
** CHECK (get4(h1) == "Ψ");
** \endcode
**
@ -69,17 +69,12 @@
#include "lib/error.hpp"
//#include "lib/symbol.hpp"
#include "lib/nocopy.hpp"
//#include "lib/linked-elements.hpp"
#include "lib/meta/typelist.hpp"
#include "lib/meta/typelist-manip.hpp"
//#include "lib/meta/typelist-util.hpp"
#include "lib/meta/typelist-util.hpp"
#include "lib/meta/typeseq-util.hpp"
#include "lib/test/test-helper.hpp"
//#include <algorithm>
//#include <vector>
#include <utility>
#include <tuple>
@ -115,6 +110,9 @@ namespace lib {
template<typename SPEC>
void linkInto (HeteroData<SPEC>&);
template<size_t slot> auto& get() noexcept { return std::get<slot>(*this); }
template<typename X> auto& get() noexcept { return std::get<X>(*this); }
};
@ -149,11 +147,26 @@ namespace lib {
return * reinterpret_cast<_Tail*> (Frame::next);
}
template<typename...SPEC>
static _Self&
recast (HeteroData<SPEC...>& frontChain)
{
return reinterpret_cast<_Self&> (frontChain);
}
template<typename...SPEC>
static _Self const&
recast (HeteroData<SPEC...> const& frontChain)
{
return reinterpret_cast<_Self const&> (frontChain);
}
template<typename...XX>
friend class HeteroData; ///< allow chained types to use recursive type definitions
using Frame::Frame; ///< data elements shall be populated through the builder front-ends
public:
HeteroData() = default;
@ -163,9 +176,11 @@ namespace lib {
return localSiz + _Tail::size();
}
/** access type to reside in the given slot of the _complete chain_ */
template<size_t slot>
using Elm_t = typename PickType<slot>::type;
/** access data elements within _complete chain_ by index pos */
template<size_t slot>
Elm_t<slot>&
@ -185,48 +200,68 @@ namespace lib {
return const_cast<HeteroData*>(this)->get<slot>();
}
/**
* Accessor-functor to get at the data residing within some tuple element
* Using the enclosing typed scope to ensure safe storage access
* @tparam slot numer of the data element, counting from zero over the full chain
* @note this functor holds no data, but shall be applied to some existing HeteroData.
*/
template<size_t slot>
struct Accessor
{
using Type = Elm_t<slot>;
template<class SPEC>
Type&
static Type&
get (HeteroData<SPEC>& frontEnd)
{
auto& fullChain = reinterpret_cast<_Self&> (frontEnd);
auto& fullChain = _Self::recast (frontEnd);
return fullChain.template get<slot>();
}
template<typename HH>
Type& operator() (HH& frontEnd) const { return Accessor::get(frontEnd); }
};
/**
* Constructor-functor to build an extra data segment, which can then be linked to the chain.
* @tparam VALS data types to use in the extra storage tuple
* @note Using this functor is the only safe path to create and add new data blocks.
* Each such data block can be linked in once, and only if the base chain matches
* the structure embedded into the type of the enclosing scope.
* - storage frames can be default constructed, but not copied / moved thereafter
* - the #build() function can be used to create the block and init the data
* - after creating a frame, it must be explicitly linked in by invoking NewFrame::linkInto()
* - the #recast() function will re-interpret _any_ `HeteroData&` into the storage structure
* which can be expected after building the extension frame (use with care!)
* - the nested template ChainExtent is a follow-up constructor-functor to add a further block
* - the nested template Accessor shall be used for any type-save access to data values
* - if all types are distinct, the Accessor can also be selected by-type
*/
template<typename...VALS>
struct Chain
{
using NewFrame = StorageFrame<seg+1, VALS...>;
using ChainType = HeteroData<typename meta::Append<meta::Node<Frame,TAIL>,NewFrame>::List>;
using Segments = meta::Node<Frame,TAIL>; // ◁———this type describes current chain structure
using NewFrame = StorageFrame<meta::count<Segments>::value, VALS...>;
using ChainType = HeteroData<typename meta::Append<Segments,NewFrame>::List>;
// ...and this would be the extended chain structure
template<typename...INIT>
static NewFrame
build (INIT&& ...initArgs)
{
return {initArgs ...};
return {initArgs ...}; // Note: NewFrame is non-copyable
}
template<typename...SPEC>
static ChainType&
recast (HeteroData<SPEC...>& frontChain)
template<class HET>
static auto&
recast (HET& frontChain)
{
return reinterpret_cast<ChainType&> (frontChain);
}
template<typename...SPEC>
static ChainType&
recast (HeteroData<SPEC...> const& frontChain)
{
return reinterpret_cast<ChainType const&> (frontChain);
return ChainType::recast (frontChain);
}
template<typename...XVALS>
using ChainExtension = typename ChainType::template Chain<XVALS...>;
using ChainExtent = typename ChainType::template Chain<XVALS...>;
template<size_t slot>
using Accessor = typename ChainType::template Accessor<_Self::size()+slot>;
@ -306,7 +341,7 @@ namespace lib {
, segments);
return last->next;
}
}
}//(End)helper
/**

View file

@ -41,6 +41,7 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
#include "lib/nocopy.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/hetero-data.hpp"
namespace steam {

View file

@ -434,7 +434,7 @@ return: 0
END
PLANNED "Heterogeneous data in local storage" HeteroData_test <<END
TEST "Heterogeneous data in local storage" HeteroData_test <<END
return: 0
END

View file

@ -19,7 +19,8 @@
#include "lib/test/run.hpp"
#include "lib/hetero-data.hpp"
#include "lib/meta/trait.hpp"
#include "lib/test/diagnostic-output.hpp"/////////////////TODO
#include "lib/test/test-helper.hpp"
#include "lib/uninitialised-storage.hpp"
#include "lib/util.hpp"
#include <string>
@ -31,15 +32,20 @@ namespace test{
using std::string;
using meta::is_Subclass;
using util::isSameObject;
using util::isSameAdr;
using util::getAdr;
/*************************************************************//**
/******************************************************************//**
* @test maintain a sequence of data tuples in local storage,
* providing pre-configured type-safe data access.
*
* - the initial block is just a tuple of data in local storage
* - but further extension segments can be created _elsewhere_
* and attached to an existing chain
* - a compile-time »overlay« of constructor- and accessor-functors
* is provided as _guard rails_ to prevent out-of bounds access.
* @see lib::HeteroData
* @see NodeBase_test::verify_TurnoutSystem()
*/
@ -49,9 +55,23 @@ namespace test{
virtual void
run (Arg)
{
simpleUsage();
verify_FrontBlock();
verify_ChainBlock();
// verify_Accessors();
verify_Accessors();
}
void
simpleUsage()
{
using F = lib::HeteroData<uint,double>; // define type of the front-end segment
auto h1 = F::build (1,2.3); // build the front-end, including first data tuple
using C = F::Chain<bool,string>; // define a constructor type for a follow-up segment
auto b2 = C::build (true, "Ψ"); // build this follow-up segment free-standing
b2.linkInto(h1); // link it as second segment into the chain
C::AccessorFor<string> get4; // get an accessor functor (picked by value type)
CHECK (get4(h1) == "Ψ"); // use accessor on front-type (involves force-cast)
}
@ -152,6 +172,140 @@ namespace test{
// auto& [z0,z1,z2,z3] = chain2; // Error: 4 names provided for structured binding, while HeteroData... decomposes into 3 elements
// auto& [z0,z1,z2] = b1; // Error: HeteroData<Node<StorageFrame<0, uint>, NullType> >' decomposes into 1 element
}
/** @test demonstrate elaborate storage layout with several chain frames
* - follow-up frames shall be built using constructor types
* - these can be defined prior to any data allocation
* - individual data elements can be accessed type-safe through accessor functors
* @warning as demonstrated, this is a dangerous bare-bone memory layout without runtime checks!
*/
void
verify_Accessors()
{
using Front = lib::HeteroData<uint,double>;
using Cons2 = Front::Chain<bool,string>;
using Data2 = Cons2::NewFrame;
using List2 = Cons2::ChainType;
using Acc4 = Cons2::AccessorFor<string>;
using Acc3 = Cons2::AccessorFor<bool>;
using Acc2 = Front::Accessor<1>;
using Acc1 = Front::Accessor<0>;
using Cons3 = Cons2::ChainExtent<CStr,string>;
using Data3 = Cons3::NewFrame;
using List3 = Cons3::ChainType;
using Acc5 = Cons3::AccessorFor<CStr>;
using Acc6 = Cons3::AccessorFor<string>;
CHECK (2 == Front::size());
CHECK (4 == List2::size());
CHECK (6 == List3::size());
//
// Note: up to now, not a single actual data element has been created
// Moreover, individual blocks can be created in any order...
Data2 d2;
d2.get<1>() = "Ψ";
Front front;
CHECK (front.get<1>() == 0.0);
front.get<1>() = 2.3;
// Note the pitfall: Chain has not been connected yet,
// but the Accessors would assume otherwise
CHECK (Acc2::get(front) == 2.3);
// Acc3::get(front); // would cause NPE (or assertion failure on debug build)
Acc4 get4; // could even instantiate the accessors...
CHECK (sizeof(get4) == 1); // (empty marker object with static methods)
// get4(front); // likewise NPE or assertion fail
// Now link the second data element in properly
d2.linkInto(front);
CHECK (Acc1::get(front) == 0);
CHECK (Acc2::get(front) == 2.3);
CHECK (Acc3::get(front) == false);
CHECK (get4(front) == "Ψ");
// further allocations can even be »elsewhere«
const void* loc;
{
Acc6 get6;
auto magic = Cons3::build("magic","cloud");
loc = getAdr(magic);
CHECK (magic.get<0>() == "magic"_expect);
CHECK (magic.get<1>() == "cloud"_expect);
// link into the cloud...
magic.linkInto(front);
CHECK (get6(front) == "cloud");
}// aaand...
// it's gone
// Evil, evil...
lib::UninitialisedStorage<Data3, 1> evilSpace;
Data3& d3 = evilSpace[0]; // note: working with left-over data from expired stack frame
CHECK (isSameAdr (d3, loc));
CHECK (d3.get<0>() == "magic"_expect); // const char* points into static data, so the chars are still there
new(&d3.get<1>()) string{"mushrooms"}; // the "cloud"-string was destroyed by magic's destructor
auto& [v1,v2,v3,v4,v5,v6] = Cons3::recast(front); // using connectivity from the linked list connecting the segments
CHECK (v1 == "0"_expect);
CHECK (v2 == "2.3"_expect);
CHECK (v3 == "false"_expect);
CHECK (v4 == "Ψ"_expect);
CHECK (v5 == "magic"_expect);
CHECK (v6 == "mushrooms"_expect);
v1 = 42;
v2 = 5.5;
v3 = true;
CHECK (front.get<0>() == 42);
CHECK (front.get<1>() == 5.5);
CHECK (d2.get<0>() == true);
CHECK (d2.get<1>() == "Ψ");
CHECK (isSameAdr (Acc1::get(front), v1));
CHECK (isSameAdr (Acc2::get(front), v2));
CHECK (isSameAdr (Acc3::get(front), v3));
CHECK (isSameAdr (Acc4::get(front), v4));
CHECK (isSameAdr (Acc5::get(front), v5));
CHECK (isSameAdr (Acc6::get(front), v6));
CHECK (not isSameAdr (front, v1));
CHECK (not isSameAdr (d2, v3));
CHECK (not isSameAdr (d3, v5));
// we can directly re-cast into another typed front-end
List3& fullChain = Cons3::recast(front);
CHECK (isSameAdr (fullChain.get<2>(), std::get<0>(d2)));
CHECK (isSameAdr (fullChain.get<3>(), std::get<1>(d2)));
CHECK (isSameAdr (fullChain.get<4>(), std::get<0>(d3)));
CHECK (isSameAdr (fullChain.get<5>(), std::get<1>(d3)));
CHECK (isSameAdr (fullChain.get<0>(), v1));
CHECK (isSameAdr (fullChain.get<1>(), v2));
CHECK (isSameAdr (fullChain.get<2>(), v3));
CHECK (isSameAdr (fullChain.get<3>(), v4));
CHECK (isSameAdr (fullChain.get<4>(), v5));
CHECK (isSameAdr (fullChain.get<5>(), v6));
// we can even use partially specified chains
List2& partChain = Cons2::recast(fullChain);
CHECK (isSameAdr (partChain.get<0>(), v1));
CHECK (isSameAdr (partChain.get<1>(), v2));
CHECK (isSameAdr (partChain.get<2>(), v3));
CHECK (isSameAdr (partChain.get<3>(), v4));
// Note: basically we are still using stale memory,
// previously allocated to the "magic" block,
// and now covered by the UninitialisedStorage
CHECK (loc == & d3);
CHECK (loc < & v5);
CHECK (loc < & v6);
// structural binding on partial chains is limited
CHECK (partChain.size() == 4);
auto& [w1,w2,w3,w4] = partChain;
CHECK (isSameObject (v1, w1));
CHECK (isSameObject (v2, w2));
CHECK (isSameObject (v3, w3));
CHECK (isSameObject (v4, w4));
}
};

View file

@ -87263,8 +87263,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733611147207" ID="ID_867806700" MODIFIED="1733611155184" TEXT="Entwurf: Belegung der Slots">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733611147207" ID="ID_867806700" MODIFIED="1734042089166" TEXT="Entwurf: Belegung der Slots">
<icon BUILTIN="pencil"/>
<node CREATED="1733611235157" ID="ID_1373022274" MODIFIED="1733611269549" TEXT="Abstraktes Ablauf-Schema">
<icon BUILTIN="info"/>
<node CREATED="1733611321861" ID="ID_1648703683" MODIFIED="1733615415248">
@ -87586,7 +87586,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733590902929" ID="ID_1045639317" MODIFIED="1733868511337" TEXT="Implementierung overflow-Buckets">
<icon BUILTIN="pencil"/>
<node CREATED="1733765037437" ID="ID_1724101101" MODIFIED="1733765062311" TEXT="unterst&#xfc;tzte Interaktionen">
<node BACKGROUND_COLOR="#c8c0b6" CREATED="1733765037437" ID="ID_1724101101" MODIFIED="1734041962487" TEXT="unterst&#xfc;tzte Interaktionen">
<node CREATED="1733765068881" ID="ID_523511672" MODIFIED="1733765084522" TEXT="ein default TurnoutSystem mit Grund-Ausstattung"/>
<node CREATED="1733765092674" ID="ID_1865816766" MODIFIED="1733765118024">
<richcontent TYPE="NODE"><html>
@ -87612,9 +87612,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="yes"/>
</node>
</node>
<node CREATED="1733766910569" ID="ID_462136727" MODIFIED="1734020495134" TEXT="&#x27f9; gebraucht wird">
<node BACKGROUND_COLOR="#c8c0b6" CREATED="1733766910569" ID="ID_462136727" MODIFIED="1734041957415" TEXT="&#x27f9; gebraucht wird">
<icon BUILTIN="yes"/>
<node COLOR="#435e98" CREATED="1733766926415" ID="ID_1686613162" MODIFIED="1734020490977" TEXT="Library f&#xfc;r heterogene verkn&#xfc;pfte Storage-Bl&#xf6;cke">
<node COLOR="#435e98" CREATED="1733766926415" FOLDED="true" ID="ID_1686613162" MODIFIED="1734041954497" TEXT="Library f&#xfc;r heterogene verkn&#xfc;pfte Storage-Bl&#xf6;cke">
<icon BUILTIN="yes"/>
<node COLOR="#338800" CREATED="1733767199547" ID="ID_22701741" MODIFIED="1733868478977" TEXT="Template HeteroData">
<icon BUILTIN="button_ok"/>
@ -87623,12 +87623,12 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1733766989087" ID="ID_1930665408" MODIFIED="1734020488102" TEXT="typsicheres compiletime-Overlay f&#xfc;r diese">
<node COLOR="#435e98" CREATED="1733766989087" FOLDED="true" ID="ID_1930665408" MODIFIED="1734020488102" TEXT="typsicheres compiletime-Overlay f&#xfc;r diese">
<icon BUILTIN="yes"/>
<node CREATED="1733767103376" ID="ID_36453586" MODIFIED="1733928886422" TEXT="verkettete factory-Funktionen f&#xfc;r einzelne Storage-Bl&#xf6;cke"/>
<node CREATED="1733767025290" ID="ID_741129447" MODIFIED="1733928908892" TEXT="daraus sind Accessoren f&#xfc;r typsicheren Zugriff erzeugbar"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733767147610" ID="ID_966052237" MODIFIED="1733868469882" TEXT="Zugriff auf einzelne Datenwerte per Accessor">
<node COLOR="#435e98" CREATED="1733767147610" FOLDED="true" ID="ID_966052237" MODIFIED="1734041952890" TEXT="Zugriff auf einzelne Datenwerte per Accessor">
<icon BUILTIN="yes"/>
<node CREATED="1733794253049" ID="ID_524032108" MODIFIED="1733794287860" TEXT="Grundlage: das C++ - Tuple-Protocol implementieren">
<icon BUILTIN="idea"/>
@ -87655,9 +87655,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733799750738" ID="ID_532258033" MODIFIED="1733799768652" TEXT="Implementierung ausarbeiten">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1733804423613" ID="ID_1306152229" MODIFIED="1733882827467" TEXT="Zugriff">
<node COLOR="#338800" CREATED="1733799750738" ID="ID_532258033" MODIFIED="1734041922506" TEXT="Implementierung ausarbeiten">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1733804423613" FOLDED="true" ID="ID_1306152229" MODIFIED="1733882827467" TEXT="Zugriff">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1733804463800" ID="ID_1686530886" MODIFIED="1733804491599" TEXT="definiere den Datentyp rekursiv">
<icon BUILTIN="button_ok"/>
@ -87758,7 +87758,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1733804575033" ID="ID_374529337" MODIFIED="1734020509491" TEXT="Konstruktur">
<node COLOR="#338800" CREATED="1733804575033" FOLDED="true" ID="ID_374529337" MODIFIED="1734020509491" TEXT="Konstruktur">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1733804582990" FOLDED="true" ID="ID_234262358" MODIFIED="1734020457462" TEXT="puh ... komplex">
<icon BUILTIN="smily_bad"/>
@ -88175,7 +88175,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1733946409913" ID="ID_766490392" MODIFIED="1734020338263" TEXT="C++ &#xbb;Tuple-Protocol&#xab;">
<node COLOR="#338800" CREATED="1733946409913" FOLDED="true" ID="ID_766490392" MODIFIED="1734041937846" TEXT="C++ &#xbb;Tuple-Protocol&#xab;">
<icon BUILTIN="button_ok"/>
<node CREATED="1733946436854" ID="ID_1279626510" LINK="https://en.cppreference.com/w/cpp/utility/tuple/tuple-like" MODIFIED="1733946454891" TEXT="exposition-only concept &#xbb;tuple-like&#xab;"/>
<node CREATED="1733946456354" ID="ID_1814813251" MODIFIED="1733946486589">
@ -88232,8 +88232,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
hei&#223;t auch, man kann hier nicht mit SFINAE arbeiten &#8212; und exakt das hat sich am Ende auch als das Problem herausgestellt, die Compilation scheitert bevor unser Code &#252;berhaupt eingreifen kann
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#f6e2a1" COLOR="#990000" CREATED="1733960761558" ID="ID_1977939692" MODIFIED="1734020032462" TEXT="trotzdem verstehe ich das Problem nicht.....">
<icon BUILTIN="forward"/>
@ -88321,8 +88320,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
&#160;&#10233; Fehler im Test-Setup reproduzierbar
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="idea"/>
<node CREATED="1733977452943" ID="ID_1506713776" MODIFIED="1733977494203" TEXT="die Assertion-Failure kommt aus tuple_element_t&lt;I,tuple&gt;">
<icon BUILTIN="info"/>
@ -88411,8 +88409,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
damit funktionieren die <b>structured bindings</b>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#304e65" CREATED="1734017114737" ID="ID_1154017972" MODIFIED="1734017708318" TEXT="diese gehen n&#xe4;mlich noch &#xfc;ber das &#xbb;tuple-protocol&#xab; hinaus">
@ -88429,16 +88426,16 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733883489383" ID="ID_155186903" MODIFIED="1733883516460" TEXT="HeteroData_test">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1733883489383" FOLDED="true" ID="ID_155186903" MODIFIED="1734041986220" TEXT="HeteroData_test">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1733883525530" ID="ID_1918349528" MODIFIED="1734025619302" TEXT="verify_FrontBlock">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1733883562026" ID="ID_941439456" MODIFIED="1733883584764" TEXT="Datenblock erstellen"/>
<node COLOR="#435e98" CREATED="1733883567253" ID="ID_252468938" MODIFIED="1733883584764" TEXT="Datenzugriff zeigen"/>
<node COLOR="#435e98" CREATED="1733883572964" ID="ID_1308768158" MODIFIED="1734025607198" TEXT="structural binding / Tuple-Protokoll"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733883536343" ID="ID_877333475" MODIFIED="1733883538992" TEXT="verify_ChainBlock">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1733883536343" ID="ID_877333475" MODIFIED="1734041976272" TEXT="verify_ChainBlock">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1733883589092" ID="ID_1386279261" MODIFIED="1733883643827" TEXT="erst die Typen konstruieren"/>
<node COLOR="#435e98" CREATED="1733883604891" ID="ID_1254661884" MODIFIED="1733883643827" TEXT="Front-Block erstellen und populieren"/>
<node COLOR="#435e98" CREATED="1733883616620" ID="ID_1790631124" MODIFIED="1733883643827" TEXT="Chain-Block erstellen und populieren"/>
@ -88446,19 +88443,18 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<linktarget COLOR="#65a6c0" DESTINATION="ID_1607678238" ENDARROW="Default" ENDINCLINATION="189;-12;" ID="Arrow_ID_842453741" SOURCE="ID_1554305818" STARTARROW="None" STARTINCLINATION="-3;109;"/>
</node>
<node COLOR="#435e98" CREATED="1733883629524" ID="ID_88656707" MODIFIED="1733883643826" TEXT="gemeinsamen Datenzugriff direkt zeigen"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733883922133" ID="ID_745130175" MODIFIED="1733883969468" TEXT="Zugriff per Typ demonstrieren">
<linktarget COLOR="#678f9e" DESTINATION="ID_745130175" ENDARROW="Default" ENDINCLINATION="1747;-43;" ID="Arrow_ID_1832059516" SOURCE="ID_1704921041" STARTARROW="None" STARTINCLINATION="55;794;"/>
<icon BUILTIN="flag-yellow"/>
</node>
<node COLOR="#435e98" CREATED="1733883572964" ID="ID_1694822636" MODIFIED="1734025615096" TEXT="structural binding / Tuple-Protokoll"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733883656600" ID="ID_972149921" MODIFIED="1733883808249" TEXT="verify_Accessors">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1733883663184" ID="ID_1127481242" MODIFIED="1733883674938" TEXT="hier nun mit mehreren Datenbl&#xf6;cken arbeiten"/>
<node CREATED="1733883682093" ID="ID_531287492" MODIFIED="1733883721468" TEXT="Zugriffe via Accessor ohne sichtbaren Cast"/>
<node CREATED="1733883747133" ID="ID_276517152" MODIFIED="1733883759060" TEXT="structural Binding mit allen Einschr&#xe4;nkungen demonstrieren"/>
<node CREATED="1733883781976" ID="ID_1919391319" MODIFIED="1733883795270" TEXT="Speicher-Adressen verifizieren"/>
<node CREATED="1733883796910" ID="ID_1268320323" MODIFIED="1733883805336" TEXT="Grenzen / Gefahren / Manipulation zeigen"/>
<node COLOR="#338800" CREATED="1733883656600" ID="ID_972149921" MODIFIED="1734041984704" TEXT="verify_Accessors">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1733883663184" ID="ID_1127481242" MODIFIED="1734040977954" TEXT="hier nun mit mehreren Datenbl&#xf6;cken arbeiten"/>
<node COLOR="#435e98" CREATED="1733883682093" ID="ID_531287492" MODIFIED="1734040977954" TEXT="Zugriffe via Accessor ohne sichtbaren Cast"/>
<node COLOR="#435e98" CREATED="1733883922133" ID="ID_745130175" MODIFIED="1734029997277" TEXT="Zugriff per Typ demonstrieren">
<linktarget COLOR="#678f9e" DESTINATION="ID_745130175" ENDARROW="Default" ENDINCLINATION="1747;-43;" ID="Arrow_ID_1832059516" SOURCE="ID_1704921041" STARTARROW="None" STARTINCLINATION="55;794;"/>
</node>
<node COLOR="#435e98" CREATED="1733883747133" ID="ID_276517152" MODIFIED="1734040982353" TEXT="structural Binding mit allen Einschr&#xe4;nkungen demonstrieren"/>
<node COLOR="#435e98" CREATED="1733883781976" ID="ID_1919391319" MODIFIED="1734040982354" TEXT="Speicher-Adressen verifizieren"/>
<node COLOR="#435e98" CREATED="1733883796910" ID="ID_1268320323" MODIFIED="1734040982353" TEXT="Grenzen / Gefahren / Manipulation zeigen"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733767161520" ID="ID_1853669534" MODIFIED="1733767188150" TEXT="Standard-Definition f&#xfc;r TurnoutSystem auf dieser Basis">
@ -142890,8 +142886,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
es gen&#252;gt da&#223; die Member unter dem Namen direkt zugreifbar sind; sie m&#252;ssen auch in der gleichen Struct liegen (die aber durchaus eine Basisklasse sein kann). Bit-Felder werden unterst&#252;tzt, Union-Member jedoch nicht
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node COLOR="#435e98" CREATED="1733950233731" ID="ID_609631801" LINK="https://devblogs.microsoft.com/oldnewthing/20201015-00/?p=104369" MODIFIED="1733950498051" TEXT="How to add structured binding support to your own types">