diff --git a/src/lib/meta/tuple-helper.hpp b/src/lib/meta/tuple-helper.hpp index cdf4b885d..122c79133 100644 --- a/src/lib/meta/tuple-helper.hpp +++ b/src/lib/meta/tuple-helper.hpp @@ -162,14 +162,14 @@ namespace meta { template struct BuildTupleType> { - using Seq = typename TyOLD< Node>::Seq; + using Seq = typename TySeq>::Seq; using Type = typename BuildTupleType::Type; }; template<> struct BuildTupleType { - using Type = typename BuildTupleType>::Type; + using Type = std::tuple<>; }; } diff --git a/src/lib/meta/typelist.hpp b/src/lib/meta/typelist.hpp index 6053b3c57..e58ff839d 100644 --- a/src/lib/meta/typelist.hpp +++ b/src/lib/meta/typelist.hpp @@ -31,22 +31,32 @@ This code is heavily inspired by /** @file typelist.hpp ** A template metaprogramming technique for manipulating collections of types. - ** Effectively this is a tailored and simplified version of what can be found in the Loki library. - ** We use it in other generic library-style code to generate repetitive code. + ** - **Type Sequences** are used to transport a variadic sequence of types + ** - **Type Lists** (»Loki style«) can be created from a type sequence and + ** represent the same information by _nodes_ with _head_ and _tail_. + ** The latter brings LISP style recursive manipulation techniques into the + ** realm of type metaprogramming; this approach was pioneered with the + ** **Loki Library** by Alexandrescu (2001) and makes complex processing + ** much easier to write and to understand following. Effectively the set + ** of definitions used here is a tailored version of what could be found + ** in the Loki library, and was in the following years integrated with + ** processing of variadics, function manipulation and std::tuple. + ** This framework is typically used to generate repetitive code, + ** based on a collection of types, with type-specific adaptations. ** @remark If you tend to find the use of template metaprogramming detrimental ** (or functional programming and generally any kind of abstraction) ** please kindly ignore the technical details and just consider the ** benefit of simplification for the client code. ** - ** Interface for using this facility is the template `Types`. + ** Interface for using this facility is the template `Types` (the type sequence). ** To start typelist processing, other templates typically pick up the Types<...>::List type. ** This allows for LISP-style list processing, with a pattern match on either `Node` ** or the type `Nil` to terminate recursion. In C++ template metaprogramming, "pattern match" ** is done by partial template specialisations (the compiler will pick up and thus - ** match the template parameters). A typedef acts like a declaration in normal - ** programming. Because such a "declaration" can't be changed after the fact, - ** effectively this is a flavour of functional programming. Just the - ** "execution environment" is the compiler, during compilation. + ** match the template parameters). A type definition acts like a variable declaration + ** in regular programming. Because such a "declaration" can't be changed after the fact, + ** effectively this is a flavour of functional programming; the _execution environment_ + ** is the compiler, and evaluation is set off by some template instantiation. ** ** @warning the metaprogramming part of Lumiera to deal with type sequences is in a ** state of transition, since C++11 now offers direct language support for @@ -59,10 +69,12 @@ This code is heavily inspired by ** since the latter can only be rebound through pattern matching. ** @todo transition lib::meta::Types to variadic parameters /////////////////////////////////TICKET #987 ** - ** @see lib::visitor::Applicable usage example - ** @see control::CommandSignature more elaborate usage example (dissecting a functor signature) ** @see TypeList_test ** @see TypeListManip_test + ** @see TypeSecManip_test + ** @see function.hpp + ** @see tuple-helper.hpp + ** @see variadic-helper.hpp ** */ @@ -75,24 +87,28 @@ This code is heavily inspired by namespace lib { namespace meta { - - struct Nil - { - using List = Nil; - }; - - template - struct Node - { - using List = Node; - using Head = H; - using Tail = T; - }; - - using NilNode = Node; - - - + + /** »Empty« mark */ + struct Nil + { + using List = Nil; + }; + + /** Type list with head and tail; + * T ≡ Nil marks list end. */ + template + struct Node + { + using List = Node; + using Head = H; + using Tail = T; + }; + + using NilNode = Node; + + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #987 : this is the old non-variadic definition from lib Loki -- it will be obsoleted with the transition template < class T01=Nil , class T02=Nil @@ -135,7 +151,7 @@ namespace meta { }; - //////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #987 temporary WORKAROUND -- to be obsoleted + //////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #987 temporary WORKAROUND -- transition to variadic type-sequences /** * temporary workaround: * alternative definition of "type sequence", @@ -147,13 +163,26 @@ namespace meta { * entries do not play well with other variadic defs. * @deprecated when we switch our primary type sequence type * to variadic parameters, this type will be obsoleted. ////////////////////////////////////TICKET #987 : make lib::meta::Types variadic + * @todo 6/25 the transition is now mostly settled + * and will be completed by just _renaming_ this + * definition back into `Types<...>` */ template - struct TySeq + struct TySeq; + + template + struct TySeq { - using Seq = TySeq; - using List = typename TyOLD::List; + using List = Node::List>; + using Seq = TySeq; }; - //////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #987 temporary WORKAROUND(End) -- to be obsoleted + + template<> + struct TySeq<> + { + using List = Nil; + using Seq = TySeq<>; + }; + }} // namespace lib::meta #endif diff --git a/src/lib/meta/typeseq-util.hpp b/src/lib/meta/typeseq-util.hpp index f0771b7da..13546dd52 100644 --- a/src/lib/meta/typeseq-util.hpp +++ b/src/lib/meta/typeseq-util.hpp @@ -172,7 +172,7 @@ namespace meta { struct Prepend> { using Seq = TySeq; - using List = typename TyOLD::List; + using List = typename TySeq::List; }; @@ -195,6 +195,10 @@ namespace meta { using List = Nil; using Seq = TySeq<>; }; + template<> + struct TySeq + : TySeq + { }; //////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #987 temporary WORKAROUND -- to be obsoleted @@ -338,19 +342,18 @@ namespace meta { template class Shifted { - typedef typename Split::Tail Tail; + using Tail = typename Split::Tail; public: - typedef typename Shifted::Type Type; - typedef typename Split::Head Head; + using Type = typename Shifted::Type; + using Head = typename Split::Head; }; template struct Shifted { - typedef TYPES Type; - typedef typename Split::Head Head; + using Type = TYPES; + using Head = typename Split::Head; ///< @warning may be Nil in case of an empty list }; - ///////////////////////////////////////////////////////////////////////////////////TICKET #987 : reimplement for variadic type-sequences diff --git a/tests/library/meta/typelist-diagnostics.hpp b/tests/library/meta/typelist-diagnostics.hpp index f2c1c16e0..0b27c4493 100644 --- a/tests/library/meta/typelist-diagnostics.hpp +++ b/tests/library/meta/typelist-diagnostics.hpp @@ -112,7 +112,7 @@ namespace meta { struct Printer : BASE { - static string show() { return _Fmt("-<%u>%s") % "·" % BASE::show(); } + static string show() { return _Fmt("-<%s>%s") % "·" % BASE::show(); } }; template @@ -133,19 +133,19 @@ namespace meta { struct Printer ///< display the presence of a plain int in the typelist : BASE { - static string show() { return _Fmt("-<%u>%s") % 'i' % BASE::show(); } + static string show() { return _Fmt("-<%s>%s") % 'i' % BASE::show(); } }; /** call the debug-print for a typelist * utilising the Printer template */ - template + template string printSublist () { - typedef InstantiateChained SubList; - return SubList::show(); + using PrinterChain = InstantiateChained; + return PrinterChain::show(); } /** Specialisation for debug-printing of a nested sublist */ @@ -184,8 +184,8 @@ namespace meta { string > showType () { - typedef InstantiateChained DumpPrinter; - return DumpPrinter::show(); + using TypeList = typename TYPES::List; + return printSublist(); } // Note: we define overloads of this function for other types, especially Tuples diff --git a/tests/library/meta/typelist-manip-test.cpp b/tests/library/meta/typelist-manip-test.cpp index 1c76703e1..6a2915ed4 100644 --- a/tests/library/meta/typelist-manip-test.cpp +++ b/tests/library/meta/typelist-manip-test.cpp @@ -172,8 +172,8 @@ namespace test { using NilSplit = PickLast::Type; using NilList = PickLast::List; - EXPECT (TySeq, "-"); - EXPECT (NilList , "-"); + EXPECT (NilSplit, "-"); + EXPECT (NilList , "-"); } diff --git a/tests/library/meta/typeseq-manip-test.cpp b/tests/library/meta/typeseq-manip-test.cpp index b1df48ced..6077b7349 100644 --- a/tests/library/meta/typeseq-manip-test.cpp +++ b/tests/library/meta/typeseq-manip-test.cpp @@ -136,7 +136,8 @@ namespace test { using Head_3 = TySeq::Head>; EXPECT (Head_3, "-<1>-"); using Head_4 = TySeq::Head>; EXPECT (Head_4, "-<2>-"); using Head_5 = TySeq::Head>; EXPECT (Head_5, "-<3>-"); - using Head_6 = TySeq::Head>; EXPECT (Head_6, "-"); + using Head_6 = TySeq::Head>; EXPECT (Head_6, "-" ); + using Head_7 = TySeq::Head>; EXPECT (Head_7, "-" ); } @@ -155,7 +156,10 @@ namespace test { using Head = Split::Head; using End = Split::End; - using HeadEnd = TySeq; EXPECT (HeadEnd, "-<1>-<9>-"); + using Ends = TySeq; EXPECT (Ends , "-<1>-<9>-"); + + using NoList = Split>::List; EXPECT (NoList, "-"); + using NoHead = Split>::Head; EXPECT (NoHead, "-"); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 04dab7a16..78c682f12 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -164238,6 +164238,21 @@ Since then others have made contributions, see the log for the history. + + + + + + +

+ bisher wurde das durch Delegieren an die alte Loki-Implementierung bewerkstelligt; das nun direkt auf der Basis von Variadics zu machen, wäre der zentrale Schritt, der das neue Ökosystem der variadischen Typlisten autonom macht (so daß man am Ende die alte nicht-variadische Definition entfernen kann) +

+ + +
+ + +
@@ -164274,12 +164289,12 @@ Since then others have made contributions, see the log for the history. - + - + @@ -164309,17 +164324,19 @@ Since then others have made contributions, see the log for the history. - - + + - - + + + + @@ -164394,7 +164411,7 @@ Since then others have made contributions, see the log for the history. - + @@ -164415,7 +164432,9 @@ Since then others have made contributions, see the log for the history. - + + +