本系列全部转载自kuibyshev.bokee.com
C++的发展史是一个不断吸收程序设计领域精华和不断积累充实语言特性的过程。它的创造者Stroustrup在这门新的编程语言草创之初就定下了几个基本的目标,二十年过去了,至今这些目标仍然是C++继续发展的指南针。其中他明确指出,这种语言不应强迫程序员使用单一程序设计形式[20];就是说C++语言应该是一种“多种花样”的语言。正是因为Stroustrup这种高瞻远瞩的构想,才使得C++逐渐发展成为一门最具综合性、用途最广泛的语言,受到世界上最多的程序员喜爱。也正是因为同样的原因,人们在使用C++的过程中,探索出许多精巧优雅的编程技法,其中不少技法依赖着C++本身丰富的特性,在别种编程语言中并没有对应。例如伴随C++的模板技术而衍生的各种各样的技法,就能生动地说明这一点。
1994年的一次C++标准委员会的会议上,Erwin Unruh提交了一个很特别的C++程序,这个程序能够产生一系列素数,但与普通程序最大的不同,运算结果的产生是在编译期完成的,为了显示这些结果,甚至故意产生了一些编译期的错误信息,也就是说,程序从未完成编译过程,却能得到结果[13]。过程如此奇异,实际上是利用了C++模板的可递归特性,或者称为“编译期递归”。
受此启发,Todd Veldhuizen在1995年的一篇文章[27]中提出了“模板元编程(Template Metaprogramming)”这个概念,不但指出模板的特化(Specialization)能力可以用于针对编译期的编程,而且提出了几种实用的控制分支结构。从此C++的编程技术分出一门旁支,C++代码拥有的编译期和运行期的两段执行能力受到人们关注。
Krzysztof Czarnecki与Ulrich W. Eisenecker在1999年出版了《Generative Programming Methods, Tools, and Applications》一书,这本书对模板元编程的贡献是实现了一个辅助库,提出了更完善的控制结构的编写方法。
2004年出版的《C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond》一书归纳了十年来模板元编程的技术动向,成为第一本论述C++模板元编程技术的的专著。
模板元编程尽管处于C++程序设计的浪尖,仍然有不少C++程序库的作者直接或间接地利用它,甚至开发出专用于模板元编程的库,当中包括著名的Boost、Loki和Blitz++等。其中Boost提供了MPL(Meta-Programming Library),用以辅助模板元编程,当中提出了许多极有创新性的概念。
目前模板元编程已经成为C++语言的一项庞大的分支,并仍然在迅速发展。许多C++程序员都十分热衷于讨论这门技术,不断提出很多新颖的概念。
元编程(Metaprogramming)的前缀meta-表示“处于较高发展状态”的意思,从这个意义上讲,metaprogramming指的就是高阶的编程,即编写一种程序,使得这种程序可以把某些程序作为输入数据,生成或者操作其他的程序。一般而言,这些高阶的程序运行在编译时。因此,元编程并非一个新概念,事实上任何一种高级语言的编译器都可以视为元编程的工具,因为它们的程序必须被转换为汇编语言或者机器语言以后,才能够运行在计算机上。Lex和Yacc也是很传统的元编程工具,它们能够把一种新的语言根据规范转换成对应的C语言代码。
C++强大的模板机制赋予了模板在编译时的运算能力。例如以下的代码计算n!,借助于模板的特化能力形成递归,所有运算都在编译时完成:
#include
template< unsigned n >
struct factorial
{
static const unsigned value = n * factorial < 0 > ::value;
};
template<>
struct factorial<0>
{
static const unsigned value = 1;
};
int main()
{
std::cout<<factorial < 6 > ::value<<std::endl; 6!="720
}
在这个例子里面,factorial在传统意义上是一个类模板,但用元编程的观点去看待,则可以认为是一个元函数(Metafunction)。这个元函数接受一个整型的模板参数,它的返回值是元函数的一个静态成员。注意元函数与普通的函数很不一样,一方面,元函数往往需要定义一个以上的特化版本作为终结条件,另一方面,元函数的返回值需要显式地提取出来。
这个简单的程序似乎仅仅是玩弄技巧,但正如1994年Erwin Unruh所演示的那个载入史册的素数生成程序,它们其实都只是引起人们注意的冰山一角,为了深入研究模板元编程的能力、使用范围和局限性,必须清楚了解其背后的机理。