From 61f8c1814dab1d1848859a4e5fb29b232033fb57 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 22 Jun 2009 06:05:32 +0200 Subject: [PATCH] tuple test pass --- src/lib/meta/tuple.hpp | 58 +++++++++------ tests/40components.tests | 109 ++++++++++++++++++++++++++++- tests/lib/meta/type-tuple-test.cpp | 94 ++++++++++++++++--------- 3 files changed, 207 insertions(+), 54 deletions(-) diff --git a/src/lib/meta/tuple.hpp b/src/lib/meta/tuple.hpp index 3876c7a88..d8e4c8d39 100644 --- a/src/lib/meta/tuple.hpp +++ b/src/lib/meta/tuple.hpp @@ -22,13 +22,13 @@ /** @file tuple.hpp - ** Metaprogramming with tuples-of-types and a very simple Tuple datatype. + ** Metaprogramming with tuples-of-types and a simple Tuple (record) datatype. ** The metaprogramming part of this header complements typelist.hpp and allows ** to re-build a new tuple-of-types from an existing typelist. Such a finite - ** tuple of types can at times be more handy than a typelist, especially when - ** capturing specific types to use as template parameter. + ** sequence or tuple of types can at times be more handy than a typelist, + ** especially when capturing specific types to use as template parameter. ** - ** Additionally, this header augments the Tuple template into a very simple Tuple + ** Additionally, this header augments the Tuple template into a simple Tuple ** (run time) datatype. This isn't meant as competing with std::tr1::tuple, which is ** much more capable, but also has the downside of pulling in a lot of other headers. ** But when all we need is to define a generic typed record of N data elements and @@ -55,8 +55,8 @@ namespace lumiera { namespace typelist{ - - + + /** * Helper: prepend a type to an existing type sequence, @@ -99,6 +99,8 @@ namespace typelist{ , T06,T07,T08,T09,T10 , T11,T12,T13,T14,T15 , T16,T17,T18,T19,T20 > Tuple; + + typedef typename Tuple::List List; }; @@ -171,13 +173,23 @@ namespace typelist{ typedef TYPES Type; typedef typename Split::Head Head; }; - + /** * simple generic Tuple datatype. * Usable both for metaprogramming and as a generic record. * The types within this tuple can either be specified - * as Type sequence or as typelist + * as Type sequence or as typelist. Default and canonical + * is the type-sequence based tuple form \c Tuple> + * The secondary from of specifying a tuple is based on a typelist + * (and this form is used actually to implement the storage, while + * the plain-flat (type sequence based) form acts as interface. + * + * Irrespective of the flavour actually used, you can always + * - get the canonical TupleType (sequence based) + * - get the types of head and tail, and a list version of the types + * - access the head element and the tail tuple + * - access the Nth element and a shifted-b-N sub (tail) tuple */ template struct Tuple; @@ -248,6 +260,7 @@ namespace typelist{ typedef Tuple Type; }; + template typename ShiftedTuple::Type& getShifted () @@ -375,6 +388,8 @@ namespace typelist{ + /* ====== Helpers for working with Tuples ========= */ + namespace tuple { // some convenience access functions template @@ -494,9 +509,10 @@ namespace typelist{ return Tuple > (a1,a2,a3,a4,a5,a6,a7,a8,a9); } - } - - + } // (END) access / tuple building helper functions (namespace tuple) + + + /** Trait template for detecting a type tuple */ template class is_Tuple @@ -504,7 +520,7 @@ namespace typelist{ template struct Check { typedef No_t It; }; template struct Check > { typedef Yes_t It; }; - public: + public: static const bool value = (sizeof(Yes_t)==sizeof(typename Check::It)); }; @@ -513,7 +529,7 @@ namespace typelist{ template class is_TupleListType { - template + template struct Check { enum{ result = sizeof(No_t)}; @@ -546,7 +562,7 @@ namespace typelist{ template class is_NullTuple { - template + template struct Check { enum{ result = sizeof(No_t)}; @@ -555,9 +571,9 @@ namespace typelist{ template struct Check > { - Yes_t check(Types<>*); - Yes_t check(NullType*); - No_t check(...); + Yes_t static check(Types<>*); + Yes_t static check(NullType*); + No_t static check(...); enum{ result = sizeof(check( (TY*)0)) }; }; @@ -565,7 +581,7 @@ namespace typelist{ public: static const bool value = (sizeof(Yes_t)== Check::result); }; - + /** * Decorating a tuple type with auxiliary data access operations. @@ -576,13 +592,13 @@ namespace typelist{ * type of the individual elements within the Tuple. To achieve this, for each * type within the Tuple, the BASE type is decorated with an instance of the * template passed in as template template parameter _X_. Each of these - * decorating instances is provided with a member pointer to access "his" + * decorating instances is provided with a index allowing to access "his" * specific element within the underlying tuple. * * The decorating template _X_ need to take its own base class as template * parameter. Typically, operations on _X_ will be defined in a recursive fashion, * calling down into this templated base class. To support this, an instantiation - * of _X_ with the 0 member ptr is generated for detecting recursion end + * of _X_ with the empty type sequence is generated for detecting recursion end * (built as innermost decorator, i.e. immediate subclass of BASE) */ template @@ -645,7 +661,7 @@ namespace typelist{ }; - + }} // namespace lumiera::typelist diff --git a/tests/40components.tests b/tests/40components.tests index 7e48db913..ba3050091 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -562,7 +562,114 @@ return: 0 END -PLANNED "TypeTuple_test" TypeTuple_test <-<3>-<5>- +out: L2 :-<2>-<4>- +out: L3 :-<7>- +out: Tup1 :TYPES-<>-<1>-<3>-<5>- +out: Tup1\(\) :...Tuple\(\(1\),\(3\),\(5\)\) +out: tup1x :...Tuple\(\{11\},\(3\),\(5\)\) +out: Type1 :-<1>-<3>-<5>- +out: T_L1 :TYPES-\[\]-<1>-<3>-<5>- +out: T1 :TYPES-<>-<1>-<3>-<5>- +out: tup1 :...Tuple\(\{8\},\(3\),\(5\)\) +out: tup2 :...Tuple\(\{9\},\(3\),\(5\)\) +out: Prepend :TYPES-\[\]--<1>-<3>-<5>- +out: prepend :...Tuple\(22,\{9\},\(3\),\(5\)\) +out: :$ +out: : ---Sub-Tuple-Types---- +out: T_L2 :TYPES-\[\]-<2>-<4>-<1>-<3>-<5>- +out: Head :-<2>- +out: Tail :-<4>-<1>-<3>-<5>- +out: T2 :TYPES-<>-<2>-<4>-<1>-<3>-<5>- +out: Head2 :-<2>- +out: Tail2 :-<4>-<1>-<3>-<5>- +out: T2::Type :-<2>-<4>-<1>-<3>-<5>- +out: T2::TailType :-<4>-<1>-<3>-<5>- +out: T2::TupleType :TYPES-<>-<2>-<4>-<1>-<3>-<5>- +out: T2::ThisType :TYPES-<>-<2>-<4>-<1>-<3>-<5>- +out: T2::Tail :TYPES-<>-<4>-<1>-<3>-<5>- +out: T2::ArgList :-<2>-<4>-<1>-<3>-<5>- +out: T_L2::Type :-<2>-<4>-<1>-<3>-<5>- +out: T_L2::TailType :-<4>-<1>-<3>-<5>- +out: T_L2::TupleType :TYPES-<>-<2>-<4>-<1>-<3>-<5>- +out: T_L2::ThisType :TYPES-\[\]-<2>-<4>-<1>-<3>-<5>- +out: T_L2::Tail :TYPES-\[\]-<4>-<1>-<3>-<5>- +out: T_L2::ArgList :-<2>-<4>-<1>-<3>-<5>- +out: NulT::Type :- +out: NulT::TailType :- +out: NulT::TupleType :TYPES-<>- +out: NulT::ThisType :TYPES-<>- +out: NulT::Tail :TYPES-<>- +out: NulT::ArgList :- +out: NulL::Type :- +out: NulL::TailType :- +out: NulL::TupleType :TYPES-<>- +out: NulL::ThisType :TYPES-\[\]- +out: NulL::Tail :TYPES-\[\]- +out: NulL::ArgList :- +out: :$ +out: : ---Shifted-Tuple--- +out: Ty_0 :-<2>-<4>-<7>- +out: Ty_1 :-<4>-<7>- +out: Ty_2 :-<7>- +out: Ty_3 :- +out: Ty_4 :- +out: T_0 :TYPES-\[\]-<2>-<4>-<7>- +out: T_1 :TYPES-\[\]-<4>-<7>- +out: T_2 :TYPES-\[\]-<7>- +out: T_3 :TYPES-\[\]- +out: T_4 :TYPES-\[\]- +out: tu3 :...Tuple\(\(2\),\(4\),\(7\)\) +out: tu3_0 :...Tuple\(\(2\),\(4\),\(7\)\) +out: tu3_1 :...Tuple\(\(4\),\(7\)\) +out: tu3_2 :...Tuple\(\(7\)\) +out: tu3_3 :...Tuple\(\) +out: tu3_4 :...Tuple\(\) +out: :$ +out: : ---creating-Tuples--- +out: tup1 :...Tuple\(\(1\),\(3\),\(5\)\) +out: tup11 :...Tuple\(\{11\},\(3\),\(5\)\) +out: tup12 :...Tuple\(\(1\),\{33\},\(5\)\) +out: tup13 :...Tuple\(\{11\},\{33\},\(5\)\) +out: Tup2 :TYPES-<>---<11>- +out: tup2 :...Tuple\(41,42,\{43\}\) +out: Tup22 :TYPES-<>--<11>- +out: tup22 :...Tuple\(42,\{43\}\) +out: Tup222 :TYPES-<>-<11>- +out: tup222 :...Tuple\(\{43\}\) +out: T0T :TYPES-<>- +out: T0L :TYPES-\[\]- +out: nullT :...Tuple\(\) +out: nullL :...Tuple\(\) +out: nulTcpy :...Tuple\(\) +out: nulTref :...Tuple\(\) +out: :$ +out: : ---copy-operations--- +out: tup1 :...Tuple\(\{11\},\{33\},\(5\)\) +out: tup11 :...Tuple\(\{11\},\{33\},\{44\}\) +out: tup1 :...Tuple\(\{11\},\{33\},\{44\}\) +out: tupL :...Tuple\(\{11\},\{33\},\{44\}\) +out: tup1L :...Tuple\(\{11\},\{33\},\{44\}\) +out: :$ +out: : ---value-access--- +out: TupX :TYPES-\[\]-<2>-<4>-<2>-<4>- +out: tupX :...Tuple\(\(2\),\(4\),\(2\),\(4\)\) +out: tu2 :...Tuple\(\(2\),\(4\)\) +out: tu2 :...Tuple\(\{5\},\{5\}\) +out: tupX :...Tuple\(\(2\),\(4\),\{5\},\{5\}\) +out: T4 :TYPES-<>-<2>-<4>- +out: t4 :...Tuple\(\{5\},\{5\}\) +out: TupX::Type :-<2>-<4>-<2>-<4>- +out: TupX::TailType :-<4>-<2>-<4>- +out: TupX::ThisType :TYPES-\[\]-<2>-<4>-<2>-<4>- +out: TupX::TupleType :TYPES-<>-<2>-<4>-<2>-<4>- +out: TupT::Type :-<2>-<4>-<2>-<4>- +out: TupT::TailType :-<4>-<2>-<4>- +out: TupT::ThisType :TYPES-<>-<2>-<4>-<2>-<4>- +out: TupT::TupleType :TYPES-<>-<2>-<4>-<2>-<4>- +out: tupXcopy :...Tuple\(\(2\),\(4\),\{5\},\{5\}\) +out: tupXcast :...Tuple\(\(2\),\(4\),\{5\},\{5\}\) return: 0 END diff --git a/tests/lib/meta/type-tuple-test.cpp b/tests/lib/meta/type-tuple-test.cpp index d8de75bd3..80f15929a 100644 --- a/tests/lib/meta/type-tuple-test.cpp +++ b/tests/lib/meta/type-tuple-test.cpp @@ -22,8 +22,8 @@ /** @file type-tuple-test.cpp - ** Interconnection of typelists, type tuples and simple record - ** data types build on top of them. + ** Interplay of typelists, type tuples and simple record + ** data types build on top of them. ** ** @see lumiera::typelist::Tuple ** @see tuple.hpp @@ -34,18 +34,13 @@ #include "lib/test/run.hpp" -#include "lib/meta/typelist.hpp" ////////////TODO really? #include "lib/meta/tuple.hpp" #include "meta/typelist-diagnostics.hpp" #include "meta/tuple-diagnostics.hpp" -#include -#include #include using ::test::Test; - -using std::string; using std::cout; using std::endl; @@ -81,9 +76,10 @@ namespace test { * - build a tuple type from an existing typelist * - create sub tuple types and types with shifted parameters * Additionally, check the behaviour when creating tuple instances - * at runtime. Effectively, these are simple record types, which are - * synthesised by recursion over the related typelist. - * - create tuples from a list of values + * at runtime. Effectively, these are simple record types, which + * are synthesised by recursion over the related typelist. + * - diagnostics through TupleAccessor retrieving stored values + * - creating tuples by direct function call, providing values * - copy and copy construct * - access the "head" and access values by numeric index * - create a tuple with shifted values @@ -130,7 +126,7 @@ namespace test { void check_tuple_from_Typelist() { - typedef Types1::List L1; // starting from an existing Typelist... + typedef Types1::List L1; // starting from an existing Typelist... typedef Tuple T_L1; // ListType based tuple type typedef Tuple::TupleType T1; // corresponding plain tuple type @@ -150,6 +146,40 @@ namespace test { Prepend prepend (22, tup2); // but note: the ListType based tuple has an "(head,tail)" style ctor DUMPVAL (prepend); // ... and in construction, tup2 has been copied and coerced to ListType style + + typedef Tuple > NulT; // plain-flat empty Tuple + typedef Tuple NulL; // list-style empty Tuple + + ASSERT ( is_Tuple::value); + ASSERT ( is_TuplePlain::value); + ASSERT (! is_TupleListType::value); + ASSERT (! is_NullTuple::value); + + ASSERT ( is_Tuple::value); + ASSERT (! is_TuplePlain::value); + ASSERT ( is_TupleListType::value); + ASSERT (! is_NullTuple::value); + + ASSERT ( is_Tuple::value); + ASSERT ( is_TuplePlain::value); + ASSERT (! is_TupleListType::value); + ASSERT ( is_NullTuple::value); + + ASSERT ( is_Tuple::value); + ASSERT (! is_TuplePlain::value); + ASSERT ( is_TupleListType::value); + ASSERT ( is_NullTuple::value); + + ASSERT (! is_Tuple::value); + ASSERT (! is_TuplePlain::value); + ASSERT (!is_TupleListType::value); + ASSERT (! is_NullTuple::value); + + ASSERT (! is_Tuple::value); + ASSERT (! is_TuplePlain::value); + ASSERT (!is_TupleListType::value); + ASSERT (! is_NullTuple::value); + } @@ -160,36 +190,36 @@ namespace test { typedef Append::List L2; - typedef Tuple T_L2; + typedef Tuple T_L2; // list-style Tuple typedef Types Head; typedef T_L2::TailType Tail; DISPLAY (T_L2); DISPLAY (Head); DISPLAY (Tail); - typedef T_L2::TupleType T2; + typedef T_L2::TupleType T2; // plain-flat Tuple typedef Types Head2; typedef T2::TailType Tail2; DISPLAY (T2); DISPLAY (Head2); DISPLAY (Tail2); - typedef Tuple > NulT; - typedef Tuple NulL; + typedef Tuple > NulT; // plain-flat empty Tuple + typedef Tuple NulL; // list-style empty Tuple - DISPLAY (T2::Type); - DISPLAY (T2::TailType); - DISPLAY (T2::TupleType); + DISPLAY (T2::Type); // irrespective of the flavour, + DISPLAY (T2::TailType); // a basic set of typedefs is + DISPLAY (T2::TupleType); // always available DISPLAY (T2::ThisType); DISPLAY (T2::Tail); DISPLAY (T2::ArgList); - DISPLAY (T_L2::Type); - DISPLAY (T_L2::TailType); - DISPLAY (T_L2::TupleType); - DISPLAY (T_L2::ThisType); - DISPLAY (T_L2::Tail); - DISPLAY (T_L2::ArgList); + DISPLAY (T_L2::Type); // the element types as type sequence + DISPLAY (T_L2::TailType); // the element types of the "tail" tuple + DISPLAY (T_L2::TupleType); // corresponding plain-flat tuple type + DISPLAY (T_L2::ThisType); // "type_of(this)" + DISPLAY (T_L2::Tail); // tail tuple + DISPLAY (T_L2::ArgList); // typelist comprised of the element types DISPLAY (NulT::Type); DISPLAY (NulT::TailType); @@ -243,8 +273,8 @@ namespace test { { cout << "\t:\n\t: ---creating-Tuples---\n"; - Tuple tup1 ; - Tuple tup11 (Num<1>(11) ); + Tuple tup1 ; + Tuple tup11 (Num<1>(11) ); Tuple tup12 (Num<1>(), Num<3>(33) ); Tuple tup13 (Num<1>(11), Num<3>(33), Num<5>() ); DUMPVAL (tup1); @@ -253,7 +283,7 @@ namespace test { DUMPVAL (tup13); typedef Tuple > > Tup2; - Tup2 tup2 = tuple::make(41,42, Num<11>(43)); + Tup2 tup2 = tuple::make(41,42, Num<11>(43)); // build tuple from given values DISPLAY (Tup2); DUMPVAL (tup2); @@ -298,7 +328,7 @@ namespace test { DUMPVAL (tup1); Tuple tupL = tup11.getShifted<0>(); - Tuple tup1L (tupL); + Tuple tup1L (tupL); // create plain tuple from list-style tuple DUMPVAL (tupL); DUMPVAL (tup1L); } @@ -320,8 +350,8 @@ namespace test { tuple::element<1>(tu2).o_ = 5; tu2.getHead() = Num<2> (tu2.getAt<1>().o_); DUMPVAL (tu2); - - + + tupX.getShifted<2>() = tu2; DUMPVAL (tupX); @@ -344,10 +374,10 @@ namespace test { TupT tupXcopy (tupX); DUMPVAL (tupXcopy); - TupT& tupXcast (tupX.tupleCast()); + TupT& tupXcast (tupX.tupleCast()); // (down)cast list-style to plain tuple DUMPVAL (tupXcast); } - + };