Upgrade: develop better formulation for ''and-all-generic''

...need to do this in a test context first,
since `variadic-helper` is in widespread use
This commit is contained in:
Fischlurch 2025-06-23 04:23:55 +02:00
parent 7d461adabc
commit 49e7b31511
3 changed files with 226 additions and 8 deletions

View file

@ -128,6 +128,10 @@ main (int, char**)
show<Hetero>(); show<Hetero>();
show<int>(); show<int>();
SHOW_EXPR(bool(std::is_integral_v<int>))
SHOW_EXPR(bool(std::is_integral_v<char>))
SHOW_EXPR(bool(std::is_integral_v<double>))
cout << "\n.gulp." <<endl; cout << "\n.gulp." <<endl;
return 0; return 0;
} }

View file

@ -27,12 +27,17 @@
#include "lib/meta/tuple-helper.hpp" #include "lib/meta/tuple-helper.hpp"
#include "meta/typelist-diagnostics.hpp" #include "meta/typelist-diagnostics.hpp"
#include "meta/tuple-diagnostics.hpp" #include "meta/tuple-diagnostics.hpp"
#include "lib/format-string.hpp"
#include "lib/format-cout.hpp" #include "lib/format-cout.hpp"
#include "lib/test/diagnostic-output.hpp"////////////////TODO
#include <string> #include <string>
using lib::test::showSizeof; using lib::test::showSizeof;
using util::toString; using util::toString;
using util::_Fmt;
using std::is_same_v;
using std::make_tuple;
using std::get; using std::get;
namespace lib { namespace lib {
@ -57,7 +62,88 @@ namespace test {
} // (End) test data } // (End) test data
////////////////////////////////////////OOO
template<class TTX>
class WithIdxSeq2
{
template<class FUN, size_t...idx>
static void
invoke_forEach (FUN&& fun, std::index_sequence<idx...>)
{
(fun (std::integral_constant<size_t,idx>{}), ...);
}
template<class FUN, size_t...idx>
static bool
and_forEach (FUN&& fun, std::index_sequence<idx...>)
{
return (fun (std::integral_constant<size_t,idx>{}) and ...);
}
template<class FUN, size_t...idx>
static bool
or_forEach (FUN&& fun, std::index_sequence<idx...>)
{
return (fun (std::integral_constant<size_t,idx>{}) or ...);
}
using IdxSeq = typename ElmTypes<TTX>::Idx;
public:
template<class FUN>
static void
invoke (FUN&& fun)
{
invoke_forEach (std::forward<FUN>(fun), IdxSeq{});
}
template<class FUN>
static bool
andAll (FUN&& fun)
{
return and_forEach (std::forward<FUN>(fun), IdxSeq{});
}
template<class FUN>
static bool
orAny (FUN&& fun)
{
return or_forEach (std::forward<FUN>(fun), IdxSeq{});
}
};
/**
* Invoke a function (or λ) with index numbers derived from some variadic count.
* Notably this construct can be used for compile-time iteration over a structure.
* Instances of `std::integral_constant` are passed in sequence to the functor.
* The _size_ of the index sequence is derived from the following sources
* - if the type \a TTX is _tuple-like,_ then std::tuple_size<TTX> is used
* - otherwise, if the type is a loki-style type sequence or type list,
* the number of type nodes is used
* - otherwise, as fall-back the number of template parameters is used
*/
template<class TTX, class FUN>
inline void
forEachIDX2 (FUN&& fun)
{
WithIdxSeq2<TTX>::invoke (std::forward<FUN> (fun));
}
template<class TTX, class FUN>
inline bool
andAllIDX2 (FUN&& fun)
{
return WithIdxSeq2<TTX>::andAll (std::forward<FUN> (fun));
}
template<class TTX, class FUN>
inline bool
orAnyIDX2 (FUN&& fun)
{
return WithIdxSeq2<TTX>::orAny (std::forward<FUN> (fun));
}
////////////////////////////////////////OOO
/*********************************************************************//** /*********************************************************************//**
@ -74,6 +160,7 @@ namespace test {
{ {
check_diagnostics(); check_diagnostics();
check_tuple_from_Typelist(); check_tuple_from_Typelist();
demonstrate_generic_iteration();
} }
@ -162,6 +249,66 @@ namespace test {
CHECK (sizeof(prep) == sizeof(int)+sizeof(Num<1>)+sizeof(Num<3>)+sizeof(Num<5>)); CHECK (sizeof(prep) == sizeof(int)+sizeof(Num<1>)+sizeof(Num<3>)+sizeof(Num<5>));
} }
/** @test demonstrate generic tuple iteration mechanisms
* - apply a generic lambda to each element of a tuple
* - iterate over all index numbers of a tuple (or tuple-like)
* @remark the _iteration_ happens at compile-time, i.e. the given
* lambda-template is instantiated for each type of the tuple;
* however, at runtime, each of these instantiations is invoked
* in sequence, performing the body of the λ-function, which may
* access the actual data value for each of the tuple elements.
*/
void
demonstrate_generic_iteration()
{
auto tup = make_tuple (1, 2.3, '4');
using Tup = decltype(tup);
CHECK (toString(tup) == "«tuple<int, double, char>»──(1,2.3,4)"_expect);
string dump{};
CHECK (dump == "");
// apply λ-generic to each element...
forEach (tup, [&](auto elm){ dump += "|"+toString(elm); });
CHECK (dump == "|1|2.3|4"_expect);
// apply λ-generic to each element and build new tuple from results
auto tupStr = mapEach (tup, [](auto const& elm){ return toString(elm); });
CHECK (tupStr == "«tuple<string, string, string>»──(1,2.3,4)"_expect);
_Fmt showElm{"|%d|▷%s◁"};
dump = "";
// apply λ-generic with (constexpr) index
forEachIDX2<Tup> ([&](auto idx)
{
using Idx = decltype(idx);
using Iii = std::integral_constant<size_t, idx.value>;
CHECK ((is_same_v<Idx, Iii>));
dump += showElm % uint(idx) % get<idx>(tup);
});
CHECK (dump == "|0|▷1◁|1|▷2.3◁|2|▷4◁"_expect);
// apply λ-generic and combine results
auto boolFun = [&](auto idx){ return bool(get<idx>(tup)); };
CHECK ( andAllIDX2<Tup> (boolFun));
get<0>(tup) = 0; // ◁————————————————————— demonstrate that a run-time evaluation happens
CHECK (not andAllIDX2<Tup> (boolFun));
CHECK ( orAnyIDX2<Tup> (boolFun));
// can use this mechanism also for sole compile-time computation
auto integralCheckFun = [](auto idx){ return std::is_integral_v<std::tuple_element_t<idx,Tup>>;};
CHECK (not andAllIDX2<Tup> (integralCheckFun));
CHECK ( orAnyIDX2<Tup> (integralCheckFun));
// Note however, the same can also be achieved simpler,
// using any meta-function which takes a single type argument...
CHECK (not ElmTypes<Tup>::AndAll<std::is_integral>()); // ... __and_<is_integral<int>,is_integral<double>,is_integral<char>>
CHECK ( ElmTypes<Tup>::OrAll<std::is_integral>());
}
}; };

View file

@ -166216,8 +166216,7 @@ Since then others have made contributions, see the log for the history.</font></
...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... ...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> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
</node> </node>
<node CREATED="1750527289637" ID="ID_416596147" MODIFIED="1750527297966" TEXT="sehe aber nicht, da&#xdf; die STL sowas definiert"/> <node CREATED="1750527289637" ID="ID_416596147" MODIFIED="1750527297966" TEXT="sehe aber nicht, da&#xdf; die STL sowas definiert"/>
</node> </node>
@ -166253,8 +166252,78 @@ Since then others have made contributions, see the log for the history.</font></
</html></richcontent> </html></richcontent>
</node> </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 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"> <node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1750613423187" ID="ID_1618598998" MODIFIED="1750645085262" TEXT="gef&#xe4;hrlich: erst mal als Prototyp ausarbeiten">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="yes"/>
<node CREATED="1750644668800" ID="ID_1281176074" MODIFIED="1750644964850" TEXT="es gibt nur eine Verwendung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
in der FeedManifold (spielt dort aber eine essentielle Rolle, weil nur auf diesem Weg die v&#246;llige Flexibilit&#228;t in allen Argumenten erreicht wird)
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1750644685406" ID="ID_1212918834" MODIFIED="1750645047284" TEXT="diese arbeitet auf einem std::tuple">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
ElmTypes&lt;TUP&gt;::Tup macht ein <i>variadic rebind</i>&#160;von einer Typ-Sequenz in ein std::tuple
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1750644713169" ID="ID_516674271" MODIFIED="1750644829139" TEXT="kann daher die anderen F&#xe4;lle auf ElmTypes&lt;TUP&gt; aufbauen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...das bedeutet, der Fall einer reinen Loki-Typliste f&#228;llt erst mal weg (wird ja derzeit nicht verwendet), und der sonderbare &#187;fallback&#171; &#228;ndert nun sein Veralten und w&#252;rde zu einem 1-Tupel. Daf&#252;r kann die gesamte constexpr-if-Logik wegfallen, weil ElmTypes&lt;Tup&gt; bereits eine Index-Sequenz fertig bereitstellt.
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1750644831088" ID="ID_242745821" MODIFIED="1750644856938" TEXT="in dem so umgebauten Impl-Template lassen sich die AND / OR -F&#xe4;lle dann leicht unterbringen"/>
<node COLOR="#338800" CREATED="1750644870205" ID="ID_1710911939" MODIFIED="1750644878073" TEXT="funktioniert im Test">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1750645066536" ID="ID_668574243" MODIFIED="1750645077745" TEXT="nun in der Codebasis schwenken">
<icon BUILTIN="flag-pink"/>
</node>
<node CREATED="1750645117460" ID="ID_1103267230" MODIFIED="1750645177258" TEXT="nett ... aber">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
siehe Entdeckung, die ich im Test dokumentiert habe: eine reine Compile-Time evaluation kann man zwar so machen, das w&#228;re aber <i>von hinten durch die Brust ins Auge...</i>
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="smiley-oh"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1750645178948" ID="ID_1910704680" MODIFIED="1750645270253" TEXT="es gibt n&#xe4;mlich bereits ein ElmTypes&lt;TUP&gt;::AndAll">
<icon BUILTIN="idea"/>
<node CREATED="1750645202768" ID="ID_839783730" MODIFIED="1750645212812" TEXT="das nimmt eine Metafunktion mit einem Typ-Argument"/>
<node CREATED="1750645213479" ID="ID_854944912" MODIFIED="1750645228717" TEXT="also m&#xfc;&#xdf;te man den Check f&#xfc;r das concept nur entsprechend verpacken"/>
<node CREATED="1750645229565" ID="ID_1427627425" MODIFIED="1750645242030" TEXT="das w&#xfc;rde gehen per templated typedef"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1750645244779" ID="ID_1784615021" MODIFIED="1750645258874" TEXT="wird es dadurch lesbar / klar genug?">
<icon BUILTIN="help"/>
</node>
</node> </node>
</node> </node>
<node CREATED="1750608261914" ID="ID_235249081" MODIFIED="1750608264567" TEXT="abl&#xf6;sen"> <node CREATED="1750608261914" ID="ID_235249081" MODIFIED="1750608264567" TEXT="abl&#xf6;sen">
@ -166346,8 +166415,7 @@ Since then others have made contributions, see the log for the history.</font></
</div> </div>
</div> </div>
</body> </body>
</html> </html></richcontent>
</richcontent>
<node CREATED="1750431987479" ID="ID_1874210875" MODIFIED="1750431993919" TEXT="der reine Konstruktor-Aufruf"/> <node CREATED="1750431987479" ID="ID_1874210875" MODIFIED="1750431993919" TEXT="der reine Konstruktor-Aufruf"/>
<node CREATED="1750431994699" ID="ID_36138667" MODIFIED="1750432009276" TEXT="Basisklasse mu&#xdf; public inherited sein"/> <node CREATED="1750431994699" ID="ID_36138667" MODIFIED="1750432009276" TEXT="Basisklasse mu&#xdf; public inherited sein"/>
<node CREATED="1750431861506" ID="ID_349299837" MODIFIED="1750433803907" TEXT="wird nur getriggert mit initialiser-List-Syntax"> <node CREATED="1750431861506" ID="ID_349299837" MODIFIED="1750433803907" TEXT="wird nur getriggert mit initialiser-List-Syntax">
@ -166368,8 +166436,7 @@ Since then others have made contributions, see the log for the history.</font></
vermutlich ein <i>sehr spezieller</i>&#160;Compiler-Bug vermutlich ein <i>sehr spezieller</i>&#160;Compiler-Bug
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
<icon BUILTIN="clanbomber"/> <icon BUILTIN="clanbomber"/>
</node> </node>
<node COLOR="#338800" CREATED="1750433708917" ID="ID_1697745986" MODIFIED="1750436517188" TEXT="einfacher Workaround: keine initialiser-List-Syntax verwenden"> <node COLOR="#338800" CREATED="1750433708917" ID="ID_1697745986" MODIFIED="1750436517188" TEXT="einfacher Workaround: keine initialiser-List-Syntax verwenden">