正 文

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


www.7dspace.com  更新日期:2006-2-8 10:34:57  七度空间


  traits 对 built-in types(内建类型)必须有效的事实意味着将信息嵌入到类型内部是不可以的,因为没有办法将信息嵌入指针内部。那么,一个类型的 traits 信息,必须在类型外部。标准的方法是将它放到 template(模板)以及这个 template(模板)的一个或更多的 specializations(特化)中。对于 iterators(迭代器),标准库中 template(模板)被称为 iterator_traits:

template<typename IterT> // template for information about
struct iterator_traits; // iterator types

  就像你能看到的,iterator_traits 是一个 struct(结构体)。根据惯例,traits 总是被实现为 struct(结构体)。另一个惯例就是用来实现 traits 的 structs(结构体)以 traits classes(这可不是我捏造的)闻名。

  iterator_traits 的工作方法是对于每一个 IterT 类型,在 struct(结构体)iterator_traits<IterT> 中声明一个名为 iterator_category 的 typedef。这个 typedef 被看成是 IterT 的 iterator category(迭代器种类)。

   iterator_traits 通过两部分实现这一点。首先,它强制要求任何 user-defined iterator(用户定义迭代器)类型必须包含一个名为 iterator_category 的嵌套 typedef 用以识别适合的 tag struct(标签结构体)。例如,deque 的 iterators(迭代器)是随机访问的,所以一个 deque iterators 的 class 看起来就像这样:

template < ... > // template params elided
class deque {
 public:
  class iterator {
   public:
    typedef random_access_iterator_tag iterator_category;
    ...
  };
 ...
};

  然而,list 的 iterators(迭代器)是双向的,所以它们是这样做的:

template < ... >
class list {
 public:
 class iterator {
  public:
  typedef bidirectional_iterator_tag iterator_category;
  ...
 };
 ...
};

  iterator_traits 仅仅是简单地模仿了 iterator class 的嵌套 typedef:

// the iterator_category for type IterT is whatever IterT says it is;
// see Item 42 for info on the use of "typedef typename"
template<typename IterT>
struct iterator_traits {
 typedef typename IterT::iterator_category iterator_category;
 ...
};

  这样对于 user-defined types(用户定义类型)能很好地运转。但是对于本身是 pointers(指针)的 iterators(迭代器)根本不起作用,因为不存在类似于带有一个嵌套 typedef 的指针的东西。iterator_traits 实现的第二个部分处理本身是 pointers(指针)的 iterators(迭代器)。

  为了支持这样的 iterators(迭代器),iterator_traits 为 pointer types(指针类型)提供了一个 partial template specialization(部分模板特化)。pointers 的行为类似 random access iterators(随机访问迭代器),所以这就是 iterator_traits 为它们指定的种类:

template<typename IterT> // partial template specialization
struct iterator_traits<IterT*> // for built-in pointer types
{
 typedef random_access_iterator_tag iterator_category;
 ...
};

  到此为止,你了解了如何设计和实现一个 traits class:

  ·识别你想让它可用的关于类型的一些信息(例如,对于 iterators(迭代器)来说,就是它们的 iterator category(迭代器种类))。

  ·选择一个名字标识这个信息(例如,iterator_category)。

  ·提供一个 template(模板)和一系列 specializations(特化)(例如,iterator_traits),它们包含你要支持的类型的信息。

  给出了 iterator_traits ——实际上是 std::iterator_traits,因为它是 C++ 标准库的一部分——我们就可以改善我们的 advance 伪代码:

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))
 ...
}

  这个虽然看起来有点希望,但它不是我们想要的。在某种状态下,它会导致编译问题,这个问题我们以后再来研究它,现在,有一个更基础的问题要讨论。 IterT 的类型在编译期间是已知的,所以 iterator_traits<IterT>::iterator_category 可以在编译期间被确定。但是 if 语句还是要到运行时才能被求值。为什么要到运行时才做我们在编译期间就能做的事情呢?它浪费了时间(严格意义上的),而且使我们的执行码膨胀。

3页,页码:[1] [2] [3] 

上一篇:QQ宠物常见问题解答(六)
下一篇:巧用Photoshop笔刷表现写实木纹
标题:C++箴言:为类型信息使用特征类 作者:fatalerror99 来源:blog
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐