STL源码剖析(四)迭代器iterators设计与traits特性

迭代器类型:iterator_category

迭代器根据移动特性和执行操作,可分为五类:
①Input iterator: 输入迭代器,只读,不写,单遍扫描,只能递增
②Output iterator: 输出迭代器,只写,不读,单遍扫描,只能递增
③Forward iterator: 前向迭代器,可读写,多遍扫描,只能递增
④Bidirectional iterator: 双向迭代器,可读写,多遍扫描,可递增递减
⑤Random Access Iterator: 随机访问迭代器,可读写,多遍扫描,支持全部迭代器运算
*前四种迭代器都只支持一部分指针算术能力,前三种支持operator++,第四种支持operator- -,第五种则支持指针所有算术能力,包括p+n, p-n, p[n], p1-p2, p1<p2。

这些迭代器的分类与从属关系:
(Input iterator, Output iterator)——强化——>Forward iterator——强化——>Bidirectional iterator——强化——>Random Access Iterator。

当定义算法时,输入参数为迭代器,因五种迭代器支持操作不同,而算法无法区分上述五种迭代器,如果执行时期才决定使用哪一种迭代器会影响效率,程序希望在编绎时期就选择正确的版本,此时重载函数机制可达成目标。

traits特性
traits可提取出迭代器的种类,作为算法参数,在编绎期决定使用相应迭代器的重载版本。
traits的iterator_category即为迭代器类型。

迭代器的设计
STL的中心思想在于:将数据容器(containers)和算法(algorithms)分开,彼此独立设计。
容器和算法的泛型化,C++的class templates和function templates可分别达成目标。
迭代器扮演容器和算法之间的粘胶角色。

iterator模式定义为:提供一种方法,使之能够依序访问某个聚合物(容器)所含的每个元素,而又无需暴露该聚合物的内部表达方式。

迭代器是一种smart pointer
迭代器是一种行为类似指针的对象,指针行为中最常见的便是解引用和成员访问,因此迭代器最重要的编程工作就是对operator*和operator->进行重载工作。

namespace std _GLIBCXX_VISIBILITY(default)
{
  //定义五种迭代器类型的tag,仅作为标记用,类中不需要任何成员
  //iterator_traits<Iterator>::iterator_category()可得到以下五种tag类型
  struct input_iterator_tag { }; //input iterators.
  struct output_iterator_tag { }; //output iterators.
  //Forward iterators support a superset of input iterator operations.
  struct forward_iterator_tag : public input_iterator_tag { };
  //Bidirectional iterators support a superset of forward iterator operations.
  struct bidirectional_iterator_tag : public forward_iterator_tag { };
  //Random-access iterators support a superset of bidirectional iterator operations.
  struct random_access_iterator_tag : public bidirectional_iterator_tag { };

  //算法中使用迭代器时,可能会用到相应类型,例迭代器所指元素类型等
  //函数模板形参可通过实参推断,但返回类型无法推断
  //将返回类型等一应类型封装为类,类中声明各种类型,解决模板函数返回类型无法推断问题
  //类中不含任何成员,后三个模板参数皆有默认值,新设计的迭代器继承自它,提供前两个模板参数即可
  template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t,
           typename _Pointer = _Tp*, typename _Reference = _Tp&>
    struct iterator //iterator模板类
    {
      typedef _Category  iterator_category; //迭代器的类型,不同的迭代器支持的操作不同
      typedef _Tp        value_type; //元素类型,即迭代器所指对象类型
      typedef _Distance  difference_type; //两迭代器之间的距离,足够表示容器最大容量,STL的count()的返回类型
      typedef _Pointer   pointer; //指向迭代器元素的指针,等同于value_type*
      typedef _Reference reference; //元素的左值引用,与value_type&含义相同
    };

  template<typename _Iterator, typename = __void_t<>>
    struct __iterator_traits { }; //__iterator_traits模板类一

  template<typename _Iterator> //__iterator_traits模板类二
    struct __iterator_traits<_Iterator,
			     __void_t<typename _Iterator::iterator_category,
				      typename _Iterator::value_type,
				      typename _Iterator::difference_type,
				      typename _Iterator::pointer,
				      typename _Iterator::reference>>
    {
      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;
    };

  //iterator_traits设计如下:
  template<typename _Iterator> //iterator_traits模板类,继承__iterator_traits模板类
    struct iterator_traits
    : public __iterator_traits<_Iterator> { };
    
  //内置指针类型不是class类型,无法内嵌类型,需定义特例化版本
  //iterator_traits针对传入类型为pointer及const pointer设计特例化版本。
  //特例化版本的指针类型是random_access_iterator_tag类型
  template<typename _Tp>
    struct iterator_traits<_Tp*>
    {
      typedef random_access_iterator_tag iterator_category; //指针类型为random_access_iterator_tag类型
      typedef _Tp                         value_type;
      typedef ptrdiff_t                   difference_type;
      typedef _Tp*                        pointer;
      typedef _Tp&                        reference;
    };
  
  template<typename _Tp>
    struct iterator_traits<const _Tp*>
    {
      typedef random_access_iterator_tag iterator_category; //指针类型为random_access_iterator_tag类型
      typedef _Tp                         value_type;
      typedef ptrdiff_t                   difference_type;
      typedef const _Tp*                  pointer;
      typedef const _Tp&                  reference;
    };

  //返回迭代器的类型
  //iterator_traits<Iterator>::iterator_category()返回上述定义的五种tag类型
  template<typename _Iter>
    inline _GLIBCXX_CONSTEXPR
    typename iterator_traits<_Iter>::iterator_category
    __iterator_category(const _Iter&)
    { return typename iterator_traits<_Iter>::iterator_category(); }

  template<typename _InIter>
    using _RequireInputIter = typename
      enable_if<is_convertible<typename
		iterator_traits<_InIter>::iterator_category,
			       input_iterator_tag>::value>::type;
} // namespace
namespace std _GLIBCXX_VISIBILITY(default)
{
  template <typename> struct _List_iterator;
  template <typename> struct _List_const_iterator;

  //以下是整组distance函数
  //__distance()只在内部使用,第三参数根据五种tag形成重载
  //第三参数为input_iterator_tag时,迭代器循环累计距离
  //output_iterator_tag、forward_iterator_tag、bidirectional_iterator_tag使用此版本
  //STL算法命名规则,以算法所能接受之最低阶迭代器类型为迭代器类型参数命名
  template<typename _InputIterator>
    inline _GLIBCXX14_CONSTEXPR
    typename iterator_traits<_InputIterator>::difference_type
    __distance(_InputIterator __first, _InputIterator __last,
               input_iterator_tag)
    {
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)

      typename iterator_traits<_InputIterator>::difference_type __n = 0;
      while (__first != __last)
		{
		  ++__first;
		  ++__n;
		}
      return __n;
    }
  //第三参数为random_access_iterator_tag时,迭代器直接计算距离
  template<typename _RandomAccessIterator>
    inline _GLIBCXX14_CONSTEXPR
    typename iterator_traits<_RandomAccessIterator>::difference_type
    __distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
               random_access_iterator_tag)
    {
      // concept requirements
      __glibcxx_function_requires(_RandomAccessIteratorConcept<
				  _RandomAccessIterator>)
      return __last - __first;
    }
  
  //_List_iterator和_List_const_iterator的特例化版本
  template<typename _Tp>
    ptrdiff_t
    __distance(_GLIBCXX_STD_C::_List_iterator<_Tp>,
	       _GLIBCXX_STD_C::_List_iterator<_Tp>,
	       input_iterator_tag);

  template<typename _Tp>
    ptrdiff_t
    __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>,
	       _GLIBCXX_STD_C::_List_const_iterator<_Tp>,
	       input_iterator_tag);
  //distance根据不同迭代器类型调用不同__distance
  template<typename _InputIterator>
    inline _GLIBCXX17_CONSTEXPR
    typename iterator_traits<_InputIterator>::difference_type
    distance(_InputIterator __first, _InputIterator __last)
    {
      //__iterator_category()获取迭代器类型调用相应版本
      //根据迭代器类型重载不同版本__distance()
      return std::__distance(__first, __last,
			     std::__iterator_category(__first));
    }

  //以下是整组的advance函数
  //第三参数为input_iterator_tag时,迭代器单向,+1前进
  template<typename _InputIterator, typename _Distance>
    inline _GLIBCXX14_CONSTEXPR void
    __advance(_InputIterator& __i, _Distance __n, input_iterator_tag)
    {
      // concept requirements
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      __glibcxx_assert(__n >= 0);
      while (__n--)
		++__i;
    }

  //第三参数为bidirectional_iterator_tag时,迭代器双向,+1或-1
  template<typename _BidirectionalIterator, typename _Distance>
    inline _GLIBCXX14_CONSTEXPR void
    __advance(_BidirectionalIterator& __i, _Distance __n,
	      bidirectional_iterator_tag)
    {
      // concept requirements
      __glibcxx_function_requires(_BidirectionalIteratorConcept<
				  _BidirectionalIterator>)
      if (__n > 0)
        while (__n--)
	  		++__i;
      else
        while (__n++)
	  		--__i;
    }

  //第三参数为random_access_iterator_tag时,迭代器双向,跳跃前进
  template<typename _RandomAccessIterator, typename _Distance>
    inline _GLIBCXX14_CONSTEXPR void
    __advance(_RandomAccessIterator& __i, _Distance __n,
              random_access_iterator_tag)
    {
      // concept requirements
      __glibcxx_function_requires(_RandomAccessIteratorConcept<
				  _RandomAccessIterator>)
      if (__builtin_constant_p(__n) && __n == 1)
		++__i;
      else if (__builtin_constant_p(__n) && __n == -1)
		--__i;
      else
		__i += __n;
    }
  //advance根据不同迭代器类型调用不同__advance
  template<typename _InputIterator, typename _Distance>
    inline _GLIBCXX17_CONSTEXPR void
    advance(_InputIterator& __i, _Distance __n)
    {
      //__iterator_category()获取迭代器类型调用相应版本
      //根据迭代器类型重载不同版本__advance()
      typename iterator_traits<_InputIterator>::difference_type __d = __n;
      std::__advance(__i, __d, std::__iterator_category(__i));
    }

  //单向迭代器,获取当前迭代器的后置
  template<typename _InputIterator>
    inline _GLIBCXX17_CONSTEXPR _InputIterator
    next(_InputIterator __x, typename
	 iterator_traits<_InputIterator>::difference_type __n = 1)
    {
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      std::advance(__x, __n);
      return __x;
    }

  //双向迭代器,获取当前迭代器的前置
  template<typename _BidirectionalIterator>
    inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator
    prev(_BidirectionalIterator __x, typename
	 iterator_traits<_BidirectionalIterator>::difference_type __n = 1) 
    {
      __glibcxx_function_requires(_BidirectionalIteratorConcept<
				  _BidirectionalIterator>)
      std::advance(__x, -__n);
      return __x;
    }
} // namespace
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值