从哪里来看,这章都是这整本书的重中之重: 介绍了模板元编程, 编译期间编程的利器。 同时实现了typelist这个整本书为之基石的类。 虽说模板元编程晦涩难懂, 但是作者以渐进的方式, typelist为例, 将之阐述的条例清楚, 只要有一定的template基础, 还是能够看明白的了。
typelist的目的: 是为了用同样的代码来泛型处理不同类型, 只需要提供一系列的类型,那么就会自动为这一系列类型生成代码。
typlist的定义: 由一系列类型组合而成的list, 为了实现编译期的递归处理, typelist采用了一种递归定义方法:如:
#define LOKI_TYPELIST_1(T1) ::Loki::Typelist<T1, ::Loki::NullType>
#define LOKI_TYPELIST_2(T1, T2) ::Loki::Typelist<T1, LOKI_TYPELIST_1(T2) >
#define LOKI_TYPELIST_3(T1, T2, T3) ::Loki::Typelist<T1, LOKI_TYPELIST_2(T2, T3) >
更大的typelist由比他小1的typelist加一个类型构成。
接下来, 介绍了各种typelist的操作, 作者由简入深, 通过介绍这些操作, 将模板元编程的奥妙展现无遗。
1. 计算长度. 这是一个递归运算, 第一个特化, 意思是当递归到起点, 没有类型的时候, 此时:TList为NullType. 长度=0.第二个特化就是递归定义, 当长度不等于0的时候, 长度= 1 + 去掉头的typelist的长度。 相当于我们程序实现了一个递归。 区别只是: 这里利用了编译期间的模板实现来进行递归。
template <class TList> struct Length;
template <> struct Length<NullType>
{
enum { value = 0 };
};
template <class T, class U>
struct Length< Typelist<T, U> >
{
enum { value = 1 + Length<U>::value };
};
从这里可以看出编译期实现的一些特性:
1. Template, 模板提供了编译期的分支语句, 即通过不同的类型或者值(值经过intToType包装,相当于不同的类型), 生成不同的特化版本。相当于实现了不同类型之间的差异性。
2. 数值计算: 编译期间只能使用常量, 所以任何辅助的值都是常量。
3. typedefs , 可以用作定义类型常量, 当然,这个类型定义之后就不能改变了。
由于编译期间没有任何的变量可以使用, 所以只能用递归实现行为了。
2. 索引访问 提供了根据索引得到typelist中的对应类型. 递归方式类似length.
template <class TList, unsigned int index> struct 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;
};
3. 查找typelists 提供了在typelist中搜索T的行为。 是一个古典的递归线性查找, 可以看出, 模板的特化步骤就是线性查找的实现.
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<T, Tail>, T>
{
enum { value = 0 };
};
template <class Head, class Tail, class T>
struct IndexOf<Typelist<Head, Tail>, T>
{
private:
enum { temp = IndexOf<Tail, T>::value };
public:
enum { value = (temp == -1 ? -1 : 1 + temp) };
};
4. Append, 加入新的元素, 加入到typelist的尾部, 同样使用递归:
template <class TList, class T> struct Append;
template <> struct Append<NullType, NullType>
{
typedef NullType Result;
};
template <class T> struct Append<NullType, T>
{
typedef Typelist<T,NullType> Result;
};
template <class Head, class Tail>
struct Append<NullType, Typelist<Head, Tail> >
{
typedef 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;
};
5. Erase 去处typelist中的第一个特定类型
template <class TList, class T> struct Erase;
template <class T> // Specialization 1
struct Erase<NullType, T>
{
typedef NullType Result;
};
template <class T, class Tail> // Specialization 2
struct Erase<Typelist<T, Tail>, T>
{
typedef Tail Result;
};
template <class Head, class Tail, class T> // Specialization 3
struct Erase<Typelist<Head, Tail>, T>
{
typedef Typelist<Head,
typename Erase<Tail, T>::Result>
Result;
};
6. EraseAll, 去处typelist中的所有特定类型
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;
};
7. 去处重复类型 这个递归使用了Erase, 将typelist分为head, tail. 然后在tail中删去head这个元素类型, 最后将head和删去后的tail连接起来, 完成递归。
template <class TList> struct NoDuplicates;
template <> struct NoDuplicates<NullType>
{
typedef NullType Result;
};
template <class Head, class Tail>
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;
};
8. Replace 取代某个特定元素
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;
};
9. 部分排序: 以派生关系为依据,对typelist中的类型进行排序。 当然, 这里要用到以前所实现的SUPERSUBCLASS, 用以判断两个类型之间的派生关系。
MostDerived: 以T为基类, 在typelist中找到以T为基类的派生顺序的最底层。
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: 实现了最终算法, 这个算法应用了MostDerived:
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;
};