为了加深你对Typelist采用的模板元编程技术的认识,我从Loki程序库剥离出如下代码,放入一个typelistlite.h文件中:
// typelistlite.h
// 声明Nulltype
class NullType;
// Typelist的定义
template <class T, class U>
struct Typelist
{
typedef T Head;
typedef U Tail;
};
// IndexOf的定义
// IndexOf原始模板
template <class TList, class T> struct IndexOf;
// 针对NullType的局部特化版
template <class T>
struct IndexOf<NullType, T>
{
enum { value = -1 };
};
// 针对“TList头部就是我们要查找的T”的局部特化版
template <class T, class Tail>
struct IndexOf<Typelist<T, Tail>, T>
{
enum { value = 0 };
};
// 处理TList尾部的局部特化版
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) };
};
测试程序如下:
// typelistlite_test.cpp
#include <iostream>
#include "typelistlite.h"
// 自定义类型Royal
class Royal {};
// 定义一个包含有char、int、Royal和float的Typelist
typedef Typelist<char, Typelist<int, Typelist<Royal, Typelist<float, NullType> > > > CIRF;
int main()
{
std::cout << "IndexOf<CIRF, int>::value = " << IndexOf<CIRF, int>::value << "\n";
std::cout << "IndexOf<CIRF, Royal>::value = " << IndexOf<CIRF, Royal>::value << "\n";
std::cout << "IndexOf<CIRF, double>::value = " << IndexOf<CIRF, double>::value << "\n";
}
程序输出如下:
IndexOf<CIRF, int>::value = 1
IndexOf<CIRF, Royal>::value = 2
IndexOf<CIRF, double>::value = -1
结语
模板元编程技术并非都是优点,比方说,模板元程序编译耗时,带有模板元程序的程序生成的代码尺寸要比普通程序的大,而且通常这种程序调试起来也比常规程序困难得多。另外,对于一些程序员来说,以类模板的方式描述算法也许有点抽象。
编译耗时的代价换来的是卓越的运行期性能。通常来说,一个有意义的程序的运行次数(或服役时间)总是远远超过编译次数(或编译时间)。为程序的用户带来更好的体验,或者为性能要求严格的数值计算换取更高的性能,值得程序员付出这样的代价。
很难想象模板元编程技术会成为每一个普通程序员的日常工具,相反,就像Blitz++和Loki那样,模板元程序几乎总是应该被封装在一个程序库的内部。对于库的用户来说,它应该是透明的。模板元程序可以(也应该)用作常规模板代码的内核,为关键的算法实现更好的性能,或者为特别的目的实现特别的效果。
模板元编程技术首次正式亮相于Todd Veldhuizen的《Using C++ Template Metaprograms》论文之中。这篇文章首先发表于1995年5月的C++ Report期刊上,后来Stanley Lippman编辑《C++ Gems》一书时又收录了它。参考文献中给出了这篇文章的链接,它还描述了许多本文没有描述到的内容。
David Vandevoorde和Nicolai M. Josuttis合著的《C++ Templates: The Complete Guide》一书花了一整章的篇幅介绍模板元编程技术,它同样是本文的参考资料并且也应该作为你的补充阅读材料。
Andrei Alexandrescu的天才