template<typename Head, typename Tail>
struct TypeList
{
typedef Head H;
typedef Tail T;
};
#define TYPELIST_1(T1) TypeList<T1, TL::NullType>
#define TYPELIST_2(T1, T2) TypeList<T1, TL::TYPELIST_1(T2)>
#define TYPELIST_3(T1, T2, T3) TypeList<T1, TL::TYPELIST_2(T2, T3)>
#define TYPELIST_4(T1, T2, T3, T4) TypeList<T1, TL::TYPELIST_3(T2, T3, T4)>
#define TYPELIST_5(T1, T2, T3, T4, T5) TypeList<T1, TL::TYPELIST_4(T2, T3, T4, T5)>
#define TYPELIST_6(T1, T2, T3, T4, T5, T6) TypeList<T1, TL::TYPELIST_5(T2, T3, T4, T5, T6)>
#define TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) TypeList<T1, TL::TYPELIST_6(T2, T3, T4, T5, T6, T7)>
#define TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) TypeList<T1, TL::TYPELIST_7(T2, T3, T4, T5, T6, T7, T8)>
#define TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) TypeList<T1, TL::TYPELIST_8(T2, T3, T4, T5, T6, T7, T8, T9)>
#define TYPELIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) TypeList<T1, TL::TYPELIST_9(T2, T3, T4, T5, T6, T7, T8, T9, T10)>
#define TYPELIST_11(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) TypeList<T1, TL::TYPELIST_10(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)>
#define TYPELIST_12(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) TypeList<T1, TL::TYPELIST_11(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)>
#define TYPELIST_13(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) TypeList<T1, TL::TYPELIST_12(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)>
#define TYPELIST_14(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) TypeList<T1, TL::TYPELIST_13(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)>
#define TYPELIST_15(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) TypeList<T1, TL::TYPELIST_14(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)>
#define TYPELIST_16(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) TypeList<T1, TL::TYPELIST_15(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16)>
#define TYPELIST_17(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) TypeList<T1, TL::TYPELIST_16(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17)>
#define TYPELIST_18(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) TypeList<T1, TL::TYPELIST_17(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18)>
#define TYPELIST_19(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) TypeList<T1, TL::TYPELIST_18(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19)>
#define TYPELIST_20 (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) TypeList<T1, TL::TYPELIST_19(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20)>
TypeList分别有一个Head和Tail的内置类型,但是该新的数据类型并非只是两种类型的复合,目前支持20种,因为Head或者Tail本身就可以是TypeList,如:
string,int,int可以表示为
TypeList<
string
,TypeList<int,TypeList<int,NullType>>>。
我们可以将三种分开的类型,用一种数据类型表示,但是我们不能每次都自己去写成这么纠结的
生成
TypeList<
string
,TypeList<int,TypeList<int,NullType>>>类型,所以提供一种生成
TypeList类型的工具:
template<class T1=NullType, class T2=NullType, class T3= NullType, class T4= NullType, class T5= NullType,
class T6= NullType, class T7= NullType, class T8= NullType, class T9= NullType, class T10= NullType,
class T11= NullType, class T12= NullType, class T13= NullType, class T14= NullType, class T15= NullType,
class T16= 1, class T17= NullType, class T18= NullType, class T19= NullType, class T20= NullType>
struct TLMaker
{
private:
typedef TYPELIST_20( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) TmpList;
public:
typedef typename EraseAll<TmpList, NullType>::Result Result;
};
其中
EraseAll如下:
template<class TList, class T> struct EraseAll;
template<class T> struct EraseAll< NullType, T>
{
typedef NullType Result;
};
template<class T, class Tail> struct EraseAll< TypeList< T, Tail>, T>
{
typedef typename EraseAll< Tail, T>:: Result Result;
};
template<class Head, class Tail, class T> struct EraseAll<TypeList <Head, Tail>, T>
{
typedef TypeList<Head, typename EraseAll< Tail, T>:: Result> Result;
};
使用的时候:
TLMaker<int, int>::Result可以得到TypeList<int,TypeList<int,NullType>>类型。
步骤如下:
1)
TLMaker<int,
int
>::Result是需要TLMake中内置的Result类型,也就是
EraseAll
<
TmpList
,
NullType
>::
Result,也就是需要
EraseAll
<
TmpList
,
NullType
>内置的Result。而这里有四个
EraseAll声明,我们需要通过Template的类型看偏特化使用哪一个EraseAll的声明,这就需要我们首先解析TmpList。
2)
typedef
TYPELIST_20(
T1
,
T2
,
T3
,
T4
,
T5
,
T6
,
T7
,
T8
,
T9
,
T10
,
T11
,
T12
,
T13
,
T14
,
T15
,
T16
,
T17
,
T18
,
T19
,
T20
)
TmpList其中我们指定了第一个模版类型int,第二个模版类型也是int,其他的模版类型都是默认的NullType,我们将产生一个拥有
TYPELIST_20
,
经过
20层define递归的,TypeList如下:
TypeList<int,TypeList<int,TypeLIst<
NullType,TypeList<
NullType,TypeList<.....20
>>,我们需要借助EraseAll来消除多余的NullType,将之变成
TypeList<int,TypeList<int,NullType>>。
3)
EraseAll
<
TmpList
,
NullType
>其中TmpList为
TypeList<int,TypeList<int,TypeLIst<
NullType,TypeList<
NullType,TypeList<.....20
>>,可以看成TypeList<int,Tail>的类型,其中由于int不为NullType,所以不能匹配
template
<
class
T
,
class
Tail
>
struct
EraseAll
<
TypeList
<
T
,
Tail
>,
T
>的偏特化,只能匹配
template
<
class
Head
,
class
Tail
,
class
T
>
struct
EraseAll
<
TypeList
<
Head
,
Tail
>,
T
>的EraseAll的偏特化,其中Head为int,Tail为
TypeLIst<
NullType,TypeList<
NullType,TypeList<.....20
>,T为NullType,而该偏特化中的Result其实本身是一个嵌套的递归的Result,继续按照这个方法往下推断,直到TypeList中的Head为NullType为止(其实也就是递归
两次,我们这里只有两个int),这个时候将可以匹配
template
<
class
T
,
class
Tail
>
struct
EraseAll
<
TypeList
<
T
,
Tail
>,
T
>这个偏特化模版。最后直到结果成为
TypeList<i
nt,TypeList<int,NullType>>.
下面是一个类型萃取器:
template<bool flag, typename U, typename V>
struct TypeSelect
{
typedef U Result;
};
template<typename U, typename V>
struct TypeSelect<false, U, V>
{
typedef V Result;
};
///////////////////////////////////////////////////////////////////////////////////////
/**
* 类型萃取器, copy至 Loki库
*/
template<typename T>
class TypeTraits
{
private:
///////////////////////////////////////////////////////
//提取引用的原始类型(即去掉引用类型)
template<class U>
struct ReferenceTraits
{
enum { result = false };
typedef U Result;
};
template<class U>
struct ReferenceTraits<U&>
{
enum { result = true };
typedef U Result;
};
///////////////////////////////////////////////////////
//指针类型
template<class U>
struct PointerTraits
{
enum { result = false };
typedef TL:: NullType Result;
};
template<class U>
struct PointerTraits<U*>
{
enum { result = true };
typedef U Result;
};
template<class U>
struct PointerTraits<U*&>
{
enum { result = true };
typedef U Result;
};
///////////////////////////////////////////////////////
//成员函数指针, gcc 下面支持有问题, 屏蔽之
template<typename U>
struct PointerToMemberTraits
{
enum { result = false };
};
template<class U, class V>
struct PointerToMemberTraits< U V::*>
{
enum { result = true };
};
template<class U, class V>
struct PointerToMemberTraits< U V::*&>
{
enum { result = true };
};
///////////////////////////////////////////////////////
// const
template<typename U>
struct UnConstTraits
{
enum { result = false };
typedef U Result;
};
template<typename U>
struct UnConstTraits<const U>
{
enum { result = true };
typedef U Result;
};
template<typename U>
struct UnConstTraits<const U&>
{
enum { result = true };
typedef U& Result;
};
///////////////////////////////////////////////////////
// volatile
template<typename U>
struct UnVolatileTraits
{
enum { result = false };
typedef U Result;
};
template<typename U>
struct UnVolatileTraits<volatile U>
{
enum { result = true };
typedef U Result;
};
template<typename U>
struct UnVolatileTraits<volatile U&>
{
enum { result = true };
typedef U& Result;
};
public:
//T是否是指针类型
enum { isPointer = PointerTraits< T>::result };
//T是否是引用类型
enum { isReference = ReferenceTraits<T >::result };
//T是否指向成员函数的指针
enum { isMemberPointer = PointerToMemberTraits<T >::result };
//T是否是Const类型
enum { isConst = UnConstTraits< T>::result };
//T是否是Volatile类型
enum { isVolatile = UnVolatileTraits< T>::result };
//如果T是指针类型,则获取T的原类型, 即去掉指针类型
typedef typename PointerTraits<T>::Result PointeeType;
//如果T是引用类型,则获取T的原类型, 即去掉引用类型
typedef typename ReferenceTraits<T>::Result ReferencedType;
//如果T是Const类型,则获取T的原类型, 即去掉 Const类型
typedef typename UnConstTraits<T>::Result NonConstType;
//如果T是volatile类型,则获取T的原类型, 即去掉volatile类型
typedef typename UnVolatileTraits<T>::Result NonVolatileType;
//去掉const volatile类型
typedef typename UnVolatileTraits<typename UnConstTraits<T >::Result >::Result UnqualifiedType ;
public:
//////////////////////////////////////////////////////
//
typedef TL::TLMaker<unsigned char, unsigned short, unsigned int , unsigned long, unsigned long long>::Result UnsignedInts;
typedef TL::TLMaker<signed char, short, int, long, long long>:: Result SignedInts;
typedef TL::TLMaker<bool, char, wchar_t>::Result OtherInts;
typedef TL::TLMaker<float, double, long double>::Result Floats;
typedef TL::TYPELIST_2(TL:: EmptyType, TL:: NullType) NullTypes;
//无符号整形
enum { isStdUnsignedInt = TL:: IndexOf< UnsignedInts, T>::value >= 0 };
//有符号整形
enum { isStdSignedInt = TL:: IndexOf< SignedInts, T>::value >= 0 };
//整形
enum { isStdInt = isStdUnsignedInt || isStdSignedInt || TL::IndexOf <OtherInts , T>::value >= 0 };
//浮点类型
enum { isStdFloat = TL:: IndexOf< Floats, T>::value >= 0 };
//数值类型
enum { isStdArith = isStdInt || isStdFloat };
//基础类型(包括void)
enum { isStdFundamental = isStdArith || TL::IndexOf<TL::TYPELIST_1( void), T>::value >= 0};
//空类型
enum { isNullType = TL:: IndexOf< NullTypes, T>::value >= 0 };
//简单类型
enum { isBaseType = isStdArith || isPointer || isMemberPointer };
//对于复杂类型, 获取数据的引用类型, 即加上引用类型
typedef typename TypeSelect<isBaseType, T, ReferencedType&>::Result ReferenceType ;
//对于复杂类型且非空类型, 获取数据的引用类型, 即加上引用类型
//typedef typename TypeSelect<isBaseType || isNullType, T, ReferencedType&>::Result ReferenceTypeEx;
//获取数据的原类型, 消除引用的引用这种情况
typedef typename TypeSelect<!isReference, T, ReferencedType&>::Result ParameterType ;
};
下面我们分析一下,如何通过一个引用类型获取原生类型,通过一个原生类型获取引用类型,通过一个指针类型,获取原生类型。
typedef
typename
TypeTraits
<
string&
>::
ParameterType
Param1
将会把
Param1定义为
sting类型。
1)该
TypeTraits的模版类型为String&,我们要获取其中的
ParameterType,也就是
typedef
typename
TypeSelect
<!
isReference
,
T
,
ReferencedType
&>::
Result
;
2)我们需要确定是使用
TypeSelect的那个偏特化,首先得知道
isReference
到底是true还是false。
3)
enum
{
isReference
=
ReferenceTraits
<
T
>::result }是
TypeTraits中的一个匿名枚举,作用和静态变量类似,我们需要确定
isReference
的值,首先需要一个
ReferenceTraits。
ReferenceTraits的定义如下:
template<class U>
struct ReferenceTraits
{
enum { result = false };
typedef U Result;
};
template<class U>
struct ReferenceTraits< U&>
{
enum { result = true };
typedef U Result;
};
//指针类型
template<class U>
struct PointerTraits
{
enum { result = false };
typedef TL:: NullType Result;
};
template<class U>
struct PointerTraits<U*>
{
enum { result = true };
typedef U Result;
};
template<class U>
struct PointerTraits<U*&>
{
enum { result = true };
typedef U Result;
};