迭代器是容器和算法相联系的重要部件(粘合剂),设计迭代器需要了解相应容器的实现细节,为了隐藏这些细节,STL每个容器都自己提供了专属迭代器。
这些迭代器需要实现对容器的各种操作:如++,--,==,!=等。
我们在使用泛型算法如:find时,在find内,需要使用迭代器的相应型别(一共有五种:①所指之物的类型,②迭代器类型,③指针类型,④引用类型,⑤差值类型)。声明内嵌型别可以获取迭代器相应型别,但对于原生指针不适用。所以用到了萃取的技术去获取相应型别,通过偏特化<T*>使之也可以获取原生指针的相关类型信息。
//五种迭代器类型:
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 {}; //随机
//基类迭代器
template<class Category,class T,class Distance = ptrdiff_t, // int
class Pointer = T*, //默认为原生指针
class Reference = T& >
struct iterator{
typedef Category iterator_category;
typedef T value_type;
typedef Distance difference;
typedef Pointer pointer;
typedef Reference reference;
};
//mylist迭代器:自定义的容器迭代器可以继承自上述父类迭代器
template<class Item>
class ListIter : public std::iterator<std::forward_iterator_tag,Item>
{
……
};
//“榨汁机”
template<class I> // I是一个迭代器类型
struct iterator_traits{
typedef typename I::iterator_category iterator_category;
typedef typename I::value_type value_type;
typedef typename I:;difference_type difference_type;
typedef typename I::pointer pointer;
typedef typename I::reference referencr;
};
//针对原生指针的偏特化版本“榨汁机”
template<class I> // I是一个迭代器类型
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& referencr;
};
//针对const原生指针的偏特化版本“榨汁机”
template<class I> // I是一个迭代器类型
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& referencr;
};
//这个函数可以很方便的决定某个迭代器的类型(category)
template<class Iterator>
inline typename iterator:_traits<Iterator>::iterator_category
Iterator_category(const Iterator&){
typename iterator_traits<Iterator>::iterator_category category;
return category();
}
//advance算法函数
template<class InputIterator,class Distance>
inline void advance(InputIterator& i,Distance n)
{
_advance(I,n,iterator_category(i)); //通过得到的迭代器类型决定调用哪个函数
}
萃取技术就是可以让泛型算法通过迭代器获取这个迭代器相关的类型:比如说迭代器的类型、迭代器所指之物的类型、迭代器所指之物的引用类型、指针类型等等。
比如说,在STL的析构函数中要析构first和last两个迭代器之间的所有对象。如果这个范围很大,而且这个析构函数是无关紧要的(像元素中没有指针类型,析构函数就是无关痛痒的)。频繁的调用析构函数没有意义,那我们就可以什么都不用做。所以我们需要知道迭代器所指元素的类型,萃取技术就是通过迭代器推导出元素类型的技术。
具体的推导方法简单来说:每个容器的迭代器都会将迭代器型别、所指之物类型、指针类型、引用类型、还有差值类型等都重新命名。使这个容器的这些类型使用相同的名称,为了使原生指针也能被萃取类型,所以要在加入中间层萃取类模板,重新将迭代器的这些相关类型重命名,再对原生指针的相关类型进行偏特化。这样在泛型算法中就可以得到迭代器相应性别了。