advance()函式
阿新 • • 發佈:2018-12-15
目錄
--------參考文獻 侯捷.STL原始碼剖析[M].武漢:華中科技大學出版社,2002.6:90-94.
一、 迭代器
#include<cstddef> template<typename T> class iter { public: typedef iter iterator_category; //自身型別 typedef T value_type; //相關型別 typedef ptrdiff_t difference_type; //距離 此處是int typedef T* pointer; //指標型別 typedef T& reference; //引用型別 };
部分迭代器是用原生指標(pointer-to-const和pointer-to-non-const)實現的!
二、 型別萃取機
型別萃取機是與迭代器配套使用的。
2.1 處理類實現的迭代器
template<class 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 reference; };
2.2 處理原生指標實現的迭代器
部分迭代器使用原生指標(pointer-to-const和pointer-to-non-const)實現的,故而沒有類作用域,需要特殊處理:
template<class T> struct iterator_traits<T*> //剔除指標型別 { typedef T* 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*> //剔除指標型別以及const修飾 { typedef T* iterator_category; typedef T value_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; };
三、 advance
3.1 iterator_category
根據移動特性和行為,迭代器被分為5類:
- Input Iterator:這種迭代器所指向的物件,不允許外界改變。只讀(read only)。
- Output Iterator:只寫(write only)。
- Forward Iterator:允許“寫入型”演算法(例如replace())在此種迭代器所形成的區間上進行讀寫操作。
- Bidirectional Iterator:可雙向移動。某些演算法需要逆向走訪迭代器區間(例如逆向拷貝某範圍內的元素),可以使用Bidirectional Iterator。
- Random Access Iterator:前四種迭代器都只供應一部分指標算術能力(前三種支援operator++,第四種再加上operator--),第五種則涵蓋所有指標算術能力,包括p+n, p-n, p[n], p1-p2, p1<p2。
3.2 啟用過載機制
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 InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, //前進
input_iterator_tag) //第三個引數是沒有引數名
{
while (n--)++i;
}
template<class ForwardIterator, class Distance>
inline void __advance(ForwardIterator& i, Distance n, //類似於有一個介面,本質還是前進
forward_iterator_tag)
{
__advance(i, n, input_iterator_tag());
}
template<class BidirectionalIterator, class Distance>
inline void __advance(BidirectionalIterator& i, Distance n, //雙向
bidirectional_iterator_tag)
{
if (n >= 0)
while (n--)++i;
else
while (n++)--i;
}
template<class RandomAccessIterator, class Distance>
inline void __advance(RandomAccessIterator& i, Distance n,
random_access_iterator_tag)
{
i += n; //雙向,跳躍
}
3.3 實現advance函式
值得注意的是,到底是何種迭代器在編譯期就能確定下來,而不用等到執行時,以提高效率。
template<class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n)
{
typedef iterator_traits<InputIterator>::iterator_category iterator_category;
__advance(i, n, iterator_category()); //過載時,編譯器會自動去呼叫該呼叫的函式
}