STL源码剖析:Iterator
Iterator需要遵循的原则
迭代器是算法和容器之间的桥梁
· 迭代器必须提供5种相关类型(associated types),以配合算法
Iterator的五种类型
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
-
input_iterator_tag: 该种迭代器所指向类型只读
-
output_iterator_tag: 所指向类型只写
-
forward_iterator_tag:允许读写操作
-
bidirectional_iterator_tag:允许双向移动(++ 和 --)
-
random_iterator_tag: 允许跳跃访问
将迭代器设计成为继承式有一个好处是可以消除“单纯传递调用的函数”
对于没有指定类型对应的重载函数时,会调用参数类型为其父类的重载函数。
Iterator的5种associated types
template <class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&>
struct iterator {
typedef Category iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
};
- iterator_category:迭代器的类别
- value_type:迭代器所指向的对象的型别
- difference_type:用来表示两个迭代器的距离,也可以用来表示一个容器的最大容量
- pointer:所指向对象的型别的指针
- reference:所指向对象的型别的引用
Traits (萃取机)
迭代器不一定是class,它有可能是native pointer,原生指针无法定义其关联类型,所以需要一个萃取机来分辨所得到的iterator是class还是native pointer,并利用partial specialization(偏特化)来得到其关联的类型。
萃取机的三个类别:
//萃取机 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 T* pointer;
typedef T& reference;
};
通过traits获取迭代器相关型别的方法
- 获取迭代器的category
template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&) {
typedef typename iterator_traits<Iterator>::iterator_category category;
return category();
}
- 获取迭代器的distance type
template <class Iterator>
inline typename iterator_traits<Iterator>::difference_type* distance_type(const Iterator&) {
return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
}
- 获取迭代器的value type
template <class Iterator>
inline typename iterator_traits<Iterator>::value_type* value_type(const Iterator&) {
return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
}
根据迭代器的类型,调用不同处理函数的方法
对于外部接口,只接受迭代器和相关参数。然后在外部接口中,添加上迭代器的类型来调用重载函数。
例如:
//对外接口
template <class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n) {
__advance(i, n iterator_category(i));
}
//以下为对内接口
template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
......
}
template <class BidirectionalIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, bidirectional_iterator_tag) {
......
}
template <class RandomAccessIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, random_access_iterator_tag) {
......
}