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>