now able to remove our old Tuple type (closes #988)
all unit-tests PASS again
This commit is contained in:
parent
f6d04d4d02
commit
297f986b5f
5 changed files with 78 additions and 1820 deletions
|
|
@ -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
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue