模板元编程(template metaprograming)
今天第一次听说模板元编程,或者之前没在意,见到了还以为是和模板编程一样的概念,结果今天在看何海涛的面试100题第9题的时候发现下面有个解法颇为不解,查了一下,叫模板元编程。她给出的解法是这样的。
#include<iostream>using namespace std;template<int N>class SUM
{public:
const static int value = N+SUM<N-1>::value;};template<>
class SUM<1>
{public:
const static int value = 1;};int main()
{cout<<SUM<10>::value<<endl;return 0;
}
之前看过c++ template ,还以为template<int N>是偏特化,后来仔细想了想,查看了一下偏特化也不像,才重新查阅了一下资料,得知了模板元编程这个概念,维基百科给出的概念是这样的:
模板元编程(英语:Template metaprogramming;缩写:TMP)是一种元编程技术,编译器使用模板产生暂时性的源码,然后再和剩下的源码混合并编译。这些模板的输出包括编译时期常数、数据结构以及完整的函数。如此利用模板可以被想成编译期的运行。这种技术被许多语言使用,最为知名的当属C++和Ada,其他还有Curl、D、Eiffel,以及语言扩展,如en:Template Haskell。
里面关键的一句话就是“模板可以想象成编译期的运行”,因此模板元编程可以被看做是“编译期的程序设计”,说白了就是把认为能够在编译期就确定的值全部算出了,以减少运行程序体积和运行时间。
使用模板作为元编程的技术需要两阶段的操作。首先,模板必须被定义;第二,定义的模板必须被实体化才行。 模板的定义描述了生成源码的一般形式,而使实体化则导致了某些源码的组合根据该模板而生成。也就是说最终的可执行文件中只有模板元的实例,模板元编程没有可变的变量,其中的变量一旦初始化就不能够改动。
模板元编程也有特化的概念,如上面例子中这一段:
template<>
class SUM<1>
{public:
const static int value = 1;};
特化方式类似于模板编程,现在我还没看完c++ template,等我看完了再来维护一下这个章节吧。
在wiki和salomon的这篇博客里都提到了模板元编程的优劣与适用情形,摘抄如下:
优劣及适用情况通过将计算从运行期转移至编译期,在结果程序启动之前做尽可能多的工作,最终获得速度更快的程序。也就是说模板元编程的优势在于:1.以编译耗时为代价换来卓越的运行期性能(一般用于为性能要求严格的数值计算换取更高的性能)。通常来说,一个有意义的程序的运行次数(或服役时间)总是远远超过编译次数(或编译时间)。2.提供编译期类型计算,通常这才是模板元编程大放异彩的地方。模板元编程技术并非都是优点:1.代码可读性差,以类模板的方式描述算法也许有点抽象。2.调试困难,元程序执行于编译期,没有用于单步跟踪元程序执行的调试器(用于设置断点、察看数据等)。程序员可做的只能是等待编译过程失败,然后人工破译编译器倾泻到屏幕上的错误信息。3.编译时间长,通常带有模板元程序的程序生成的代码尺寸要比普通程序的大,4.可移植性较差,对于模板元编程使用的高级模板特性,不同的编译器的支持度不同。总结:模板元编程技术不适用普通程序员的日常应用,它常常会做为类库开发的提供技术支持,为常规模板代码的内核的关键算法实现更好的性能或者编译期类型计算。模板元程序几乎总是应该与常规代码结合使用被封装在一个程序库的内部。对于库的用户来说,它应该是透明的。