template metaPRogramming (TMP)(模板元编程)是写 template-based(基于模板)的运行于编译期间的 C++ 程序的过程。考虑一下:一个 template metaprogram(模板元程序)是用 C++ 写的运行于 C++ 编译器中的程序。当一个 TMP 程序运行完成,它的输出——从 templates(模板)实例化出的 C++ 源代码片断——随后被正常编译。
假如你仅把它看作古怪的特性而没有打动你,那你就不会对它有足够的深入的思考。
C++ 并不是为 template metaprogramming(模板元编程)设计的,但是自从 TMP 在 1990 年代早期被发现以来,它已被证实非常有用,使 TMP 变轻易的扩展很可能会被加入到语言和它的标准库之中。是的,TMP 是被发现,而不是被发明。TMP 所基于的特性在 templates(模板)被加入 C++ 的时候就已经被引进了。所需要的全部就是有人注重到它们能够以一种精巧的而且意想不到的方式被使用。
TMP 有两个强大的力量。首先,它使得用其它方法很难或不可能的一些事情变得轻易。第二,因为 template metaprograms(模板元程序)在 C++ 编译期间执行,它们能将工作从运行时转移到编译时。一个结果就是通常在运行时才能被察觉的错误能够在编译期间被发现。另一个结果是 C++ 程序使得 TMP 的使用在以下每一个方面都能更有效率:更小的可执行代码,更短的运行时间,更少的内存需求。(然而,将工作从运行时转移到编译时的一个结果就是编译过程变得更长。使用 TMP 的程序可能比它们的 non-TMP 对等物占用长得多的编译时间。)
template<typename IterT, typename DistT> void advance(IterT& iter, DistT d) { if (iter is a random access iterator) { iter += d; // use iterator arithmetic } // for random access iters else { if (d >= 0) { while (d--) ++iter; } // use iterative calls to else { while (d++) --iter; } // ++ or -- for other } // iterator categories } 我们可以用 typeid 把伪代码变成真正的代码。这就产生了一个解决此问题的“常规”的 C++ 方法——它的全部工作都在运行时做:
iter += d; // use iterator arithmetic } // for random access iters else { if (d >= 0) { while (d--) ++iter; } // use iterative calls to else { while (d++) --iter; } // ++ or -- for other } // iterator categories } 《C++箴言:为类型信息使用特征类》中指出这个 typeid-based(基于 typeid)的方法比使用 traits 的方法效率低,因为这个方法,(1)类型检测发生在运行时而不是编译期,(2)用来做运行时类型检测的代码必须出现在可执行代码中。实际上,这个例子展示了 TMP 如何能比一个“常规”C++ 程序更高效,因为 traits 方法是 TMP。记住,traits 答应编译时在类型上的 if...else 计算。
TMP 的支持程度在不断提升。很可能在 C++ 的下一个版本中将对它提供直接的支持,而且 TR1 已经这样做了。关于这一主题的书籍也即将开始出版(目前,C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond 已经出版——译者注),而 web 上的 TMP 信息也正在保持增长。TMP 也许永远不会成为主流,但是对于某些程序员——非凡是库开发者——它几乎必然会成为主料。