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:
parent
7d461adabc
commit
49e7b31511
3 changed files with 226 additions and 8 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -166216,8 +166216,7 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
...wenn man selber Typen für das »tuple-protocol« einrichtet, hat man i.d.R nicht die Zeit, sich um alle CV-Varianten + RValues zu kümmern (es gibt ja einen konkreten Use-case); allerdings spielen die CV-Varianten nur für eine get<i>()-Funktion tatsächlich eine Rolle, denn dort muß sich diese Variante auf den Ergebnistyp auswirken; man könnte diese Varianten komplett genersich per Library-Funktion aus einer Basis-Impl ableiten...
|
...wenn man selber Typen für das »tuple-protocol« einrichtet, hat man i.d.R nicht die Zeit, sich um alle CV-Varianten + RValues zu kümmern (es gibt ja einen konkreten Use-case); allerdings spielen die CV-Varianten nur für eine get<i>()-Funktion tatsächlich eine Rolle, denn dort muß sich diese Variante auf den Ergebnistyp auswirken; man kö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ß die STL sowas definiert"/>
|
<node CREATED="1750527289637" ID="ID_416596147" MODIFIED="1750527297966" TEXT="sehe aber nicht, daß 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önnte gehen ⟹ dazu die Aritäts-Erkennung in das Impl-Template"/>
|
<node CREATED="1750613385497" ID="ID_1466450048" MODIFIED="1750613415281" TEXT="könnte gehen ⟹ dazu die Aritäts-Erkennung in das Impl-Template"/>
|
||||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1750613423187" ID="ID_1618598998" MODIFIED="1750613435979" TEXT="gefährlich: erst mal als Prototyp ausarbeiten">
|
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1750613423187" ID="ID_1618598998" MODIFIED="1750645085262" TEXT="gefä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öllige Flexibilitä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<TUP>::Tup macht ein <i>variadic rebind</i> 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älle auf ElmTypes<TUP> aufbauen">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
...das bedeutet, der Fall einer reinen Loki-Typliste fällt erst mal weg (wird ja derzeit nicht verwendet), und der sonderbare »fallback« ändert nun sein Veralten und würde zu einem 1-Tupel. Dafür kann die gesamte constexpr-if-Logik wegfallen, weil ElmTypes<Tup> 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ä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ä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ämlich bereits ein ElmTypes<TUP>::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üßte man den Check für das concept nur entsprechend verpacken"/>
|
||||||
|
<node CREATED="1750645229565" ID="ID_1427627425" MODIFIED="1750645242030" TEXT="das wü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ösen">
|
<node CREATED="1750608261914" ID="ID_235249081" MODIFIED="1750608264567" TEXT="ablö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ß public inherited sein"/>
|
<node CREATED="1750431994699" ID="ID_36138667" MODIFIED="1750432009276" TEXT="Basisklasse muß 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> Compiler-Bug
|
vermutlich ein <i>sehr spezieller</i> 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">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue