📄 typelist.h
字号:
enum
{
NoneList_ID = 0,
Typelist_ID = 1,
AtomList_ID = 2,
NullType_ID = 4
};
////////////////////////////////////////////////////////////////////////////////
// class template IsTypelist
// detects if type is Typelist (including Nulltype)
// Invocation :
// IsTypelist<T>::value
////////////////////////////////////////////////////////////////////////////////
template<typename T>
struct IsTypelist
{
private:
typedef TypeTag<1>::X List;
typedef TypeTag<2>::X AtomList;
typedef TypeTag<3>::X NullList;
typedef TypeTag<4>::X NoList;
// VC 6.0 does not allow overloads
// for check(Type2Type< Typelist<Head, Tail> >)
// and check(Type2Type<NullType>);
// so we must use to different functions
template<class Head, class Tail>
static TypeTag<1>::X check(Type2Type< Typelist<Head, Tail> >);
static TypeTag<4>::X check(...);
template <class U>
static TypeTag<2>::X check2(Type2Type< Typelist<U, NullType> >);
static TypeTag<4>::X check2(...);
static TypeTag<3>::X check3(Type2Type<NullType>);
static TypeTag<4>::X check3(...);
public:
enum
{
temp1 = sizeof(check(Type2Type<T>())) == sizeof(TypeTag<1>::X) ? Typelist_ID : NoneList_ID,
temp2 = sizeof(check2(Type2Type<T>())) == sizeof(TypeTag<2>::X) ? AtomList_ID : NoneList_ID,
temp4 = temp2 ? Typelist_ID :NoneList_ID,
temp3 = sizeof(check3(Type2Type<T>())) == sizeof(TypeTag<3>::X) ? NullType_ID : NoneList_ID,
value = temp1 || temp2 || temp3,
type_id = (temp1 ^ temp4) | temp2 | temp3
};
typedef typename Select
<
type_id == Typelist_ID || type_id == AtomList_ID,
Typelist_tag,
typename Select<type_id == NullType_ID, NullType_tag, NoneList_tag>::Result
>
::Result type_tag;
};
} // end of namespace Private
////////////////////////////////////////////////////////////////////////////////
// class template MakeTypelist
// Takes a number of arguments equal to its numeric suffix
// The arguments are type names.
// MakeTypeList<T1, T2, ...>::Result
// returns a typelist that is of T1, T2, ...
////////////////////////////////////////////////////////////////////////////////
// MakeTypeList-Template from Rani Sharoni's VC 7 port.
template
< typename T1 = NullType, typename T2 = NullType, typename T3 = NullType,
typename T4 = NullType, typename T5 = NullType, typename T6 = NullType,
typename T7 = NullType, typename T8 = NullType, typename T9 = NullType,
typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
>
struct MakeTypelist
{
private:
typedef typename MakeTypelist
<
T2 , T3 , T4 ,
T5 , T6 , T7 ,
T8 , T9 , T10,
T11, T12, T13,
T14, T15, T16,
T17, T18
>
::Result TailResult;
public:
typedef Typelist<T1, TailResult> Result;
};
template<>
struct MakeTypelist
<
NullType, NullType, NullType,
NullType, NullType, NullType,
NullType, NullType, NullType,
NullType, NullType, NullType,
NullType, NullType, NullType,
NullType, NullType, NullType
>
{
typedef NullType Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template Length
// Computes the length of a typelist
// Invocation (TList is a typelist):
// Length<TList>::value
// returns a compile-time constant containing the length of TList, not counting
// the end terminator (which by convention is NullType)
////////////////////////////////////////////////////////////////////////////////
template <class TList>
struct Length
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
public:
enum {value = 1 + Length<Tail>::value};
};
// explicit specialization for an empty list.
// this is the border case for the recursive length-calculation
template <>
struct Length<NullType>
{
enum {value = 0};
};
////////////////////////////////////////////////////////////////////////////////
// class template TypeAt
// Finds the type at a given index in a typelist
// Invocation (TList is a typelist and index is a compile-time integral
// constant):
// TypeAt<TList, index>::Result
// returns the type in position 'index' in TList
// If you pass an out-of-bounds index, the result is a compile-time error
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
// The type at Index i is the type at i-1 of the List's Tail
template <unsigned int Index>
struct TypeAtImpl
{
template <class TList>
struct In
{
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
typedef typename TypeAtImpl<Index-1>::template In<Tail>::Result Result;
};
};
// the border case is represented by an explicit specialization
// The type at Index 0 is the type of the head.
template <>
struct TypeAtImpl<0>
{
template <class TList>
struct In
{
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef Head Result;
};
};
} // end of namespace Private
template <class TList, unsigned int Index>
struct TypeAt
{
typedef typename Private::TypeAtImpl<Index>::template In<TList>::Result Result ;
};
////////////////////////////////////////////////////////////////////////////////
// class template TypeAtNonStrict
// Finds the type at a given index in a typelist
// Invocations (TList is a typelist and index is a compile-time integral
// constant):
// a) TypeAt<TList, index>::Result
// returns the type in position 'index' in TList, or NullType if index is
// out-of-bounds
// b) TypeAt<TList, index, D>::Result
// returns the type in position 'index' in TList, or D if index is out-of-bounds
////////////////////////////////////////////////////////////////////////////////
template <class TList, unsigned int i, class DefType = NullType>
struct TypeAtNonStrict;
namespace Private
{
// if TList is not NullType, check if Index is 0.
// if Index is 0, the result is TList::Head
// if Index is > 0, the result is the result of appliying TypeAtNonStrict
// to the list's and Index-1
template <class TList>
struct TypeAtNonStrictImpl
{
template <class DefType, unsigned int Index>
struct In
{
ASSERT_TYPELIST(TList);
typedef typename Select
<
Index == 0, // The condition
typename TList::Head, // true-case
typename TypeAtNonStrict<typename TList::Tail, Index-1, DefType>::Result
>::Result Result;
};
};
// if TList is NullType the result is *always* the specified DefaultType.
template <>
struct TypeAtNonStrictImpl<NullType>
{
template <class DefType, unsigned int Index>
struct In
{
typedef DefType Result;
};
};
} // end of namespace Private
template <class TList, unsigned int i, class DefType>
struct TypeAtNonStrict
{
typedef typename
Private::TypeAtNonStrictImpl<TList>::template In<DefType, i>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template IndexOf
// Finds the index of a type in a typelist
// Invocation (TList is a typelist and T is a type):
// IndexOf<TList, T>::value
// returns the position of T in TList, or -1 if T is not found in TList
////////////////////////////////////////////////////////////////////////////////
template <class TList, class T>
struct IndexOf;
namespace Private
{
// If TList is a typelist and TList::Head is T, then the Index is 0
// If TList::Head is not T, compute the result of IndexOf applied to
// TList's tail and T into a temporary value temp.
// If temp is -1, then value is -1
// Else value is 1 + temp
template <class TList>
struct IndexOfImpl
{
template <class T>
struct In
{
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
enum {temp = IsEqualType<T, Head>::value != 0 ? 0
: IndexOf<Tail, T>::temp};
public:
enum {value = temp == -1 ? -1 : 1 + temp};
};
};
// T cannot be in an empty list.
// Therefore return -1 to indicate Not-In-List
template <>
struct IndexOfImpl<NullType>
{
template <class T>
struct In
{
enum {value = -1};
};
};
} // end of namespace Private
// The primary IndexOfImpl-Template is always one step ahead.
// Therefore if T is in list, we need to subtract one from the result.
template <class TList, class T>
struct IndexOf
{
enum {temp = Private::IndexOfImpl<TList>::template In<T>::value};
enum {value = temp == -1 ? -1 : temp - 1};
};
////////////////////////////////////////////////////////////////////////////////
// class template Append
// Appends a type or a typelist to another
// Invocation (TList is a typelist and T is either a type or a typelist):
// Append<TList, T>::Result
// returns a typelist that is TList followed by T and NullType-terminated
////////////////////////////////////////////////////////////////////////////////
template <class TList, class T>
struct Append;
namespace Private
{
template <class TList>
struct AppendImpl
{ // if TList is not NullType the result
// is a typelist having TList::Head as its Head and
// and the result of appending T to TList::Tail as its tail.
ASSERT_TYPELIST(TList);
template <class T>
struct In
{
typedef Typelist<typename TList::Head,
typename Append<typename TList::Tail, T>::Result> Result;
};
};
template <>
struct AppendImpl<NullType>
{ // if TList is NullType, check if T is NullType, a single type
// or a typelist
// If TList is NullType and T is NullType
// the result is NullType, too
//
// If TList is NullType and T is not NullType.
// Check if T is a Typelist
//
// if TList is NullType and T is a typelist the result is T
// if TList is NullType and T is not a typelist
// the result is a typelist containing only T
template <class T>
struct In
{
typedef typename Select
<
IsEqualType<T, NullType>::value, // is T == Nulltype?
NullType, // yes
typename Select // no. check if T is a Typelist
<
IsTypelist<T>::value, // is T a typelist?
T, // yes
Typelist<T, NullType> // no
>::Result
>::Result Result;
};
};
} // end of namespace Private
template <class TList, class T>
struct Append
{
typedef typename Private::AppendImpl<TList>::template In<T>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template Erase
// Erases the first occurence, if any, of a type in a typelist
// Invocation (TList is a typelist and T is a type):
// Erase<TList, T>::Result
// returns a typelist that is TList without the first occurence of T
////////////////////////////////////////////////////////////////////////////////
template <class TList, class T>
struct Erase;
namespace Private
{
template <class TList>
struct EraseImpl
{ // TList is not NullType.
// Check if TList::Head is equal to T
// if T is the same as TList::Head, then the Result is TList::Tail
//
// if TList is not NullType and TList::Head is not equal to T,
// then the Result is a Typelist having TList::Head as its Head
// and the result of applying Erase to the tail of list as its
// tail.
template <class T>
struct In
{
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
typedef typename Select
<
IsEqualType<Head, T>::value, // is T equal to Head?
Tail, // Yes. Result is tail
Typelist<typename TList::Head, // No. recurse
typename Erase<typename TList::Tail, T>::Result>
>::Result Result;
};
};
// if TList is NullType the result is NullType.
template <>
struct EraseImpl<NullType>
{
template <class T>
struct In
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -