Typelists是一个用来操作一大群型别的C++工具,就像lists对数值提供各种基本操作一样。
1.定义Typelists
Typelist是以一种特殊的型别结束:NullType
class NullType {}; struct EmptyType {}; // could be instantiated template <class T, class U> struct Typelist { typedef T Head; typedef U Tail; };
下面我们可以定义以NullType结束的型别,每个typelist都必须以NullType结尾。NullType可以视为一个结束记号,类似'\0'的功能。
typedef Typelist< char, Typelist<signed char,
Typelist<unsigned char, NullType> > > Charlist;
注:Typelists内部没有任何数值:他们的实体是空的,不含任何的状态,也未定义任何的函数。执行期间typelists也不带任何数值。它们存在的理由只是为了携带型别信息。因此,对typelist的任何处理都一定发生在编译期而不是执行期。
2.将Typelist的生成线性化
用宏来将递归形式转化成比较简单的枚举形式,取代比较冗长的的重复动作。Loki把Typelists的长度扩充到了50.
#define TYPELIST_1(T1) ::Loki::Typelist<T1, ::Loki::NullType> #define TYPELIST_2(T1, T2) ::Loki::Typelist<T1, LOKI_TYPELIST_1(T2) > #define TYPELIST_3(T1, T2, T3) ::Loki::Typelist<T1, LOKI_TYPELIST_2(T2, T3) > #define TYPELIST_4(T1, T2, T3, T4) \ ::Loki::Typelist<T1, LOKI_TYPELIST_3(T2, T3, T4) >
现在可以用简单的方式定义Charlist了
typedef TYPELIST_3(char, signed char, unsigned char) Charlist;
3.计算长度
假设TList typelist,它有一个编译期常数代表其长度。因为typelists是一种静态构件,所以这个与typelists相关的计算在编译期完成。计算typelist长度的代码如下:
// // 长度 // template <class TList> struct Length; template <> struct Length<NullType> //Length的全特化,只匹配NullType { enum { value = 0 }; }; template <class T, class U> struct Length <Typelist<T,U> > //Length的偏特化,可以匹配任何Typelist<T,U>型别,包括复合型 { enum { value = 1 + Length<U>::value }; };
4.索引访问
一个带有索引操作的template的声明式如下:
template<class TList,unsigned int index>struct TypeAt;
TypeAt:
输入:typelist TList,索引值i
输出:内部某型别Result
如果TList不为null且i=0,那么Result就是TList的头部
否则
如果TList不为null且i不为0,那么Result就是将TypeAt施行于TList尾端及i-1的结果
否则越界访问,造成编译错误。
TypeAt的算法如下:
template <class Head, class Tail> struct TypeAt< TypeList<Head, Tail>, 0> { typedef Head Result; }; template <class Head, class Tail, unsigned int i> struct TypeAt< TypeList<Head, Tail, i> { typedef typename TypeAt<Tail,i-1>::Result Result; };
5.查找Typelists
流程如下:
if TList is NullType then -1
if the Head is T then 0
if IndexOf(Tail,T)==-1 then -1
else IndexOf(Tail,T)+1
算法如下:
template <class TList, class T> struct IndexOf; template <class T> struct IndexOf< NullType, T> { enum { value = -1 }; }; template <class T, class Tail> struct IndexOf< Typelist<Head, Tail>, T> { private: enum { temp = IndexOf<Tail, T>::value }; public: enum { value = (temp == -1) ? -1 : 1+temp }; };
6.附加元素到Typelist
// // Append // template <class TList, class T> struct Append; template <> struct Append< NullType, NullType> { typedef NullType Result; }; template <class T> struct Append< NullType, T> { typedef TYPELIST_1(T) Result; }; template <class Head, class Tail> struct Append< NullType, Typelist<Head,Tail> > { tyepdef Typelist<Head,Tail> Result; }; template <class Head, class Tail, class T> struct Append< Typelist<Head,Tail>, T> { typedef Typelist<Head, typename Append<Tail,T>::Result> Result; };
使用方法如下:
typedef Append<SignedIntegrals,
TYPELIST_3(float,double,long double)>::Result SignedTypes;
7.移除Typelist中的某个元素
// // Erase // template <class TList, class T> struct Erase; template <class T> struct Erase< NullType, T> { typedef NullType Result; }; template <class T, clas Tail> struct Erase< Typelist<T, Tail>, T> { typedef Tail Result; }; template <class Head, class Tail, class T> struct Erase< TypeList<Head, Tail>, T> { typedef TypeList<Head, typename Erase<Tail,T>::Result> Result; };
使用方法:
typedef Erase<SignedTypes,float>::Result SomeSignedTypes;
移除所有的元素:
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> { // Go all the way down the list removing the type typedef typename EraseAll<Tail, T>::Result Result; }; template <class Head, class Tail, class T> struct EraseAll<Typelist<Head, Tail>, T> { // Go all the way down the list removing the type typedef Typelist<Head, typename EraseAll<Tail, T>::Result> Result; };
8.移除重复的元素
template <class TList> struct NoDuplicates; template <> struct NoDuplicates<NullType> { typedef NullType Result; }; template <class Head, class struct NoDuplicates< Typelist<Head, Tail> > { private: typedef typename NoDuplicates<Tail>::Result L1; typedef typename Erase<L1, Head>::Result L2; public: typedef Typelist<Head, L2> Result; };
9.取代Typelist中的某个元素(以型别U取代型别T)
template <class TList, class T, class U> struct Replace; template <class T, class U> struct Replace<NullType, T, U> { typedef NullType Result; }; template <class T, class Tail, class U> struct Replace<Typelist<T, Tail>, T, U> { typedef Typelist<U, Tail> Result; }; template <class Head, class Tail, class T, class U> struct Replace<Typelist<Head, Tail>, T, U> { typedef Typelist<Head, typename Replace<Tail, T, U>::Result> Result; };
10. 为Typelists局部更换次序
让派生型别出现在基础型别之前。MostDerived算法接受一个typelist和一个Base型别,传回typelist中base的最深层派生型别。如果找不到任何派生型别,就返回Base自己。
如下:
template <class TList, class T> struct MostDerived; template <class T> struct MostDerived<NullType, T> { typedef T Result; }; 、 template <class Head, class Tail, class T> struct MostDerived<Typelist<Head, Tail>, T> { private: typedef typename MostDerived<Tail, T>::Result Candidate; public: typedef typename Select< SuperSubclass<Candidate,Head>::value, Head, Candidate>::Result Result; };
DerivedToFront算法是以MostDerivedwei为基础,如下:
template <class TList> struct DerivedToFront; template <> struct DerivedToFront<NullType> { typedef NullType Result; }; template <class Head, class Tail> struct DerivedToFront< Typelist<Head, Tail> > { private: typedef typename MostDerived<Tail, Head>::Result TheMostDerived; typedef typename Replace<Tail, TheMostDerived, Head>::Result Temp; typedef typename DerivedToFront<Temp>::Result L; public: typedef Typelist<TheMostDerived, L> Result; };
DerivedToFront转换可以高效的将“型别处理工序”自动化。