1.iterator_category
(1)Input Iterator:这种迭代器所指的对象,不允许外接改变,只读。
(2)Output Iterator:只写。
(3)Forward Iterator:允许“写入型”算法在此迭代器所形成的区间上进行读写操作。
(4)Bidirectional Iterator:可双向移动。某些算法需要逆向走访某个迭代器区间,可使用Bidirectional Iterator。
(5)Random Access Iterator:前四种迭代器只提供一部分指针的能力(前三种只支持operator++,operator--),第五种涵盖所有指针算术能力。包括p+n、p-n、p[n]、p1-p2,p1<p2。
为了能够提供编译迭代器动态选择,STL定义了五种标记用的型别,这样我们在调用涉及到迭代器的函数时,就能选择符合相应迭代器特性的函数。五个迭代器分别为:
struct input_iterator_tag{};
struct output_iterator_tag{};
struct forward_iterator_tag: public input_iterator_tag{};
struct bidirection_iterator_tag: public forward_iterator_tag{};
struct random_access_iterator_tag: public bidirection_iterator_tag{};
这些class只作标记使用,不占用任何空间。
//advance()为例 //最后一个参数只是用来重载,不需要任何成员 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; } //调用的时候,InputIterator可以是所有上面的五种迭代器之一 template<class InputIterator,class Distance> inline void advance(InputIterator& i,Distance n) { //自动选择上面的四个函数 //萃取iterator_category必须在每个iterator_traits里面 __advance( i,n,iterator_traits<InputIterator>::iterator_category()); }
2.std::iterator的保证
为了符合规范,任何迭代器都必须要相应的型别,以利于traits萃取,否则便是自别于整个STL架构,可能无法与STL组件顺利搭配。STL定义了一个标准的iterator class,每个迭代器都继承自它,这样就保证了统一行。
template< class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T& > struct iterator{ typedef Category iterator_category; typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference ; };
iterator class不含任何成员,纯粹型别定义,所以继承不会招致任何负担,由于后三个参数皆有默认值。故心得迭代器只需要提供两个参数即可。
template<class T>
struct ListIter:public std: iterator<std::forward_iterator_tag,Item>
{...........}
3.__type_traits
类型粗略的讲有两种,一种是用class封转,并且它的复制拷贝很费时,比如需要深度复制,需要safe copying——即需要调用构造函数完成复制;另一种是所谓的POD(plain old data),一般是build-in类型或是c式的struct类型,这种类型复制和拷贝时只需直接复制内存块就可以了,于是有了bitwise copying或是trival construct/deconstruct/copy/assignment的概念。
SGI STL中使用__type_traits就可以在编译期间就确定复制一个对象是调用赋值构造函数还是直接调用memcpy,从而提高效率。看SGI STL的源代码: