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> template<class H, typename TAIL>
struct BuildTupleType<Node<H, 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; using Type = typename BuildTupleType<Seq>::Type;
}; };
template<> template<>
struct BuildTupleType<Nil> 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 /** @file typelist.hpp
** A template metaprogramming technique for manipulating collections of types. ** 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. ** - **Type Sequences** are used to transport a variadic sequence of types
** We use it in other generic library-style code to generate repetitive code. ** - **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 ** @remark If you tend to find the use of template metaprogramming detrimental
** (or functional programming and generally any kind of abstraction) ** (or functional programming and generally any kind of abstraction)
** please kindly ignore the technical details and just consider the ** please kindly ignore the technical details and just consider the
** benefit of simplification for the client code. ** 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. ** 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>` ** 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" ** 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 ** 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 ** match the template parameters). A type definition acts like a variable declaration
** programming. Because such a "declaration" can't be changed after the fact, ** in regular programming. Because such a "declaration" can't be changed after the fact,
** effectively this is a flavour of functional programming. Just the ** effectively this is a flavour of functional programming; the _execution environment_
** "execution environment" is the compiler, during compilation. ** 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 ** @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 ** 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. ** since the latter can only be rebound through pattern matching.
** @todo transition lib::meta::Types to variadic parameters /////////////////////////////////TICKET #987 ** @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 TypeList_test
** @see TypeListManip_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 lib {
namespace meta { namespace meta {
struct Nil /** »Empty« mark */
{ struct Nil
using List = Nil; {
}; using List = Nil;
};
template<class H, class T>
struct Node /** Type list with head and tail;
{ * T ≡ Nil marks list end. */
using List = Node; template<class H, class T>
using Head = H; struct Node
using Tail = T; {
}; using List = Node;
using Head = H;
using NilNode = Node<Nil,Nil>; 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 template
< class T01=Nil < class T01=Nil
, class T02=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: * temporary workaround:
* alternative definition of "type sequence", * alternative definition of "type sequence",
@ -147,13 +163,26 @@ namespace meta {
* entries do not play well with other variadic defs. * entries do not play well with other variadic defs.
* @deprecated when we switch our primary type sequence type * @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 * 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> template<typename...TYPES>
struct TySeq struct TySeq;
template<typename T, typename...TS>
struct TySeq<T,TS...>
{ {
using Seq = TySeq; using List = Node<T, typename TySeq<TS...>::List>;
using List = typename TyOLD<TYPES...>::List; using Seq = TySeq;
}; };
//////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #987 temporary WORKAROUND(End) -- to be obsoleted
template<>
struct TySeq<>
{
using List = Nil;
using Seq = TySeq<>;
};
}} // namespace lib::meta }} // namespace lib::meta
#endif #endif

View file

@ -172,7 +172,7 @@ namespace meta {
struct Prepend<T, TySeq<TYPES...>> struct Prepend<T, TySeq<TYPES...>>
{ {
using Seq = TySeq<T, 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 List = Nil;
using Seq = TySeq<>; using Seq = TySeq<>;
}; };
template<>
struct TySeq<NilNode>
: TySeq<Nil>
{ };
//////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #987 temporary WORKAROUND -- to be obsoleted //////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #987 temporary WORKAROUND -- to be obsoleted
@ -338,19 +342,18 @@ namespace meta {
template<class TYPES, uint i=1> template<class TYPES, uint i=1>
class Shifted class Shifted
{ {
typedef typename Split<TYPES>::Tail Tail; using Tail = typename Split<TYPES>::Tail;
public: public:
typedef typename Shifted<Tail,i-1>::Type Type; using Type = typename Shifted<Tail,i-1>::Type;
typedef typename Split<Type>::Head Head; using Head = typename Split<Type>::Head;
}; };
template<class TYPES> template<class TYPES>
struct Shifted<TYPES,0> struct Shifted<TYPES,0>
{ {
typedef TYPES Type; using Type = TYPES;
typedef typename Split<Type>::Head Head; 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> struct Printer<Nil, BASE>
: 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> 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 struct Printer<int, BASE> ///< display the presence of a plain int in the typelist
: BASE : 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 /** call the debug-print for a typelist
* utilising the Printer template */ * utilising the Printer template */
template<class L> template<class LIST>
string string
printSublist () printSublist ()
{ {
typedef InstantiateChained<L, Printer, NullP> SubList; using PrinterChain = InstantiateChained<LIST, Printer, NullP>;
return SubList::show(); return PrinterChain::show();
} }
/** Specialisation for debug-printing of a nested sublist */ /** Specialisation for debug-printing of a nested sublist */
@ -184,8 +184,8 @@ namespace meta {
string > string >
showType () showType ()
{ {
typedef InstantiateChained<typename TYPES::List, Printer, NullP> DumpPrinter; using TypeList = typename TYPES::List;
return DumpPrinter::show(); return printSublist<TypeList>();
} }
// Note: we define overloads of this function for other types, especially Tuples // 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 NilSplit = PickLast<Nil>::Type;
using NilList = PickLast<Nil>::List; using NilList = PickLast<Nil>::List;
EXPECT (TySeq<NilSplit>, "-"); EXPECT (NilSplit, "-");
EXPECT (NilList , "-"); EXPECT (NilList , "-");
} }

View file

@ -136,7 +136,8 @@ namespace test {
using Head_3 = TySeq<Shifted<Seq,3>::Head>; EXPECT (Head_3, "-<1>-"); 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_4 = TySeq<Shifted<Seq,4>::Head>; EXPECT (Head_4, "-<2>-");
using Head_5 = TySeq<Shifted<Seq,5>::Head>; EXPECT (Head_5, "-<3>-"); 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 Head = Split<Seq>::Head;
using End = Split<Seq>::End; 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> </node>
<node COLOR="#435e98" CREATED="1748828247849" ID="ID_476644412" MODIFIED="1748869713383" TEXT="Verbindung mit Typelisten"> <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"> <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;"/> <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"> <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"/> <font NAME="SansSerif" SIZE="10"/>
</node> </node>
</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;"/> <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="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 CREATED="1748828933676" ID="ID_1716238563" MODIFIED="1748828952655" TEXT="man k&#xf6;nnte dann convenience-Front-End definieren"/>
</node> </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"> <node CREATED="1748828767089" ID="ID_1047311703" MODIFIED="1748828818895" TEXT="meta::is_Typelist ist geschickt definiert">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head>
@ -164309,17 +164324,19 @@ Since then others have made contributions, see the log for the history.</font></
</node> </node>
</node> </node>
</node> </node>
<node CREATED="1748829095135" ID="ID_1295682918" MODIFIED="1748829098145" TEXT="Funktionen"> <node COLOR="#435e98" CREATED="1748829095135" ID="ID_1295682918" MODIFIED="1749007403090" TEXT="Funktionen">
<node CREATED="1748829099022" ID="ID_766756688" MODIFIED="1748829101916" TEXT="Signatur-Utils"> <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 CREATED="1748829959670" ID="ID_1188075291" MODIFIED="1748829968228" TEXT="sind bereits mit beiden kompatibel"/>
</node> </node>
<node CREATED="1748829102455" ID="ID_1254282139" MODIFIED="1748829106392" TEXT="Closure"> <node COLOR="#338800" CREATED="1748829102455" ID="ID_1254282139" MODIFIED="1749007395415" TEXT="Closure">
<node CREATED="1748829838133" ID="ID_1933174501" MODIFIED="1748829845923" TEXT="hat nur wenige Verwendungen"> <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="1748829860803" ID="ID_517247632" MODIFIED="1748829863739" TEXT="Commands"/>
<node CREATED="1748829872320" ID="ID_568804131" MODIFIED="1748829875428" TEXT="Random-Draw"/> <node CREATED="1748829872320" ID="ID_568804131" MODIFIED="1748829875428" TEXT="Random-Draw"/>
<node CREATED="1748829881837" ID="ID_1354679657" MODIFIED="1748829885400" TEXT="tuple-closure"/> <node CREATED="1748829881837" ID="ID_1354679657" MODIFIED="1748829885400" TEXT="tuple-closure"/>
<node CREATED="1748829890844" ID="ID_1803577911" MODIFIED="1748829894782" TEXT="view-spec-dsl"/> <node CREATED="1748829890844" ID="ID_1803577911" MODIFIED="1748829894782" TEXT="view-spec-dsl"/>
</node> </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="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="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"> <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="1748829468217" MODIFIED="1748829468217" TEXT="SessionServiceAccess_test"/>
<node CREATED="1748829480048" MODIFIED="1748829480048" TEXT="FunctionClosure_test"/> <node CREATED="1748829480048" MODIFIED="1748829480048" TEXT="FunctionClosure_test"/>
<node CREATED="1748829502213" MODIFIED="1748829502213" TEXT="FunctionComposition_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"> <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;"/> <linktarget COLOR="#a9b4c1" DESTINATION="ID_803058969" ENDARROW="Default" ENDINCLINATION="852;0;" ID="Arrow_ID_1971292758" SOURCE="ID_511778446" STARTARROW="None" STARTINCLINATION="302;17;"/>
</node> </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"> <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;"/> <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>
<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 CREATED="1748829607017" MODIFIED="1748829607017" TEXT="Variant_test"/>
</node> </node>
</node> </node>