迭代器是容器和算法相聯繫的重要部件(粘合劑),設計迭代器需要了解相應容器的實現細節,爲了隱藏這些細節,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兩個迭代器之間的所有對象。如果這個範圍很大,而且這個析構函數是無關緊要的(像元素中沒有指針類型,析構函數就是無關痛癢的)。頻繁的調用析構函數沒有意義,那我們就可以什麼都不用做。所以我們需要知道迭代器所指元素的類型,萃取技術就是通過迭代器推導出元素類型的技術。
具體的推導方法簡單來說:每個容器的迭代器都會將迭代器型別、所指之物類型、指針類型、引用類型、還有差值類型等都重新命名。使這個容器的這些類型使用相同的名稱,爲了使原生指針也能被萃取類型,所以要在加入中間層萃取類模板,重新將迭代器的這些相關類型重命名,再對原生指針的相關類型進行偏特化。這樣在泛型算法中就可以得到迭代器相應性別了。