让你的容器兼容STL

大家知道,STL最最主要,也是最最常用的部分就是泛型容器和范型算法。而联系起这两大部分的,就是iterator(迭代器)。

迭代器大体分为这么几类(级别从低到高)

只读迭代器input_iterator

只写迭代器output_iterator

forward_iterator,这个其实是允许写入型算法在其所形成的区间上做读写操作

双向移动可读写bidirectional_iterator

随机访问迭代器random_access_iterator

很明了,各种不同的迭代器其实规定了其宿主所具有的能力。 比方说,forward_iterator只允许但方向遍历,像单项链表之类的数据结构,就只能拥有此类迭代器。一些需要双向操作或反向操作的算法,就不支持此类容器了。

而最高级别的随机访问迭代器,则不但允许双向读写,而且支持随即访问,也就是像操作内置数组那样。比如std::vector就属于随即访问型容器。

我记得侯叔叔的《STL源码抛析》里面说过,使用STL分为三个境界,第一层:使用;第二层:了解;第三次:扩展STL。

那么我们现在先窥探一下第三层的大门,至少让自己的类型和STL兼容。

那前面发过的Array动态数组做例子吧,其实这个类就是个简易的vector,根本够不上对STL的扩展,只是向这个境界迈那么一小步而已。

其实,要让自己的容器兼容STL的反省算法,就必须要让这些算法知道你的容器是那种类型的,换句话说,要让它们知道你的容器拥有哪种类型的迭代器。

STL为我们定义了上述集中迭代器类型

 

 1 struct input_iterator_tag
 2     {    // identifying tag for input iterators
 3     };
 4 
 5 struct output_iterator_tag
 6     {    // identifying tag for output iterators
 7     };
 8 
 9 struct forward_iterator_tag
10     : public input_iterator_tag
11     {    // identifying tag for forward iterators
12     };
13 
14 struct bidirectional_iterator_tag
15     : public forward_iterator_tag
16     {    // identifying tag for bidirectional iterators
17     };
18 
19 struct random_access_iterator_tag
20     : public bidirectional_iterator_tag
21     {    // identifying tag for random-access iterators
22     };

其实这些类型什么也不做,只是一个标识(identity),告诉别人能做什么,怎么做。

另外,还需要定义下面几个类型,这些都是什么我就不具体说了,大家有兴趣可以看STL源代吗或侯叔叔的书。不过要看源代码最好看STLPort的,比较清晰。

1         typedef T value_type;
2         typedef typename allocator<T>::difference_type difference_type;
3         typedef typename allocator<T>::const_pointer pointer;
4         typedef typename allocator<T>::const_reference reference;

 

好了,让我们来修改Array的迭代器,让它兼容STL

 1     struct Iterator 

 3     {
 4         typedef random_access_iterator_tag iterator_category;
 5         typedef T value_type;
 6         typedef typename allocator<T>::difference_type difference_type;
 7         typedef typename allocator<T>::const_pointer pointer;
 8         typedef typename allocator<T>::const_reference reference;
 9 
10         Iterator(T* ptr):m_ptr(ptr){}
11 
12         reference operator*()
13         {
14             return (*m_ptr);
15         }
16 
17         pointer operator->()
18         {
19             return (&**this);
20         }
21 
22         Iterator& operator++()
23         {
24             ++m_ptr;
25             return *this;
26         }
27         Iterator operator++(int)
28         {
29             Iterator temp = *this;
30             ++(*this);
31             return temp;
32         }
33 
34         Iterator& operator--()
35         {
36             --m_ptr;
37             return *this;
38         }
39         Iterator operator--(int)
40         {
41             Iterator temp = *this;
42             --(*this);
43             return temp;
44         }
45 
46         bool operator!=(const Iterator &it)
47         {
48             return m_ptr != it.m_ptr;
49         }
50 
51         bool operator==(const Iterator &it)
52         {
53             return m_ptr == it.m_ptr;
54         }
55 
56         bool operator<(const Iterator &it)
57         {
58             return m_ptr<it.m_ptr;
59         }
60 
61         Iterator operator+(difference_type off) const
62         {
63             Iterator tmp = *this;
64             tmp.m_ptr+=off;
65             return tmp;
66         }
67 
68 
69 
70         Iterator operator-(difference_type off)
71         {
72             Iterator tmp = *this;
73             tmp.m_ptr-=off;
74             return tmp;
75         }
76 
77         difference_type operator-(const Iterator& it)
78         {
79             return m_ptr - it.m_ptr;
80         }
81 
82 
83         T* m_ptr;
84     };

posted @ 2008-10-08 22:55  刺儿头  阅读(403)  评论(0编辑  收藏  举报