Invocation: get structural bindings to work

It seemed like we're doomed...
Yet we barely escaped our horrid fate, because the C++ structured bindings happen to look also for get<i> member functions!

Any other solution involving a free function `get<i>(h)` would not work, since the `std::tuple` used as base class would inevitably drag in std::get via ADL
Obviously, the other remedy would be to turn the `StorageFrame` into a member; yet doing so is not desirable, as makes the actual storage layout more obscure (and also more brittle)
This commit is contained in:
Fischlurch 2024-12-12 19:03:43 +01:00
parent 41a6e93057
commit e6403cbc7e
5 changed files with 263 additions and 146 deletions

View file

@ -33,15 +33,7 @@ typedef unsigned int uint;
#include <string>
#include <tuple>
using lib::test::showType;
template<typename...TS>
string
showTypes()
{
return "<" + ((showType<TS>()+",") + ... + ">");
}
using lib::test::showTypes;
using std::tuple;
struct B { };
@ -104,18 +96,21 @@ main (int, char**)
using Het = lib::HeteroData<uint,double>;
Het h1;
SHOW_EXPR(getty(h1));
SHOW_EXPR(std::get<1>(h1) = 5.5)
// SHOW_EXPR(std::get<1>(h1) = 5.5)
SHOW_EXPR(h1.get<1>() = 5.5)
using Constructor = Het::Chain<bool,string>;
auto h2 = Constructor::build (true, "Ψ");
h2.linkInto(h1);
using Het2 = Constructor::ChainType;
Het2& chain2 = reinterpret_cast<Het2&> (h1);
Het2& chain2 = Constructor::recast (h1);
SHOW_TYPE(Het2)
SHOW_EXPR(getty(chain2));
SHOW_EXPR(std::get<1>(chain2))
// SHOW_EXPR(std::get<1>(chain2))
// SHOW_EXPR(std::get<3>(chain2))
SHOW_EXPR(chain2.get<1>())
SHOW_EXPR(chain2.get<3>())
SHOW_EXPR(gritty<1>(chain2))
SHOW_EXPR(gritty<3>(chain2))

View file

@ -29,6 +29,32 @@
** requires traversal in several steps, which, on the other hand, can be justified by a good
** cache locality of recently used stack frames, thereby avoiding heap allocations altogether.
**
** # Usage
** @warning it is essential to understand where actual storage resides!
** A HeteroData chain is built-up gradually, starting with a front-block
** - the front-block is usually placed at an _anchor location_ and populated with data
** - retrieve a _chain constructor type_ from the _type_ of the front-block,
** i.e `HeteroData<D1,D2,...>::Chain<D21,...>`
** - use this chain constructor to create a follow-up data block elsewhere
** - need to link this data block explicitly into the front
** - get _accessor types_ from the _chain constructor_
** - use these to work with individual data elements _through the front-block._
** @example
** \code
** using Front = lib::HeteroData<uint,double>;
** auto h1 = Front::build (1,2.3);
** using Cons1 = Front::Chain<bool,string>;
** auto b2 = Cons1::build (true, "Ψ");
** b2.linkInto(c1);
** auto& [d1,d2,d3,d4] = Cons1::recast(h1);
** CHECK (d1 == 1);
** CHECK (d2 == 2.3);
** CHECK (d3 == true);
** CHECK (d4 == "Ψ");
** Cons1::Accessor<string> get4;
** CHECK (get4(h1) == "Ψ");
** \endcode
**
** @todo WIP-WIP this is the draft of a design sketch regarding the render node network,
** which seems to be still pretty much in flux as of 12/2024
** @see HeteroData_test
@ -61,17 +87,23 @@
namespace lib {
/**
* A setup with chained data tuples residing in distributed storage.
* A HeteroData-chain is started from a front-end block and can later be
* extended by a linked list of further data blocks allocated elsewhere.
* @warning this is a low-level memory layout without storage management.
* @see HeteroData_test
*/
template<typename...DATA>
class HeteroData;
/** linked list of StorageFrame elements */
struct StorageLoc
: util::NonCopyable
{
StorageLoc* next{nullptr};
};
/** individual storage frame in a chain, holding a data tuple */
template<size_t seg, typename...DATA>
struct StorageFrame
: protected StorageLoc
@ -86,6 +118,12 @@ namespace lib {
};
/**
* @internal implementation specialisation to manage a sublist of StorageFrame elements
* @tparam seg a type tag to mark the position of StorageFrame elements
* @tparam DATA tuple element types residing in the first segment
* @tparam TAIL recursive Loki-style type list to describe the rest of the chain
*/
template<size_t seg, typename...DATA, class TAIL>
class HeteroData<meta::Node<StorageFrame<seg, DATA...>,TAIL>>
: StorageFrame<seg, DATA...>
@ -103,7 +141,7 @@ namespace lib {
template<size_t slot>
using PickType = std::conditional_t<isLocal<slot>, std::tuple_element<slot,Tuple>
, typename _Tail::template PickType<slot-localSiz>>;
// need to use this helper to prevent eager evaluation on Elm_t<i>
_Tail&
accessTail()
{
@ -114,7 +152,7 @@ namespace lib {
template<typename...XX>
friend class HeteroData; ///< allow chained types to use recursive type definitions
using Frame::Frame;
using Frame::Frame; ///< data elements shall be populated through the builder front-ends
public:
HeteroData() = default;
@ -128,7 +166,7 @@ namespace lib {
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>&
get() noexcept
@ -174,6 +212,19 @@ namespace lib {
return {initArgs ...};
}
template<typename...SPEC>
static ChainType&
recast (HeteroData<SPEC...>& frontChain)
{
return reinterpret_cast<ChainType&> (frontChain);
}
template<typename...SPEC>
static ChainType&
recast (HeteroData<SPEC...> const& frontChain)
{
return reinterpret_cast<ChainType const&> (frontChain);
}
template<typename...XVALS>
using ChainExtension = typename ChainType::template Chain<XVALS...>;
@ -185,6 +236,9 @@ namespace lib {
};
};
/**
* @internal implementation specialisation to mark the end of a chain
*/
template<>
class HeteroData<meta::NullType>
{
@ -197,6 +251,12 @@ namespace lib {
using PickType = void;
};
/*************************************************************************//**
* @remark this is the front-end for regular usage
* - create and populate with the #build operation
* - data access with the `get<i>` member function (inherited)
* - use `HeteroData<DATA...>::Chain<TY...>` to build follow-up segments
*/
template<typename...DATA>
class HeteroData
: public HeteroData<meta::Node<StorageFrame<0, DATA...>, meta::NullType>>
@ -248,6 +308,22 @@ namespace lib {
}
}
/**
* Attach a new storage frame at the end of an existing HeteroData-chain.
* @tparam seg the number of the separate data segment, must match target
* @param prefixChain with `seg - 1` existing chained tuple-segments
* @remark The core function actually to extend a chain with a new segment,
* which should have been built using a suitable nested `HeteroData::Chain`
* constructor type. Further segments can be defined working from there,
* since each such constructor in turn has a member type `ChainExtension`
* @note Always use this strongly typed extension and access path, to prevent
* out-of-bounds memory access. The actual HeteroData stores no run time
* type information, and thus a force-cast is necessary internally to
* access the follow-up data tuple frames. The typing, and especially
* the `seg` template parameter used to mark each StorageFrame is
* the only guard-rail provided, and ensures safe data access.
*/
template<size_t seg, typename...DATA>
template<typename SPEC>
inline void
@ -258,10 +334,12 @@ namespace lib {
ENSURE (lastLink == nullptr);
lastLink = this;
}
}// namespace lib
} // namespace lib
namespace std {// Specialisation to support C++ »Tuple Protocol«
namespace std { // Specialisation to support C++ »Tuple Protocol« and structured bindings.
/** determine compile-time fixed size of a HeteroData */
template<typename...DATA>
@ -281,33 +359,9 @@ namespace std {// Specialisation to support C++ »Tuple Protocol«
static_assert ("accessing element-type of an empty HeteroData block");
};
/** access by reference to the I-th data value held in a HeteroData chain */
template<size_t I, typename...DATA>
constexpr tuple_element_t<I, lib::HeteroData<DATA...>>&
get (lib::HeteroData<DATA...> & heDa) noexcept
{
return heDa.template get<I>();
}
template<size_t I, typename...DATA>
constexpr tuple_element_t<I, lib::HeteroData<DATA...>> const&
get (lib::HeteroData<DATA...> const& heDa) noexcept
{
return heDa.template get<I>();
}
template<size_t I, typename...DATA>
constexpr tuple_element_t<I, lib::HeteroData<DATA...>>&&
get (lib::HeteroData<DATA...>&& heDa) noexcept
{
using ElmType = tuple_element_t<I, lib::HeteroData<DATA...>>;
return forward<ElmType&&> (heDa.template get<I>());
}
template<std::size_t I, typename...DATA>
constexpr std::tuple_element_t<I, lib::HeteroData<DATA...>> const &&
get (lib::HeteroData<DATA...> const && heDa) noexcept
{
using ElmType = tuple_element_t<I, lib::HeteroData<DATA...>>;
return forward<ElmType const&&> (heDa.template get<I>());
}
// Note: deliberately NOT providing a free get<i> function.
// Overload resolution would fail, since it attempts to instantiate std::get<i>(tuple) as a candidate,
// which triggers an assertion failure when using an index valid only for the full chain, not the base tuple
/** determine compile-time fixed size of a StorageFrame */
@ -322,13 +376,8 @@ namespace std {// Specialisation to support C++ »Tuple Protocol«
: std::tuple_element<I, typename lib::StorageFrame<seg,DATA...>::Tuple>
{ };
/** delegate to the element data access of a StorageFrame's underlying tuple */
// template<size_t I, size_t seg, typename...DATA>
// std::tuple_element_t<I, lib::StorageFrame<seg,DATA...>>&
// get (lib::StorageFrame<seg,DATA...>& block)
// {
// return std::get
// };
// no need to define an overload for std::get<i>
// (other than a template specialisation, it will use base-type conversion to std::tuple on its argument;
}// namespace std
#endif /*LIB_HETERO_DATA_H*/

View file

@ -263,6 +263,13 @@ namespace test{
+ Case::postfix;
}
template<typename...TS>
string
showTypes()
{
return "<| " + ((showType<TS>()+", ") + ... + "|>");
}
/** helper for investigating a variadic argument pack
* @remark you can pass arguments directly to this function,

View file

@ -49,11 +49,9 @@ namespace test{
virtual void
run (Arg)
{
// seedRand();
// checksum = 0;
verify_FrontBlock();
verify_ChainBlock();
// verify_Accessors();
}
@ -78,6 +76,11 @@ namespace test{
CHECK (2 == std::tuple_size_v<Block1::NewFrame::Tuple>); // referring to the embedded tuple type
CHECK (2 == std::tuple_size_v<Block1::NewFrame>); // StorageFrame itself complies to the C++ tuple protocol
CHECK (2 == std::tuple_size_v<Block1>); // likewise for the complete HeteroData Chain
auto& [_,p] = b2; // can use structured bindings...
CHECK (p == 3.14);
p = 3.14159;
CHECK (3.14159 == b2.get<1>());
}
@ -97,7 +100,7 @@ namespace test{
b2.linkInto(b1);
using Chain2 = Constructor::ChainType;
Chain2& chain2 = reinterpret_cast<Chain2&> (b1);
Chain2& chain2 = Constructor::recast (b1);
CHECK (b1.size() == 1);
CHECK (chain2.size() == 3);
@ -130,12 +133,24 @@ namespace test{
CHECK ((showType<std::tuple_element_t<0, Block2>>() == "double"_expect));
CHECK ((showType<std::tuple_element_t<1, Block2>>() == "string"_expect));
CHECK (std::get<0> (chain2) == 42);
// CHECK (std::get<1> (chain2) == "1.618034"_expect); ////////////////////////////TODO somehow the overload for std::tuple takes precedence here
// CHECK (std::get<2> (chain2) == "Φ"_expect);
// CHECK (std::get<0> (chain2) == "42"_expect); // std::tuple is inaccessible base of HeteroData
CHECK (std::get<0> (b2) == "1.618034"_expect);
CHECK (std::get<1> (b2) == "Φ"_expect);
// CHECK (std::get<1> (chain2) == "1.618034"_expect); // does not compile due to range restriction for the base tuple
// (as such this is correct — yet prevents definition of a custom get-function)
auto& [u0] = b1;
CHECK (u0 == "42"_expect);
auto& [v0,v1] = b2; // b2 is typed as StorageFrame and thus the tuple base is accessible
CHECK (v0 == "1.618034"_expect);
CHECK (v1 == "Φ"_expect);
auto& [x0,x1,x2] = chain2; // Note: structured binding on the fully typed chain uses the get<i>-Member
CHECK (x0 == "42"_expect);
CHECK (x1 == "1.618034"_expect);
CHECK (x2 == "Φ"_expect);
// 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
}
};

View file

@ -22967,9 +22967,7 @@
</node>
<node CREATED="1480780140741" ID="ID_1754958261" MODIFIED="1539382659205" TEXT="und ein dritter ist wirklich wasserdicht">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
wenn alle Objekte <i>wirklich</i>&#160;auf partiell initialisierten Zustand vorbereitet sind,
@ -23321,9 +23319,7 @@
</node>
<node CREATED="1666486003675" ID="ID_563456586" MODIFIED="1666486275676" TEXT="DisplayMetric* speichern">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Da im Clip die Anfrage an die Metrik-&#220;bersetzung x-fach (bei jedem Fokus-Wechsel) erfolgt, dagegen das generelle re-Positionieren auf dem Canvas nur nach einem Strukturwechsel oder Zoom-Wechsel, w&#228;re eine sehr einfache und effektive Optimierung, sich den DisplayMetric-Pointer <i>im individuellen Clip</i>&#160;eigens zu speichern. Das w&#228;re <i>allerings ein zus&#228;tzlicher &#187;Slot&#171; pro Clip! </i>... eine Variante mit einer zus&#228;tzlichen Pointer-Indirektion w&#252;rde den DisplayMetric*-Pointer im CanvasHook speichern, und damit einmal pro Track (also wesentlich kleinerer Hebel)
@ -23914,9 +23910,7 @@
</node>
<node CREATED="1582988935367" ID="ID_829958563" MODIFIED="1672875280897" TEXT="Problem mit automatischer Scrollbar">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...deutet darauf hin, da&#223; in diesem Zusammenhang etwas schiefl&#228;uft
@ -24630,9 +24624,7 @@
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1674161820779" ID="ID_1877059709" MODIFIED="1674161920084" TEXT="Stand: ElementBoxWidget als Clip, aber leer">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Ende 2022 habe ich dann doch noch das ElementBoxWidget gebaut. Nun verwenden Clips schon mal dieses, aber die ganze Logik der Clip-Anzeige <i>ist auf sp&#228;ter verschoben...</i>
@ -25887,9 +25879,7 @@
<node CREATED="1576966592939" ID="ID_495877115" MODIFIED="1576966611564" TEXT="Objekte, die zerst&#xf6;rt werden, werden automatisch aus dem Container entfernt"/>
<node CREATED="1576966612744" ID="ID_1380812898" MODIFIED="1576966693515" TEXT="der Gtkmm-Wrapper Gtk::Widget h&#xe4;lt einen ref-count">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...und h&#228;lt damit sein unterliegendes C-Objekt am Leben
@ -28043,9 +28033,7 @@
</node>
<node CREATED="1677457273534" ID="ID_617186212" MODIFIED="1677457320336" TEXT="letztlich haben wir hier keinen gef&#xe4;hrlichen Hebel">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...anders als bei den Einzel-Widgets im Timeline-Content, haben wir hier im Header nur ein StaveBracket-Widget pro Track
@ -30535,9 +30523,7 @@
</node>
<node CREATED="1672845054021" ID="ID_1400277326" MODIFIED="1672845155612" TEXT="und ist auch konsistent mit dem &#xbb;horizontal adjustment&#xab; des ScrolledWindow">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
per DUMP-Print verifiziert: Maximalwert der Scrollbar (=hadj) ist identisch mit get_allocated_width
@ -31787,9 +31773,7 @@
</node>
<node CREATED="1563043712231" ID="ID_680778611" MODIFIED="1563043724620" TEXT="&#xfc;berarbeitete Version">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
window.background box.vertical box[2/3].horizontal widget[2/2] widget paned.vertical widget box.vertical notebook[1/1].frame paned.horizontal.timeline-page box.vertical.timeline.timeline-body fork.timeline
@ -34736,9 +34720,7 @@
<node CREATED="1661693702610" ID="ID_1055135476" MODIFIED="1661693718279" TEXT="empf&#xe4;ngt Inhalts- und Metadaten-&#xc4;nderungen als Nachricht per UI-Bus"/>
<node CREATED="1661695087724" ID="ID_1578237138" MODIFIED="1661695191411" TEXT="stellt bei Bedarf die Verbindung her zu einem Placement-UI">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
das Placement-UI wird z.B. durch Klick auf das Placement-Icon aktiviert &#8212; aber es kann auch <i>modal gemacht werden, </i>und dann wird es in ein Property-Box/Grid-UI alloziert
@ -37126,9 +37108,7 @@
<node CREATED="1613334249690" ID="ID_1792797047" MODIFIED="1613334275524" TEXT="&#x27f9; in den Frameworks fehlt der abstrakte gemeiname Einstiegspunkt">
<node CREATED="1613334316121" ID="ID_1190900510" MODIFIED="1613334356211" TEXT="GTK bietet nur ein copy/move drag-n-drop">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
und das zu allem &#220;berflu&#223; auch noch ziemlich hart verdrahtet. Man kann nicht einmal frei &#252;ber die Modifier-Keys verf&#252;gen
@ -38111,9 +38091,7 @@
<node CREATED="1617569229030" ID="ID_601910999" MODIFIED="1617569234719" TEXT="echtes Problem"/>
<node CREATED="1617569235666" ID="ID_1093451410" MODIFIED="1617569408809" TEXT="betrachte ich als Unfall">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
wenn das <i>Dragging </i>funktioniert, sollte es eigentlich rein logisch unm&#246;glich sein, das Widget zu verlassen, weil dieses sich ja mitbewegt. Allerdings sind vielerlei undl&#252;ckliche Umst&#228;nde denkbar, z.B. versp&#228;tete Reaktion der Software, sehr schnelle Mausbewegungen, limitierte Bewegung am Rand eines Containers.
@ -38999,9 +38977,7 @@
<icon BUILTIN="button_ok"/>
<node CREATED="1620419793888" ID="ID_1040008985" MODIFIED="1620419938844" TEXT="Einschr&#xe4;nkung von InPlaceBuffer / PlantingHandle">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
diese verwalten nicht aktiv den Typ und Zustand im Buffer.
@ -39303,9 +39279,7 @@
<node CREATED="1624113167761" ID="ID_1626319182" MODIFIED="1624113229429" TEXT="Cairo zeichnet eine Linienfolge"/>
<node CREATED="1624113230924" ID="ID_391833497" MODIFIED="1624113256653">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
jede Zeichen-Primitive zeichnet von der <i>aktuellen Position</i>&#160;weg
@ -39469,9 +39443,7 @@
</node>
<node COLOR="#435e98" CREATED="1679359094871" ID="ID_895795423" MODIFIED="1679359187122">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
<u>Stand</u>: Konzeptstudie erfolgreich
@ -87640,8 +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="1733766922508" TEXT="&#x27f9; gebraucht wird">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733766926415" ID="ID_1686613162" MODIFIED="1733868469882" TEXT="Library f&#xfc;r heterogene verkn&#xfc;pfte Storage-Bl&#xf6;cke">
<node CREATED="1733766910569" ID="ID_462136727" MODIFIED="1734020495134" 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">
<icon BUILTIN="yes"/>
<node COLOR="#338800" CREATED="1733767199547" ID="ID_22701741" MODIFIED="1733868478977" TEXT="Template HeteroData">
<icon BUILTIN="button_ok"/>
@ -87650,7 +87623,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733766989087" ID="ID_1930665408" MODIFIED="1733868469882" TEXT="typsicheres compiletime-Overlay f&#xfc;r diese">
<node COLOR="#435e98" CREATED="1733766989087" 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"/>
@ -87781,13 +87754,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
<node COLOR="#338800" CREATED="1733851835255" ID="ID_1021269190" MODIFIED="1733852014748" TEXT="Accessoren auch &#xfc;ber den Konstruktor abgreifbar">
<linktarget COLOR="#01ba2e" DESTINATION="ID_1021269190" ENDARROW="Default" ENDINCLINATION="-582;31;" ID="Arrow_ID_1159712630" SOURCE="ID_13086801" STARTARROW="None" STARTINCLINATION="-91;0;"/>
<linktarget COLOR="#01ba2e" DESTINATION="ID_1021269190" ENDARROW="Default" ENDINCLINATION="-602;29;" ID="Arrow_ID_1159712630" SOURCE="ID_13086801" STARTARROW="None" STARTINCLINATION="-116;4;"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733804575033" ID="ID_374529337" MODIFIED="1733804581760" TEXT="Konstruktur">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1733804582990" ID="ID_234262358" MODIFIED="1733868402231" TEXT="puh ... komplex">
<node COLOR="#338800" CREATED="1733804575033" 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"/>
<node CREATED="1733804622226" ID="ID_13001974" MODIFIED="1733804637342" TEXT="ich will zuerst Konstruktor-Typen konstruieren">
<node CREATED="1733804722045" ID="ID_1072077887" MODIFIED="1733804736615" TEXT="von diesem sollen bereits Accessoren abgenommen werden k&#xf6;nnen"/>
@ -87850,7 +87823,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#580099" CREATED="1733834483620" ID="ID_585239021" MODIFIED="1733883011509" TEXT="Situation des Nutzens vergegenw&#xe4;rtigen">
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#580099" CREATED="1733834483620" FOLDED="true" ID="ID_585239021" MODIFIED="1734020448858" TEXT="Situation des Nutzens vergegenw&#xe4;rtigen">
<icon BUILTIN="forward"/>
<node CREATED="1733834527058" ID="ID_1496514894" MODIFIED="1733834543856" TEXT="aufgerufen wird eine spezielle ParamNode">
<node CREATED="1733834545401" ID="ID_47691367" MODIFIED="1733834566914" TEXT="effektiv ist das dann ein Port mit speziellem WeavingPattern"/>
@ -88097,8 +88070,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1733851922106" ID="ID_421589500" MODIFIED="1733852040199" TEXT="somit reduziert sich die Implementierung auf einige Typedefs">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1733851935617" ID="ID_13086801" MODIFIED="1733852025559" TEXT="und kann auch ganz einfach den Chain-Konstruktor oder die Accessoren bieten">
<arrowlink COLOR="#01ba2e" DESTINATION="ID_1021269190" ENDARROW="Default" ENDINCLINATION="-582;31;" ID="Arrow_ID_1159712630" STARTARROW="None" STARTINCLINATION="-91;0;"/>
<node COLOR="#338800" CREATED="1733851935617" ID="ID_13086801" MODIFIED="1734020470771" TEXT="und kann auch ganz einfach den Chain-Konstruktor oder die Accessoren bieten">
<arrowlink COLOR="#01ba2e" DESTINATION="ID_1021269190" ENDARROW="Default" ENDINCLINATION="-602;29;" ID="Arrow_ID_1159712630" STARTARROW="None" STARTINCLINATION="-116;4;"/>
<icon BUILTIN="idea"/>
</node>
</node>
@ -88202,7 +88175,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node CREATED="1733946409913" ID="ID_766490392" MODIFIED="1733946421787" TEXT="C++ &#xbb;Tuple-Protocol&#xab;">
<node COLOR="#338800" CREATED="1733946409913" ID="ID_766490392" MODIFIED="1734020338263" 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">
<richcontent TYPE="NODE"><html>
@ -88221,7 +88195,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1733946498997" ID="ID_1699016974" MODIFIED="1733946531556" TEXT="l&#xe4;&#xdf;t sich direkt auf std::integral_constant zur&#xfc;ckf&#xfc;hren"/>
<node CREATED="1733946533117" ID="ID_1111331922" MODIFIED="1733946542098" TEXT="implementiert f&#xfc;r beliebige HeteroData"/>
<node CREATED="1733946542902" ID="ID_139021842" MODIFIED="1733946550153" TEXT="auch gleich implementiert f&#xfc;r StorageFrame"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1733946551317" ID="ID_555431810" MODIFIED="1733946586881" TEXT="Beachte: Template-Spezialisierungen greifen nicht f&#xfc;r abgeleitete Klassen">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1733946551317" FOLDED="true" ID="ID_555431810" MODIFIED="1733946586881" TEXT="Beachte: Template-Spezialisierungen greifen nicht f&#xfc;r abgeleitete Klassen">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1733946590316" ID="ID_626664530" MODIFIED="1733946600694" TEXT="nach zwemal Nachdenken: ist auch sinnvoll"/>
<node CREATED="1733946621803" ID="ID_333291639" MODIFIED="1733946638813" TEXT="man w&#xfc;rde dann statisch auf der Basis-Klasse operieren"/>
@ -88233,17 +88207,38 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1733946659490" ID="ID_668547104" MODIFIED="1733946664745" TEXT="ebenso"/>
<node CREATED="1733946672501" ID="ID_235658194" MODIFIED="1733946690942" TEXT="static_assert f&#xfc;r den Fall eines HetroData&lt;NullType&gt;"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733946695947" ID="ID_1366785972" MODIFIED="1733946699508" TEXT="std::get">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1733946700889" ID="ID_729503649" MODIFIED="1733946713139" TEXT="im Prinzip klar ... aber m&#xfc;hsam"/>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1733946713943" ID="ID_1873953043" MODIFIED="1733946732567" TEXT="funktioniert nicht .... Compiler nimmt Overload f&#xfc;r std::tuple">
<node COLOR="#5b280f" CREATED="1733946695947" ID="ID_1366785972" MODIFIED="1734020009409" TEXT="std::get">
<icon BUILTIN="button_cancel"/>
<node CREATED="1733946700889" ID="ID_729503649" MODIFIED="1734020224188" TEXT="im Prinzip klar ... aber m&#xfc;hsam">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Brauche wirklich alle vier Varianten (&amp;, const&amp;, &amp;&amp; und const&amp;&amp;). Und auch f&#252;r jede einen explizit ausgeschribenen korrekten Return-Typ per std::tuple_element_t
</p>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1733946713943" FOLDED="true" ID="ID_1873953043" MODIFIED="1734020418870" TEXT="funktioniert nicht .... Compiler nimmt Overload f&#xfc;r std::tuple">
<icon BUILTIN="broken-line"/>
<node CREATED="1733946765784" ID="ID_1087783493" MODIFIED="1733946780713" TEXT="das bekannte Problem mit Funktion Overloads"/>
<node CREATED="1733946781559" ID="ID_1787763968" MODIFIED="1733946793699" TEXT="es ist dann eben keine partielle Template-Spezialisierung"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733960761558" ID="ID_1977939692" MODIFIED="1733960781184" TEXT="trotzdem verstehe ich das Problem nicht.....">
<node COLOR="#5b280f" CREATED="1733946765784" ID="ID_1087783493" MODIFIED="1734020236696" TEXT="das bekannte Problem mit Funktion Overloads??">
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1733946781559" ID="ID_1787763968" MODIFIED="1734020321264" TEXT="es ist dann eben keine partielle Template-Spezialisierung">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
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>
</node>
<node BACKGROUND_COLOR="#f6e2a1" COLOR="#990000" CREATED="1733960761558" ID="ID_1977939692" MODIFIED="1734020032462" TEXT="trotzdem verstehe ich das Problem nicht.....">
<icon BUILTIN="forward"/>
<node CREATED="1733960786954" ID="ID_1320100813" MODIFIED="1733960810467" TEXT="er sollte dann doch den gegebenen Overload verwenden"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733960871534" ID="ID_1458313610" MODIFIED="1733960901968" TEXT="versuche mal den std::tuple-Basistyp herauszunehmen">
<node COLOR="#435e98" CREATED="1733960871534" ID="ID_1458313610" MODIFIED="1734020038961" TEXT="versuche mal den std::tuple-Basistyp herauszunehmen">
<icon BUILTIN="idea"/>
<node CREATED="1733964059183" ID="ID_39714121" MODIFIED="1733964345755" TEXT="vorsicht Empty-Baseclass">
<richcontent TYPE="NOTE"><html>
@ -88265,6 +88260,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</p>
</body>
</html></richcontent>
<linktarget COLOR="#bf1358" DESTINATION="ID_715175218" ENDARROW="Default" ENDINCLINATION="-419;23;" ID="Arrow_ID_849929100" SOURCE="ID_1313304599" STARTARROW="None" STARTINCLINATION="222;-63;"/>
</node>
<node CREATED="1733964348236" ID="ID_1028912337" MODIFIED="1733970622428" TEXT="damit funktioniert der Test &#x27f9; meine Spezialisierung als Solche war korrekt"/>
</node>
@ -88282,7 +88278,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1733970625236" ID="ID_1475799809" MODIFIED="1733970641577" TEXT="beide Kandidaten sind Funktions-Templates"/>
<node CREATED="1733970647177" ID="ID_305236337" MODIFIED="1733970684664" TEXT="Parameter &#x27fc; Tuple(Base) gilt als Conversion"/>
<node CREATED="1733970685828" ID="ID_442077561" MODIFIED="1733970703973" TEXT="deshalb sollte m.E. dieser Fall einen schlechteren Rang bekommen"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1733970909696" ID="ID_1168280520" MODIFIED="1733970922306" TEXT="Untersuchung">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1733970909696" ID="ID_1168280520" MODIFIED="1734020044994" TEXT="Untersuchung">
<icon BUILTIN="forward"/>
<node CREATED="1733972793050" ID="ID_1370589924" MODIFIED="1733972813148" TEXT="im einfachen Beispiel verh&#xe4;lt sich alles wie erwartet...">
<icon BUILTIN="smily_bad"/>
@ -88301,8 +88297,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
ja wirklich: der Code geht durch den Compiler und zur Laufzeit kann ich mit dem Debugger in unseren Overload steppen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1733976405948" ID="ID_558042856" MODIFIED="1733976504495" TEXT="std::get&lt;2&gt;(chain2) &#x27f6; compile-time-Assertion &#x27f9; std::tuple-Overload">
<richcontent TYPE="NOTE"><html>
@ -88315,7 +88310,19 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1733976996794" ID="ID_1396891623" MODIFIED="1733977038241" TEXT="exakt diese Funktionen unter anderem Namen &#x27f9; Fehler im Test-Setup reproduzierbar">
<node BACKGROUND_COLOR="#e1c197" COLOR="#690f14" CREATED="1733976996794" ID="ID_1396891623" MODIFIED="1734020085624">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
exakt diese Funktionen unter anderem Namen
</p>
<p>
&#160;&#10233; Fehler im Test-Setup reproduzierbar
</p>
</body>
</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"/>
@ -88329,8 +88336,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
durch decltype(auto) ersetzt &#10233; compiliert und <b>unser Overload</b>&#160;wird genommen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#7c13ac" CREATED="1733977636822" ID="ID_1077880173" MODIFIED="1734014031096" TEXT="die std::get-Implementierung ist problematisch">
@ -88353,14 +88359,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
Ich verwende ja einen <i>uralten Compiler</i>&#160;und eine OS-Version, die schon am Ende der Lebensdauer ist; gut m&#246;glich, da&#223; dieses Problem anderswo l&#228;ngst erkannt und behoben wurde &#8212; es w&#252;rde ja bereits gen&#252;gen, die assertion erst im Body der Funktion zu haben, denn dann k&#246;nnte die Overload-Resolution arbeiten und daran vorbeikommen. Andererseits ist die Assertion grunds&#228;tzlich in Ordnung, denn <i>falls es hier keine custom-Version g&#228;be</i>, w&#228;re der Aufruf ja tats&#228;chlich gef&#228;hrlich und m&#252;&#223;te verhindert werden
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1734014085401" ID="ID_1101168757" MODIFIED="1734014196485">
<node BACKGROUND_COLOR="#dac5b1" CREATED="1734014085401" HGAP="5" ID="ID_1101168757" MODIFIED="1734020399036" STYLE="bubble" VSHIFT="5">
<richcontent TYPE="NODE"><html>
<head/>
<body>
@ -88376,8 +88381,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
unser Overload ist in Ordnung, wird vom Compiler gew&#228;hlt und funktioniert fehlerfrei.... wenn da nur nicht die Implementierung von std::get w&#228;re, welche bereits bei der Instantiierung mit konkreten Parametern eine Assertion triggert und damit die Compilierung stoppt.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<edge COLOR="#9a4c4c"/>
</node>
</node>
</node>
@ -88387,23 +88392,50 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1734014236281" ID="ID_1176641246" MODIFIED="1734014246708" TEXT="unsere custom-Implementierung ist in Ordnung"/>
<node CREATED="1734014247626" ID="ID_456472930" MODIFIED="1734014267450" TEXT="aber wegen der Implementierung von std::get haben wir praktisch keine Chance"/>
<node CREATED="1734014280187" ID="ID_1101163116" MODIFIED="1734014286536" TEXT="man kann das Problem nur umgehen">
<node CREATED="1734014287759" ID="ID_1313304599" MODIFIED="1734014318718" TEXT="auf die Vererbung verzichten &#xd83e;&#xdc32; anderweitig sehr problematisch"/>
<node CREATED="1734014322719" ID="ID_916809252" MODIFIED="1734014356341" TEXT="mit einer freien get-Funktion im Namespace arbeiten"/>
<node COLOR="#731a95" CREATED="1734014287759" ID="ID_1313304599" MODIFIED="1734016992436" TEXT="auf die Vererbung verzichten &#xd83e;&#xdc32; anderweitig sehr problematisch">
<arrowlink COLOR="#bf1358" DESTINATION="ID_715175218" ENDARROW="Default" ENDINCLINATION="-419;23;" ID="Arrow_ID_849929100" STARTARROW="None" STARTINCLINATION="222;-63;"/>
<icon BUILTIN="stop-sign"/>
</node>
<node COLOR="#5b280f" CREATED="1734014322719" ID="ID_916809252" MODIFIED="1734016976604" TEXT="mit einer freien get-Funktion im Namespace arbeiten">
<icon BUILTIN="button_cancel"/>
<node CREATED="1734016996841" HGAP="32" ID="ID_652034195" MODIFIED="1734017012465" TEXT="l&#xf6;st das Problem gar nicht"/>
<node CREATED="1734017016107" ID="ID_1335862574" MODIFIED="1734017054201" TEXT="die std::tuple-Basisklasse zieht std::get per ADL in das Kandidaten-Set &#x27f9; &#xd83d;&#xddf1;"/>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#294354" CREATED="1734017066519" ID="ID_195019328" MODIFIED="1734019995115" TEXT="nur mit der HeteroData.get&lt;i&gt; arbeiten">
<icon BUILTIN="idea"/>
<node COLOR="#338800" CREATED="1734017089284" ID="ID_826898743" MODIFIED="1734017112640">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
damit funktionieren die <b>structured bindings</b>
</p>
</body>
</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">
<arrowlink COLOR="#608fc7" DESTINATION="ID_141049889" ENDARROW="Default" ENDINCLINATION="-1267;70;" ID="Arrow_ID_1556834813" STARTARROW="None" STARTINCLINATION="-716;33;"/>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1734020128096" ID="ID_1997610038" MODIFIED="1734020157997" TEXT="funktioniert trotzdem &#x27f8; &#xbb;structured binding&#xab; verwendet get-Member">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733883489383" ID="ID_155186903" MODIFIED="1733883516460" TEXT="HeteroData_test">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733883525530" ID="ID_1918349528" MODIFIED="1733883530794" TEXT="verify_FrontBlock">
<icon BUILTIN="pencil"/>
<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 BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733883572964" ID="ID_1308768158" MODIFIED="1733883582117" TEXT="structural binding / Tuple-Protokoll">
<icon BUILTIN="flag-yellow"/>
</node>
<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"/>
@ -88418,9 +88450,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<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 BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733883572964" ID="ID_1694822636" MODIFIED="1733883582117" TEXT="structural binding / Tuple-Protokoll">
<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"/>
@ -142843,6 +142873,27 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<icon BUILTIN="idea"/>
</node>
<node CREATED="1733950377664" ID="ID_242038986" LINK="https://en.cppreference.com/w/cpp/utility/tuple/tuple-like" MODIFIED="1733950483299" TEXT="verwendbar f&#xfc;r alles was das &#xbb;tuple protocoll&#xab; erf&#xfc;llt"/>
<node COLOR="#435e98" CREATED="1734017209791" ID="ID_141049889" LINK="https://en.cppreference.com/w/cpp/language/structured_binding#Binding_process" MODIFIED="1734017690782" TEXT="unterst&#xfc;tzt dar&#xfc;ber hinaus aber noch weitere F&#xe4;lle">
<linktarget COLOR="#608fc7" DESTINATION="ID_141049889" ENDARROW="Default" ENDINCLINATION="-1267;70;" ID="Arrow_ID_1556834813" SOURCE="ID_1154017972" STARTARROW="None" STARTINCLINATION="-716;33;"/>
<icon BUILTIN="idea"/>
<node CREATED="1734017307143" ID="ID_533210041" MODIFIED="1734017312267" TEXT="klassische C-Arrays"/>
<node CREATED="1734017328298" ID="ID_897952923" MODIFIED="1734017340750" TEXT="das tuple-protocol">
<node CREATED="1734017366121" ID="ID_112237017" MODIFIED="1734017404574" TEXT="versucht zus&#xe4;tzlich auch get-Member "/>
<node CREATED="1734017405354" ID="ID_1219918380" MODIFIED="1734017412846" TEXT="versucht auch ADL-Lookup"/>
<node CREATED="1734017413889" ID="ID_1604370482" MODIFIED="1734017421236" TEXT="f&#xe4;llt nur zuletzt auf std::get zur&#xfc;ck"/>
</node>
<node CREATED="1734017422624" ID="ID_758396086" MODIFIED="1734017583946" TEXT="Felder in einer einfachen Struct">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
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>
</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">
<linktarget COLOR="#3362d9" DESTINATION="ID_609631801" ENDARROW="Default" ENDINCLINATION="-1197;56;" ID="Arrow_ID_145396423" SOURCE="ID_1814813251" STARTARROW="None" STARTINCLINATION="-581;47;"/>
<icon BUILTIN="info"/>