• 欢迎浏览“String me = Creater\忠实的资深Linux玩家;”,请文明浏览,理性发言,有侵犯你的权益请邮件我(creater@vip.qq.com).
  • 把任何的失败都当作一次尝试,不要自卑;把所有的成功都想成是一种幸运,不要自傲。
  •    5年前 (2013-04-26)  STL |   2 条评论  22 
    文章评分 0 次,平均分 0.0

    很早以前,第一次看STL源码,第一次接触iterator_traits,我觉得他是一个巧妙的发明。
    而现在再来看他,我觉得他变得更加绝妙。

    iterator_traits是和迭代器在一起的,是针对迭代器来说的。也就是说通过iterator_traits可以了解到迭代器的信息和迭代器所指向元素的信息。
    在编码的时候,往往需要定义一个迭代器指向对象类型的变量或者对象,我们可以利用函数模板推导来获得value_type类型。

    template <class I, clss T>
    void _func(I iter, T t)
    {
    	T tmp;
    	/*---*/
    }
    
    template <class I>
    void func(I iter)
    {
    	_func(iter, *iter);
    }


    func是我们知道的接口,传入一个迭代器作为参数,但是我们函数内部需要定义一个该迭代器指向类型的对象,就可以像上面那样包裹并利用模板推导来完成。
    但是如果我们想根据模板参数I,和I指向的类型value_tyoe作为返回值,上边好像就无能为力了。

    现在该特性萃取机iterator_traits上场了

    template <class Iterator>
    struct iterator_traits {
      typedef typename Iterator::iterator_category iterator_category;
      typedef typename Iterator::value_type        value_type;
      typedef typename Iterator::difference_type   difference_type;
      typedef typename Iterator::pointer           pointer;
      typedef typename Iterator::reference         reference;
    };
    
    template <class T>
    struct iterator_traits<T*> {
      typedef random_access_iterator_tag iterator_category;
      typedef T                          value_type;
      typedef ptrdiff_t                  difference_type;
      typedef T*                         pointer;
      typedef T&                         reference;
    };
    
    template <class T>
    struct iterator_traits<const T*> {
      typedef random_access_iterator_tag iterator_category;
      typedef T                          value_type;
      typedef ptrdiff_t                  difference_type;
      typedef const T*                   pointer;
      typedef const T&                   reference;
    };
    

    先大体看看,就知道了任何迭代器都需要有以上的哪几种类型定义
    iterator_category;
    value_type;
    difference_type;
    pointer;
    reference;
    通过萃取器就可以采用如下方式获取迭代器指向元素的value_type
    iterator_traits::value_type
    但是内置类型的指针不是类结构,不能定义value_type,但是我们可以通过模板特化解决。
    那么为什么还要针对const T*特化呢?因为不特化的话,value_type将是const T。

    另外iterator_category的作用是,针对不同的迭代器类型在加上一个数时效率不同,而需要分开处理来设计的。比如advance

    template <class InputIterator, class Distance>
    inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
      while (n--) ++i;
    }
    
    #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
    #pragma set woff 1183
    #endif
    
    template <class BidirectionalIterator, class Distance>
    inline void __advance(BidirectionalIterator& i, Distance n, 
                          bidirectional_iterator_tag) {
      if (n >= 0)
        while (n--) ++i;
      else
        while (n++) --i;
    }
    
    #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
    #pragma reset woff 1183
    #endif
    
    template <class RandomAccessIterator, class Distance>
    inline void __advance(RandomAccessIterator& i, Distance n, 
                          random_access_iterator_tag) {
      i += n;
    }
    
    template <class InputIterator, class Distance>
    inline void advance(InputIterator& i, Distance n) {
      __advance(i, n, iterator_category(i));
    }
    

    advance为对外开放的接口,客户只知道该接口可以对一个指针进行增加,并不知道针对不同的迭代器处理方式不一样,比如随机迭代器只需要一次加运算就可以完成。
    在advance里调用了__advance(i, n, iterator_category(i));或者__advance(i, n, iterator_category::itreator_category());通过特性萃取器iterator_category可以提取出当前迭代器的类型来选择不同的处理方式。其中的iterator_category(i),只不过是利用了函数模板的推导性进行了包装,返回的是一个对象。

    template <class Iterator>
    inline typename iterator_traits<Iterator>::iterator_category
    iterator_category(const Iterator&) {
      typedef typename iterator_traits<Iterator>::iterator_category category;
      return category();
    }
     

    除特别注明外,本站所有文章均为String me = "Creater\忠实的资深Linux玩家";原创,转载请注明出处来自http://unix8.net/home.php/877.html

    关于

    发表评论

    暂无评论

    切换注册

    登录

    忘记密码 ?

    切换登录

    注册

    扫一扫二维码分享