Upgrade: explore construction of a ''tuple-like'' concept

Motivated by the difficulties encountered with `std::apply` —
which basically forced us to define our own alternative with
conceptually more adequate limitations....

...so these are the first attempts towards building a C++20 concept.
This commit is contained in:
Fischlurch 2025-06-22 19:42:03 +02:00
parent de066348af
commit 7d461adabc
5 changed files with 277 additions and 130 deletions

View file

@ -1,6 +1,7 @@
/* try.cpp - to try out and experiment with new features....
* scons will create the binary bin/try
*/
// 06/25 - provide a concept to accept _tuple-like_ objects
// 06/25 - investigate function type detection of std::bind Binders
// 12/24 - investigate problem when perfect-forwarding into a binder
// 12/24 - investigate overload resolution on a templated function similar to std::get
@ -9,130 +10,123 @@
/** @file try.cpp
* Investigate ambiguities regarding the function type of standard binders.
* The Binder objects returned from `std::bind` provide a set of overloaded
* function call `operator()` (with variants for c/v). Unfortunately this defeats
* the common techniques to detect a function signature from a callable, when
* only a concrete instance of such a binder is given. Furthermore, looking
* at the definition of `class _Bind_result<_Result, _Functor(_Bound_args...)>`
* in my implementation of the C++ Stdlib, it seems we are pretty much out
* of luck, and even `std::function` fails with the template argument detection.
* A possible workaround could be to wrap the Binder object immediately into
* a lambda, but only if the actual types for the argument list can be
* provided directly to a template to generate this λ-wrapper.
* @note there is a nasty twist regarding const-correctness, which almost made
* this workaround fail altogether. The overloaded operator() from std::bind
* serves the same purpose (to deal with const/volatile), and this is the
* very reason that defeats the detection of the function signature.
* The workaround attempts to expose precisely one function call operator,
* and this becomes problematic as soon as the resulting object is processed
* further, and maybe bound into another lambda capture. Thus we define the
* wrapper class explicitly, so that any const-ness can be cast away.
* This turns out to be necessary in tuple-closure.hpp.
* Develop a concept to detect _tuple-like_ classes, based on the requirements
* of the »tuple protocol«. Using some ideas from [Stackoverflow] as starting point.
* [Stackoverflow]: https://stackoverflow.com/q/68443804/444796
*/
#include "lib/format-cout.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/test/diagnostic-output.hpp"
#include "lib/meta/function.hpp"
#include "lib/meta/variadic-rebind.hpp"
#include "lib/meta/tuple-helper.hpp"
#include "lib/hetero-data.hpp"
#include "lib/util.hpp"
#include <functional>
#include <concepts>
using std::forward;
using std::placeholders::_1;
using lib::meta::_Fun;
using std::string;
namespace lib {
namespace meta {
template<class TUP>
concept tuple_sized = requires
{
{ std::tuple_size<TUP>::value } -> std::convertible_to<size_t>;
};
void
fun (int& a)
{
std::cout << a << std::endl;
}
short
fup (long l, long long ll)
{
return short(l - ll);
}
/** WORKAROUND: wrap a binder to yield clear function signature */
template<typename...ARGS>
struct AdaptInvokable
{
template<class FUN>
static auto
buildWrapper (FUN&& fun)
{
struct Wrap
{
FUN fun_;
Wrap(FUN&& f) : fun_{forward<FUN>(f)} { }
auto
operator() (ARGS... args)
{
return fun_(forward<ARGS>(args)...);
}
};
return Wrap{forward<FUN>(fun)};
///////////////////////////////////////////////////////////// NOTE
///////////////////////////////////////////////////////////// can not use a Lambda, since we're then trapped
///////////////////////////////////////////////////////////// in an unsurmountable mixture of const and non-const
// return [functor = forward<FUN>(fun)]
// (ARGS... args) mutable
// {
// return functor (forward<ARGS> (args)...);
// };
}
};
template<class TYPES, class FUN>
auto
buildInvokableWrapper (FUN&& fun)
{
using ArgTypes = typename TYPES::Seq;
using Builder = typename lib::meta::RebindVariadic<AdaptInvokable, ArgTypes>::Type;
template<class TUP, std::size_t N>
concept tuple_adl_accessible = requires(TUP tup)
{
typename std::tuple_element_t<N, TUP>;
{ get<N>(tup) } -> std::convertible_to<std::tuple_element_t<N, TUP>&>;
};
return Builder::buildWrapper (forward<FUN> (fun));
template<class TUP, std::size_t N>
concept tuple_mem_accessible = requires(TUP tup)
{
typename std::tuple_element_t<N, TUP>;
{ tup.template get<N>() } -> std::convertible_to<std::tuple_element_t<N, TUP>&>;
};
template<class TUP, std::size_t N>
concept tuple_accessible = tuple_mem_accessible<TUP,N> or tuple_adl_accessible<TUP,N>;
template<class TUP>
class AndAll
{
template<size_t...idx>
static constexpr bool
canAccessAll (std::index_sequence<idx...>)
{
return (tuple_accessible<TUP, idx> and ...);
}
using IdxSeq = typename ElmTypes<TUP>::Idx;
public:
static constexpr bool can_AccessElement = canAccessAll(IdxSeq{});
};
template<class TUP>
concept tuple_like = not is_reference_v<TUP>
and tuple_sized<remove_cv_t<TUP>>
and AndAll<remove_cv_t<TUP>>::can_AccessElement;
}}//namespace lib::meta
template<typename X>
void
show()
{
SHOW_TYPE(X)
}
template<lib::meta::tuple_like X>
void
show()
{
cout << "Tup!! "<< lib::test::showType<X>() <<endl;
lib::meta::forEachIDX<X> ([](auto i)
{
using Elm = std::tuple_element_t<i, X>;
cout <<" "<<uint(i)<<": "<< lib::test::showType<Elm>() <<endl;
});
}
int
main (int, char**)
{
SHOW_EXPR (fup(2,3))
auto bup = std::bind (fup, _1, 5);
SHOW_EXPR (bup)
using Bup = decltype(bup);
using Fub = _Fun<Bup>;
SHOW_TYPE (Bup)
SHOW_TYPE (Fub)
// using Sub = Fub::Sig; ////////////////Problem: does not compile
using Tup = std::tuple<long>;
using Arr = std::array<int,3>;
using Hetero = lib::HeteroData<int,string>::Chain<short>::ChainExtent<bool,lib::meta::Nil>::ChainType;
using Fut = decltype(fun);
SHOW_TYPE (_Fun<Fut>::Sig)
SHOW_EXPR((lib::meta::tuple_sized<Tup> ))
SHOW_EXPR((lib::meta::tuple_sized<Arr> ))
SHOW_EXPR((lib::meta::tuple_sized<Hetero> ))
SHOW_EXPR((lib::meta::tuple_sized<int> ))
auto wup = buildInvokableWrapper<lib::meta::Types<int>>(bup);
SHOW_EXPR((lib::meta::tuple_accessible<Tup,0>))
// SHOW_EXPR((lib::meta::tuple_accessible<Tup,2>))
SHOW_EXPR((lib::meta::tuple_accessible<Hetero,0>))
SHOW_EXPR((lib::meta::AndAll<Tup>::can_AccessElement))
SHOW_EXPR((lib::meta::AndAll<Hetero>::can_AccessElement))
using Wup = decltype(wup);
using WupSig = _Fun<Wup>::Sig;
SHOW_TYPE (WupSig);
SHOW_EXPR (wup(3))
SHOW_EXPR (sizeof(bup))
SHOW_EXPR (sizeof(wup))
SHOW_EXPR((lib::meta::tuple_like<Tup> ))
SHOW_EXPR((lib::meta::tuple_like<Arr> ))
SHOW_EXPR((lib::meta::tuple_like<Hetero> ))
SHOW_EXPR((lib::meta::tuple_like<int> ))
auto waua = buildInvokableWrapper<lib::meta::Types<>> (std::bind (fun, 55));
waua ();
SHOW_TYPE (_Fun<decltype(waua)>::Sig)
show<Tup>();
show<Arr>();
show<Hetero>();
show<int>();
cout << "\n.gulp." <<endl;
return 0;

View file

@ -201,9 +201,9 @@ namespace lib {
template<size_t slot>
Elm_t<slot> const&
get() const noexcept
{
return const_cast<HeteroData*>(this)->get<slot>();
}
{
return const_cast<HeteroData*>(this)->get<slot>();
}
/**

View file

@ -24,7 +24,7 @@
** So what is provided here is _not a parser library_ yet aims at »making
** simple things simple« and let you implement the complicated ones yourselves.
** Several decisions were taken accordingly, like only supporting std::string_view
** and automatically consuming any leading whitespace. And notably the focus was
** and to consume any leading whitespace automatically. And notably the focus was
** _not placed_ on the challenging aspects of parsing while still allowing a
** pathway towards definition of arbitrarily recursive grammars, if so desired.
**
@ -40,7 +40,7 @@
** the C++ matcher object as result and thus essentially some pointers into
** the original sequence, which has to be passed in as C++ string_view.
**
** An essential concept of this parsing support framework is that each parser
** An essential feature of this parsing support framework is that each parser
** can be decorated by a _model transformation functor,_ which gets the result
** of the wrapped parser and can return _any arbitrary value object._ In essence,
** this framework does not provide the notion of an _abstract syntax tree_ yet
@ -57,7 +57,7 @@
** - `accept_opt` builds a clause to optionally accept in accordance
** to the given definition; if no match is found, parsing backtracks.
** - `accept_repeated` builds a clause to accept a repetition of the
** structure accepted by its argument, optionally with an explicit delimiter
** structure accepted by its argument, optionally with an explicit separator
** and possibly with a limited number of instances. The result values are
** obviously all from the same type and will be collected into a IterModel,
** which essentially is a std::vector<RES> (note: heap storage!).
@ -68,24 +68,26 @@
** described by the SPEC _after_ the structure already described by the syntax.
** Both parts must succeed for the parse to be successful. The result value
** is packaged into a parse::SeqModel, which essentially is a tuple; when
** attaching several .seq() specifications, it can become a N-ary tuple.
** attaching several .seq() specifications, it is extended to a N-ary tuple.
** - `<syntax>.alt(SPEC)` adds an _alternative branch_ to the existing syntax.
** Either part alone is sufficient for a successful parse. First the existing
** branch(es) are tried, and only if those do not succeed, backtracking is
** performed and then the alternative branch is tried. Once some match is
** found, further branches will _not be attempted._ (short-circuit).
** Thus there is _always one_ result model, is placed into an AltModel,
** Thus there is _always one_ result model, placed into an AltModel,
** which is a _variant data type_ with a common inline result buffer.
** The _selector field_ must be checked to find out which branch of the
** syntax succeeded, and then the result must be handled with its appropriate
** type, because the various branches can possibly yield entirely different
** result value types.
** - `<syntax>.repeat()` _sequentially adds_ a repeated clause be accepted
** _after_ what the existing syntax accepts. The result is thus a SeqModel.
** - `<syntax>.repeat()` _sequentially adds_ a repeated clause to be accepted
** _after_ what the existing syntax accepts. The result is thus a SeqModel,
** with the result-model from the repetition in the last tuple element;
** the repetition itself yields an IterModel.
** - `<syntax>.bracket()` _sequentially adds_ a bracketing clause to be
** accepted _after_ parsing with the existing syntax. Again, the result
** is a SeqModel, with the result-model from the repetition in the last
** tuple element. The repetition itself yields an IterModel.
** is a SeqModel, with the result-model from the bracket contents
** packaged into the last tuple element.
** - `<syntax>.bind(FUN)` is a postfix-operator and decorates the existing
** syntax with a result-binding functor `FUN`: The syntax's result value
** is passed into this functor and whatever this functor returns will
@ -99,8 +101,8 @@
** A _recursive syntax definition_ is what unleashes the parsing technique's
** full strength; but recursive grammars can be challenging to master at times
** and may in fact lead to deadlock due to unlimited recursion. Since this
** framework is focused on ease of use in simple situations, recursion is
** considered an advanced usage and thus supported in a way that requires
** framework is focused on ease of use for the simple situations, recursion
** is considered an advanced usage and thus supported in a way that requires
** some preparation and help by the user. In essence...
** - a syntax clause to be referred recursively _must be pre-declared_
** - this pre-declaration gives it a known, fixed result type and will

View file

@ -187,19 +187,19 @@ namespace test{
using Front = lib::HeteroData<uint,double>;
using Cons2 = Front::Chain<bool,string>;
using Data2 = Cons2::NewFrame;
using List2 = Cons2::ChainType;
using HeDa2 = 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 HeDa3 = Cons3::ChainType;
using Acc5 = Cons3::AccessorFor<CStr>;
using Acc6 = Cons3::AccessorFor<string>;
CHECK (2 == Front::size());
CHECK (4 == List2::size());
CHECK (6 == List3::size());
CHECK (4 == HeDa2::size());
CHECK (6 == HeDa3::size());
//
// Note: up to now, not a single actual data element has been created
// Moreover, individual blocks can be created in any order...
@ -278,7 +278,7 @@ namespace test{
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);
HeDa3& 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)));
@ -290,7 +290,7 @@ namespace test{
CHECK (isSameAdr (fullChain.get<4>(), v5));
CHECK (isSameAdr (fullChain.get<5>(), v6));
// we can even use partially specified chains
List2& partChain = Cons2::recast(fullChain);
HeDa2& partChain = Cons2::recast(fullChain);
CHECK (isSameAdr (partChain.get<0>(), v1));
CHECK (isSameAdr (partChain.get<1>(), v2));
CHECK (isSameAdr (partChain.get<2>(), v3));

View file

@ -91601,7 +91601,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1733946409913" FOLDED="true" ID="ID_766490392" MODIFIED="1734041937846" TEXT="C++ &#xbb;Tuple-Protocol&#xab;">
<node COLOR="#338800" CREATED="1733946409913" FOLDED="true" ID="ID_766490392" MODIFIED="1750556525752" 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">
@ -91643,7 +91643,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</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">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1733946713943" FOLDED="true" ID="ID_1873953043" MODIFIED="1750556525770" TEXT="funktioniert nicht .... Compiler nimmt Overload f&#xfc;r std::tuple">
<icon BUILTIN="broken-line"/>
<node COLOR="#5b280f" CREATED="1733946765784" ID="ID_1087783493" MODIFIED="1734020236696" TEXT="das bekannte Problem mit Funktion Overloads??">
<icon BUILTIN="button_cancel"/>
@ -91783,6 +91783,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1750605910739" ID="ID_734827065" MODIFIED="1750605957925" TEXT="Problem besteht weiterhin mit GCC-14 (2025)">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
</node>
</node>
@ -156835,6 +156838,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<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;"/>
<linktarget COLOR="#4989d4" DESTINATION="ID_141049889" ENDARROW="Default" ENDINCLINATION="-494;29;" ID="Arrow_ID_789791822" SOURCE="ID_1129626446" STARTARROW="None" STARTINCLINATION="-1100;-64;"/>
<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">
@ -157075,6 +157079,24 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<node CREATED="1617648902994" ID="ID_276316646" MODIFIED="1617648906362" TEXT="C++20">
<node CREATED="1749407118772" ID="ID_1741477135" MODIFIED="1750347983055" TEXT="C++20 kennenlernen">
<linktarget COLOR="#5b78d0" DESTINATION="ID_1741477135" ENDARROW="Default" ENDINCLINATION="-1445;183;" ID="Arrow_ID_120232332" SOURCE="ID_160865224" STARTARROW="None" STARTINCLINATION="714;86;"/>
<node CREATED="1750442180561" ID="ID_1483771731" MODIFIED="1750442186844" TEXT="Tooling / Eclipse">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1750442188215" ID="ID_26311727" MODIFIED="1750442206176" TEXT="der klassische Editor unterst&#xfc;tzt kein C++20">
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1750442208883" ID="ID_639319394" MODIFIED="1750443928132" TEXT="ein neue LSP-basierter Editor ist eingebunden (unfertig)">
<icon BUILTIN="idea"/>
<node CREATED="1750442236141" ID="ID_1373598733" MODIFIED="1750442259870">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
dazu im OS: <font face="Monospaced"><b>clangd</b></font>&#160;installieren
</p>
</body>
</html></richcontent>
</node>
</node>
</node>
<node CREATED="1749407144792" ID="ID_1869633875" MODIFIED="1749407148565" TEXT="Richtlinien">
<node CREATED="1749407149503" ID="ID_824791307" LINK="https://quuxplusone.github.io/blog/2021/04/03/static-constexpr-whittling-knife/" MODIFIED="1749407166664" TEXT="Reihenfolge der Deklarations-Qualifier">
<node CREATED="1749407219192" ID="ID_1604663290" MODIFIED="1749407248162" TEXT="attributes-friendness-storage-constness-virtualness-explicitness-signedness-length-type id">
@ -166104,8 +166126,141 @@ Since then others have made contributions, see the log for the history.</font></
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1750173439337" ID="ID_1832825819" MODIFIED="1750173477173" TEXT="Schritt-2 : concept tuple_like einf&#xfc;hren">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1750173439337" ID="ID_1832825819" MODIFIED="1750437317253" TEXT="Schritt-2 : concept tuple_like einf&#xfc;hren">
<icon BUILTIN="full-2"/>
<node CREATED="1750603208092" ID="ID_1027099855" MODIFIED="1750603215948" TEXT="Design-Fragen">
<node BACKGROUND_COLOR="#d2a99c" COLOR="#683b31" CREATED="1750603078830" ID="ID_1129626446" MODIFIED="1750606092989" TEXT="Basis f&#xfc;r Concept tuple_like ?">
<arrowlink COLOR="#4989d4" DESTINATION="ID_141049889" ENDARROW="Default" ENDINCLINATION="-494;29;" ID="Arrow_ID_789791822" STARTARROW="None" STARTINCLINATION="-1100;-64;"/>
<icon BUILTIN="help"/>
<node CREATED="1750603270220" ID="ID_1796957923" MODIFIED="1750603293611" TEXT="minimal-Heuristik : tuple_size"/>
<node CREATED="1750603306121" ID="ID_1429160230" MODIFIED="1750603318670" TEXT="hinreichend vollst&#xe4;ndig: Zugriff"/>
<node CREATED="1750603344042" ID="ID_1866646887" MODIFIED="1750603365810" TEXT="Zweck: Datenzugriff">
<node CREATED="1750603367100" ID="ID_730035620" MODIFIED="1750603395784" TEXT="per structured Binding"/>
<node CREATED="1750603384299" ID="ID_1020038748" MODIFIED="1750603392055" TEXT="per meta-Iteratrion"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1750603402218" ID="ID_470643972" MODIFIED="1750606109292" TEXT="Hindernisse">
<icon BUILTIN="clanbomber"/>
<node CREATED="1750603406649" ID="ID_722727058" MODIFIED="1750604154381" TEXT="die Element-Typen sind heterogen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
das limitiert die Nutzbarkeit ohnehin sehr stark, da man mit <i>unlimitiert generischen</i>&#160;Typen wenig Gemeinsames anfangen kann
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1750604156028" ID="ID_1521006525" MODIFIED="1750604169583" TEXT="structued Bindings sind f&#xfc;r den konkreten Einhzelfall gedacht"/>
<node CREATED="1750604220710" ID="ID_440079383" MODIFIED="1750604274377" TEXT="structured Bindings und das Tupel-Protokoll sind zweierlei"/>
<node CREATED="1750604614495" ID="ID_1340240394" MODIFIED="1750606165686" TEXT="es ist unklar wohin das &#xfc;berhaupt f&#xfc;hrt">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...auch der Standard gibt keine klaren Ziele an &#8212; vermutlich deshalb auch diese Diskrepanz, da&#223; &#187;tuple-like&#171; nun doch nur f&#252;r bestimmte STL-Klassen gelten soll; f&#252;r diese engere Auswahl synthetisiert der Compiler nun (C++20) auch Vergleichsoperatoren. Aber dar&#252;ber hinaus? es bleibt eine Art Parameter-Satz oder generischer Datensatz, mit dem man letztlich wenig anfangen kann ohne zus&#228;tzliche Anhaltspunkte (Referenzen, Kopierbarkeit, semantisches...)
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#845a67" DESTINATION="ID_326674613" ENDARROW="Default" ENDINCLINATION="21;-52;" ID="Arrow_ID_1130948047" STARTARROW="None" STARTINCLINATION="-77;5;"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1750606050049" ID="ID_326674613" MODIFIED="1750606165686" TEXT="als Experiment / Erweiterung betrachten">
<linktarget COLOR="#845a67" DESTINATION="ID_326674613" ENDARROW="Default" ENDINCLINATION="21;-52;" ID="Arrow_ID_1130948047" SOURCE="ID_1340240394" STARTARROW="None" STARTINCLINATION="-77;5;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
<node CREATED="1750606352138" ID="ID_395333940" MODIFIED="1750606364459" TEXT="m&#xf6;glichst neben die bestehenden Strukturen bauen"/>
<node CREATED="1750606379162" ID="ID_1298795914" MODIFIED="1750606392271" TEXT="beobachten was auf dieser Basis entsteht"/>
<node CREATED="1750606452227" ID="ID_1156552141" MODIFIED="1750606760885" TEXT="an structured Bindings anlehnen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
aber nur auf den einen Fall, der <i>allgemeine Typen</i>&#160;betrifft...
</p>
<p>
d.h. wir unterst&#252;tzen auch eine Memberfunktion get&lt;i&gt;()
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1750606686156" ID="ID_900094987" MODIFIED="1750606706321" TEXT="get()-Adapter bereitstellen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
mit duck-typing
</p>
</body>
</html></richcontent>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1750443947483" ID="ID_58139169" MODIFIED="1750443961178" TEXT="schrittweise...">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1750443954960" ID="ID_750458131" MODIFIED="1750443959664" TEXT="has_tuple_size">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1750527186585" ID="ID_1525384931" MODIFIED="1750608058172" TEXT="Zugriff auf tuple_element_t">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1750527194686" ID="ID_505645521" MODIFIED="1750607802335" TEXT="Problem: CV-Varianten">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1750527215075" ID="ID_160799608" MODIFIED="1750527224453" TEXT="werden in der STL unterst&#xfc;tzt"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#940109" CREATED="1750527225378" ID="ID_934892679" MODIFIED="1750607814794" TEXT="typischerweise nicht f&#xfc;r custom-Typen?">
<icon BUILTIN="help"/>
<node CREATED="1750527281789" ID="ID_270337751" MODIFIED="1750608012143" TEXT="eigentlich k&#xf6;nnte das generisch sein">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...wenn man selber Typen f&#252;r das &#187;tuple-protocol&#171; einrichtet, hat man i.d.R nicht die Zeit, sich um alle CV-Varianten + RValues zu k&#252;mmern (es gibt ja einen konkreten Use-case); allerdings spielen die CV-Varianten nur f&#252;r eine get&lt;i&gt;()-Funktion tats&#228;chlich eine Rolle, denn dort mu&#223; sich diese Variante auf den Ergebnistyp auswirken; man k&#246;nnte diese Varianten komplett genersich per Library-Funktion aus einer Basis-Impl ableiten...
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1750527289637" ID="ID_416596147" MODIFIED="1750527297966" TEXT="sehe aber nicht, da&#xdf; die STL sowas definiert"/>
</node>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1750527261050" ID="ID_11850475" MODIFIED="1750527277291" TEXT="sollte auf das Minimal-Kriterium beschr&#xe4;nken">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1750608204631" ID="ID_228997425" MODIFIED="1750608220478" STYLE="fork" TEXT="get()-Adapter entwerfen">
<icon BUILTIN="pencil"/>
</node>
<node COLOR="#338800" CREATED="1750608171148" ID="ID_645315221" MODIFIED="1750608181337" TEXT="experimental-Test funktioniert">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1750608083733" ID="ID_801317220" MODIFIED="1750608187648" TEXT="Schritt-3 : bestehende Heuristiken ersetzen">
<icon BUILTIN="full-3"/>
<node CREATED="1750608225207" ID="ID_1091625286" MODIFIED="1750608242780" TEXT="auf tuple-helper.hpp konzentrieren">
<node CREATED="1750608253290" ID="ID_1066975990" MODIFIED="1750608258692" TEXT="bestehendes is_Structured f&#xe4;llt weg"/>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1750613310659" ID="ID_1955387309" MODIFIED="1750613325702" TEXT="kann man forEachIDX erweitern auf AndAll ?">
<icon BUILTIN="help"/>
<node CREATED="1750613329800" ID="ID_737752412" MODIFIED="1750613379696" TEXT="es st&#xf6;rt mich, wenn ich jetzt den Namen AndAll verwende">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
und doch nur einen fest verdrahteten Spezialfall definiere, blo&#223; weil's jetzt grade convenient ernscheint
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1750613385497" ID="ID_1466450048" MODIFIED="1750613415281" TEXT="k&#xf6;nnte gehen &#x27f9; dazu die Arit&#xe4;ts-Erkennung in das Impl-Template"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1750613423187" ID="ID_1618598998" MODIFIED="1750613435979" TEXT="gef&#xe4;hrlich: erst mal als Prototyp ausarbeiten">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node CREATED="1750608261914" ID="ID_235249081" MODIFIED="1750608264567" TEXT="abl&#xf6;sen">
<node CREATED="1750608267425" ID="ID_1368025835" MODIFIED="1750608268258" TEXT="is_Structured"/>
<node CREATED="1750608320496" ID="ID_575832691" MODIFIED="1750608321852" TEXT="enable_if_TupleProtocol"/>
</node>
</node>
</node>
</node>
@ -166122,9 +166277,7 @@ Since then others have made contributions, see the log for the history.</font></
<icon BUILTIN="yes"/>
<node CREATED="1750431808678" ID="ID_1965718984" MODIFIED="1750433611399" TEXT="reproduzierbar auf Minimum reduziert">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<div style="background-color: #eee0b5; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 2px">
<div style="color: #202020; background-color: #eee0b5; font-family: Bitstream Vera Sans Mono; font-size: 9pt; white-space: pre">
@ -166209,9 +166362,7 @@ Since then others have made contributions, see the log for the history.</font></
</node>
<node CREATED="1750433674672" ID="ID_1918452895" MODIFIED="1750436510834">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
vermutlich ein <i>sehr spezieller</i>&#160;Compiler-Bug