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. - + + + + + +