快速业务通道

C++箴言:谨慎使用模板元编程

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-30

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 对等物占用长得多的编译时间。)

考虑STL的advance伪代码。(在《C++箴言:为类型信息使用特征类》中。你现在可能需要读该文,因为在本文中,我假设你已经熟悉了该文的内容。),我突出表示代码中的伪代码部分:

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++ 方法——它的全部工作都在运行时做:

template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d)
{
if (typeid(typename std::iterator_traits<IterT>::iterator_category) ==
typeid(std::random_access_iterator_tag)) {
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++ 中更简单,而 advance 提供了这方面的一个例子。Item 47 提到 advance 的 typeid-based(基于 typeid)的实现可能会导致编译问题,而这就是一个产生问题的例子:

std::list<int>::iterator iter;
...
advance(iter, 10); // move iter 10 elements forward;
// won''t compile with above impl.

考虑 advance 为上面

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号