本文介绍迭代器的value type,difference type,reference type,pointer type,iterator_category五种型别,阅读本文前,请确保你已经理解Traits编程技巧。
value type
指迭代器所指对象型别。
difference type
指两个迭代器之间的距离,也可以用它表示容器最大容量,即头尾迭代器距离。如果一个泛型算法提供计数功能,例如STL中的count()其返回值必须使用difference type。
template <class I, class T>
typename iterator_traits<I>::difference_type count(I first, I last, const T& value) {
typename iterator_traits<I>::difference_type n = 0;
while(first != last) {
if(*(first++) == value) {
++n;
}
}
}
stddef.h定义了ptrdiff_t作为原生指针的difference type,针对T*与const T*设计偏特化萃取机,就可以使用typename iterator_traits<I>::difference_type萃取任何迭代器的difference type。
reference type & pointer type
reference type与pointer type分别对应引用与指针类型。
template <class I>
struct iterator_traits {
typedef typename I::pointer pointer;
typedef typename I::reference reference;
};
template <class I>
struct iterator_traits<T*> {
typedef T* pointer;
typedef T& reference;
};
template <class I>
struct iterator_traits<const T*> {
typedef const T* pointer;
typedef const T& reference;
};
iterator_category
迭代器可根据移动特性与施行操作分为五类:
Input Iterator:只读迭代器。
Output Iterator:只写迭代器。
Forward Iterator:单向读写迭代器。
Bidirectional Iterator:双向读写迭代器。
Random Access Iterator:类指针迭代器。
以advanced()函数为例,该函数可以让某个迭代器前进n次,对于不同的迭代器类型,其前进方式是不一样的,例如Forward Iterator通过++运算符前进,但是Random Access Iterator可以通过+=运算符前进,当时当程序调用advanced()时,调用FI版本对RAI而言效率过低,而调用RAI版本则无法接受FI,下面的代码是一种解决办法。
template <class InputIterator, class Distance>
void advanced(InputIterator& i, Distance n) {
if(is_FI(i)) {
advanced_FI(i, n);
} else if(is_RAI(i)) {
advanced_RAI(i, n);
} ...
}
但是这样在是形式才确定advanced()版本,效率低,我们希望在编译器确定它,函数重载机制可以帮助我们实现这个目标,我们需要一个占位参数用于重载决议。
struct ii_tag {};
struct oi_tag {};
struct fi_tag: public ii_tag {};
struct bi_tag: public fi_tag {};
struct rai_tag: public bi_tag {};
这些类不需要成员,仅用于重载决议,继承机制使多态得以实现,例如ii与fi版本的advanced()实现相同,fi也可以使用ii版本的函数,不必再在fi版本函数中传递调用ii版本函数。
template <class I>
struct iterator_traits {
typedef typename I::iterator_category iterator_category;
};
template <class I>
struct iterator_traits<T*> {
// 原生指针是rai,我们总将迭代器类型认为是最强化的那一种
typedef rai_tag iterator_category;
};
template <class I>
struct iterator_traits<const T*> {
typedef rai_tag iterator_category;
};
template <class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n) {
__advance(i, n, iterator_traits<InputIterator>::iterator_category());
}
template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, ii_tag) {
while(n--) ++i;
}
template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, bi_tag) {
if(n > 0) {
while(n--) ++i;
} else {
while(n--) --i;
}
}
template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, rai_tag) {
n > 0 ? i += n : i -= n;
}
iterator
STL提供了iterator class,自设计的迭代器可以直接继承iterator,无需再自定义内嵌型别。
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;
};
// 使用方式
template <class T>
struct Iter: public std::iterator<std::rai_tag, T> {...};
本文内容参考 —— 《STL源码剖析》