快速业务通道

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

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-30
这个调用生成的版本。用 iter 和 10 的类型取代 template parameters(模板参数)IterT 和 DistT 之后,我们得到这个:

void advance(std::list<int>::iterator& iter, int d)
{
if (typeid(std::iterator_traits<std::list<int>::iterator>::iterator_category) ==
typeid(std::random_access_iterator_tag)) {
iter += d; // error!
}
else {
if (d >= 0) { while (d--) ++iter; }
else { while (d++) --iter; }
}
}

问题在突出显示的行,使用了 += 的那行。在当前情况下,我们试图在一个 list<int>::iterator 上使用 +=,但是 list<int>::iterator 是一个 bidirectional iterator(双向迭代器)(参见《C++箴言:为类型信息使用特征类》),所以它不支持 +=。只有 random access iterators(随机访问迭代器)才支持 +=。此时,我们知道我们永远也不会试图执行那个 += 行,因为那个 typeid 检测对于 list<int>::iterators 永远不成立,但是编译器被责成确保所有源代码是正确的,即使它不被执行,而当 iter 不是一个 random access iterator(随机访问迭代器)时 "iter += d" 是不正确的。traits-based(基于 traits)的 TMP 解决方案与此对比,那里针对不同类型的代码被分离到单独的函数中,其中每一个都只使用了可用于它所针对的类型的操作。

TMP 已经被证明是 Turing-complete(图灵完备)的,这意味着它强大得足以计算任何东西。使用 TMP,你可以声明变量,执行循环,编写和调用函数,等等。但是这些结构看起来与其在“常规”C++ 中的样子非常不同。例如,《C++箴言:为类型信息使用特征类》展示了 if...else 条件在 TMP 中是如何通过 templates(模板)和 template specializations(模板特化)被表达的。但那是 assembly-level(汇编层次)的 TMP。针对 TMP 的库提供了一种更高层次的语法,虽然还不至于让你把它误认为是“常规”C++。

为了一窥其它东西在 TMP 中如何工作,让我们来看看 loops(循环)。TMP 中没有真正的 looping construct(循环结构),因此 loops(循环)的效果是通过 recursion(递归)完成的。(如果你对 recursion(递归)感到不舒服,在你斗胆进入 TMP 之前一定要解决它。TMP 很大程度上是一个 functional language(函数性语言),而 recursion(递归)之于 functional language(函数性语言)就像电视之于美国流行文化:是密不可分的。)然而,甚至 recursion(递归)都不是常规样式的,因为 TMP loops 不涉及 recursive function calls(递归函数调用),它们涉及 recursive template instantiations(递归模板实例化)。

TMP 的 "hello world" 程序在编译期间计算一个阶乘。它不是一个很令人兴奋的程序,不过,即使不是 "hello world",也有助于语言入门。TMP 阶乘计算示范了通过 recursive template instantiation(递归模板实例化)实现循环。它也示范了在 TMP 中创建和使用变量的一种方法。看:

template<unsigned n> // general case: the value of
struct Factorial { // Factorial<n> is n times the value
// of Factorial<n-1>
enum { value = n * Factorial<n-1>::value };
};
template<> // special case: the value of
struct Factorial<0> { // Factorial<0> is 1
enum { value = 1 };
};

给出这个 template metaprogram(模板元程序)(实际上只是单独的 template metafunction(模板元函数)Factorial),你可以通过引用 Factorial<n>::value 得到 factorial(n) 的值。

代码的循环部分出现在 template instantiation(模板实例化)Factorial<

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站: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号