now able to remove our old Tuple type (closes #988)

all unit-tests PASS again
This commit is contained in:
Fischlurch 2016-01-20 01:25:40 +01:00
parent f6d04d4d02
commit 297f986b5f
5 changed files with 78 additions and 1820 deletions

View file

@ -143,6 +143,19 @@ namespace meta {
using Type = typename BuildTupleType<VariadicSeq>::Type;
};
template<class H, typename TAIL>
struct BuildTupleType<Node<H, TAIL>>
{
using Seq = typename Types< Node<H,TAIL>>::Seq;
using Type = typename BuildTupleType<Seq>::Type;
};
template<>
struct BuildTupleType<NullType>
{
using Type = typename BuildTupleType<Types<>>::Type;
};
}
@ -213,620 +226,13 @@ namespace meta {
template<size_t>
using FilledWith = IndexSeq<>;;
};
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////OBSOLETE :: TICKET #988
/**
* 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. Default and canonical
* is the type-sequence based tuple form \c Tuple<Types<T1,T2,...>>
* 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<class TYPES>
struct Tuple;
template<>
struct Tuple<NullType>
{
typedef NullType HeadType;
typedef Types<> TailType;
typedef Types<> Type;
typedef NullType ArgList;
typedef Tuple<Type> TupleType;
typedef Tuple<NullType> ThisType;
typedef Tuple<NullType> Tail;
enum { SIZE = 0 };
NullType& getHead() { return bottom(); }
Tail& getTail() { return *this; }
Tuple (HeadType const&, Tail const&) { }
Tuple () { }
template<uint> struct ShiftedTuple { typedef Tail Type;};
template<uint> Tail& getShifted () { return *this; }
template<uint> NullType& getAt () { return bottom(); }
const NullType getHead_const() const { return bottom(); }
const Tail& getTail_const() const { return *this; }
TupleType&
tupleCast ()
{
return reinterpret_cast<TupleType&> (*this);
}
NullType&
bottom() const
{
return (NullType&) (*this);
}
};
template<class TY, class TYPES>
struct Tuple<Node<TY,TYPES> >
: Tuple<TYPES>
{
typedef TY HeadType;
typedef typename Tuple<TYPES>::Type TailType;
typedef typename Prepend<TY,TailType>::Seq Type;
typedef Node<TY,TYPES> ArgList;
typedef Tuple<Type> TupleType;
typedef Tuple<ArgList> ThisType;
typedef Tuple<TYPES> Tail;
enum { SIZE = count<ArgList>::value };
Tuple ( TY a1 =TY()
, Tail tail =Tail()
)
: Tail (tail.getHead(), tail.getTail()),
val_(a1)
{ }
TY & getHead() { return val_; }
Tail& getTail() { return static_cast<Tail&> (*this); }
TY const& getHead_const() const { return val_; }
Tail const& getTail_const() const { return static_cast<const Tail&> (*this); }
template<uint i>
class ShiftedTuple
{
typedef typename Tuple::Type OurType_;
typedef typename Shifted<OurType_,i>::Type ShiftedTypes_;
public:
typedef Tuple<typename ShiftedTypes_::List> Type;
};
template<uint i>
typename ShiftedTuple<i>::Type&
getShifted ()
{
typedef typename ShiftedTuple<i>::Type Tail_I;
return static_cast<Tail_I&> (*this);
}
TupleType&
tupleCast () ///< note makes this List-style Tuple appear as plain-flat Tuple
{
return reinterpret_cast<TupleType&> (*this);
}
template<uint i>
typename Shifted<Type,i>::Head&
getAt ()
{
return getShifted<i>().getHead();
}
private:
TY val_;
};
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
, typename T8
, typename T9
>
struct Tuple<Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> >
: Tuple<typename Types<T1,T2,T3,T4,T5,T6,T7,T8,T9>::List>
{
typedef T1 HeadType;
typedef Types<T2,T3,T4,T5,T6,T7,T8,T9,NullType> TailType;
typedef Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> Type;
typedef typename Type::List ArgList;
typedef Tuple<Type> TupleType;
typedef Tuple<Type> ThisType;
typedef Tuple<TailType> Tail;
enum { SIZE = count<ArgList>::value };
/** standard ctor: create from values */
Tuple ( T1 a1 =T1()
, T2 a2 =T2()
, T3 a3 =T3()
, T4 a4 =T4()
, T5 a5 =T5()
, T6 a6 =T6()
, T7 a7 =T7()
, T8 a8 =T8()
, T9 a9 =T9()
)
: Tuple<ArgList>(a1, Tuple<TailType>(a2,a3,a4,a5,a6,a7,a8,a9))
{ }
/** shortcut: allow copy construction from a tuple
* which is rather defined by a list type */
Tuple (Tuple<ArgList> const& listTuple)
: Tuple<ArgList> (listTuple)
{ }
using Tuple<ArgList>::getHead;
Tail& getTail() ///< note makes the Tail appear as plain-flat shifted tuple
{
return Tuple<ArgList>::getTail().tupleCast();
}
};
template<>
struct Tuple<Types<> >
: Tuple<NullType>
{
enum { SIZE = 0 };
typedef Tuple<NullType> TupNilList;
typedef Tuple<Types<> > ThisType;
typedef ThisType Tail;
Tuple ( NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
)
{ } ///< end recursion of chained ctor calls
/** shortcut: allow copy construction from a tuple
* which is rather defined by a list type */
Tuple (TupNilList const&)
{ }
};
/** specialisation to shift plain tuple types */
template<class TYPES, uint i>
struct Shifted<Tuple<TYPES>,i>
{
typedef typename Shifted<TYPES,i>::Type Type;
typedef typename Shifted<TYPES,i>::Head Head;
typedef Tuple<Type> TupleType;
};
template<class TYPES>
struct Shifted<Tuple<TYPES>, 0>
{
typedef typename Tuple<TYPES>::Type Type;
typedef typename Tuple<TYPES>::HeadType Head;
typedef Tuple<Type> TupleType;
};
/* ====== Helpers for working with Tuples ========= */
namespace tuple { // some convenience access functions
template<uint n, class TUP>
inline
typename Shifted<TUP,n>::Head&
element (TUP& tup)
{
return tup.template getAt<n>();
}
inline
Tuple< Types<> >
makeNullTuple ()
{
return Tuple<Types<> > ();
}
template<typename T1>
inline
Tuple< Types<T1> >
make ( T1 a1
)
{
return Tuple<Types<T1> > (a1);
}
template< typename T1
, typename T2
>
inline
Tuple< Types<T1,T2> >
make ( T1 a1
, T2 a2
)
{
return Tuple<Types<T1,T2> > (a1,a2);
}
template< typename T1
, typename T2
, typename T3
>
inline
Tuple< Types<T1,T2,T3> >
make ( T1 a1
, T2 a2
, T3 a3
)
{
return Tuple<Types<T1,T2,T3> > (a1,a2,a3);
}
template< typename T1
, typename T2
, typename T3
, typename T4
>
inline
Tuple< Types<T1,T2,T3,T4> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
)
{
return Tuple<Types<T1,T2,T3,T4> > (a1,a2,a3,a4);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
>
inline
Tuple< Types<T1,T2,T3,T4,T5> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
)
{
return Tuple<Types<T1,T2,T3,T4,T5> > (a1,a2,a3,a4,a5);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
>
inline
Tuple< Types<T1,T2,T3,T4,T5,T6> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
, T6 a6
)
{
return Tuple<Types<T1,T2,T3,T4,T5,T6> > (a1,a2,a3,a4,a5,a6);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
>
inline
Tuple< Types<T1,T2,T3,T4,T5,T6,T7> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
, T6 a6
, T7 a7
)
{
return Tuple<Types<T1,T2,T3,T4,T5,T6,T7> > (a1,a2,a3,a4,a5,a6,a7);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
, typename T8
>
inline
Tuple< Types<T1,T2,T3,T4,T5,T6,T7,T8> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
, T6 a6
, T7 a7
, T8 a8
)
{
return Tuple<Types<T1,T2,T3,T4,T5,T6,T7,T8> > (a1,a2,a3,a4,a5,a6,a7,a8);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
, typename T8
, typename T9
>
inline
Tuple< Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
, T6 a6
, T7 a7
, T8 a8
, T9 a9
)
{
return Tuple<Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> > (a1,a2,a3,a4,a5,a6,a7,a8,a9);
}
/**
* Helper to construct a new tuple, partially using provided argument values.
* Arguments are expected as a tuple, which is assumed to be a sub-tuple of
* the target type to be created. The start index of this sub-tuple may be
* provided as additional parameter, otherwise it is assumed to be zero,
* (i.e. the sub tuple starting left aligned). Any further arguments
* of the target type, which aren't covered by the argument tuple,
* are default initialised.
* @param TYPES type sequence or type list denoting the target tuple type
* @param ARGS type sequence of type list denoting the argument tuple type
* @param pos start index of the ARGS sequence within the TYPES sequence
*
* @note call the embedded #create function to invoke
* @note when types or positions disagree, argument tuple will be ignored
* @see TypeTuple_test#check_build_from_subTuple
*/
template<typename TYPES, typename ARGS, uint pos=0>
struct BuildTuple
{
typedef typename Tuple<TYPES>::TupleType ThisTuple;
typedef typename Tuple<TYPES>::ArgList TypeList;
typedef typename Tuple<ARGS>::ArgList ArgTypeList;
/**
* @param the argument values, contained in a list or flat- tuple
* of the type denoted by ARGS
* @return a plain-flat Tuple<TYPES> instance, initialised with
* the values found within arg
*/
static ThisTuple
create (Tuple<ArgTypeList> const& arg)
{
return BuildTuple<TypeList,ArgTypeList,pos>
::create(arg)
.tupleCast();
}
};
template<typename TYPES, typename ARGS, uint pos>
struct BuildTuple<Tuple<TYPES>, Tuple<ARGS>, pos> ///< tuples allowed instead of plain type sequences/lists
: BuildTuple<TYPES,ARGS,pos>
{ };
template< typename T
, typename TS
, typename A
, typename AS
, uint pos
>
struct BuildTuple<Node<T,TS>, Node<A,AS>, pos> ///< case: recursion \em before start of arg tuple
{
typedef Tuple<Node<T,TS> > ThisTuple;
typedef Tuple<Node<A,AS> > ThisArg;
static ThisTuple
create (ThisArg const& arg)
{
return ThisTuple( T()
, BuildTuple<TS, Node<A,AS>, pos-1>::create(arg)
);
}
};
template< typename A
, typename TS
, typename AS
>
struct BuildTuple<Node<A,TS>, Node<A,AS>, 0> ///< case: start of argument tuple detected
{
typedef Tuple<Node<A,TS> > ThisTuple;
typedef Tuple<Node<A,AS> > ThisArg;
static ThisTuple
create (ThisArg const& arg)
{
return ThisTuple( arg.getHead_const()
, BuildTuple<TS, AS, 0>::create (arg.getTail_const())
);
}
};
template< typename ARGS
, uint i
>
struct BuildTuple<NullType, ARGS, i> ///< case: hit end of target typelist
{
typedef Tuple<NullType> ThisTuple;
typedef Tuple<ARGS> ThisArg;
static ThisTuple
create (ThisArg const&)
{
return ThisTuple();
}
};
template< typename T
, typename TS
, uint i
>
struct BuildTuple<Node<T,TS>, NullType, i> ///< case: hit end of argument tuple
{
typedef Tuple<Node<T,TS> > ThisTuple;
typedef Tuple<NullType> ThisArg;
static ThisTuple
create (ThisArg const&)
{
return ThisTuple();
}
};
} // (END) access / tuple building helper functions (namespace tuple)
/** Trait template for detecting a type tuple */
template<typename TUP>
class is_Tuple
{
template<class X> struct Check { typedef No_t It; };
template<class TY> struct Check<Tuple<TY> > { typedef Yes_t It; };
public:
static const bool value = (sizeof(Yes_t)==sizeof(typename Check<TUP>::It));
};
/** Trait template detecting especially tuples
* built directly on top of a Typelist */
template<typename TUP>
class is_TupleListType
{
template<class X>
struct Check
{
enum{ result = sizeof(No_t)};
};
template<class N>
struct Check<Tuple<N> >
{
template<class H, class T>
Yes_t static check(Node<H,T>*);
Yes_t static check(NullType*);
No_t static check(...);
enum{ result = sizeof(check( (N*)0)) };
};
public:
static const bool value = (sizeof(Yes_t)== Check<TUP>::result);
};
/** Trait template to discern plain tuples and list-type tuples */
template<typename TUP>
struct is_TuplePlain
{
static const bool value = is_Tuple<TUP>::value
&& !is_TupleListType<TUP>::value;
};
/** Trait template detecting an empty tuple type */
template<typename TUP>
class is_NullTuple
{
template<class X>
struct Check
{
enum{ result = sizeof(No_t)};
};
template<class TY>
struct Check<Tuple<TY> >
{
Yes_t static check(Types<>*);
Yes_t static check(NullType*);
No_t static check(...);
enum{ result = sizeof(check( (TY*)0)) };
};
public:
static const bool value = (sizeof(Yes_t)== Check<TUP>::result);
};
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////OBSOLETE :: TICKET #988
/**

View file

@ -1,758 +0,0 @@
/*
TUPLE.hpp - metaprogramming utilities for type tuples and data tuples
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file tuple.hpp
** Metaprogramming with tuples-of-types and a simple Tuple (record) datatype.
** The metaprogramming part of this header complements typelist.hpp and allows
** some additional manipulations on type sequences. Such a finite 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 simple Tuple
** (run time) datatype. This isn't meant as competing with std::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
** later re-accessing them (but no further advanced processing), the Tuple template
** might come in handy.
**
** @deprecated obsoleted by `std::tuple` -- to be removed soon /////////////////////TICKET #988
**
** @see control::CommandDef usage example
** @see tuple-test.cpp
** @see typelist.hpp
** @see function.hpp
** @see generator.hpp
**
*/
#ifndef LIB_META_TUPLE_H
#define LIB_META_TUPLE_H
#include "lib/meta/typelist.hpp"
#include "lib/meta/typelist-util.hpp"
#include "lib/meta/typeseq-util.hpp"
#include "lib/meta/util.hpp"
namespace lib {
namespace meta {
/**
* 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. Default and canonical
* is the type-sequence based tuple form \c Tuple<Types<T1,T2,...>>
* 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
*
* @deprecated will be replaced by `std::tuple`
*/
template<class TYPES>
struct Tuple;
template<>
struct Tuple<NullType>
{
typedef NullType HeadType;
typedef Types<> TailType;
typedef Types<> Type;
typedef NullType ArgList;
typedef Tuple<Type> TupleType;
typedef Tuple<NullType> ThisType;
typedef Tuple<NullType> Tail;
enum { SIZE = 0 };
NullType& getHead() { return bottom(); }
Tail& getTail() { return *this; }
Tuple (HeadType const&, Tail const&) { }
Tuple () { }
template<uint> struct ShiftedTuple { typedef Tail Type;};
template<uint> Tail& getShifted () { return *this; }
template<uint> NullType& getAt () { return bottom(); }
const NullType getHead_const() const { return bottom(); }
const Tail& getTail_const() const { return *this; }
TupleType&
tupleCast ()
{
return reinterpret_cast<TupleType&> (*this);
}
NullType&
bottom() const
{
return (NullType&) (*this);
}
};
template<class TY, class TYPES>
struct Tuple<Node<TY,TYPES> >
: Tuple<TYPES>
{
typedef TY HeadType;
typedef typename Tuple<TYPES>::Type TailType;
typedef typename Prepend<TY,TailType>::Seq Type;
typedef Node<TY,TYPES> ArgList;
typedef Tuple<Type> TupleType;
typedef Tuple<ArgList> ThisType;
typedef Tuple<TYPES> Tail;
enum { SIZE = count<ArgList>::value };
Tuple ( TY a1 =TY()
, Tail tail =Tail()
)
: Tail (tail.getHead(), tail.getTail()),
val_(a1)
{ }
TY & getHead() { return val_; }
Tail& getTail() { return static_cast<Tail&> (*this); }
TY const& getHead_const() const { return val_; }
Tail const& getTail_const() const { return static_cast<const Tail&> (*this); }
template<uint i>
class ShiftedTuple
{
typedef typename Tuple::Type OurType_;
typedef typename Shifted<OurType_,i>::Type ShiftedTypes_;
public:
typedef Tuple<typename ShiftedTypes_::List> Type;
};
template<uint i>
typename ShiftedTuple<i>::Type&
getShifted ()
{
typedef typename ShiftedTuple<i>::Type Tail_I;
return static_cast<Tail_I&> (*this);
}
TupleType&
tupleCast () ///< note makes this List-style Tuple appear as plain-flat Tuple
{
return reinterpret_cast<TupleType&> (*this);
}
template<uint i>
typename Shifted<Type,i>::Head&
getAt ()
{
return getShifted<i>().getHead();
}
private:
TY val_;
};
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
, typename T8
, typename T9
>
struct Tuple<Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> >
: Tuple<typename Types<T1,T2,T3,T4,T5,T6,T7,T8,T9>::List>
{
typedef T1 HeadType;
typedef Types<T2,T3,T4,T5,T6,T7,T8,T9,NullType> TailType;
typedef Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> Type;
typedef typename Type::List ArgList;
typedef Tuple<Type> TupleType;
typedef Tuple<Type> ThisType;
typedef Tuple<TailType> Tail;
enum { SIZE = count<ArgList>::value };
/** standard ctor: create from values */
Tuple ( T1 a1 =T1()
, T2 a2 =T2()
, T3 a3 =T3()
, T4 a4 =T4()
, T5 a5 =T5()
, T6 a6 =T6()
, T7 a7 =T7()
, T8 a8 =T8()
, T9 a9 =T9()
)
: Tuple<ArgList>(a1, Tuple<TailType>(a2,a3,a4,a5,a6,a7,a8,a9))
{ }
/** shortcut: allow copy construction from a tuple
* which is rather defined by a list type */
Tuple (Tuple<ArgList> const& listTuple)
: Tuple<ArgList> (listTuple)
{ }
using Tuple<ArgList>::getHead;
Tail& getTail() ///< note makes the Tail appear as plain-flat shifted tuple
{
return Tuple<ArgList>::getTail().tupleCast();
}
};
template<>
struct Tuple<Types<> >
: Tuple<NullType>
{
enum { SIZE = 0 };
typedef Tuple<NullType> TupNilList;
typedef Tuple<Types<> > ThisType;
typedef ThisType Tail;
Tuple ( NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
, NullType =NullType()
)
{ } ///< end recursion of chained ctor calls
/** shortcut: allow copy construction from a tuple
* which is rather defined by a list type */
Tuple (TupNilList const&)
{ }
};
/** specialisation to shift plain tuple types */
template<class TYPES, uint i>
struct Shifted<Tuple<TYPES>,i>
{
typedef typename Shifted<TYPES,i>::Type Type;
typedef typename Shifted<TYPES,i>::Head Head;
typedef Tuple<Type> TupleType;
};
template<class TYPES>
struct Shifted<Tuple<TYPES>, 0>
{
typedef typename Tuple<TYPES>::Type Type;
typedef typename Tuple<TYPES>::HeadType Head;
typedef Tuple<Type> TupleType;
};
/* ====== Helpers for working with Tuples ========= */
namespace tuple { // some convenience access functions
template<uint n, class TUP>
inline
typename Shifted<TUP,n>::Head&
element (TUP& tup)
{
return tup.template getAt<n>();
}
inline
Tuple< Types<> >
makeNullTuple ()
{
return Tuple<Types<> > ();
}
template<typename T1>
inline
Tuple< Types<T1> >
make ( T1 a1
)
{
return Tuple<Types<T1> > (a1);
}
template< typename T1
, typename T2
>
inline
Tuple< Types<T1,T2> >
make ( T1 a1
, T2 a2
)
{
return Tuple<Types<T1,T2> > (a1,a2);
}
template< typename T1
, typename T2
, typename T3
>
inline
Tuple< Types<T1,T2,T3> >
make ( T1 a1
, T2 a2
, T3 a3
)
{
return Tuple<Types<T1,T2,T3> > (a1,a2,a3);
}
template< typename T1
, typename T2
, typename T3
, typename T4
>
inline
Tuple< Types<T1,T2,T3,T4> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
)
{
return Tuple<Types<T1,T2,T3,T4> > (a1,a2,a3,a4);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
>
inline
Tuple< Types<T1,T2,T3,T4,T5> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
)
{
return Tuple<Types<T1,T2,T3,T4,T5> > (a1,a2,a3,a4,a5);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
>
inline
Tuple< Types<T1,T2,T3,T4,T5,T6> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
, T6 a6
)
{
return Tuple<Types<T1,T2,T3,T4,T5,T6> > (a1,a2,a3,a4,a5,a6);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
>
inline
Tuple< Types<T1,T2,T3,T4,T5,T6,T7> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
, T6 a6
, T7 a7
)
{
return Tuple<Types<T1,T2,T3,T4,T5,T6,T7> > (a1,a2,a3,a4,a5,a6,a7);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
, typename T8
>
inline
Tuple< Types<T1,T2,T3,T4,T5,T6,T7,T8> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
, T6 a6
, T7 a7
, T8 a8
)
{
return Tuple<Types<T1,T2,T3,T4,T5,T6,T7,T8> > (a1,a2,a3,a4,a5,a6,a7,a8);
}
template< typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
, typename T8
, typename T9
>
inline
Tuple< Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> >
make ( T1 a1
, T2 a2
, T3 a3
, T4 a4
, T5 a5
, T6 a6
, T7 a7
, T8 a8
, T9 a9
)
{
return Tuple<Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> > (a1,a2,a3,a4,a5,a6,a7,a8,a9);
}
/**
* Helper to construct a new tuple, partially using provided argument values.
* Arguments are expected as a tuple, which is assumed to be a sub-tuple of
* the target type to be created. The start index of this sub-tuple may be
* provided as additional parameter, otherwise it is assumed to be zero,
* (i.e. the sub tuple starting left aligned). Any further arguments
* of the target type, which aren't covered by the argument tuple,
* are default initialised.
* @param TYPES type sequence or type list denoting the target tuple type
* @param ARGS type sequence of type list denoting the argument tuple type
* @param pos start index of the ARGS sequence within the TYPES sequence
*
* @note call the embedded #create function to invoke
* @note when types or positions disagree, argument tuple will be ignored
* @see TypeTuple_test#check_build_from_subTuple
*/
template<typename TYPES, typename ARGS, uint pos=0>
struct BuildTuple
{
typedef typename Tuple<TYPES>::TupleType ThisTuple;
typedef typename Tuple<TYPES>::ArgList TypeList;
typedef typename Tuple<ARGS>::ArgList ArgTypeList;
/**
* @param the argument values, contained in a list or flat- tuple
* of the type denoted by ARGS
* @return a plain-flat Tuple<TYPES> instance, initialised with
* the values found within arg
*/
static ThisTuple
create (Tuple<ArgTypeList> const& arg)
{
return BuildTuple<TypeList,ArgTypeList,pos>
::create(arg)
.tupleCast();
}
};
template<typename TYPES, typename ARGS, uint pos>
struct BuildTuple<Tuple<TYPES>, Tuple<ARGS>, pos> ///< tuples allowed instead of plain type sequences/lists
: BuildTuple<TYPES,ARGS,pos>
{ };
template< typename T
, typename TS
, typename A
, typename AS
, uint pos
>
struct BuildTuple<Node<T,TS>, Node<A,AS>, pos> ///< case: recursion \em before start of arg tuple
{
typedef Tuple<Node<T,TS> > ThisTuple;
typedef Tuple<Node<A,AS> > ThisArg;
static ThisTuple
create (ThisArg const& arg)
{
return ThisTuple( T()
, BuildTuple<TS, Node<A,AS>, pos-1>::create(arg)
);
}
};
template< typename A
, typename TS
, typename AS
>
struct BuildTuple<Node<A,TS>, Node<A,AS>, 0> ///< case: start of argument tuple detected
{
typedef Tuple<Node<A,TS> > ThisTuple;
typedef Tuple<Node<A,AS> > ThisArg;
static ThisTuple
create (ThisArg const& arg)
{
return ThisTuple( arg.getHead_const()
, BuildTuple<TS, AS, 0>::create (arg.getTail_const())
);
}
};
template< typename ARGS
, uint i
>
struct BuildTuple<NullType, ARGS, i> ///< case: hit end of target typelist
{
typedef Tuple<NullType> ThisTuple;
typedef Tuple<ARGS> ThisArg;
static ThisTuple
create (ThisArg const&)
{
return ThisTuple();
}
};
template< typename T
, typename TS
, uint i
>
struct BuildTuple<Node<T,TS>, NullType, i> ///< case: hit end of argument tuple
{
typedef Tuple<Node<T,TS> > ThisTuple;
typedef Tuple<NullType> ThisArg;
static ThisTuple
create (ThisArg const&)
{
return ThisTuple();
}
};
} // (END) access / tuple building helper functions (namespace tuple)
/** Trait template for detecting a type tuple */
template<typename TUP>
class is_Tuple
{
template<class X> struct Check { typedef No_t It; };
template<class TY> struct Check<Tuple<TY> > { typedef Yes_t It; };
public:
static const bool value = (sizeof(Yes_t)==sizeof(typename Check<TUP>::It));
};
/** Trait template detecting especially tuples
* built directly on top of a Typelist */
template<typename TUP>
class is_TupleListType
{
template<class X>
struct Check
{
enum{ result = sizeof(No_t)};
};
template<class N>
struct Check<Tuple<N> >
{
template<class H, class T>
Yes_t static check(Node<H,T>*);
Yes_t static check(NullType*);
No_t static check(...);
enum{ result = sizeof(check( (N*)0)) };
};
public:
static const bool value = (sizeof(Yes_t)== Check<TUP>::result);
};
/** Trait template to discern plain tuples and list-type tuples */
template<typename TUP>
struct is_TuplePlain
{
static const bool value = is_Tuple<TUP>::value
&& !is_TupleListType<TUP>::value;
};
/** Trait template detecting an empty tuple type */
template<typename TUP>
class is_NullTuple
{
template<class X>
struct Check
{
enum{ result = sizeof(No_t)};
};
template<class TY>
struct Check<Tuple<TY> >
{
Yes_t static check(Types<>*);
Yes_t static check(NullType*);
No_t static check(...);
enum{ result = sizeof(check( (TY*)0)) };
};
public:
static const bool value = (sizeof(Yes_t)== Check<TUP>::result);
};
/**
* Decorating a tuple type with auxiliary data access operations.
* This helper template builds up a subclass of the given TUP (base) type
* (which is assumed to be a Tuple or at least need to be copy constructible
* from \c Tuple<TYPES> ). The purpose is to use the Tuple as storage, but
* to add a layer of access functions, which in turn might rely on the exact
* type of the individual elements within the Tuple. To achieve this, for each
* type within the Tuple, the TUP 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 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 empty type sequence is generated for detecting recursion end
* (built as innermost decorator, i.e. immediate subclass of TUP)
*/
template
< typename TYPES ///< Type sequence to use within the Accessor (usually the Tuple Types)
, template<class,class,class, uint> class _X_ ///< user provided template<Type, Base, TupleType, arg-No>
, class TUP =Tuple<TYPES> ///< the tuple type to build on
, uint i = 0 ///< tuple element index counter
>
class BuildTupleAccessor
{
typedef Tuple<TYPES> ArgTuple;
typedef typename ArgTuple::HeadType Head;
typedef typename ArgTuple::TailType Tail;
typedef BuildTupleAccessor<Tail,_X_,TUP, i+1> NextBuilder;
typedef typename NextBuilder::Accessor NextAccessor;
ArgTuple const& argData_;
public:
/** type of the product created by this template.
* Will be a subclass of TUP */
typedef _X_< Head // the type to use for this accessor
, NextAccessor // the base type to inherit from
, TUP // the tuple type we build upon
, i // current element index
> Accessor;
BuildTupleAccessor (ArgTuple const& tup)
: argData_(tup)
{ }
/** used to get the product of this builder template... */
operator Accessor() { return Accessor(argData_); }
};
template
< template<class,class,class, uint> class _X_
, class TUP
, uint i
>
class BuildTupleAccessor<Types<>, _X_, TUP, i>
{
typedef Tuple<Types<> > ArgTuple;
ArgTuple const& argData_;
public:
typedef _X_<NullType, TUP, TUP, 0> Accessor;
BuildTupleAccessor (ArgTuple const& tup)
: argData_(tup)
{ }
/** used to get the product of this builder template... */
operator Accessor() { return Accessor(argData_); }
};
}} // namespace lib::meta
#endif

View file

@ -144,10 +144,10 @@ out-lit: Args :-<5>-<9>-
out-lit: NewArgs :-<1>-<5>-<9>-
out-lit: :
out-lit: : ---Apply---
out-lit: tup0 :...Tuple()
out-lit: tup1 :...Tuple(11)
out-lit: tup2 :...Tuple(11,12)
out-lit: tup3 :...Tuple(11,12,13)
out-lit: tup0 :«tuple<>»──()
out-lit: tup1 :«tuple<int>»──(11)
out-lit: tup2 :«tuple<int, int>»──(11,12)
out-lit: tup3 :«tuple<int, int, int>»──(11,12,13)
out-lit: :
out-lit: : ---Bind----
return: 0
@ -541,134 +541,21 @@ TEST "tuple metaprogramming helpers" TupleHelper_test <<END
out-lit: L1 :-<1>-<3>-<5>-
out-lit: L2 :-<2>-<4>-
out-lit: L3 :-<7>-
out-lit: Tup1 :TYPES-<>-<1>-<3>-<5>-
out-lit: Tup1() :...Tuple((1),(3),(5))
out-lit: tup1x :...Tuple({11},(3),(5))
out-lit: Type1 :-<1>-<3>-<5>-
out-lit: T_L1 :TYPES-[]-<1>-<3>-<5>-
out-lit: T1 :TYPES-<>-<1>-<3>-<5>-
out-lit: tup1 :...Tuple({8},(3),(5))
out-lit: tup2 :...Tuple({9},(3),(5))
out-lit: Prepend :TYPES-[]-<i>-<1>-<3>-<5>-
out-lit: prepend :...Tuple(22,{9},(3),(5))
out-lit: :
out-lit: : ---Sub-Tuple-Types----
out-lit: T_L2 :TYPES-[]-<2>-<4>-<1>-<3>-<5>-
out-lit: Head :-<2>-
out-lit: Tail :-<4>-<1>-<3>-<5>-
out-lit: T2 :TYPES-<>-<2>-<4>-<1>-<3>-<5>-
out-lit: Head2 :-<2>-
out-lit: Tail2 :-<4>-<1>-<3>-<5>-
out-lit: T2::Type :-<2>-<4>-<1>-<3>-<5>-
out-lit: T2::TailType :-<4>-<1>-<3>-<5>-
out-lit: T2::TupleType :TYPES-<>-<2>-<4>-<1>-<3>-<5>-
out-lit: T2::ThisType :TYPES-<>-<2>-<4>-<1>-<3>-<5>-
out-lit: T2::Tail :TYPES-<>-<4>-<1>-<3>-<5>-
out-lit: T2::ArgList :-<2>-<4>-<1>-<3>-<5>-
out-lit: T_L2::Type :-<2>-<4>-<1>-<3>-<5>-
out-lit: T_L2::TailType :-<4>-<1>-<3>-<5>-
out-lit: T_L2::TupleType :TYPES-<>-<2>-<4>-<1>-<3>-<5>-
out-lit: T_L2::ThisType :TYPES-[]-<2>-<4>-<1>-<3>-<5>-
out-lit: T_L2::Tail :TYPES-[]-<4>-<1>-<3>-<5>-
out-lit: T_L2::ArgList :-<2>-<4>-<1>-<3>-<5>-
out-lit: NulT::Type :-
out-lit: NulT::TailType :-
out-lit: NulT::TupleType :TYPES-<>-
out-lit: NulT::ThisType :TYPES-<>-
out-lit: NulT::Tail :TYPES-<>-
out-lit: NulT::ArgList :-
out-lit: NulL::Type :-
out-lit: NulL::TailType :-
out-lit: NulL::TupleType :TYPES-<>-
out-lit: NulL::ThisType :TYPES-[]-
out-lit: NulL::Tail :TYPES-[]-
out-lit: NulL::ArgList :-
out-lit: :
out-lit: : ---Shifted-Tuple---
out-lit: Ty_0 :-<2>-<4>-<7>-
out-lit: Ty_1 :-<4>-<7>-
out-lit: Ty_2 :-<7>-
out-lit: Ty_3 :-
out-lit: Ty_4 :-
out-lit: T_0 :TYPES-[]-<2>-<4>-<7>-
out-lit: T_1 :TYPES-[]-<4>-<7>-
out-lit: T_2 :TYPES-[]-<7>-
out-lit: T_3 :TYPES-[]-
out-lit: T_4 :TYPES-[]-
out-lit: tu3 :...Tuple((2),(4),(7))
out-lit: tu3_0 :...Tuple((2),(4),(7))
out-lit: tu3_1 :...Tuple((4),(7))
out-lit: tu3_2 :...Tuple((7))
out-lit: tu3_3 :...Tuple()
out-lit: tu3_4 :...Tuple()
out-lit: :
out-lit: : ---creating-Tuples---
out-lit: tup1 :...Tuple((1),(3),(5))
out-lit: tup11 :...Tuple({11},(3),(5))
out-lit: tup12 :...Tuple((1),{33},(5))
out-lit: tup13 :...Tuple({11},{33},(5))
out-lit: Tup2 :TYPES-<>-<i>-<i>-<11>-
out-lit: tup2 :...Tuple(41,42,{43})
out-lit: Tup22 :TYPES-<>-<i>-<11>-
out-lit: tup22 :...Tuple(42,{43})
out-lit: Tup222 :TYPES-<>-<11>-
out-lit: tup222 :...Tuple({43})
out-lit: T0T :TYPES-<>-
out-lit: T0L :TYPES-[]-
out-lit: nullT :...Tuple()
out-lit: nullL :...Tuple()
out-lit: nulTcpy :...Tuple()
out-lit: nulTref :...Tuple()
out-lit: :
out-lit: : ---build-from-sub-Tuples---
out-lit: T1357L :TYPES-[]-<1>-<3>-<5>-<7>-
out-lit: T1357T :TYPES-<>-<1>-<3>-<5>-<7>-
out-lit: T135L :TYPES-[]-<1>-<3>-<5>-
out-lit: T57T :TYPES-<>-<5>-<7>-
out-lit: T35T :TYPES-<>-<3>-<5>-
out-lit: sub135 :...Tuple((1),(3),(5))
out-lit: b_135 :...Tuple((1),(3),(5),(7))
out-lit: b_135 :...Tuple((1),(3),(5),(7))
out-lit: b_135 :...Tuple((1),(3),(5),(7))
out-lit: b_135 :...Tuple((1),(3),(5),(7))
out-lit: sub57 :...Tuple((5),(7))
out-lit: b_57 :...Tuple((1),(3),(5),(7))
out-lit: sub35 :...Tuple({8},{8})
out-lit: b_35 :...Tuple((1),{8},{8},(7))
out-lit: b_35 :...Tuple((1),(3),(5),(7))
out-lit: b_35 :...Tuple((1),(3),(5),(7))
out-lit: sub78 :...Tuple({77},{88})
out-lit: b_78 :...Tuple((1),(3),(5),{77})
out-lit: b_nul :...Tuple((1),(3),(5),(7))
out-lit: b_nul :...Tuple((1),(3),(5),(7))
out-lit: b_nul2 :...Tuple()
out-lit: b_nul2 :...Tuple()
out-lit: :
out-lit: : ---copy-operations---
out-lit: tup1 :...Tuple({11},{33},(5))
out-lit: tup11 :...Tuple({11},{33},{44})
out-lit: tup1 :...Tuple({11},{33},{44})
out-lit: tupL :...Tuple({11},{33},{44})
out-lit: tup1L :...Tuple({11},{33},{44})
out-lit: :
out-lit: : ---value-access---
out-lit: TupX :TYPES-[]-<2>-<4>-<2>-<4>-
out-lit: tupX :...Tuple((2),(4),(2),(4))
out-lit: tu2 :...Tuple((2),(4))
out-lit: tu2 :...Tuple({5},{5})
out-lit: tupX :...Tuple((2),(4),{5},{5})
out-lit: T4 :TYPES-<>-<2>-<4>-
out-lit: t4 :...Tuple({5},{5})
out-lit: TupX::Type :-<2>-<4>-<2>-<4>-
out-lit: TupX::TailType :-<4>-<2>-<4>-
out-lit: TupX::ThisType :TYPES-[]-<2>-<4>-<2>-<4>-
out-lit: TupX::TupleType :TYPES-<>-<2>-<4>-<2>-<4>-
out-lit: TupT::Type :-<2>-<4>-<2>-<4>-
out-lit: TupT::TailType :-<4>-<2>-<4>-
out-lit: TupT::ThisType :TYPES-<>-<2>-<4>-<2>-<4>-
out-lit: TupT::TupleType :TYPES-<>-<2>-<4>-<2>-<4>-
out-lit: tupXcopy :...Tuple((2),(4),{5},{5})
out-lit: tupXcast :...Tuple((2),(4),{5},{5})
out-lit: Tup1 :TUPLE-<1>-<3>-<5>-
out-lit: Tup1() :«tuple<Num<1>, Num<3>, Num<5> >»──((1),(3),(5))
out-lit: tup1x :«tuple<Num<1>, Num<3>, Num<5> >»──({11},(3),{55})
out-lit: T_L1 :TUPLE-<1>-<3>-<5>-
out-lit: Seq1 :-<1>-<3>-<5>-
out-lit: tup1 :«tuple<Num<1>, Num<3>, Num<5> >»──((1),(3),(5))
out-lit: Prepend :TUPLE-<i>-<1>-<3>-<5>-
out-lit: prep :«tuple<int, Num<1>, Num<3>, Num<5> >»──(22,{11},{33},(5))
out-lit: «tuple<Num<1>, Num<3>, Num<5> >»──((1),(3),(5))
out-lit: «tuple<int, Num<1>, Num<3>, Num<5> >»──(22,{11},{33},(5))
out-lit: «tuple<>»──()
out: sizeof. tuple<Num<1>, Num<3>, Num<5> > . = 12
out: sizeof. tuple<int, Num<1>, Num<3>, Num<5> > . = 16
out-lit: sizeof( tuple<> ) = 1
out-lit: sizeof( tuple<> ) = 1
return: 0
END

View file

@ -32,15 +32,15 @@
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/meta/tuple-helper.hpp"
#include "meta/typelist-diagnostics.hpp"
#include "meta/tuple-diagnostics.hpp"
#include "lib/format-cout.hpp"
#include <iostream>
using ::test::Test;
using std::cout;
using std::endl;
using lib::test::showSizeof;
namespace lib {
@ -72,8 +72,8 @@ namespace test {
* @test Cover various aspects of the integration of our type sequences
* with the tuple type from the standard library
* - verify our generic tuple access decorator
* - TODO
* @todo to be written
* - verify generating tuple types from type list processing
* - TODO more helpers to come
*/
class TupleHelper_test : public Test
{
@ -81,18 +81,12 @@ namespace test {
run (Arg)
{
check_diagnostics();
// check_tuple_from_Typelist();
// check_sub_tuple_types();
// check_shiftedTuple();
// check_tuple_creation();
// check_build_from_subTuple();
// check_tuple_copy();
// check_value_access();
check_tuple_from_Typelist();
}
/** verify the test input data
* @see TypeListManipl_test#check_diagnostics()
* @see TypeListManip_test::check_diagnostics()
* for an explanation of the DISPLAY macro
*/
void
@ -107,7 +101,7 @@ namespace test {
DISPLAY (L3);
typedef Tuple<Types1> Tup1;
Tup1 tup1x (Num<1>(11), Num<3>(), Num<5>());
Tup1 tup1x (Num<1>(11), Num<3>(), 55);
DISPLAY (Tup1); // prints the type
DUMPVAL (Tup1()); // prints the contents
@ -115,330 +109,56 @@ namespace test {
}
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////OBSOLETE :: TICKET #988
/** @test verify the ability to generate tuple types from typelist metaprogramming
* - the resulting types are plain flat `std::tuple` instantiations
* - memory layout is identical to a POD, as expected
* - our generic string conversion is extended to work with tuples
*/
void
check_tuple_from_Typelist()
{
typedef Types1::List L1; // starting from an existing Typelist...
typedef Tuple<L1> T_L1; // ListType based tuple type
typedef Tuple<L1>::TupleType T1; // corresponding plain tuple type
typedef Tuple<L1>::Type Type1; // extract the underlying type sequence
typedef Tuple<L1> T_L1; // derive a tuple type from this typelist
typedef Types<T_L1>::Seq Seq1; // extract the underlying type sequence
DISPLAY (Type1);
DISPLAY (T_L1);
DISPLAY (T1);
DISPLAY (Seq1);
T_L1 tup1 (Num<1>(8)); // both flavours can be created at runtime
T1 tup2 (Num<1>(9)); // (and we provide an explicit value for the 1st element)
T_L1 tup1; // can be instantiated at runtime (and is just a std:tuple)
DUMPVAL (tup1);
DUMPVAL (tup2);
typedef Tuple<Node<int, L1> > Prepend;
using Prepend = Tuple<Node<int, L1>>;
DISPLAY (Prepend); // another ListType based tuple created by prepending
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
Prepend prep (22, 11,33,Num<5>());
DUMPVAL (prep);
typedef Tuple<Types<> > NulT; // plain-flat empty Tuple
typedef Tuple<NullType> NulL; // list-style empty Tuple
CHECK ( is_Tuple<T1>::value);
CHECK ( is_TuplePlain<T1>::value);
CHECK (! is_TupleListType<T1>::value);
CHECK (! is_NullTuple<T1>::value);
NulT nulT; // and these, too, can be instantiated
NulL nulL;
CHECK ( is_Tuple<T_L1>::value);
CHECK (! is_TuplePlain<T_L1>::value);
CHECK ( is_TupleListType<T_L1>::value);
CHECK (! is_NullTuple<T_L1>::value);
using S4 = struct{int a,b,c,d;}; // expect this to have the same memory layout
CHECK (sizeof(S4) == sizeof(prep));
CHECK (1 == sizeof(nulL)); // ...minimal storage, as expected
CHECK ( is_Tuple<NulT>::value);
CHECK ( is_TuplePlain<NulT>::value);
CHECK (! is_TupleListType<NulT>::value);
CHECK ( is_NullTuple<NulT>::value);
CHECK ( is_Tuple<NulL>::value);
CHECK (! is_TuplePlain<NulL>::value);
CHECK ( is_TupleListType<NulL>::value);
CHECK ( is_NullTuple<NulL>::value);
CHECK (is_Tuple<T_L1>());
CHECK (is_Tuple<Prepend>());
CHECK (is_Tuple<NulT>());
CHECK (!is_Tuple<Seq1>());
CHECK (! is_Tuple<Type1>::value);
CHECK (! is_TuplePlain<Type1>::value);
CHECK (!is_TupleListType<Type1>::value);
CHECK (! is_NullTuple<Type1>::value);
CHECK (! is_Tuple<Types1::List>::value);
CHECK (! is_TuplePlain<Types1::List>::value);
CHECK (!is_TupleListType<Types1::List>::value);
CHECK (! is_NullTuple<Types1::List>::value);
cout << tup1 <<endl // these automatically use our generic string conversion
<< prep <<endl
<< nulL <<endl;
cout << showSizeof(tup1) <<endl
<< showSizeof(prep) <<endl
<< showSizeof(nulT) <<endl
<< showSizeof(nulL) <<endl;
}
void
check_sub_tuple_types()
{
cout << "\t:\n\t: ---Sub-Tuple-Types----\n";
typedef Append<Types2::List, Types1::List>::List L2;
typedef Tuple<L2> T_L2; // list-style Tuple
typedef Types<T_L2::HeadType> Head;
typedef T_L2::TailType Tail;
DISPLAY (T_L2);
DISPLAY (Head);
DISPLAY (Tail);
typedef T_L2::TupleType T2; // plain-flat Tuple
typedef Types<T2::HeadType> Head2;
typedef T2::TailType Tail2;
DISPLAY (T2);
DISPLAY (Head2);
DISPLAY (Tail2);
typedef Tuple<Types<> > NulT; // plain-flat empty Tuple
typedef Tuple<NullType> NulL; // list-style empty Tuple
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); // 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);
DISPLAY (NulT::TupleType);
DISPLAY (NulT::ThisType);
DISPLAY (NulT::Tail);
DISPLAY (NulT::ArgList);
DISPLAY (NulL::Type);
DISPLAY (NulL::TailType);
DISPLAY (NulL::TupleType);
DISPLAY (NulL::ThisType);
DISPLAY (NulL::Tail);
DISPLAY (NulL::ArgList);
}
void
check_shiftedTuple()
{
cout << "\t:\n\t: ---Shifted-Tuple---\n";
typedef Append<Types2::List, Types3::List>::List L3;
typedef Tuple<L3>::Type Ty3;
typedef Tuple<Ty3> T3;
typedef Shifted<Ty3,0>::Type Ty_0; DISPLAY (Ty_0);
typedef Shifted<Ty3,1>::Type Ty_1; DISPLAY (Ty_1);
typedef Shifted<Ty3,2>::Type Ty_2; DISPLAY (Ty_2);
typedef Shifted<Ty3,3>::Type Ty_3; DISPLAY (Ty_3);
typedef Shifted<Ty3,4>::Type Ty_4; DISPLAY (Ty_4);
typedef T3::ShiftedTuple<0>::Type T_0; DISPLAY (T_0);
typedef T3::ShiftedTuple<1>::Type T_1; DISPLAY (T_1);
typedef T3::ShiftedTuple<2>::Type T_2; DISPLAY (T_2);
typedef T3::ShiftedTuple<3>::Type T_3; DISPLAY (T_3);
typedef T3::ShiftedTuple<4>::Type T_4; DISPLAY (T_4);
T3 tu3; DUMPVAL (tu3);
T_0 tu3_0 = tu3.getShifted<0>(); DUMPVAL (tu3_0);
T_1 tu3_1 = tu3.getShifted<1>(); DUMPVAL (tu3_1);
T_2 tu3_2 = tu3.getShifted<2>(); DUMPVAL (tu3_2);
T_3 tu3_3 = tu3.getShifted<3>(); DUMPVAL (tu3_3);
T_4 tu3_4 = tu3.getShifted<4>(); DUMPVAL (tu3_4);
}
void
check_tuple_creation()
{
cout << "\t:\n\t: ---creating-Tuples---\n";
Tuple<Types1> tup1 ;
Tuple<Types1> tup11 (Num<1>(11) );
Tuple<Types1> tup12 (Num<1>(), Num<3>(33) );
Tuple<Types1> tup13 (Num<1>(11), Num<3>(33), Num<5>() );
DUMPVAL (tup1);
DUMPVAL (tup11);
DUMPVAL (tup12);
DUMPVAL (tup13);
typedef Tuple<Types<int,int,Num<11> > > Tup2;
Tup2 tup2 = tuple::make(41,42, Num<11>(43)); // build tuple from given values
DISPLAY (Tup2);
DUMPVAL (tup2);
typedef Tup2::Tail Tup22;
Tup22 tup22 = tup2.getTail();
DISPLAY (Tup22);
DUMPVAL (tup22);
typedef Tup2::Tail::Tail Tup222;
Tup222 tup222 = tup22.getTail();
DISPLAY (Tup222);
DUMPVAL (tup222);
typedef Tuple<Types<> > T0T;
typedef Tuple<NullType> T0L;
T0T nullT = tuple::makeNullTuple();
T0L nullL = tuple::makeNullTuple();
T0T nulTcpy (nullL);
T0T& nulTref (nullL.tupleCast());
DISPLAY (T0T);
DISPLAY (T0L);
DUMPVAL (nullT);
DUMPVAL (nullL);
DUMPVAL (nulTcpy);
DUMPVAL (nulTref);
}
void
check_build_from_subTuple()
{
cout << "\t:\n\t: ---build-from-sub-Tuples---\n";
typedef Append<Types1::List, Types3::List>::List TL;
typedef Tuple<TL>::Type TT;
typedef Tuple<TL> T1357L;
typedef Tuple<TT> T1357T;
DISPLAY (T1357L);
DISPLAY (T1357T);
typedef Tuple<Types1::List> T135L;
typedef Tuple<Types<Num<5>,Num<7> > > T57T;
typedef Tuple<Types<Num<3>,Num<5> > > T35T;
DISPLAY (T135L);
DISPLAY (T57T);
DISPLAY (T35T);
T135L sub135;
T57T sub57;
T35T sub35 (Num<3>(8),Num<5>(8));
DUMPVAL (sub135);
T1357T b_135 = tuple::BuildTuple<T1357T,T135L>::create(sub135);
DUMPVAL (b_135);
b_135 = tuple::BuildTuple<T1357L,T135L>::create(sub135);
DUMPVAL (b_135);
b_135 = tuple::BuildTuple<TL,Types1>::create(sub135);
DUMPVAL (b_135);
b_135 = tuple::BuildTuple<TT,Types1::List>::create(sub135);
DUMPVAL (b_135); // all variations of type specification lead to the same result
DUMPVAL (sub57);
T1357T b_57 = tuple::BuildTuple<T1357T,T57T,2>::create(sub57);
DUMPVAL (b_57);
DUMPVAL (sub35);
T1357T b_35 = tuple::BuildTuple<T1357T,T35T,1>::create(sub35);
DUMPVAL (b_35);
b_35 = tuple::BuildTuple<T1357T,T35T,2>::create(sub35);
DUMPVAL (b_35); // note: wrong start position, argument tuple ignored completely
b_35 = tuple::BuildTuple<T1357T,T35T,4>::create(sub35);
DUMPVAL (b_35);
// use an argument tuple beyond the last argument of the target tuple...
typedef Tuple<Types<Num<7>,Num<8> > > T78T;
T78T sub78 (Num<7>(77),Num<8>(88));
DUMPVAL (sub78);
T1357T b_78 = tuple::BuildTuple<T1357T,T78T,3>::create(sub78);
DUMPVAL (b_78); // note: superfluous arguments ignored
typedef Tuple<Types<> > NulT;
NulT nult;
T1357T b_nul = tuple::BuildTuple<T1357T,NulT,1>::create(nult);
DUMPVAL (b_nul);
b_nul = tuple::BuildTuple<T1357T,NulT,4>::create(nult);
DUMPVAL (b_nul);
NulT b_nul2 = tuple::BuildTuple<NulT,T78T>::create(sub78);
DUMPVAL (b_nul2)
b_nul2 = tuple::BuildTuple<NulT,T78T,1>::create(sub78);
DUMPVAL (b_nul2)
}
void
check_tuple_copy()
{
cout << "\t:\n\t: ---copy-operations---\n";
Tuple<Types1> tup1 (Num<1>(11), Num<3>(33), Num<5>() );
Tuple<Types1> tup11 (tup1);
tup11.getAt<2>().o_ = 44;
DUMPVAL (tup1);
DUMPVAL (tup11);
tup1 = tup11;
DUMPVAL (tup1);
Tuple<Types1::List> tupL = tup11.getShifted<0>();
Tuple<Types1> tup1L (tupL); // create plain tuple from list-style tuple
DUMPVAL (tupL);
DUMPVAL (tup1L);
}
void
check_value_access()
{
cout << "\t:\n\t: ---value-access---\n";
typedef Append<Types2::List, Types2::List>::List T2424;
typedef Tuple<T2424> TupX;
TupX tupX;
DISPLAY (TupX);
DUMPVAL (tupX);
Tuple<Types2> tu2;
DUMPVAL (tu2);
tuple::element<1>(tu2).o_ = 5;
tu2.getHead() = Num<2> (tu2.getAt<1>().o_);
DUMPVAL (tu2);
tupX.getShifted<2>() = tu2;
DUMPVAL (tupX);
typedef Shifted<TupX::TupleType,2>::TupleType T4;
T4 t4 (tupX.getShifted<2>());
DISPLAY (T4);
DUMPVAL (t4);
DISPLAY (TupX::Type)
DISPLAY (TupX::TailType)
DISPLAY (TupX::ThisType)
DISPLAY (TupX::TupleType)
typedef TupX::TupleType TupT;
DISPLAY (TupT::Type)
DISPLAY (TupT::TailType)
DISPLAY (TupT::ThisType)
DISPLAY (TupT::TupleType)
TupT tupXcopy (tupX);
DUMPVAL (tupXcopy);
TupT& tupXcast (tupX.tupleCast()); // (down)cast list-style to plain tuple
DUMPVAL (tupXcast);
}
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////OBSOLETE :: TICKET #988
};

View file

@ -95,8 +95,8 @@ namespace meta {
namespace test { // unit tests covering typelist manipulating templates
namespace { // hidden internals for diagnostics....
namespace test{ // unit tests covering typelist manipulating templates
namespace { // internals to support diagnostics in unit tests....
using util::_Fmt;
@ -109,8 +109,12 @@ namespace meta {
/** debugging template,
* printing the "number" used for instantiation on ctor call
*/
template<class NUM=NullType, class BASE=NullP>
struct Printer;
template<class T=NullType, class BASE=NullP>
struct Printer
: BASE
{
static string print () { return _Fmt("-<%s>%s") % typeStr<T>() % BASE::print(); }
};
template<class BASE>
struct Printer<NullType, BASE>
@ -177,7 +181,6 @@ namespace meta {
}
};
} // (End) internal defs