clean-up: define variadic type-sequences independently

To bootstrap this tricky refactoring, initially a bridge definition
was used, with a variadic argument pack, but delegating to the old
non-variadic type sequence and from there further into LISP style
list processing of types and meta definitions, as pioneered by the
Loki libarary. Luimiera uses this technique since a long time to
perform the complex tasks sometimes required for code generation
and generic function and type adaptation.

with this changeset, a direct variadics based entrance into
type list processing is provided, so that the old definition
is now completely separate and can be removed eventually.
This commit is contained in:
Fischlurch 2025-06-04 03:21:18 +02:00
parent 412abbace2
commit 429a7e2339
7 changed files with 115 additions and 60 deletions

View file

@ -162,14 +162,14 @@ namespace meta {
template<class H, typename TAIL>
struct BuildTupleType<Node<H, TAIL>>
{
using Seq = typename TyOLD< Node<H,TAIL>>::Seq;
using Seq = typename TySeq<Node<H,TAIL>>::Seq;
using Type = typename BuildTupleType<Seq>::Type;
};
template<>
struct BuildTupleType<Nil>
{
using Type = typename BuildTupleType<TyOLD<>>::Type;
using Type = std::tuple<>;
};
}

View file

@ -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<TS...>`.
** Interface for using this facility is the template `Types<TS...>` (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<TY,TYPES>`
** 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<class H, class T>
struct Node
{
using List = Node;
using Head = H;
using Tail = T;
};
using NilNode = Node<Nil,Nil>;
/** »Empty« mark */
struct Nil
{
using List = Nil;
};
/** Type list with head and tail;
* T Nil marks list end. */
template<class H, class T>
struct Node
{
using List = Node;
using Head = H;
using Tail = T;
};
using NilNode = Node<Nil,Nil>;
//////////////////////////////////////////////////////////////////////////////////////////////////////////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<TYPES...> variadic
* @todo 6/25 the transition is now mostly settled
* and will be completed by just _renaming_ this
* definition back into `Types<...>`
*/
template<typename...TYPES>
struct TySeq
struct TySeq;
template<typename T, typename...TS>
struct TySeq<T,TS...>
{
using Seq = TySeq;
using List = typename TyOLD<TYPES...>::List;
using List = Node<T, typename TySeq<TS...>::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

View file

@ -172,7 +172,7 @@ namespace meta {
struct Prepend<T, TySeq<TYPES...>>
{
using Seq = TySeq<T, TYPES...>;
using List = typename TyOLD<T, TYPES...>::List;
using List = typename TySeq<T, TYPES...>::List;
};
@ -195,6 +195,10 @@ namespace meta {
using List = Nil;
using Seq = TySeq<>;
};
template<>
struct TySeq<NilNode>
: TySeq<Nil>
{ };
//////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #987 temporary WORKAROUND -- to be obsoleted
@ -338,19 +342,18 @@ namespace meta {
template<class TYPES, uint i=1>
class Shifted
{
typedef typename Split<TYPES>::Tail Tail;
using Tail = typename Split<TYPES>::Tail;
public:
typedef typename Shifted<Tail,i-1>::Type Type;
typedef typename Split<Type>::Head Head;
using Type = typename Shifted<Tail,i-1>::Type;
using Head = typename Split<Type>::Head;
};
template<class TYPES>
struct Shifted<TYPES,0>
{
typedef TYPES Type;
typedef typename Split<Type>::Head Head;
using Type = TYPES;
using Head = typename Split<Type>::Head; ///< @warning may be Nil in case of an empty list
};
///////////////////////////////////////////////////////////////////////////////////TICKET #987 : reimplement for variadic type-sequences

View file

@ -112,7 +112,7 @@ namespace meta {
struct Printer<Nil, BASE>
: BASE
{
static string show() { return _Fmt("-<%u>%s") % "·" % BASE::show(); }
static string show() { return _Fmt("-<%s>%s") % "·" % BASE::show(); }
};
template<class BASE, int I>
@ -133,19 +133,19 @@ namespace meta {
struct Printer<int, BASE> ///< 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<class L>
template<class LIST>
string
printSublist ()
{
typedef InstantiateChained<L, Printer, NullP> SubList;
return SubList::show();
using PrinterChain = InstantiateChained<LIST, Printer, NullP>;
return PrinterChain::show();
}
/** Specialisation for debug-printing of a nested sublist */
@ -184,8 +184,8 @@ namespace meta {
string >
showType ()
{
typedef InstantiateChained<typename TYPES::List, Printer, NullP> DumpPrinter;
return DumpPrinter::show();
using TypeList = typename TYPES::List;
return printSublist<TypeList>();
}
// Note: we define overloads of this function for other types, especially Tuples

View file

@ -172,8 +172,8 @@ namespace test {
using NilSplit = PickLast<Nil>::Type;
using NilList = PickLast<Nil>::List;
EXPECT (TySeq<NilSplit>, "-");
EXPECT (NilList , "-");
EXPECT (NilSplit, "-");
EXPECT (NilList , "-");
}

View file

@ -136,7 +136,8 @@ namespace test {
using Head_3 = TySeq<Shifted<Seq,3>::Head>; EXPECT (Head_3, "-<1>-");
using Head_4 = TySeq<Shifted<Seq,4>::Head>; EXPECT (Head_4, "-<2>-");
using Head_5 = TySeq<Shifted<Seq,5>::Head>; EXPECT (Head_5, "-<3>-");
using Head_6 = TySeq<Shifted<Seq,6>::Head>; EXPECT (Head_6, "-");
using Head_6 = TySeq<Shifted<Seq,6>::Head>; EXPECT (Head_6, "-" );
using Head_7 = TySeq<Shifted<Seq,7>::Head>; EXPECT (Head_7, "-" );
}
@ -155,7 +156,10 @@ namespace test {
using Head = Split<Seq>::Head;
using End = Split<Seq>::End;
using HeadEnd = TySeq<Head,End>; EXPECT (HeadEnd, "-<1>-<9>-");
using Ends = TySeq<Head,End>; EXPECT (Ends , "-<1>-<9>-");
using NoList = Split<TySeq<>>::List; EXPECT (NoList, "-");
using NoHead = Split<TySeq<>>::Head; EXPECT (NoHead, "-");
}

View file

@ -164238,6 +164238,21 @@ Since then others have made contributions, see the log for the history.</font></
</node>
</node>
<node COLOR="#435e98" CREATED="1748828247849" ID="ID_476644412" MODIFIED="1748869713383" TEXT="Verbindung mit Typelisten">
<node COLOR="#338800" CREATED="1749001830758" ID="ID_91346918" MODIFIED="1749007560980" TEXT="eigenst&#xe4;ndige Konstruktion von Type-Listen hinzuf&#xfc;gen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
bisher wurde das durch Delegieren an die alte Loki-Implementierung bewerkstelligt; das nun direkt auf der Basis von Variadics zu machen, w&#228;re der zentrale Schritt, der das neue &#214;kosystem der variadischen Typlisten autonom macht (so da&#223; man am Ende die alte nicht-variadische Definition entfernen kann)
</p>
</body>
</html>
</richcontent>
<arrowlink COLOR="#8ec9a3" DESTINATION="ID_1097523075" ENDARROW="Default" ENDINCLINATION="1324;0;" ID="Arrow_ID_370033957" STARTARROW="None" STARTINCLINATION="481;24;"/>
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#435e98" CREATED="1748828313009" ID="ID_1470463237" MODIFIED="1748869832016" TEXT="R&#xfc;ckweg Typelist &#x27f6; Typsequenz">
<arrowlink DESTINATION="ID_281104576" ENDARROW="Default" ENDINCLINATION="589;-82;" ID="Arrow_ID_351374746" STARTARROW="None" STARTINCLINATION="458;41;"/>
<node CREATED="1748828416378" ID="ID_1994646495" MODIFIED="1748869656471" TEXT="es gibt eine Spezialisierung von TyOLD">
@ -164274,12 +164289,12 @@ Since then others have made contributions, see the log for the history.</font></
<font NAME="SansSerif" SIZE="10"/>
</node>
</node>
<node CREATED="1748828920169" ID="ID_511778446" MODIFIED="1748869770714" TEXT="generator.hpp arbeitet ebenfalls nur auf Typlisten">
<node COLOR="#435e98" CREATED="1748828920169" ID="ID_511778446" MODIFIED="1749003965023" 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;"/>
<node CREATED="1748828953483" ID="ID_1328523415" MODIFIED="1748828958980" TEXT="das kommt mir nun zugute"/>
<node CREATED="1748828933676" ID="ID_1716238563" MODIFIED="1748828952655" TEXT="man k&#xf6;nnte dann convenience-Front-End definieren"/>
</node>
<node CREATED="1748828754106" ID="ID_138237629" MODIFIED="1748869733060" TEXT="typelist-diagnostic ebenso">
<node COLOR="#435e98" CREATED="1748828754106" ID="ID_138237629" MODIFIED="1749003967494" TEXT="typelist-diagnostic ebenso">
<node CREATED="1748828767089" ID="ID_1047311703" MODIFIED="1748828818895" TEXT="meta::is_Typelist ist geschickt definiert">
<richcontent TYPE="NOTE"><html>
<head>
@ -164309,17 +164324,19 @@ Since then others have made contributions, see the log for the history.</font></
</node>
</node>
</node>
<node CREATED="1748829095135" ID="ID_1295682918" MODIFIED="1748829098145" TEXT="Funktionen">
<node CREATED="1748829099022" ID="ID_766756688" MODIFIED="1748829101916" TEXT="Signatur-Utils">
<node COLOR="#435e98" CREATED="1748829095135" ID="ID_1295682918" MODIFIED="1749007403090" TEXT="Funktionen">
<node COLOR="#435e98" CREATED="1748829099022" ID="ID_766756688" MODIFIED="1749007398648" TEXT="Signatur-Utils">
<node CREATED="1748829959670" ID="ID_1188075291" MODIFIED="1748829968228" TEXT="sind bereits mit beiden kompatibel"/>
</node>
<node CREATED="1748829102455" ID="ID_1254282139" MODIFIED="1748829106392" TEXT="Closure">
<node CREATED="1748829838133" ID="ID_1933174501" MODIFIED="1748829845923" TEXT="hat nur wenige Verwendungen">
<node COLOR="#338800" CREATED="1748829102455" ID="ID_1254282139" MODIFIED="1749007395415" TEXT="Closure">
<icon BUILTIN="button_ok"/>
<node CREATED="1748829838133" ID="ID_1933174501" MODIFIED="1748995159628" TEXT="wenige wichtige Verwendungen">
<node CREATED="1748829860803" ID="ID_517247632" MODIFIED="1748829863739" TEXT="Commands"/>
<node CREATED="1748829872320" ID="ID_568804131" MODIFIED="1748829875428" TEXT="Random-Draw"/>
<node CREATED="1748829881837" ID="ID_1354679657" MODIFIED="1748829885400" TEXT="tuple-closure"/>
<node CREATED="1748829890844" ID="ID_1803577911" MODIFIED="1748829894782" TEXT="view-spec-dsl"/>
</node>
<node CREATED="1749007506535" ID="ID_240022720" MODIFIED="1749007506535" TEXT="mu&#xdf; auf einen Schlag geschwenkt werden (Komplexit&#xe4;t)"/
<node CREATED="1748829733384" ID="ID_83679265" MODIFIED="1748829744922" TEXT="sollte sich bereits ohne weiteres schwenken lassen"/>
<node CREATED="1748829745682" ID="ID_61352432" MODIFIED="1748829759664" TEXT="erzeugt nur Tuple, oder macht Split / Prepend"/>
<node CREATED="1748829779637" ID="ID_1158113558" MODIFIED="1748829835939" TEXT="man k&#xf6;nnte dann im Nachgang die Apply-Definition eliminieren">
@ -164394,7 +164411,7 @@ Since then others have made contributions, see the log for the history.</font></
<node CREATED="1748829468217" MODIFIED="1748829468217" TEXT="SessionServiceAccess_test"/>
<node CREATED="1748829480048" MODIFIED="1748829480048" TEXT="FunctionClosure_test"/>
<node CREATED="1748829502213" MODIFIED="1748829502213" TEXT="FunctionComposition_test"/>
<node CREATED="1748829512571" MODIFIED="1748829512571" TEXT="GeneratorCombinations_test"/>
<node COLOR="#435e98" CREATED="1748829512571" ID="ID_1542151497" MODIFIED="1749007468620" TEXT="GeneratorCombinations_test"/>
<node COLOR="#435e98" CREATED="1748829523737" ID="ID_803058969" MODIFIED="1748883754992" TEXT="TypeListGenerator_test">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_803058969" ENDARROW="Default" ENDINCLINATION="852;0;" ID="Arrow_ID_1971292758" SOURCE="ID_511778446" STARTARROW="None" STARTINCLINATION="302;17;"/>
</node>
@ -164415,7 +164432,9 @@ Since then others have made contributions, see the log for the history.</font></
<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;"/>
</node>
<node CREATED="1748829567920" ID="ID_1097523075" MODIFIED="1748959903101" TEXT="TypeList_test"/>
<node COLOR="#435e98" CREATED="1748829567920" ID="ID_1097523075" MODIFIED="1749007565198" TEXT="TypeList_test">
<linktarget COLOR="#8ec9a3" DESTINATION="ID_1097523075" ENDARROW="Default" ENDINCLINATION="1324;0;" ID="Arrow_ID_370033957" SOURCE="ID_91346918" STARTARROW="None" STARTINCLINATION="481;24;"/>
</node>
<node CREATED="1748829607017" MODIFIED="1748829607017" TEXT="Variant_test"/>
</node>
</node>