From 47b57da6461c80e8cc48cb09b465ea2a8dd8ee06 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 2 Jun 2025 23:55:08 +0200 Subject: [PATCH] clean-up: validate the typelist manipulations As expected, these work on the new-style variadic type sequences equally well than on the old ones (tail-filled with `Nil` markers). On that occasion, a complete makeover of the huge test case was carried out, now relying on `ExpectString` instead of printing to STDOUT. This has the benefit of showing the expectation immediately next to the code to be tested, and thus makes it much easier to ''actually see'' how these meta-functions operate on their parameters (which in fact are types in a type list) --- src/lib/meta/typelist-manip.hpp | 222 +++++----- src/lib/meta/typeseq-util.hpp | 8 +- src/steam/control/command-signature.hpp | 6 +- tests/12metaprogramming.tests | 127 ------ tests/library/meta/tuple-diagnostics.hpp | 2 +- tests/library/meta/typelist-diagnostics.hpp | 49 ++- tests/library/meta/typelist-manip-test.cpp | 426 ++++++++++++-------- wiki/thinkPad.ichthyo.mm | 43 +- 8 files changed, 439 insertions(+), 444 deletions(-) diff --git a/src/lib/meta/typelist-manip.hpp b/src/lib/meta/typelist-manip.hpp index 52de4b86d..a61af8845 100644 --- a/src/lib/meta/typelist-manip.hpp +++ b/src/lib/meta/typelist-manip.hpp @@ -18,19 +18,26 @@ ** implementations by combining some basic building blocks. Typically, there ** is a number of similar, but not suitably related types involved. We want to ** process those types using a common scheme, without being forced to squeeze - ** all those types into a artificial inheritance relationship. Now, generating + ** all those types into a artificial inheritance relationship. Instead, generating ** some kind of common factory or adapter, while mixing in pieces of code tailored ** specifically to the individual types, allows still to build a common processing ** in such situations. ** ** The facilities in this header provide the basics of simple functional list ** processing (mostly with tail recursion). Usually, there is one template parameter - ** TYPES, which accepts a \em Type-list. The result of the processing step is then - ** accessible as an embedded typedef named \c List . Here, all of the 'processing' - ** to calculate this result is performed by the compiler, as a side-effect of - ** figuring out the resulting concrete type. At run time, in the generated - ** code, typically the resulting classes are empty, maybe just - ** exposing a specifically built-up function. + ** TYPES, which accepts a _type-list_. The result of the processing step is then + ** accessible as nested type definition named `List`. Here, all of the „processing“ + ** to calculate this result is performed by the compiler, as a side-effect set + ** off by the need to compute a requested concrete result type. At run time, + ** in the generated code, typically the resulting classes are empty, maybe + ** just exposing a function outfitted for a specific purpose. + ** + ** @remark historically, these functions were developed for the first draft of + ** the render engine, which (for other reasons) did not come to fruition. + ** Over time, some of these functions were used on and off for various + ** purposes; and since (as of 2025) Loki-style type lists are considered + ** an integral part of the Lumiera framework, useful meta-functions are + ** added and documented here, even when not currently in use. ** ** @see generator.hpp ** @see typelist-manip-test.cpp @@ -57,17 +64,17 @@ namespace meta { template struct Pick { - typedef Nil Type; + using Type = Nil; }; template struct Pick, 0> { - typedef TY Type; + using Type = TY; }; template struct Pick, i> { - typedef typename Pick::Type Type; + using Type = typename Pick::Type; }; @@ -75,121 +82,124 @@ namespace meta { /** apply a transformation (template) to each type in the list */ template class _TRANS_> - struct Apply { typedef TY List; }; + struct Apply { using List = TY; }; template< class TY, class TYPES , template class _TRANS_ > - struct Apply, _TRANS_ > { typedef Node< typename _TRANS_::Type - , typename Apply::List - > List; }; + struct Apply, _TRANS_ > { using List = Node< typename _TRANS_::Type + , typename Apply::List + >;}; /** conditional node: skip an element based on evaluating a predicate */ template - struct CondNode { typedef TAIL Next; }; + struct CondNode { using Next = TAIL; }; template - struct CondNode { typedef Node Next; }; + struct CondNode { using Next = Node; }; /** filter away those types which don't fulfil a predicate metafunction */ - template< class TYPES + template< class TYPES , template class _P_ ///< a template providing a boolean member \c ::value > struct Filter; template class _P_> - struct Filter { typedef Nil List; }; + struct Filter { using List = Nil; }; template< class TY, class TYPES , template class _P_ > - struct Filter,_P_> { typedef typename CondNode< _P_::value - , TY - , typename Filter::List - >::Next - List; }; + struct Filter,_P_> { using List = typename CondNode< _P_::value + , TY + , typename Filter::List + >::Next + ; }; - /** append lists-of-types */ + /** append (concatenate) lists-of-types */ template - struct Append { typedef Node::List> List; }; + struct Append { using List = Node::List>; }; template< class TY, class TYPES , class TAIL > - struct Append, TAIL> { typedef Node::List> List; }; + struct Append, TAIL> { using List = Node::List>; }; template - struct Append> { typedef Node List; }; + struct Append> { using List = Node; }; template - struct Append, Nil> { typedef Node List; }; + struct Append, Nil> { using List = Node; }; template - struct Append { typedef Node List; }; + struct Append { using List = Node; }; template - struct Append { typedef Node List; }; + struct Append { using List = Node; }; template<> - struct Append { typedef Nil List; }; + struct Append { using List = Nil; }; /** access the last list element */ template - struct SplitLast; + struct PickLast; template<> - struct SplitLast { typedef Nil Type; - typedef Nil List; }; + struct PickLast { using Type = Nil; + using List = Nil; }; template - struct SplitLast> { typedef TY Type; - typedef Nil List; }; + struct PickLast> { using Type = TY; + using List = Nil; }; template - struct SplitLast> { typedef typename SplitLast::Type Type; - typedef typename Append< TY, - typename SplitLast::List - >::List - List; }; + struct PickLast> { using Type = typename PickLast::Type; + using List = typename Append< TY + , typename PickLast::List + >::List + ; }; - /** - * splice a typelist like an overlay - * into an base typelist, starting at given index. + /** + * splice some typelist like an overlay + * into a base typelist, starting at given index. * @return either the combined (spliced) List, or * the Front/Back part before or after the Overlay - * @note using a Nil as OVERLAY allows to extract + * @remark can be used to _exchange_ some elements in a list, + * without shifting the position of the other ones. + * @note using a Nil-type as OVERLAY allows to extract * an arbitrary Front/Back part of the list */ template struct Splice; template - struct Splice, OVERLAY, i> { typedef Node::List> List; - typedef Node::Front> Front; - typedef typename Splice::Back Back; }; + class OVERLAY, + uint i> + struct Splice, OVERLAY, i> { using List = Node::List>; + using Front = Node::Front>; + using Back = typename Splice::Back; }; template - struct Splice,Node,0> { typedef Node::List> List; - typedef Nil Front; - typedef typename Splice::Back Back; }; + struct Splice,Node,0> { using List = Node::List>; + using Front = Nil; + using Back = typename Splice::Back; }; template - struct Splice, Nil, 0> { typedef Node List; - typedef Nil Front; - typedef Node Back; }; + struct Splice, Nil, 0> { using List = Node; + using Front = Nil; + using Back = Node; }; template - struct Splice { typedef Nil List; - typedef Nil Front; - typedef Nil Back; }; + struct Splice { using List = Nil; + using Front = Nil; + using Back = Nil; }; @@ -204,49 +214,49 @@ namespace meta { template struct Dissect> { - typedef Node List; ///< the complete list - typedef T Head; ///< first element - typedef Node First; ///< a list containing the first element - typedef TYPES Tail; ///< remainder of the list starting with the second elm. - typedef typename SplitLast::List Prefix;///< all of the list, up to but excluding the last element - typedef typename SplitLast::Type End; ///< the last element - typedef Node Last; ///< a list containing the last element + using List = Node; ///< the complete list + using Head = T; ///< first element + using First = Node; ///< a list containing the first element + using Tail = TYPES; ///< remainder of the list starting with the second elm. + using Prefix = typename PickLast::List; ///< all of the list, up to but excluding the last element + using End = typename PickLast::Type; ///< the last element + using Last = Node; ///< a list containing the last element }; template<> struct Dissect { - typedef Nil List; - typedef Nil Head; - typedef Nil First; - typedef Nil Tail; - typedef Nil Prefix; - typedef Nil End; - typedef Nil Last; + using List = Nil; + using Head = Nil; + using First = Nil; + using Tail = Nil; + using Prefix = Nil; + using End = Nil; + using Last = Nil; }; - /** + /** * prefix each of the elements, * yielding a list-of lists-of-types */ template - struct PrefixAll { typedef Node< typename Append::List, Nil> List; }; + struct PrefixAll { using List = Node< typename Append::List, Nil>; }; template - struct PrefixAll { typedef Nil List; }; + struct PrefixAll { using List = Nil; }; template - struct PrefixAll { typedef Node< typename Append::List, Nil> List; }; + struct PrefixAll { using List = Node< typename Append::List, Nil>; }; template< class T , class TY, class TYPES > - struct PrefixAll> { typedef Node< typename Append::List - , typename PrefixAll::List - > List; }; + struct PrefixAll> { using List = Node< typename Append::List + , typename PrefixAll::List + >;}; @@ -258,61 +268,65 @@ namespace meta { * sources, i.e. the Cartesian product. */ template - struct Distribute { typedef typename PrefixAll::List List; }; + struct Distribute { using List = typename PrefixAll::List; }; template - struct Distribute { typedef Nil List; }; + struct Distribute { using List = Nil; }; template< class TY, class TYPES , class TAIL > - struct Distribute,TAIL> { typedef typename Append< typename PrefixAll::List - , typename Distribute::List - >::List - List; }; + struct Distribute,TAIL> { using List = typename Append< typename PrefixAll::List + , typename Distribute::List + >::List + ; }; - /** - * build all possible combinations, based on a enumeration of the basic cases. + /** + * Build all possible combinations, based on a enumeration of the basic cases. * For each of the types in the argument list, an "enumeration generator" template is invoked, - * yielding a list of the possible base cases. These base cases are then combined with all the + * to produce a list of the possible base cases. These base cases are then combined with all the * combinations of the rest, yielding all ordered combinations of all cases. Here, "ordered" * means that the base cases of the n-th element will appear in the n-th position of the * resulting lists, - * - * For the typical example, the "base cases" are {flag(on), flag(off)}, so we get a - * list-of-lists, featuring all possibilities to combine these distinct toggles. + * @tparam X a type or type list to drive the tabulation process + * @tparam _ENUM_ a case generator meta function, which takes one type from the input(list) + * and generates a type-list of cases, which are then feed to `Distribute` + * @remark For the typical example, the "base cases" are {flag(on), flag(off)}, so we get a + * list-of-lists, featuring all possibilities to combine these distinct toggles. */ template< class X , template class _ENUM_> - struct Combine { typedef typename Distribute< typename _ENUM_::List - , Node - >::List List; }; + struct Combine { using List = typename Distribute< typename _ENUM_::List + , NilNode + >::List; }; template< template class _ENUM_> - struct Combine { typedef NilNode List; }; + struct Combine { using List = NilNode; }; template< class TY, class TYPES , template class _ENUM_> - struct Combine,_ENUM_> { typedef typename Distribute< typename _ENUM_::List - , typename Combine::List - >::List List; }; + struct Combine,_ENUM_> { using List = typename Distribute< typename _ENUM_::List + , typename Combine::List + >::List; }; /** enumeration generator for the Combine metafunction, - * yielding an "on" and "off" case + * yielding an "on" and "off" case; the latter is + * represented by a list with a Nil-Entry */ template struct FlagOnOff - { - typedef Node> List; + { + using List = Node; }; - /** generate all possible on-off combinations of the given flags */ + /** generate all possible on-off combinations of the given flags. + * @remark for the «off» case, the flag entry is not present */ template struct CombineFlags - { - typedef typename Combine::List List; + { + using List = typename Combine::List; }; diff --git a/src/lib/meta/typeseq-util.hpp b/src/lib/meta/typeseq-util.hpp index a8a6af59f..f0771b7da 100644 --- a/src/lib/meta/typeseq-util.hpp +++ b/src/lib/meta/typeseq-util.hpp @@ -250,11 +250,11 @@ namespace meta { // for finding the end we need the help of typelist-util.hpp - using PrefixList = typename SplitLast::List; + using PrefixList = typename PickLast::List; using TailList = typename Tail::List; using Prefix = typename TySeq::Seq; - using End = typename SplitLast::Type; + using End = typename PickLast::Type; using Last = TySeq; }; @@ -320,11 +320,11 @@ namespace meta { // for finding the end we need the help of typelist-util.hpp - typedef typename SplitLast::List PrefixList; + typedef typename PickLast::List PrefixList; typedef typename Tail::List TailList; typedef typename TyOLD::Seq Prefix; - typedef typename SplitLast::Type End; + typedef typename PickLast::Type End; typedef TyOLD Last; }; diff --git a/src/steam/control/command-signature.hpp b/src/steam/control/command-signature.hpp index d312462be..58727e0c0 100644 --- a/src/steam/control/command-signature.hpp +++ b/src/steam/control/command-signature.hpp @@ -61,7 +61,7 @@ namespace control { using lib::meta::_Fun; using lib::meta::TyOLD; using lib::meta::Append; - using lib::meta::SplitLast; + using lib::meta::PickLast; /** @@ -130,8 +130,8 @@ namespace control { { using Args = typename ARG::List; - using Memento = typename SplitLast::Type; - using OperationArglist = typename SplitLast::List; + using Memento = typename PickLast::Type; + using OperationArglist = typename PickLast::List; using OperationArgs = typename TyOLD::Seq; using OperateSig = typename BuildFunType::Sig; diff --git a/tests/12metaprogramming.tests b/tests/12metaprogramming.tests index b10ad1768..38fa4fa8f 100644 --- a/tests/12metaprogramming.tests +++ b/tests/12metaprogramming.tests @@ -370,133 +370,6 @@ END TEST "Typelist manipulation" TypeListManip_test <-<2>-<3>- out-lit: List2 :-<5>-<6>-<7>- -out-lit: Added2 :-<3>-<4>-<5>- -out-lit: FilterEven :-<2>-<6>- -out-lit: Append1 :- -out-lit: Append2 :-<11>-<22>- -out-lit: Append3 :-<111>- -out-lit: Append4 :-<222>- -out-lit: Append5 :-<1>-<2>-<3>- -out-lit: Append6 :-<5>-<6>-<7>- -out-lit: Append7 :-<111>-<5>-<6>-<7>- -out-lit: Append8 :-<1>-<2>-<3>-<222>- -out-lit: Append9 :-<1>-<2>-<3>-<5>-<6>-<7>- -out-lit: Overl01 :- -out-lit: Overl02 :- -out-lit: Overl03 :- -out-lit: Overl04 :-<9>-<8>-<3>- -out-lit: Overl05 :-<1>-<9>-<8>- -out-lit: Overl06 :-<1>-<2>-<9>- -out-lit: Overl07 :-<1>-<2>-<3>- -out-lit: Overl08 :-<1>-<2>-<3>- -out-lit: Overl09 :-<1>-<2>-<3>- -out-lit: Overl10 :-<1>-<1>-<2>- -out-lit: Overl11 :-<1>-<2>-<3>- -out-lit: Overl12 :-<1>-<2>-<3>- -out-lit: Overl13 :-<1>-<2>-<3>- -out-lit: Front1 :- -out-lit: Front2 :-<1>- -out-lit: Front3 :-<1>-<2>-<3>- -out-lit: Back1 :-<2>-<3>- -out-lit: Back2 :-<3>- -out-lit: Back3 :- -out-lit: Front4 :-<1>- -out-lit: Back4 :-<2>-<3>- -out-lit: Prefix :-<1>-<2>- -out-lit: ElmL :-<3>- -out-lit: NPrefix :- -out-lit: Types :-<3>- -out-lit: NList :- -out-lit: Types :- -out-lit: LL :-<1>-<2>-<3>-<5>-<6>-<7>- -out-lit: List :-<1>-<2>-<3>-<5>-<6>-<7>- -out-lit: First :-<1>- -out-lit: Tail :-<2>-<3>-<5>-<6>-<7>- -out-lit: Prefix :-<1>-<2>-<3>-<5>-<6>- -out-lit: Last :-<7>- -out-lit: HeadEnd :-<1>-<7>- -out-lit: Prefix1 : -out-lit: +---<11>-<22>-+- -out-lit: Prefix2 : -out-lit: +---<101>-<1>-+ -out-lit: +---<101>-<2>-+ -out-lit: +---<101>-<3>-+- -out-lit: Prefix3 : -out-lit: +---<1>-+ -out-lit: +---<2>-+ -out-lit: +---<3>-+- -out-lit: Prefix4 : -out-lit: +---<111>-<1>-<2>-<3>-+ -out-lit: +---<111>-<0>-+ -out-lit: +---<111>-<5>-<6>-<7>-+- -out-lit: Prefix5 : -out-lit: +---<1>-<2>-<3>-<5>-+ -out-lit: +---<1>-<2>-<3>-<6>-+ -out-lit: +---<1>-<2>-<3>-<7>-+- -out-lit: Prefix6 : -out-lit: +---<1>-<2>-<3>-<1>-<2>-<3>-+ -out-lit: +---<1>-<2>-<3>-<0>-+ -out-lit: +---<1>-<2>-<3>-<5>-<6>-<7>-+- -out-lit: Dist1 : -out-lit: +---<11>-<1>-+ -out-lit: +---<11>-<2>-+ -out-lit: +---<11>-<3>-+- -out-lit: Dist2 : -out-lit: +---<11>-<0>-+ -out-lit: +---<22>-<0>-+ -out-lit: +---<33>-<0>-+- -out-lit: Dist3 : -out-lit: +---<11>-<1>-+ -out-lit: +---<11>-<2>-+ -out-lit: +---<11>-<3>-+ -out-lit: +---<22>-<1>-+ -out-lit: +---<22>-<2>-+ -out-lit: +---<22>-<3>-+ -out-lit: +---<33>-<1>-+ -out-lit: +---<33>-<2>-+ -out-lit: +---<33>-<3>-+- -out-lit: Dist4 : -out-lit: +---<11>-<1>-<2>-<3>-+ -out-lit: +---<11>-<5>-<6>-<7>-+ -out-lit: +---<22>-<1>-<2>-<3>-+ -out-lit: +---<22>-<5>-<6>-<7>-+ -out-lit: +---<33>-<1>-<2>-<3>-+ -out-lit: +---<33>-<5>-<6>-<7>-+- -out-lit: Down :-<11>-<10>-<9>-<8>-<7>-<6>-<5>-<4>-<3>-<2>-<1>-<0>- -out-lit: Combi : -out-lit: +---<1>-<2>-<3>-<·>-+ -out-lit: +---<1>-<2>-<2>-<·>-+ -out-lit: +---<1>-<2>-<1>-<·>-+ -out-lit: +---<1>-<2>-<0>-<·>-+ -out-lit: +---<1>-<1>-<3>-<·>-+ -out-lit: +---<1>-<1>-<2>-<·>-+ -out-lit: +---<1>-<1>-<1>-<·>-+ -out-lit: +---<1>-<1>-<0>-<·>-+ -out-lit: +---<1>-<0>-<3>-<·>-+ -out-lit: +---<1>-<0>-<2>-<·>-+ -out-lit: +---<1>-<0>-<1>-<·>-+ -out-lit: +---<1>-<0>-<0>-<·>-+ -out-lit: +---<0>-<2>-<3>-<·>-+ -out-lit: +---<0>-<2>-<2>-<·>-+ -out-lit: +---<0>-<2>-<1>-<·>-+ -out-lit: +---<0>-<2>-<0>-<·>-+ -out-lit: +---<0>-<1>-<3>-<·>-+ -out-lit: +---<0>-<1>-<2>-<·>-+ -out-lit: +---<0>-<1>-<1>-<·>-+ -out-lit: +---<0>-<1>-<0>-<·>-+ -out-lit: +---<0>-<0>-<3>-<·>-+ -out-lit: +---<0>-<0>-<2>-<·>-+ -out-lit: +---<0>-<0>-<1>-<·>-+ -out-lit: +---<0>-<0>-<0>-<·>-+- -out-lit: OnOff : -out-lit: +---<1>-<2>-<3>-<·>-+ -out-lit: +---<1>-<2>-<·>-+ -out-lit: +---<1>-<3>-<·>-+ -out-lit: +---<1>-<·>-+ -out-lit: +---<2>-<3>-<·>-+ -out-lit: +---<2>-<·>-+ -out-lit: +---<3>-<·>-+ -out-lit: +---<·>-+- return: 0 END diff --git a/tests/library/meta/tuple-diagnostics.hpp b/tests/library/meta/tuple-diagnostics.hpp index fc1b05e08..00811d666 100644 --- a/tests/library/meta/tuple-diagnostics.hpp +++ b/tests/library/meta/tuple-diagnostics.hpp @@ -75,7 +75,7 @@ namespace test { using DumpPrinter = InstantiateChained; return "TUPLE" - + DumpPrinter::print(); + + DumpPrinter::show(); } // see the macros DISPLAY and DUMPVAL defined in typelist-diagnostics.hpp diff --git a/tests/library/meta/typelist-diagnostics.hpp b/tests/library/meta/typelist-diagnostics.hpp index 215a8d3f8..f2c1c16e0 100644 --- a/tests/library/meta/typelist-diagnostics.hpp +++ b/tests/library/meta/typelist-diagnostics.hpp @@ -17,7 +17,7 @@ ** a Printer template usable for debugging the structure of a typelist built ** upon some simple debugging-style types. Examples being a Num template, ** or the Flag type. A Printer type generated from this template provides - ** a static \c print() function. The string returned from this function + ** a static `show()` function. The string returned from this function ** visualises the structure of the typelist provided as parameter ** to the Printer template. ** @@ -30,21 +30,21 @@ #define META_TYPELIST_DIAGNOSTICS_H +#include "lib/test/test-helper.hpp" #include "lib/meta/typelist.hpp" #include "lib/meta/generator.hpp" #include "lib/format-string.hpp" #include "lib/format-cout.hpp" #include "lib/meta/util.hpp" -#include - - -using std::string; namespace lib { namespace meta { + using std::string; + + /** dummy interface / baseclass for diagnostics */ struct Numz { @@ -80,9 +80,9 @@ namespace meta { /** helper for generating test lists */ - template struct CountDown { typedef Nil List; }; - template<> struct CountDown> { typedef Node, Nil> List; }; - template struct CountDown> { typedef Node, typename CountDown>::List> List; }; + template struct CountDown { using List = Nil; }; + template<> struct CountDown> { using List = Node, Nil>; }; + template struct CountDown> { using List = Node, typename CountDown>::List>; }; @@ -95,7 +95,7 @@ namespace meta { struct NullP { - static string print () { return "-"; } + static string show() { return "-"; } }; /** debugging template, @@ -105,35 +105,35 @@ namespace meta { struct Printer : BASE { - static string print () { return _Fmt("-<%s>%s") % typeStr() % BASE::print(); } + static string show() { return _Fmt("-<%s>%s") % typeStr() % BASE::show(); } }; template struct Printer : BASE { - static string print () { return _Fmt("-<%u>%s") % "·" % BASE::print(); } + static string show() { return _Fmt("-<%u>%s") % "·" % BASE::show(); } }; template struct Printer, BASE> ///< display the presence of a Num instance in the typelist : BASE { - static string print () { return _Fmt("-<%u>%s") % uint(Num::VAL) % BASE::print(); } + static string show() { return _Fmt("-<%u>%s") % uint(Num::VAL) % BASE::show(); } }; template struct Printer, BASE> ///< display the presence of a Flag in the typelist : BASE { - static string print () { return _Fmt("-<%u>%s") % uint(Fl) % BASE::print(); } + static string show() { return _Fmt("-<%u>%s") % uint(Fl) % BASE::show(); } }; template struct Printer ///< display the presence of a plain int in the typelist : BASE { - static string print () { return _Fmt("-<%u>%s") % 'i' % BASE::print(); } + static string show() { return _Fmt("-<%u>%s") % 'i' % BASE::show(); } }; @@ -145,7 +145,7 @@ namespace meta { printSublist () { typedef InstantiateChained SubList; - return SubList::print(); + return SubList::show(); } /** Specialisation for debug-printing of a nested sublist */ @@ -153,11 +153,11 @@ namespace meta { struct Printer, BASE> : BASE { - static string print () + static string show() { typedef Node List; return string("\n\t+--") + printSublist()+"+" - + BASE::print(); + + BASE::show(); } }; @@ -165,11 +165,11 @@ namespace meta { struct Printer, BASE> : BASE { - static string print () + static string show() { typedef typename Config::Flags FlagList; return string("\n\t+-Conf-[") + printSublist()+"]" - + BASE::print(); + + BASE::show(); } }; @@ -185,20 +185,25 @@ namespace meta { showType () { typedef InstantiateChained DumpPrinter; - return DumpPrinter::print(); + return DumpPrinter::show(); } // Note: we define overloads of this function for other types, especially Tuples + + + + /* ================= convenience macro notation ================= */ + #define DISPLAY(_IT_) \ cout << STRINGIFY(_IT_) << "\t:" << showType<_IT_>() << endl; #define DUMPVAL(_IT_) \ cout << STRINGIFY(_IT_) << "\t:" << util::toString(_IT_) << endl; - - +#define EXPECT(_TY_, RENDERED_STRUCTURE ) \ + CHECK (showType<_TY_>() == RENDERED_STRUCTURE ## _expect) }}} // namespace lib::meta::test diff --git a/tests/library/meta/typelist-manip-test.cpp b/tests/library/meta/typelist-manip-test.cpp index 75d66917e..c251f93d3 100644 --- a/tests/library/meta/typelist-manip-test.cpp +++ b/tests/library/meta/typelist-manip-test.cpp @@ -33,30 +33,24 @@ #include "lib/meta/generator.hpp" #include "lib/meta/typelist-manip.hpp" #include "meta/typelist-diagnostics.hpp" +#include "lib/test/diagnostic-output.hpp"/////////////////TODO #include -#include -using ::test::Test; using std::is_same; -using std::cout; -using std::endl; namespace lib { namespace meta { namespace test { - - namespace { // test data + namespace { // type-lists to test with - - - typedef TyOLD< Num<1> + typedef TySeq< Num<1> , Num<2> , Num<3> >::List List1; - typedef TyOLD< Num<5> + typedef TySeq< Num<5> , Num<6> , Num<7> >::List List2; @@ -85,28 +79,29 @@ namespace test { class TypeListManip_test : public Test { virtual void - run (Arg) + run (Arg) { - check_diagnostics (); - check_pick_elm (); - check_apply (); - check_filter (); - check_append (); - check_splice (); - check_s_last (); - check_dissect(); - check_prefix (); - check_distribute(); - check_combine(); + demonstrate_diagnostics(); + verify_pick (); + verify_last (); + verify_append (); + verify_splice (); + verify_dissect(); + verify_apply (); + verify_filter (); + verify_prefix (); + verify_distribute(); + verify_combine(); } + /** @test can print the type list structure for diagnostic */ void - check_diagnostics () + demonstrate_diagnostics () { // Explanation: the DISPLAY macro results in the following definition.... typedef InstantiateChained Contents_List1; - cout << "List1" << "\t:" << Contents_List1::print() << endl; + cout << "List1" << "\t:" << Contents_List1::show() << endl; // That is: we instantiate the "Printer" template for each of the types in List1, // forming an inheritance chain. I.e. the defined Type "Contents_List1" inherits @@ -114,171 +109,147 @@ namespace test { // The print() function is defined to create a string showing each. DISPLAY (List2); + + // Furthermore, we use verification against lib::test::ExpectString, + // which can be given as literal "some text"_expect, to document and + // verify that the rendered type structure is indeed as expected + CHECK (showType() == "-<1>-<2>-<3>-"_expect); + + EXPECT (List2, "-<5>-<6>-<7>-"); } + /** @test pick a type by index from a type list */ void - check_pick_elm () + verify_pick () { - Pick::Type e0; - Pick::Type e1; - Pick::Type e2; + using E0 = Pick::Type; + using E1 = Pick::Type; + using E2 = Pick::Type; - using E3 = Pick::Type; - using NilE = Pick::Type; - using Irrelevant = Pick::Type; + using E3 = Pick::Type; + using NilE = Pick::Type; + using Bull = Pick::Type; + using Shit = Pick::Type; + CHECK ((is_same >() )); + CHECK ((is_same >() )); + CHECK ((is_same >() )); + + CHECK ((is_same() )); + CHECK ((is_same() )); + CHECK ((is_same() )); + CHECK ((is_same() )); + + // note: in the end, all this meta-processing yields types, + // which can be instantiated and used as if defined directly + E0 e0; + E1 e1; + E2 e2; CHECK (5 == e0); CHECK (6 == e1); CHECK (7 == e2); - - CHECK ((is_same ::value)); - CHECK ((is_same ::value)); - CHECK ((is_same::value)); + CHECK (7 == e2.o_); } void - check_append () + verify_last() { - using Append1 = Append; - DISPLAY (Append1); + using Elm = PickLast::Type; + using Prefix = PickLast::List; - using Append2 = Append,Num<22>>; - DISPLAY (Append2); + using ElmL = TySeq::List; - using Append3 = Append,Nil>; - DISPLAY (Append3); + EXPECT (Prefix, "-<1>-<2>-"); + EXPECT (ElmL , "-<3>-" ); - using Append4 = Append>; - DISPLAY (Append4); + using Elm1 = PickLast::Type; + using NPrefix = PickLast::List; - using Append5 = Append; - DISPLAY (Append5); + EXPECT (TySeq, "-<3>-"); + EXPECT (NPrefix , "-"); - using Append6 = Append; - DISPLAY (Append6); + using NilSplit = PickLast::Type; + using NilList = PickLast::List; - using Append7 = Append,List2>; - DISPLAY (Append7); - - using Append8 = Append>; - DISPLAY (Append8); - - using Append9 = Append; - DISPLAY (Append9); + EXPECT (TySeq, "-"); + EXPECT (NilList , "-"); } + /** @test append and concatenate type lists */ void - check_splice () + verify_append () { - using OLi = TyOLD,Num<8>>::List; + using Append1 = Append; EXPECT (Append1, "-" ); + using Append2 = Append , Num<22> >; EXPECT (Append2, "-<11>-<22>-" ); + using Append3 = Append, Nil >; EXPECT (Append3, "-<111>-" ); + using Append4 = Append>; EXPECT (Append4, "-<222>-" ); + using Append5 = Append; EXPECT (Append5, "-<1>-<2>-<3>-" ); + using Append6 = Append; EXPECT (Append6, "-<5>-<6>-<7>-" ); + using Append7 = Append, List2 >; EXPECT (Append7, "-<111>-<5>-<6>-<7>-" ); + using Append8 = Append>; EXPECT (Append8, "-<1>-<2>-<3>-<222>-" ); + using Append9 = Append; EXPECT (Append9, "-<1>-<2>-<3>-<5>-<6>-<7>-"); + } + + + /** @test splice (or rather paste) a list on top of a base list + * @remark the intended use case is to manipulate some parameters + * in a given function-type argument list + */ + void + verify_splice () + { + using OLi = TySeq,Num<8>>::List; // will "paste" the list OLi "on top" of another Typelist... - using Overl01 = Splice; - DISPLAY (Overl01); + using Overl01 = Splice; EXPECT (Overl01, "-"); + using Overl02 = Splice; EXPECT (Overl02, "-"); + using Overl03 = Splice; EXPECT (Overl03, "-"); + using Overl04 = Splice; EXPECT (Overl04, "-<9>-<8>-<3>-"); + using Overl05 = Splice; EXPECT (Overl05, "-<1>-<9>-<8>-"); + using Overl06 = Splice; EXPECT (Overl06, "-<1>-<2>-<9>-"); + using Overl07 = Splice; EXPECT (Overl07, "-<1>-<2>-<3>-"); + using Overl08 = Splice; EXPECT (Overl08, "-<1>-<2>-<3>-"); + using Overl09 = Splice; EXPECT (Overl09, "-<1>-<2>-<3>-"); + using Overl10 = Splice; EXPECT (Overl10, "-<1>-<1>-<2>-"); + using Overl11 = Splice; EXPECT (Overl11, "-<1>-<2>-<3>-"); + using Overl12 = Splice; EXPECT (Overl12, "-<1>-<2>-<3>-"); + using Overl13 = Splice; EXPECT (Overl13, "-<1>-<2>-<3>-"); - using Overl02 = Splice; - DISPLAY (Overl02); - - using Overl03 = Splice; - DISPLAY (Overl03); - - using Overl04 = Splice; - DISPLAY (Overl04); - - using Overl05 = Splice; - DISPLAY (Overl05); - - using Overl06 = Splice; - DISPLAY (Overl06); - - using Overl07 = Splice; - DISPLAY (Overl07); - - using Overl08 = Splice; - DISPLAY (Overl08); - - using Overl09 = Splice; - DISPLAY (Overl09); - - using Overl10 = Splice; - DISPLAY (Overl10); - - using Overl11 = Splice; - DISPLAY (Overl11); - - using Overl12 = Splice; - DISPLAY (Overl12); - - using Overl13 = Splice; - DISPLAY (Overl13); - - - using OLi2 = TyOLD>::List; - using Front1 = Splice::Front; - using Front2 = Splice::Front; - using Front3 = Splice::Front; - DISPLAY (Front1); - DISPLAY (Front2); - DISPLAY (Front3); - using Back1 = Splice::Back; - using Back2 = Splice::Back; - using Back3 = Splice::Back; - DISPLAY (Back1); - DISPLAY (Back2); - DISPLAY (Back3); + using OLi2 = TySeq>::List; + // can retrieve the remaining part of the original list, left and right of splice + using Front1 = Splice::Front; EXPECT (Front1, "-" ); + using Front2 = Splice::Front; EXPECT (Front2, "-<1>-" ); + using Front3 = Splice::Front; EXPECT (Front3, "-<1>-<2>-<3>-"); + using Back1 = Splice::Back; EXPECT (Back1 , "-<2>-<3>-" ); + using Back2 = Splice::Back; EXPECT (Back2 , "-<3>-" ); + using Back3 = Splice::Back; EXPECT (Back3 , "-" ); // Note: with a Null-Overlay, this can be used to extract arbitrary sublists: - using Front4 = Splice::Front; - using Back4 = Splice::Back; - DISPLAY (Front4); - DISPLAY (Back4); + using Front4 = Splice::Front; EXPECT (Front4, "-<1>-" ); + using Back4 = Splice::Back; EXPECT (Back4 , "-<2>-<3>-"); } - void - check_s_last() - { - using Elm = SplitLast::Type; - using Prefix = SplitLast::List; - - using ElmL = TyOLD::List; - - DISPLAY (Prefix); - DISPLAY (ElmL); - - using Elm1 = SplitLast::Type; - using NPrefix = SplitLast::List; - - DISPLAY (NPrefix); - DISPLAY (TyOLD); - - using NilSplit = SplitLast::Type; - using NList = SplitLast::List; - - DISPLAY (NList); - DISPLAY (TyOLD); - } - + /** @test dissect and access front and back parts of a list */ void - check_dissect() + verify_dissect() { - typedef Append::List LL; - DISPLAY (LL); + using LL = Append::List; EXPECT (LL , "-<1>-<2>-<3>-<5>-<6>-<7>-"); - using List = Dissect::List; DISPLAY(List); - using First = Dissect::First; DISPLAY(First); - using Tail = Dissect::Tail; DISPLAY(Tail); - using Prefix = Dissect::Prefix; DISPLAY(Prefix); - using Last = Dissect::Last; DISPLAY(Last); + using List = Dissect::List; EXPECT (List , "-<1>-<2>-<3>-<5>-<6>-<7>-"); + using First = Dissect::First; EXPECT (First , "-<1>-" ); + using Tail = Dissect::Tail; EXPECT (Tail , "-<2>-<3>-<5>-<6>-<7>-" ); + using Prefix = Dissect::Prefix; EXPECT (Prefix, "-<1>-<2>-<3>-<5>-<6>-" ); + using Last = Dissect::Last; EXPECT (Last , "-<7>-" ); using Head = Dissect::Head; using End = Dissect::End; - using HeadEnd = TyOLD; DISPLAY(HeadEnd); + using HeadEnd = TySeq; EXPECT (HeadEnd, "-<1>-<7>-"); } @@ -287,80 +258,185 @@ namespace test { template struct AddConst2 { typedef X Type; }; template struct AddConst2> { typedef Num Type; }; + /** @test apply a _meta-function_ to each type in list */ void - check_apply () + verify_apply() { using Added2 = Apply; - DISPLAY (Added2); + EXPECT (List1 , "-<1>-<2>-<3>-"); + EXPECT (Added2, "-<3>-<4>-<5>-"); } template struct IsEven { enum {value = false }; }; template struct IsEven> { enum {value = (0 == I % 2) }; }; + /** @test filter a type list based on a meta-predicate */ void - check_filter () + verify_filter() { - using FilterEven = Filter::List, IsEven >; - DISPLAY (FilterEven); + CHECK (not IsEven>::value); + CHECK ( IsEven>::value); + + using FilterEven = Filter::List, IsEven >; + EXPECT (FilterEven, "-<2>-<6>-"); } + + + /** @test verify generation of nested lists-of-lists + * by distributing the elements from the first list + * as prefix-concatenation to the elements of the second list + * @note the second list can actually be already a list-of-lists, + * allowing to set up quite elaborate generation schemes. + */ void - check_prefix () + verify_prefix () { using Prefix1 = PrefixAll,Num<22>>; - DISPLAY (Prefix1); + // Note this creates a nested two-dimensional structure, + // i.e. a type-list, whose elements are again type-lists. + // The diagnostic helper prints each sublist in a new line, + // and prefixed by a tab: + EXPECT (Prefix1, "\n\t" "+---<11>-<22>-+-"); using Prefix2 = PrefixAll,List1>; - DISPLAY (Prefix2); + EXPECT (List1 , "-<1>-<2>-<3>-"); + EXPECT (Prefix2, "\n\t" "+---<101>-<1>-+" + "\n\t" "+---<101>-<2>-+" + "\n\t" "+---<101>-<3>-+-"); using Prefix3 = PrefixAll; - DISPLAY (Prefix3); + EXPECT (Prefix3, "\n\t" "+---<1>-+" + "\n\t" "+---<2>-+" + "\n\t" "+---<3>-+-"); + + // Notably this can also be used to distribute into an already nested structure, + // since the implementation is based on Append, which will actually concatenate lists + // To demonstrate this, we first create a mixed list, where some elements are nested lists + using List_of_Lists = TySeq // ◁—————————————— this one is a regular element + ,List2::List>::List; + EXPECT (List_of_Lists, + "\n\t" "+---<1>-<2>-<3>-+" + "-<0>" // ◁—————————————— here shows the regular element + "\n\t" "+---<5>-<6>-<7>-+-"); - using List_of_Lists = TyOLD,List2::List>::List; using Prefix4 = PrefixAll, List_of_Lists>; - DISPLAY (Prefix4); + EXPECT (Prefix4, "\n\t" "+---<111>-<1>-<2>-<3>-+" // ◁——————— concatenation »flattens« the lists + "\n\t" "+---<111>-<0>-+" + "\n\t" "+---<111>-<5>-<6>-<7>-+-"); using Prefix5 = PrefixAll; - DISPLAY (Prefix5); + EXPECT (Prefix5, "\n\t" "+---<1>-<2>-<3>-<5>-+" + "\n\t" "+---<1>-<2>-<3>-<6>-+" + "\n\t" "+---<1>-<2>-<3>-<7>-+-"); using Prefix6 = PrefixAll; - DISPLAY (Prefix6); + EXPECT (Prefix6, "\n\t" "+---<1>-<2>-<3>-<1>-<2>-<3>-+" + "\n\t" "+---<1>-<2>-<3>-<0>-+" + "\n\t" "+---<1>-<2>-<3>-<5>-<6>-<7>-+-"); } + + /** @test use the Prefix mechanism to generate a _cartesian product_ */ void - check_distribute() + verify_distribute() { using Dist1 = Distribute, List1>; - DISPLAY (Dist1); + EXPECT (Dist1, "\n\t" "+---<11>-<1>-+" + "\n\t" "+---<11>-<2>-+" + "\n\t" "+---<11>-<3>-+-"); - using Prefixes = TyOLD,Num<22>,Num<33>>::List; - using Dist2 = Distribute>; - DISPLAY (Dist2); + using Prefixes = TySeq,Num<22>,Num<33>>::List; + using Dist2 = Distribute>; + EXPECT (Dist2, "\n\t" "+---<11>-<0>-+" + "\n\t" "+---<22>-<0>-+" + "\n\t" "+---<33>-<0>-+-"); using Dist3 = Distribute; - DISPLAY (Dist3); + EXPECT (Dist3, "\n\t" "+---<11>-<1>-+" + "\n\t" "+---<11>-<2>-+" + "\n\t" "+---<11>-<3>-+" + "\n\t" "+---<22>-<1>-+" + "\n\t" "+---<22>-<2>-+" + "\n\t" "+---<22>-<3>-+" + "\n\t" "+---<33>-<1>-+" + "\n\t" "+---<33>-<2>-+" + "\n\t" "+---<33>-<3>-+-"); - using Dist4 = Distribute::List>; - DISPLAY (Dist4); + using LioLi = TySeq::List; + EXPECT (LioLi, "\n\t" "+---<1>-<2>-<3>-+" + "\n\t" "+---<5>-<6>-<7>-+-"); + using Dist4 = Distribute; + EXPECT (Dist4, "\n\t" "+---<11>-<1>-<2>-<3>-+" + "\n\t" "+---<11>-<5>-<6>-<7>-+" + "\n\t" "+---<22>-<1>-<2>-<3>-+" + "\n\t" "+---<22>-<5>-<6>-<7>-+" + "\n\t" "+---<33>-<1>-<2>-<3>-+" + "\n\t" "+---<33>-<5>-<6>-<7>-+-"); } + /** @test demonstrate special setup to enumerate case combinations + * @remark can be used to pre-generate template instantiations + * at compile time, for a complete configuration space + */ void - check_combine() - { - using Down = CountDown>; - DISPLAY (Down); + verify_combine() + { // ▽▽▽ ———————————————defined in typelist-diagnostic.cpp + using Count = CountDown>; + EXPECT (Count, "-<11>-<10>-<9>-<8>-<7>-<6>-<5>-<4>-<3>-<2>-<1>-<0>-"); + // Apply on a single type and tabulate + using Apply = Combine, CountDown>; + EXPECT (Apply, "\n\t" "+---<5>-<·>-+" + "\n\t" "+---<4>-<·>-+" + "\n\t" "+---<3>-<·>-+" + "\n\t" "+---<2>-<·>-+" + "\n\t" "+---<1>-<·>-+" + "\n\t" "+---<0>-<·>-+-"); + + // Apply recursively to generate all combinations using Combi = Combine; - DISPLAY (Combi); + EXPECT (Combi, "\n\t" "+---<1>-<2>-<3>-<·>-+" + "\n\t" "+---<1>-<2>-<2>-<·>-+" + "\n\t" "+---<1>-<2>-<1>-<·>-+" + "\n\t" "+---<1>-<2>-<0>-<·>-+" + "\n\t" "+---<1>-<1>-<3>-<·>-+" + "\n\t" "+---<1>-<1>-<2>-<·>-+" + "\n\t" "+---<1>-<1>-<1>-<·>-+" + "\n\t" "+---<1>-<1>-<0>-<·>-+" + "\n\t" "+---<1>-<0>-<3>-<·>-+" + "\n\t" "+---<1>-<0>-<2>-<·>-+" + "\n\t" "+---<1>-<0>-<1>-<·>-+" + "\n\t" "+---<1>-<0>-<0>-<·>-+" + "\n\t" "+---<0>-<2>-<3>-<·>-+" + "\n\t" "+---<0>-<2>-<2>-<·>-+" + "\n\t" "+---<0>-<2>-<1>-<·>-+" + "\n\t" "+---<0>-<2>-<0>-<·>-+" + "\n\t" "+---<0>-<1>-<3>-<·>-+" + "\n\t" "+---<0>-<1>-<2>-<·>-+" + "\n\t" "+---<0>-<1>-<1>-<·>-+" + "\n\t" "+---<0>-<1>-<0>-<·>-+" + "\n\t" "+---<0>-<0>-<3>-<·>-+" + "\n\t" "+---<0>-<0>-<2>-<·>-+" + "\n\t" "+---<0>-<0>-<1>-<·>-+" + "\n\t" "+---<0>-<0>-<0>-<·>-+-"); + // Special use-case: call combinations of a set of flags using OnOff = CombineFlags; - DISPLAY (OnOff); + EXPECT (OnOff, "\n\t" "+---<1>-<2>-<3>-<·>-+" + "\n\t" "+---<1>-<2>-<·>-+" + "\n\t" "+---<1>-<3>-<·>-+" + "\n\t" "+---<1>-<·>-+" + "\n\t" "+---<2>-<3>-<·>-+" + "\n\t" "+---<2>-<·>-+" + "\n\t" "+---<3>-<·>-+" + "\n\t" "+---<·>-+-"); } - }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 46b348820..ce60d476e 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -164257,7 +164257,7 @@ Since then others have made contributions, see the log for the history. - + @@ -164269,6 +164269,10 @@ Since then others have made contributions, see the log for the history. + + + + @@ -164290,6 +164294,16 @@ Since then others have made contributions, see the log for the history. + + + + + + + + + + @@ -164320,16 +164334,19 @@ Since then others have made contributions, see the log for the history. - - + + + + - + + @@ -164344,8 +164361,11 @@ Since then others have made contributions, see the log for the history. - - + + + + + @@ -164367,7 +164387,9 @@ Since then others have made contributions, see the log for the history. - + + + @@ -164395,7 +164417,12 @@ Since then others have made contributions, see the log for the history. - + + + + + +