C 箴言:为类型信息使用特征类

2008-02-23 05:27:16来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

STL 主要是由 containers(容器),iterators(迭代器)和 algorithms(算法)的 templates(模板)构成的,但是也有几个 utility templates(实用模板)。其中一个被称为 advance。advance 将一个指定的 iterator(迭代器)移动一个指定的距离:

template<typename IterT, typename DistT> // move iter d units
void advance(IterT& iter, DistT d); // forward; if d < 0,
// move iter backward

  在概念上,advance 仅仅是在做 iter = d,但是 advance 不能这样实现,因为只有 random access iterators(随机访问迭代器)支持 = operation。不够强力的 iterator(迭代器)类型不得不通过反复利用 或 -- d 次来实现 advance。

  您不记得 STL iterator categories(迭代器种类)了吗?没问题,我们这就做一个简单回顾。对应于他们所支持的操作,共有五种 iterators(迭代器)。input iterators(输入迭代器)只能向前移动,每次只能移动一步,只能读他们指向的东西,而且只能读一次。他们以一个输入文档中的 read pointer(读指针)为原型;C 库中的 istream_iterators 就是这一种类的典型代表。output iterators(输出迭代器)和此类似,只但是用于输出:他们只能向前移动,每次只能移动一步,只能写他们指向的东西,而且只能写一次。他们以一个输出文档中的 write pointer(写指针)为原型;ostream_iterators 是这一种类的典型代表。这是两个最不强力的 iterator categories(迭代器种类)。因为 input(输入)和 output iterators(输出迭代器)只能向前移动而且只能读或写他们指向的地方最多一次,他们只适合 one-pass 运算。

  一个更强力一些的 iterator category(迭代器种类)是 forward iterators(前向迭代器)。这种 iterators(迭代器)能做 input(输入)和 output iterators(输出迭代器)能够做到的每一件事情,再加上他们能够读或写他们指向的东西一次以上。这就使得他们可用于 multi-pass 运算。STL 没有提供 singly linked list(单向链表),但某些库提供了(通常被称为 slist),而这种 containers(容器)的 iterators(迭代器)就是 forward iterators(前向迭代器)。TR1 的 hashed containers(哈希容器)的 iterators(迭代器)也能够属于 forward category(前向迭代器)。

  bidirectional iterators(双向迭代器)为 forward iterators(前向迭代器)加上了和向前相同的向后移动的能力。STL 的 list 的 iterators(迭代器)属于这一种类,set,multiset,map 和 multimap 的 iterators(迭代器)也相同。

  最强力的 iterator category(迭代器种类)是 random access iterators(随机访问迭代器)。这种 iterators(迭代器)为 bidirectional iterators(双向迭代器)加上了 "iterator arithmetic"(“迭代器运算”)的能力,也就是说,在常量时间里向前或向后跳转一个任意的距离。这样的运算类似于指针运算,这并不会让人感到惊讶,因为 random access iterators(随机访问迭代器)就是以 built-in pointers(内建指针)为原型的,而 built-in pointers(内建指针)能够和 random access iterators(随机访问迭代器)有同样的行为。vector,deque 和 string 的 iterators(迭代器)是 random access iterators(随机访问迭代器)。

  对于五种 iterator categories(迭代器种类)中的每一种,C 都有一个用于识别他的 "tag struct"(“标签结构体”)在标准库中:

struct input_iterator_tag {};

struct output_iterator_tag {};

struct forward_iterator_tag: public input_iterator_tag {};

struct bidirectional_iterator_tag: public forward_iterator_tag {};

struct random_access_iterator_tag: public bidirectional_iterator_tag {};

  这些结构体之间的 inheritance relationships(继承关系)是正当的 is-a 关系:任何的 forward iterators(前向迭代器)也是 input iterators(输入迭代器),等等,这都是成立的。我们不久就会看到这个 inheritance(继承)的功用。

  但是返回到 advance。对于不同的 iterator(迭代器)能力,实现 advance 的一个方法是使用反复增加或减少 iterator(迭代器)的循环的 lowest-common-denominator(最小共通特性)策略。然而,这个方法要花费 linear time(线性时间)。random access iterators(随机访问迭代器)支持 constant-time iterator arithmetic(常量时间迭代器运算),当他出现的时候我们最好能利用这种能力。

  我们真正想做的就是大致像这样实现 advance:

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
}

  这就需要能够确定 iter 是否是个 random access iterators(随机访问迭代器),依次下来,就需要知道他的类型,IterT,是否是个 random access iterators(随机访问迭代器)类型。换句话说,我们需要得到关于一个类型的某些信息。这就是 traits 让您做到的:他们允许您在编译过程中得到关于一个类型的信息。 traits 不是 C 中的一个关键字或预定义结构;他们是一项技术和 C 程式员遵守的惯例。建立这项技术的需要之一是他在 built-in types(内建类型)上必须和在 user-defined types(用户定义类型)上相同有效。例如,假如 advance 被一个指针(譬如一个 const char*)和一个 int 调用,advance 必须有效,但是这就意味着 traits 技术必须适用于像指针这样的 built-in types(内建类型)。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: C 对象布局及多态探索之菱形结构虚继承

下一篇: 验C 中接口和实现分离的技术