iterator和iterator_traits

 

   跟據侯捷的《STL源碼剖析》一書中提到的《Design Patterns》一書中關於iterator模式定義:提供一種方法,使之能夠依序尋訪某個聚合物(容器)所含的各個元素,而又無需暴露該聚合物的內部表達方式。

  當然,STL的中心思想在於:將數據容器和算法分開,彼此單獨設計,最後再以一帖膠着劑將他們撮合在一起。

  迭代器可以看作是一種smart pointer,故要進行內容提領和成員訪問,關鍵的工作就是對operator*和operator->進行重載

//忽略模板類定義
T &operator*()const  {return *pointee;}  //其中T作爲模板參數
T* operator->() const{return  pointee;} //pointee作爲已定義成員

  當然iterator的設計中有一條關鍵的地方就是封裝和隱藏,在此不提。

  爲了引出STL設計的關鍵部分——Traits,需提到一個“相應型別”,也就是迭代其所指之物的類型。

  在c++中只有sizeof()和RTTI中的typeid(),前者只能判斷出類型大小,無法進行類型確定,後者由於得到的只是一種別名(vs環境下爲全程,MinGW下只是開頭字母例如“int”中的‘i’。)況且後者屬於運行期判斷,不僅需要virutal而且判斷期靠後因此不能拿來使用。

  我們在這裏需要的並不是輸出一個類型的名稱,而是在調用過程中間接使用,將其隱藏起來。因此使用模板的類型推斷是個不錯的做法。

  迭代器相應型別最常用的有五種,分別是value_type,difference_type,reference,pointer,iterator_category。

  這裏我們爲了下面的Iterator_Traits技術需要提到一下模板偏特化問題。

例如:

複製代碼
template<typename T>
struct test
{
typedef  T    value_type;
T *pointer;
};
template<typename T>         //偏特化
struct test<T*>
{
typedef T value_type;
}     
複製代碼

 偏特化的定義:針對任何template參數更進一步的條件限制所設計出來的一個特化版本。

 我們需要考慮的偏特化情形有如下情況:

 1.原始指針

 2 .const T * 

 之所以進行以下兩種特化,主要願意是1.原始指針無法進行內置型別的定義,也就是說無法進行typedef操作,故對以後的過濾會造成很大的麻煩,而且原始指針不能夠被忽略。2.對於const T*來說,不能夠被輕易修改,而且如果不另外考慮,也會造成不必要的麻煩。

可對照一下代碼

//原模板
template<typename T>
struct test
{
 typedef  T  value_type;
};
//原始指針特化
template<typename T>
struct test<T*>
{
typedef T value_type;
};
//const pointer
template<typename T>
struct test<const T*>
{
typedef T value_type;
};

  這樣,我們不管是調用哪個,都會有一個value_type,而這個value_type到底是何方神聖,已經被我們隱藏起來了。

  我們可以依照上述例子描述difference_type,pointer,reference。但是difference_type可以typedef庫中的ptrdiff_t,來實現。

  至此,我們只剩下了iterator_category這一個類型了。

  iterator_category作爲一個指針移動的特性和實行操作,我們有如下五類:

 Input Iterator  Output Interator  Forward Iterator  Bidirectional Iterator  Random Access Iterator

其中 input 和output這兩種屬於訪問權限修飾,其他的三種依次深入,我們可以從下面代碼中看出

struct input_iterator{};    //只讀
struct output_iterator{};  //只寫
struct forward_iterator:public input_iterator{};    //寫入型,單項型操作
struct bidirectional_iterator:public forward_iterator{};   //可雙向移動
struct random_access_iterator:public bidirectional_iterator{};    //可進行跳躍訪問,涵蓋所有指針的運算能力

  c++中的多態性中有一個重載的概念,也就是說有如下例子

#include<iostream><br>using namespace std;<br>class base
{
//empty
};
class deriver:public base
{
//empty
};
void test(base &)
{
//empty;
}<br>int main()<br>{<br>base b;<br>deriver d;<br>test(b);    //ok <br>test(d);    //ok<br>}

 這樣,我們就可以寫更少的函數來實現我們需要的所有方法

  好,爲了使上述居多的描述更加清晰可見,思路更加清晰,上一大段代碼進行分析

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<iostream>
using namespace std;
struct input_iterator{};
struct output_iterator{};
struct forward_iterator:public input_iterator{};
struct bidirectional_iterator:forward_iterator{};
struct random_access_iterator:bidirectional_iterator{};
template<typename Category,typename T,typename Distance=ptrdiff_t,typename Pointer=T*,typename Reference=T&>
struct iterator
{
    typedef Category iterator_category;
    typedef T        value_type;
    typedef Pointer  pointer;
    typedef Reference reference;
    typedef Distance difference_type;
};
template<typename Iterator>
struct Iterator_traitss
{
    typedef typename Iterator::iterator_catergory   iterator_category;
    typedef typename Iterator::value_type       value_type;
    typedef typename Iterator::pointer      pointer;
    typedef typename Iterator::reference         reference;
    typedef typename Iterator::difference_type      difference_type;
};
template<typename T>
struct iterator_traitss<T*>
{
    typedef random_access_iterator                        iterator_category;
    typedef T                               value_type;
    typedef ptrdiff_t                           difference_type;
    typedef T*                              pointer;
    typedef T&                              reference;
};
template<typename T>
struct iterator_traitss<const T*>
{
    typedef random_access_iterator                   iterator_category;
    typedef T                           value_type;
    typedef ptrdiff_t                       difference_type;
    typedef const T*                        pointer;
    typedef const T&                        reference;
};
template<typename Iterator>
inline typename iterator_traits<Iterator>::iterator_category
    iterator_category(const Iterator&)
{
    typedef typename iterator_traitss<Iterator>::iterator_category category;
    return category();
}
int main()
{
}

  

   通過上述代碼我們可以清晰看到,有一個iterator類模板,我們在其中的模板參數除了第一個參數外,其他的都有默認值,這個和我們現在使用的vector<T>等其中的Iterator是一致的 。

  有了iterator模板後,我們需要一個強有勁的過濾器,那就是iterator_traits,這個可以將模板參數不管是什麼樣的,統統封裝成統一的typedef,例如 value_type的形成。

  這樣我們就可以很方便的進行下面的操作。請注意在iterator_traits中T*的特化還有const T*的特化那裏,iterator_category的原名是random_access_iterator.

  總結:

     我們可以通過typedef機制,隱藏,集中一類特性。

     我們可以通過模板參數推導機制,針對同一別名的不同類型進行不同操作。爲了效率因素,進行編譯期多態而非運行期多態。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章