C++ STL之Iterator

Iterator需要遵循的原则

Iterator是算法和容器的桥梁
在这里插入图片描述
iterator 需要回答在本例子中需要回答3种问题,在C++标准库开发种需要设计出5种,另外两种从未在C++标准库中被使用过:reference 和 pointer

template<typename _ForwardIterator>
inline void
rotate(_ForwardIterator _first
          _ForwardIterator _middle,
          _ForwardIterator _last){
	...
	std::_rotate(_first,_middle,_last,
					 std::iterator_category(_first));
					 //调用traits机① 可以知道该迭代器的分类,从而采取最佳的操作方式
					 //需要知道iteratords的三个associated types
}
//①得到该迭代器的 分类
template<typename _Iter>
inline typename iterator_traits<_Iter>::iterator_category
_iterator_category(const _Iter&)
{
return typename iterator_traits<_Iter>::iterator_category();
//有的iterator只能向前走++,有的可以往后走--,有的可以跳着走,不同的分类category
}
//②帮助算法逆转
template<typename _RandomAccessIterator>
void
_rotate(_RandomAccessIterator _first,
			_RandomAccessIterator _middle,
			_RandomAccessIterator _last,
			random_access_iterator_tag){//tag获取迭代器的分类
...
//iterator必须要有能力回答algorithms的提问
typedef typename iterator_traits<_RandomAccessIterator>::difference_type _Distance;//两个iterator之间的距离,unsigned int 最大是2^32 -1,容器容量小于他时,可以使用ui
typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType;//元素的类型
_Distance __n=__last-__first;
_Distance __k=__middle-__first;
...
for(;;){
	if(__k<__n-__k){
		if(_is_pod(ValueType)&&__k==1){
			_ValueType __t=GLIBCXX_MOVE(*__p);
			......
}

Iterator必须提供的5种associated types

//迭代器回答
//G2.9
template<class T,class Ref,class Ptr>
struct _list_iterator{
	typedef bidirectional_iterator_tag iterator_category;(1)//双向的标记
	typedef T value_type;//(2)
	typedef Ptr pointer;//(3)
	typedef Ref reference;//(4)
	typedef ptrdiff_t difference_type;//(5) 容器两个元素的距离,ptrdiff_t是long int,与size_t相比,size_t是unsigned类型,而ptrdiff_t可以是负数
	...
}
//此处不需要traits了,已经能够回答
//G4.9
template<typename _Tp>
struct _List_iterator
{
	typedef std::bidirectional_iterator_tag iterator_category;
	typedef _Tp value_type;
	typedef _Tp* pointer;
	typedef _Tp& reference;
	typedef ptrdiff_t differnce_type;
	...
}
//算法提问
template<typename I>
inline void
algorithm(I first,I last){
...
	I::iterator_category
	I::pointer
	I::reference
	I::value_type
	I::differce_type
...
}

只有class才能够做typedef
但是,如果iterator并不是个class呢?
例如native pointer (即是一种自然的C++指针,例如int *),
此时class iterator就不能够回答退化指针算法的这个问题
(它被视为一种退化的iterator)
迭代器被视为一种泛化的指针

因此设计traits,中介层

Traits 特性,特征,特质

Iterator Traits 用以分离class iterators 和 non_class iterators

这个traits机器必须有能力分辨它所获得的iterator是(1)class iterator T 或是 (2)native pointer to T。利用partial specialization可达到目标。
在这里插入图片描述
解决计算机问题的尚方宝剑:加一个中介层

//traits代替指针回答

//①如果I是class Iterator进入这里
template <class I>
struct iterator_traits{
 typedef typename I::value_type value_type;//trait转问I,不能直接问
}

//两个partial specialization:范围上的偏特化

//②如果是pointer to T进入这里
template <class T>
struct iterator_traits<T*>{
	typedef T value_type;
}
//③如果是pointer to const T进入这里
template<class T>
struct iterator_traits<const T*>{
	typedef T value_type;//此处注意时T不是const T!!
	/*
	value_type的主要目的时用来声明变量,而声明一个无法被赋值
	的变量没什么用,所以iterator(即便是consant iterator)的
	value type不应加上const。iterator若是const int*,其value_type
	应该是int而非const int
	*/
}

//算法询问
//于是当需要知道I的value_type时可以这么写:
template<typename I,...>
void algorithm(...){
	typename iterator_traits<I>::value_type v1;//I跳到①②③
}

完整的traits

//两种偏特化
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 T* pointer;
  typedef T& reference;
};

各式各样的traits

  • type traits <…/C++/type_traits>
  • iterator traits <…/C++/bits/stl_iterator.h>
  • char traits <…/C++/bits/char_traits.h>
  • allocator traits <…/C++/bits/alloc_traits.h>
  • pointer traits <…/C++/bits/ptr_traits.h>
  • array traits <…/C++/array>

猜你喜欢

转载自blog.csdn.net/CarmenIsOK/article/details/89297497