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转换可以高效的将“型别处理工序”自动化。