|
for void doAdvance(IterT& iter, DistT d, // random access std::random_access_iterator_tag) // iterators { iter = d; }
template<typename IterT, typename DistT> // use this impl for void doAdvance(IterT& iter, DistT d, // bidirectional std::bidirectional_iterator_tag) // iterators { if (d >= 0) { while (d--) iter; } else { while (d ) --iter; } }
template<typename IterT, typename DistT> // use this impl for void doAdvance(IterT& iter, DistT d, // input iterators std::input_iterator_tag) { if (d < 0 ) { throw std::out_of_range("Negative distance"); // see below } while (d--) iter; } 因为 forward_iterator_tag 从 input_iterator_tag 继承而来,针对 input_iterator_tag 的 doAdvance 版本也将处理 forward iterators(前向迭代器)。这就是在不同的 iterator_tag structs 之间继承的动机。(实际上,这是所有 public inheritance(公有继承)的动机的一部分:使针对 base class types(基类类型)写的代码也能对 derived class types(派生类类型)起作用。)
advance 的规范对于 random access(随机访问)和 bidirectional iterators(双向迭代器)允许正的和负的移动距离,但是如果你试图移动一个 forward(前向)或 input iterator(输入迭代器)一个负的距离,则行为是未定义的。在我检查过的实现中简单地假设 d 是非负的,因而如果一个负的距离被传入,则进入一个直到计数降为零的非常长的循环。在上面的代码中,我展示了改为一个异常被抛出。这两种实现都是正确的。未定义行为的诅咒是:你无法预知会发生什么。
给出针对 doAdvance 的各种重载,advance 需要做的全部就是调用它们,传递一个适当的 iterator category(迭代器种类)类型的额外 object 以便编译器利用 overloading resolution(重载解析)来调用正确的实现:
template<typename IterT, typename DistT> void advance(IterT& iter, DistT d) { doAdvance( // call the version iter, d, // of doAdvance typename // that is std::iterator_traits<IterT>::iterator_category() // appropriate for ); // iter's iterator } // category 我们现在能够概述如何使用一个 traits class 了:
·创建一套重载的 "worker" functions(函数)或者 function templates(函数模板)(例如,doAdvance),它们在一个 traits parameter(形参)上不同。与传递的 traits 信息一致地实现每一个函数。
·创建一个 "master" function(函数)或者 function templates(函数模板)(例如,advance)调用这些 workers,传递通过一个 traits class 提供的信息。
traits 广泛地用于标准库中。有 iterator_traits,当然,再加上 iterator_category,提供了关于 iterators(迭代器)的四块其它信息(其中最常用的是 value_type )。还有 char_traits 持有关于 character types(字符类型)的信息,还有 numeric_limits 提供关于 numeric types(数值类型)的信息,例如,可表示值的最小值和最大值,等等。(名字 numeric_limits 令人有些奇怪,因为关于 traits classes 更常用的惯例是以 "traits" 结束,但是它就是被叫做 numeric_limits,所以 numeric_limits 就是我们用的名字。)
TR1引入了一大批新的 traits classes 提供关于类型的信息,包括 is_fundamental<T>(T 是否是一个 built-in type(内建类型)),is_array<T>(T 是否是一个 array type(数组类型)),以及 is_base_of<T1, T2>(T1 是否和 T2 相同或者是 T2 的一个 base class(基类))。合计起来,TR1 在标准 C 中加入了超过 50 个 traits classes。
Things to Remember
·traits classes 使关于类型的信息在编译期间可用。它们使用 templates(模板)和 template specializations(模板特化)实现。
·结合 overloading(重载),traits classes 使得执行编译期类型 if...else 检验成为可能。
[3]
上一页 [1] [2] [3]
|