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)
This commit is contained in:
Fischlurch 2025-06-02 23:55:08 +02:00
parent c8187bdf88
commit 47b57da646
8 changed files with 439 additions and 444 deletions

View file

@ -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<class TYPES, size_t i>
struct Pick
{
typedef Nil Type;
using Type = Nil;
};
template<class TY, class TYPES>
struct Pick<Node<TY,TYPES>, 0>
{
typedef TY Type;
using Type = TY;
};
template<class TY, class TYPES, size_t i>
struct Pick<Node<TY,TYPES>, i>
{
typedef typename Pick<TYPES, i-1>::Type Type;
using Type = typename Pick<TYPES, i-1>::Type;
};
@ -75,121 +82,124 @@ namespace meta {
/** apply a transformation (template) to each type in the list */
template<class TY, template<class> class _TRANS_>
struct Apply { typedef TY List; };
struct Apply { using List = TY; };
template< class TY, class TYPES
, template<class> class _TRANS_
>
struct Apply<Node<TY,TYPES>, _TRANS_ > { typedef Node< typename _TRANS_<TY>::Type
, typename Apply<TYPES,_TRANS_>::List
> List; };
struct Apply<Node<TY,TYPES>, _TRANS_ > { using List = Node< typename _TRANS_<TY>::Type
, typename Apply<TYPES,_TRANS_>::List
>;};
/** conditional node: skip an element based on evaluating a predicate */
template<bool, class T, class TAIL>
struct CondNode { typedef TAIL Next; };
struct CondNode { using Next = TAIL; };
template<class T, class TAIL>
struct CondNode<true, T, TAIL> { typedef Node<T,TAIL> Next; };
struct CondNode<true, T, TAIL> { using Next = Node<T,TAIL>; };
/** filter away those types which don't fulfil a predicate metafunction */
template< class TYPES
template< class TYPES
, template<class> class _P_ ///< a template providing a boolean member \c ::value
>
struct Filter;
template<template<class> class _P_>
struct Filter<Nil,_P_> { typedef Nil List; };
struct Filter<Nil,_P_> { using List = Nil; };
template< class TY, class TYPES
, template<class> class _P_
>
struct Filter<Node<TY,TYPES>,_P_> { typedef typename CondNode< _P_<TY>::value
, TY
, typename Filter<TYPES,_P_>::List
>::Next
List; };
struct Filter<Node<TY,TYPES>,_P_> { using List = typename CondNode< _P_<TY>::value
, TY
, typename Filter<TYPES,_P_>::List
>::Next
; };
/** append lists-of-types */
/** append (concatenate) lists-of-types */
template<class TY1, class TY2>
struct Append { typedef Node<TY1, typename Append<TY2,Nil>::List> List; };
struct Append { using List = Node<TY1, typename Append<TY2,Nil>::List>; };
template< class TY, class TYPES
, class TAIL
>
struct Append<Node<TY,TYPES>, TAIL> { typedef Node<TY, typename Append<TYPES, TAIL>::List> List; };
struct Append<Node<TY,TYPES>, TAIL> { using List = Node<TY, typename Append<TYPES, TAIL>::List>; };
template<class TY, class TYPES>
struct Append<Nil, Node<TY,TYPES>> { typedef Node<TY,TYPES> List; };
struct Append<Nil, Node<TY,TYPES>> { using List = Node<TY,TYPES>; };
template<class TY, class TYPES>
struct Append<Node<TY,TYPES>, Nil> { typedef Node<TY,TYPES> List; };
struct Append<Node<TY,TYPES>, Nil> { using List = Node<TY,TYPES>; };
template<class TY1>
struct Append<TY1,Nil> { typedef Node<TY1,Nil> List; };
struct Append<TY1,Nil> { using List = Node<TY1,Nil>; };
template<class TY2>
struct Append<Nil,TY2> { typedef Node<TY2,Nil> List; };
struct Append<Nil,TY2> { using List = Node<TY2,Nil>; };
template<>
struct Append<Nil,Nil> { typedef Nil List; };
struct Append<Nil,Nil> { using List = Nil; };
/** access the last list element */
template<class TYPES>
struct SplitLast;
struct PickLast;
template<>
struct SplitLast<Nil> { typedef Nil Type;
typedef Nil List; };
struct PickLast<Nil> { using Type = Nil;
using List = Nil; };
template<class TY>
struct SplitLast<Node<TY,Nil>> { typedef TY Type;
typedef Nil List; };
struct PickLast<Node<TY,Nil>> { using Type = TY;
using List = Nil; };
template<class TY, class TYPES>
struct SplitLast<Node<TY,TYPES>> { typedef typename SplitLast<TYPES>::Type Type;
typedef typename Append< TY,
typename SplitLast<TYPES>::List
>::List
List; };
struct PickLast<Node<TY,TYPES>> { using Type = typename PickLast<TYPES>::Type;
using List = typename Append< TY
, typename PickLast<TYPES>::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<class BASE, class OVERLAY, uint i=0>
struct Splice;
template<class B, class BS,
class OVERLAY, uint i>
struct Splice<Node<B,BS>, OVERLAY, i> { typedef Node<B, typename Splice<BS, OVERLAY, i-1>::List> List;
typedef Node<B, typename Splice<BS, OVERLAY, i-1>::Front> Front;
typedef typename Splice<BS, OVERLAY, i-1>::Back Back; };
class OVERLAY,
uint i>
struct Splice<Node<B,BS>, OVERLAY, i> { using List = Node<B, typename Splice<BS, OVERLAY, i-1>::List>;
using Front = Node<B, typename Splice<BS, OVERLAY, i-1>::Front>;
using Back = typename Splice<BS, OVERLAY, i-1>::Back; };
template<class B, class BS,
class O, class OS >
struct Splice<Node<B,BS>,Node<O,OS>,0> { typedef Node<O, typename Splice<BS,OS, 0>::List> List;
typedef Nil Front;
typedef typename Splice<BS,OS, 0>::Back Back; };
struct Splice<Node<B,BS>,Node<O,OS>,0> { using List = Node<O, typename Splice<BS,OS, 0>::List>;
using Front = Nil;
using Back = typename Splice<BS,OS, 0>::Back; };
template<class B, class BS>
struct Splice<Node<B,BS>, Nil, 0> { typedef Node<B, BS> List;
typedef Nil Front;
typedef Node<B, BS> Back; };
struct Splice<Node<B,BS>, Nil, 0> { using List = Node<B, BS>;
using Front = Nil;
using Back = Node<B, BS>; };
template<class XX, uint i>
struct Splice<Nil, XX, i> { typedef Nil List;
typedef Nil Front;
typedef Nil Back; };
struct Splice<Nil, XX, i> { using List = Nil;
using Front = Nil;
using Back = Nil; };
@ -204,49 +214,49 @@ namespace meta {
template<class T, class TYPES>
struct Dissect<Node<T,TYPES>>
{
typedef Node<T,TYPES> List; ///< the complete list
typedef T Head; ///< first element
typedef Node<T,Nil> First; ///< a list containing the first element
typedef TYPES Tail; ///< remainder of the list starting with the second elm.
typedef typename SplitLast<List>::List Prefix;///< all of the list, up to but excluding the last element
typedef typename SplitLast<List>::Type End; ///< the last element
typedef Node<End,Nil> Last; ///< a list containing the last element
using List = Node<T,TYPES>; ///< the complete list
using Head = T; ///< first element
using First = Node<T,Nil>; ///< a list containing the first element
using Tail = TYPES; ///< remainder of the list starting with the second elm.
using Prefix = typename PickLast<List>::List; ///< all of the list, up to but excluding the last element
using End = typename PickLast<List>::Type; ///< the last element
using Last = Node<End,Nil>; ///< a list containing the last element
};
template<>
struct Dissect<Nil>
{
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<class T, class TY>
struct PrefixAll { typedef Node< typename Append<T,TY>::List, Nil> List; };
struct PrefixAll { using List = Node< typename Append<T,TY>::List, Nil>; };
template<class T>
struct PrefixAll<T, Nil> { typedef Nil List; };
struct PrefixAll<T, Nil> { using List = Nil; };
template<class T>
struct PrefixAll<T, NilNode> { typedef Node< typename Append<T, NilNode>::List, Nil> List; };
struct PrefixAll<T, NilNode> { using List = Node< typename Append<T, NilNode>::List, Nil>; };
template< class T
, class TY, class TYPES
>
struct PrefixAll<T, Node<TY,TYPES>> { typedef Node< typename Append<T,TY>::List
, typename PrefixAll<T,TYPES>::List
> List; };
struct PrefixAll<T, Node<TY,TYPES>> { using List = Node< typename Append<T,TY>::List
, typename PrefixAll<T,TYPES>::List
>;};
@ -258,61 +268,65 @@ namespace meta {
* sources, i.e. the Cartesian product.
*/
template<class TY1,class TY2>
struct Distribute { typedef typename PrefixAll<TY1,TY2>::List List; };
struct Distribute { using List = typename PrefixAll<TY1,TY2>::List; };
template<class TY>
struct Distribute<Nil,TY> { typedef Nil List; };
struct Distribute<Nil,TY> { using List = Nil; };
template< class TY, class TYPES
, class TAIL
>
struct Distribute<Node<TY,TYPES>,TAIL> { typedef typename Append< typename PrefixAll<TY,TAIL>::List
, typename Distribute<TYPES,TAIL>::List
>::List
List; };
struct Distribute<Node<TY,TYPES>,TAIL> { using List = typename Append< typename PrefixAll<TY,TAIL>::List
, typename Distribute<TYPES,TAIL>::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> class _ENUM_>
struct Combine { typedef typename Distribute< typename _ENUM_<X>::List
, Node<Nil,Nil>
>::List List; };
struct Combine { using List = typename Distribute< typename _ENUM_<X>::List
, NilNode
>::List; };
template< template<class> class _ENUM_>
struct Combine<Nil, _ENUM_ > { typedef NilNode List; };
struct Combine<Nil, _ENUM_ > { using List = NilNode; };
template< class TY, class TYPES
, template<class> class _ENUM_>
struct Combine<Node<TY,TYPES>,_ENUM_> { typedef typename Distribute< typename _ENUM_<TY>::List
, typename Combine<TYPES,_ENUM_>::List
>::List List; };
struct Combine<Node<TY,TYPES>,_ENUM_> { using List = typename Distribute< typename _ENUM_<TY>::List
, typename Combine<TYPES,_ENUM_>::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<class F>
struct FlagOnOff
{
typedef Node<F, Node<Nil,Nil>> List;
{
using List = Node<F, NilNode>;
};
/** 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<class FLAGS>
struct CombineFlags
{
typedef typename Combine<FLAGS, FlagOnOff>::List List;
{
using List = typename Combine<FLAGS, FlagOnOff>::List;
};

View file

@ -250,11 +250,11 @@ namespace meta {
// for finding the end we need the help of typelist-util.hpp
using PrefixList = typename SplitLast<List>::List;
using PrefixList = typename PickLast<List>::List;
using TailList = typename Tail::List;
using Prefix = typename TySeq<PrefixList>::Seq;
using End = typename SplitLast<List>::Type;
using End = typename PickLast<List>::Type;
using Last = TySeq<End>;
};
@ -320,11 +320,11 @@ namespace meta {
// for finding the end we need the help of typelist-util.hpp
typedef typename SplitLast<List>::List PrefixList;
typedef typename PickLast<List>::List PrefixList;
typedef typename Tail::List TailList;
typedef typename TyOLD<PrefixList>::Seq Prefix;
typedef typename SplitLast<List>::Type End;
typedef typename PickLast<List>::Type End;
typedef TyOLD<End> Last;
};

View file

@ -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<Args>::Type;
using OperationArglist = typename SplitLast<Args>::List;
using Memento = typename PickLast<Args>::Type;
using OperationArglist = typename PickLast<Args>::List;
using OperationArgs = typename TyOLD<OperationArglist>::Seq;
using OperateSig = typename BuildFunType<void, OperationArgs>::Sig;

View file

@ -370,133 +370,6 @@ END
TEST "Typelist manipulation" TypeListManip_test <<END
out-lit: List1 :-<1>-<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<Elm1> :-<3>-
out-lit: NList :-
out-lit: Types<Nil> :-
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

View file

@ -75,7 +75,7 @@ namespace test {
using DumpPrinter = InstantiateChained<TypeList, Printer, NullP>;
return "TUPLE"
+ DumpPrinter::print();
+ DumpPrinter::show();
}
// see the macros DISPLAY and DUMPVAL defined in typelist-diagnostics.hpp

View file

@ -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<int> 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 <string>
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<class X> struct CountDown { typedef Nil List; };
template<> struct CountDown<Num<0>> { typedef Node<Num<0>, Nil> List; };
template<int I> struct CountDown<Num<I>> { typedef Node<Num<I>, typename CountDown<Num<I-1>>::List> List; };
template<class X> struct CountDown { using List = Nil; };
template<> struct CountDown<Num<0>> { using List = Node<Num<0>, Nil>; };
template<int I> struct CountDown<Num<I>> { using List = Node<Num<I>, typename CountDown<Num<I-1>>::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<T>() % BASE::print(); }
static string show() { return _Fmt("-<%s>%s") % typeStr<T>() % BASE::show(); }
};
template<class BASE>
struct Printer<Nil, BASE>
: BASE
{
static string print () { return _Fmt("-<%u>%s") % "·" % BASE::print(); }
static string show() { return _Fmt("-<%u>%s") % "·" % BASE::show(); }
};
template<class BASE, int I>
struct Printer<Num<I>, BASE> ///< display the presence of a Num instance in the typelist
: BASE
{
static string print () { return _Fmt("-<%u>%s") % uint(Num<I>::VAL) % BASE::print(); }
static string show() { return _Fmt("-<%u>%s") % uint(Num<I>::VAL) % BASE::show(); }
};
template<class BASE, uint Fl>
struct Printer<Flag<Fl>, 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<class BASE>
struct Printer<int, BASE> ///< 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<L, Printer, NullP> SubList;
return SubList::print();
return SubList::show();
}
/** Specialisation for debug-printing of a nested sublist */
@ -153,11 +153,11 @@ namespace meta {
struct Printer<Node<TY,TYPES>, BASE>
: BASE
{
static string print ()
static string show()
{
typedef Node<TY,TYPES> List;
return string("\n\t+--") + printSublist<List>()+"+"
+ BASE::print();
+ BASE::show();
}
};
@ -165,11 +165,11 @@ namespace meta {
struct Printer<Config<f1,f2,f3,f4,f5>, BASE>
: BASE
{
static string print ()
static string show()
{
typedef typename Config<f1,f2,f3,f4,f5>::Flags FlagList;
return string("\n\t+-Conf-[") + printSublist<FlagList>()+"]"
+ BASE::print();
+ BASE::show();
}
};
@ -185,20 +185,25 @@ namespace meta {
showType ()
{
typedef InstantiateChained<typename TYPES::List, Printer, NullP> 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

View file

@ -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 <type_traits>
#include <iostream>
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<List1::List, Printer, NullP > 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<List1>() == "-<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<List2,0>::Type e0;
Pick<List2,1>::Type e1;
Pick<List2,2>::Type e2;
using E0 = Pick<List2,0>::Type;
using E1 = Pick<List2,1>::Type;
using E2 = Pick<List2,2>::Type;
using E3 = Pick<List2,3>::Type;
using NilE = Pick<Nil, 23>::Type;
using Irrelevant = Pick<void*,456>::Type;
using E3 = Pick<List2,3>::Type;
using NilE = Pick<Nil, 23>::Type;
using Bull = Pick<void*,456>::Type;
using Shit = Pick<string,0>::Type;
CHECK ((is_same<E0, Num<5> >() ));
CHECK ((is_same<E1, Num<6> >() ));
CHECK ((is_same<E2, Num<7> >() ));
CHECK ((is_same<E3, Nil >() ));
CHECK ((is_same<NilE, Nil >() ));
CHECK ((is_same<Bull, Nil >() ));
CHECK ((is_same<Shit, Nil >() ));
// 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<Nil, E3> ::value));
CHECK ((is_same<Nil, NilE> ::value));
CHECK ((is_same<Nil, Irrelevant>::value));
CHECK (7 == e2.o_);
}
void
check_append ()
verify_last()
{
using Append1 = Append<Nil, Nil>;
DISPLAY (Append1);
using Elm = PickLast<List1>::Type;
using Prefix = PickLast<List1>::List;
using Append2 = Append<Num<11>,Num<22>>;
DISPLAY (Append2);
using ElmL = TySeq<Elm>::List;
using Append3 = Append<Num<111>,Nil>;
DISPLAY (Append3);
EXPECT (Prefix, "-<1>-<2>-");
EXPECT (ElmL , "-<3>-" );
using Append4 = Append<Nil,Num<222>>;
DISPLAY (Append4);
using Elm1 = PickLast<ElmL>::Type;
using NPrefix = PickLast<ElmL>::List;
using Append5 = Append<List1,Nil>;
DISPLAY (Append5);
EXPECT (TySeq<Elm1>, "-<3>-");
EXPECT (NPrefix , "-");
using Append6 = Append<Nil,List2>;
DISPLAY (Append6);
using NilSplit = PickLast<Nil>::Type;
using NilList = PickLast<Nil>::List;
using Append7 = Append<Num<111>,List2>;
DISPLAY (Append7);
using Append8 = Append<List1,Num<222>>;
DISPLAY (Append8);
using Append9 = Append<List1,List2>;
DISPLAY (Append9);
EXPECT (TySeq<NilSplit>, "-");
EXPECT (NilList , "-");
}
/** @test append and concatenate type lists */
void
check_splice ()
verify_append ()
{
using OLi = TyOLD<Num<9>,Num<8>>::List;
using Append1 = Append<Nil , Nil >; EXPECT (Append1, "-" );
using Append2 = Append<Num<11> , Num<22> >; EXPECT (Append2, "-<11>-<22>-" );
using Append3 = Append<Num<111>, Nil >; EXPECT (Append3, "-<111>-" );
using Append4 = Append<Nil , Num<222>>; EXPECT (Append4, "-<222>-" );
using Append5 = Append<List1 , Nil >; EXPECT (Append5, "-<1>-<2>-<3>-" );
using Append6 = Append<Nil , List2 >; EXPECT (Append6, "-<5>-<6>-<7>-" );
using Append7 = Append<Num<111>, List2 >; EXPECT (Append7, "-<111>-<5>-<6>-<7>-" );
using Append8 = Append<List1 , Num<222>>; EXPECT (Append8, "-<1>-<2>-<3>-<222>-" );
using Append9 = Append<List1 , List2 >; 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<9>,Num<8>>::List;
// will "paste" the list OLi "on top" of another Typelist...
using Overl01 = Splice<Nil, Nil>;
DISPLAY (Overl01);
using Overl01 = Splice<Nil, Nil>; EXPECT (Overl01, "-");
using Overl02 = Splice<Nil, OLi>; EXPECT (Overl02, "-");
using Overl03 = Splice<Nil, OLi, 5>; EXPECT (Overl03, "-");
using Overl04 = Splice<List1, OLi>; EXPECT (Overl04, "-<9>-<8>-<3>-");
using Overl05 = Splice<List1, OLi, 1>; EXPECT (Overl05, "-<1>-<9>-<8>-");
using Overl06 = Splice<List1, OLi, 2>; EXPECT (Overl06, "-<1>-<2>-<9>-");
using Overl07 = Splice<List1, OLi, 3>; EXPECT (Overl07, "-<1>-<2>-<3>-");
using Overl08 = Splice<List1, OLi, 5>; EXPECT (Overl08, "-<1>-<2>-<3>-");
using Overl09 = Splice<List1, List1>; EXPECT (Overl09, "-<1>-<2>-<3>-");
using Overl10 = Splice<List1, List1, 1>; EXPECT (Overl10, "-<1>-<1>-<2>-");
using Overl11 = Splice<List1, Nil>; EXPECT (Overl11, "-<1>-<2>-<3>-");
using Overl12 = Splice<List1, Nil, 1>; EXPECT (Overl12, "-<1>-<2>-<3>-");
using Overl13 = Splice<List1, Nil, 5>; EXPECT (Overl13, "-<1>-<2>-<3>-");
using Overl02 = Splice<Nil, OLi>;
DISPLAY (Overl02);
using Overl03 = Splice<Nil, OLi, 5>;
DISPLAY (Overl03);
using Overl04 = Splice<List1, OLi>;
DISPLAY (Overl04);
using Overl05 = Splice<List1, OLi, 1>;
DISPLAY (Overl05);
using Overl06 = Splice<List1, OLi, 2>;
DISPLAY (Overl06);
using Overl07 = Splice<List1, OLi, 3>;
DISPLAY (Overl07);
using Overl08 = Splice<List1, OLi, 5>;
DISPLAY (Overl08);
using Overl09 = Splice<List1, List1>;
DISPLAY (Overl09);
using Overl10 = Splice<List1, List1, 1>;
DISPLAY (Overl10);
using Overl11 = Splice<List1, Nil>;
DISPLAY (Overl11);
using Overl12 = Splice<List1, Nil, 1>;
DISPLAY (Overl12);
using Overl13 = Splice<List1, Nil, 5>;
DISPLAY (Overl13);
using OLi2 = TyOLD<Num<99>>::List;
using Front1 = Splice<List1, OLi2, 0>::Front;
using Front2 = Splice<List1, OLi2, 1>::Front;
using Front3 = Splice<List1, OLi2, 5>::Front;
DISPLAY (Front1);
DISPLAY (Front2);
DISPLAY (Front3);
using Back1 = Splice<List1, OLi2, 0>::Back;
using Back2 = Splice<List1, OLi2, 1>::Back;
using Back3 = Splice<List1, OLi2, 5>::Back;
DISPLAY (Back1);
DISPLAY (Back2);
DISPLAY (Back3);
using OLi2 = TySeq<Num<99>>::List;
// can retrieve the remaining part of the original list, left and right of splice
using Front1 = Splice<List1, OLi2, 0>::Front; EXPECT (Front1, "-" );
using Front2 = Splice<List1, OLi2, 1>::Front; EXPECT (Front2, "-<1>-" );
using Front3 = Splice<List1, OLi2, 5>::Front; EXPECT (Front3, "-<1>-<2>-<3>-");
using Back1 = Splice<List1, OLi2, 0>::Back; EXPECT (Back1 , "-<2>-<3>-" );
using Back2 = Splice<List1, OLi2, 1>::Back; EXPECT (Back2 , "-<3>-" );
using Back3 = Splice<List1, OLi2, 5>::Back; EXPECT (Back3 , "-" );
// Note: with a Null-Overlay, this can be used to extract arbitrary sublists:
using Front4 = Splice<List1, Nil, 1>::Front;
using Back4 = Splice<List1, Nil, 1>::Back;
DISPLAY (Front4);
DISPLAY (Back4);
using Front4 = Splice<List1, Nil, 1>::Front; EXPECT (Front4, "-<1>-" );
using Back4 = Splice<List1, Nil, 1>::Back; EXPECT (Back4 , "-<2>-<3>-");
}
void
check_s_last()
{
using Elm = SplitLast<List1>::Type;
using Prefix = SplitLast<List1>::List;
using ElmL = TyOLD<Elm>::List;
DISPLAY (Prefix);
DISPLAY (ElmL);
using Elm1 = SplitLast<ElmL>::Type;
using NPrefix = SplitLast<ElmL>::List;
DISPLAY (NPrefix);
DISPLAY (TyOLD<Elm1>);
using NilSplit = SplitLast<Nil>::Type;
using NList = SplitLast<Nil>::List;
DISPLAY (NList);
DISPLAY (TyOLD<NilSplit>);
}
/** @test dissect and access front and back parts of a list */
void
check_dissect()
verify_dissect()
{
typedef Append<List1,List2>::List LL;
DISPLAY (LL);
using LL = Append<List1,List2>::List; EXPECT (LL , "-<1>-<2>-<3>-<5>-<6>-<7>-");
using List = Dissect<LL>::List; DISPLAY(List);
using First = Dissect<LL>::First; DISPLAY(First);
using Tail = Dissect<LL>::Tail; DISPLAY(Tail);
using Prefix = Dissect<LL>::Prefix; DISPLAY(Prefix);
using Last = Dissect<LL>::Last; DISPLAY(Last);
using List = Dissect<LL>::List; EXPECT (List , "-<1>-<2>-<3>-<5>-<6>-<7>-");
using First = Dissect<LL>::First; EXPECT (First , "-<1>-" );
using Tail = Dissect<LL>::Tail; EXPECT (Tail , "-<2>-<3>-<5>-<6>-<7>-" );
using Prefix = Dissect<LL>::Prefix; EXPECT (Prefix, "-<1>-<2>-<3>-<5>-<6>-" );
using Last = Dissect<LL>::Last; EXPECT (Last , "-<7>-" );
using Head = Dissect<LL>::Head;
using End = Dissect<LL>::End;
using HeadEnd = TyOLD<Head,End>; DISPLAY(HeadEnd);
using HeadEnd = TySeq<Head,End>; EXPECT (HeadEnd, "-<1>-<7>-");
}
@ -287,80 +258,185 @@ namespace test {
template<class X> struct AddConst2 { typedef X Type; };
template<int I> struct AddConst2<Num<I>> { typedef Num<I+2> Type; };
/** @test apply a _meta-function_ to each type in list */
void
check_apply ()
verify_apply()
{
using Added2 = Apply<List1, AddConst2>;
DISPLAY (Added2);
EXPECT (List1 , "-<1>-<2>-<3>-");
EXPECT (Added2, "-<3>-<4>-<5>-");
}
template<class X> struct IsEven { enum {value = false }; };
template<int I> struct IsEven<Num<I>> { enum {value = (0 == I % 2) }; };
/** @test filter a type list based on a meta-predicate */
void
check_filter ()
verify_filter()
{
using FilterEven = Filter<Append<List1,List2>::List, IsEven >;
DISPLAY (FilterEven);
CHECK (not IsEven<Num<5>>::value);
CHECK ( IsEven<Num<6>>::value);
using FilterEven = Filter<Append<List1,List2>::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<11>,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<Num<101>,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<Nil,List1>;
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<List1::List
,Num<0> // ◁—————————————— 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<List1::List,Num<0>,List2::List>::List;
using Prefix4 = PrefixAll<Num<111>, 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<List1,List2>;
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<List1,List_of_Lists>;
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<Num<11>, List1>;
DISPLAY (Dist1);
EXPECT (Dist1, "\n\t" "+---<11>-<1>-+"
"\n\t" "+---<11>-<2>-+"
"\n\t" "+---<11>-<3>-+-");
using Prefixes = TyOLD<Num<11>,Num<22>,Num<33>>::List;
using Dist2 = Distribute<Prefixes, Num<0>>;
DISPLAY (Dist2);
using Prefixes = TySeq<Num<11>,Num<22>,Num<33>>::List;
using Dist2 = Distribute<Prefixes, Num<0>>;
EXPECT (Dist2, "\n\t" "+---<11>-<0>-+"
"\n\t" "+---<22>-<0>-+"
"\n\t" "+---<33>-<0>-+-");
using Dist3 = Distribute<Prefixes, List1>;
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<Prefixes, TyOLD<List1::List,List2::List>::List>;
DISPLAY (Dist4);
using LioLi = TySeq<List1::List,List2::List>::List;
EXPECT (LioLi, "\n\t" "+---<1>-<2>-<3>-+"
"\n\t" "+---<5>-<6>-<7>-+-");
using Dist4 = Distribute<Prefixes, LioLi>;
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<Num<11>>;
DISPLAY (Down);
verify_combine()
{ // ▽▽▽ ———————————————defined in typelist-diagnostic.cpp
using Count = CountDown<Num<11>>;
EXPECT (Count, "-<11>-<10>-<9>-<8>-<7>-<6>-<5>-<4>-<3>-<2>-<1>-<0>-");
// Apply on a single type and tabulate
using Apply = Combine<Num<5>, 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<List1::List, CountDown>;
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<List1::List>;
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" "+---<·>-+-");
}
};

View file

@ -164257,7 +164257,7 @@ Since then others have made contributions, see the log for the history.</font></
<icon BUILTIN="button_ok"/>
</node>
</node>
<node CREATED="1748828579825" ID="ID_873142911" MODIFIED="1748869733060" TEXT="typelist-manip ist v&#xf6;llig eigenst&#xe4;ndig">
<node COLOR="#338800" CREATED="1748828579825" ID="ID_873142911" MODIFIED="1748900607872" TEXT="typelist-manip ist v&#xf6;llig eigenst&#xe4;ndig">
<richcontent TYPE="NOTE"><html>
<head>
@ -164269,6 +164269,10 @@ Since then others have made contributions, see the log for the history.</font></
</body>
</html>
</richcontent>
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1748900614743" ID="ID_516014802" MODIFIED="1748900632652" TEXT="durch Test belegt: funtioniert auch mit den neuen Type-Sequenzen">
<font NAME="SansSerif" SIZE="10"/>
</node>
</node>
<node CREATED="1748828920169" ID="ID_511778446" MODIFIED="1748869770714" TEXT="generator.hpp arbeitet ebenfalls nur auf Typlisten">
<arrowlink DESTINATION="ID_803058969" ENDARROW="Default" ENDINCLINATION="852;0;" ID="Arrow_ID_1971292758" STARTARROW="None" STARTINCLINATION="302;17;"/>
@ -164290,6 +164294,16 @@ Since then others have made contributions, see the log for the history.</font></
</richcontent>
</node>
<node CREATED="1748828781783" ID="ID_691444823" MODIFIED="1748828794388" TEXT="sollte also f&#xfc;r alle Varianten gleicherma&#xdf;en greifen"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1748888164617" ID="ID_145174722" MODIFIED="1748888298322" TEXT="sollte Tests ustellen auf Inline-Checks (mit _expect)">
<arrowlink DESTINATION="ID_1431343903" ENDARROW="Default" ENDINCLINATION="156;-14;" ID="Arrow_ID_1374886089" STARTARROW="None" STARTINCLINATION="253;316;"/>
<icon BUILTIN="yes"/>
<node CREATED="1748888193247" ID="ID_979097077" MODIFIED="1748888251981" TEXT="in der bisherigen Form sind sie ordentlich &#x2014; aber wertlos">
<icon BUILTIN="smiley-neutral"/>
</node>
<node CREATED="1748888215764" ID="ID_1132022634" MODIFIED="1748888243058" TEXT="(und ja ... diese Umstellung ist ein ziemlicher Aufwarnd)">
<font NAME="SansSerif" SIZE="11"/>
</node>
</node>
</node>
</node>
<node CREATED="1748829095135" ID="ID_1295682918" MODIFIED="1748829098145" TEXT="Funktionen">
@ -164320,16 +164334,19 @@ Since then others have made contributions, see the log for the history.</font></
</node>
</node>
</node>
<node CREATED="1748829133428" ID="ID_266502224" MODIFIED="1748829134942" TEXT="Tuple">
<node CREATED="1748829135672" ID="ID_1078202790" MODIFIED="1748829142923" TEXT="tuple-record-init">
<node COLOR="#435e98" CREATED="1748829133428" ID="ID_266502224" MODIFIED="1748884086384" TEXT="Tuple">
<node COLOR="#435e98" CREATED="1748829135672" ID="ID_1078202790" MODIFIED="1748884086383" TEXT="tuple-record-init">
<node CREATED="1748869115796" ID="ID_508891239" MODIFIED="1748869125930" TEXT="sehr wichtig f&#xfc;r GenNode via UI-Bus"/>
<node CREATED="1748869126637" ID="ID_1892597632" MODIFIED="1748869141216" TEXT="verwendet Type-Sequenze lediglich zum Re-binding eines Tuple-Typs"/>
<node COLOR="#338800" CREATED="1748869141825" ID="ID_893825351" MODIFIED="1748869166877" TEXT="kann man einfach auf die neue Variante schwenken">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1748884068125" ID="ID_12615533" MODIFIED="1748884080973" TEXT="ansonsten bereits beidseitig kompatibel">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1748829164245" ID="ID_1618911636" MODIFIED="1748829167991" TEXT="variadic-helper">
</node>
<node COLOR="#435e98" CREATED="1748829164245" ID="ID_1618911636" MODIFIED="1748884058416" TEXT="variadic-helper">
<node CREATED="1748830128123" ID="ID_450144323" MODIFIED="1748830132130" TEXT="(nur am Rande)"/>
<node CREATED="1748830132883" ID="ID_1589913777" MODIFIED="1748830138854" TEXT="IndexIter unterst&#xfc;tzt beide"/>
<node CREATED="1748830139501" ID="ID_622177889" MODIFIED="1748830160252" TEXT="ElmTypes ist nur f&#xfc;r neue (variadisch) definiert"/>
@ -164344,8 +164361,11 @@ Since then others have made contributions, see the log for the history.</font></
<node CREATED="1748829283559" ID="ID_373354659" MODIFIED="1748829291711" TEXT="h&#xe4;ngt vermutlich an Variant bzw. Visitor"/>
</node>
<node CREATED="1748829316732" ID="ID_733906672" MODIFIED="1748829324434" TEXT="Timecode-formate"/>
<node CREATED="1748829331775" ID="ID_1553022384" MODIFIED="1748829333067" TEXT="Tests">
<node CREATED="1748829335663" ID="ID_953757498" MODIFIED="1748829343651" TEXT="jeweils bei Bezug mit umstellen"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1748829331775" ID="ID_1553022384" MODIFIED="1748900515205" TEXT="Tests">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1748829335663" ID="ID_953757498" MODIFIED="1748900529301" TEXT="jeweils bei Bezug mit umstellen">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1748829344620" ID="ID_1034418764" MODIFIED="1748883769361" TEXT="im Einzelnen">
<icon BUILTIN="list"/>
<node CREATED="1748829369449" MODIFIED="1748829369449" TEXT="FormatSupport_test"/>
@ -164367,7 +164387,9 @@ Since then others have made contributions, see the log for the history.</font></
<node CREATED="1748829534601" MODIFIED="1748829534601" TEXT="MetaUtils_test"/>
<node CREATED="1748829542074" MODIFIED="1748829542074" TEXT="TupleHelper_test"/>
<node CREATED="1748829551216" MODIFIED="1748829551216" TEXT="TupleRecordInit_test"/>
<node CREATED="1748829559066" MODIFIED="1748829559066" TEXT="TypeListManip_test"/>
<node COLOR="#435e98" CREATED="1748829559066" ID="ID_1431343903" MODIFIED="1748900495968" TEXT="TypeListManip_test">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_1431343903" ENDARROW="Default" ENDINCLINATION="156;-14;" ID="Arrow_ID_1374886089" SOURCE="ID_145174722" STARTARROW="None" STARTINCLINATION="253;316;"/>
</node>
<node CREATED="1748829567920" MODIFIED="1748829567920" TEXT="TypeList_test"/>
<node COLOR="#435e98" CREATED="1748829576396" ID="ID_281104576" MODIFIED="1748883754992" TEXT="TypeListUtil_test">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_281104576" ENDARROW="Default" ENDINCLINATION="589;-82;" ID="Arrow_ID_351374746" SOURCE="ID_1470463237" STARTARROW="None" STARTINCLINATION="458;41;"/>
@ -164395,7 +164417,12 @@ Since then others have made contributions, see the log for the history.</font></
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1748871829578" ID="ID_308061484" MODIFIED="1748883860119" TEXT="Meta-Wertfunktionen in constexpr &#xfc;berf&#xfc;hren">
<icon BUILTIN="pencil"/>
</node>
<node CREATED="1748871856256" ID="ID_304666403" MODIFIED="1748871864810" TEXT="Tests vervollst&#xe4;ndigen"/>
<node CREATED="1748871856256" ID="ID_304666403" MODIFIED="1748900585714" TEXT="Tests ggfs vervollst&#xe4;ndigen">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1748900565184" ID="ID_1203054358" MODIFIED="1748900572521" TEXT="ExpectString verwenden">
<icon BUILTIN="pencil"/>
</node>
</node>
</node>
</node>