Traits编程技法之iterator_traits

在设计容器时,避免不了的就是设计与之契合的迭代器。迭代器,行为类似指针,担任访问元素、提领元素的重任。为什么说是重任呢?因为访问、提领虽是简单易实现的操作,但也是使用频率最高的两个操作。使用频率高,即意味着任何对性能有着极大的影响,所以我们要对迭代器的类别进行细致的划分,力求将每一种迭代器的性能都发挥到极限。(例如vector的迭代器为原生指针,原生指针可以实现随机存取(Random Access Iterator)。如果我们像是用笨拙的(相对来说)双向迭代器(Bidrectional Iterator)的一样,用++、--在相邻元素间移动,就太委屈他所拥有的能力了。)

我们首先对迭代器根据移动特性与操作方式(读、写),将其分为五类:

Input Iterator(输入迭代器):这种迭代器所指的对象,不允许外界改变。只能对其进行读操作。

Output Iterator(输出迭代器):这种迭代器所指的对象,只能对其进行写操作。

Forward Iterator( 可读可写迭代器):这种迭代器所指的对象,可以读取,也可以写入。

Bidrectional Iterator(双向迭代器):这种迭代器支持双向遍历,即支持++(递增),--(递减)操作,同时支持以上三种迭代器的操作。

Random Access Iterator(随机迭代器):这种迭代器支持跳跃式的对象处理能力,体现于支持[](根据索引值锁定目标),同时也支持以上所有迭代器的操作。

以上迭代器的能力具有层层扩展的关系,如何实现这种包含关系呢?最简单的方法就是继承:

struct stl_input_iterator_tag{};//输入迭代器
struct stl_output_iterator_tag{};//输出迭代器
struct stl_forward_iterator_tag :public stl_input_iterator_tag{};//可读写迭代器
struct stl_bidirectional_iterator_tag :public stl_forward_iterator_tag{};//双向迭代器
struct stl_random_access_iterator_tag :public stl_bidirectional_iterator_tag{};//随机迭代器

如同type_traits(型别萃取),我们设立这几个类的目的是过后为其设置类型别名,以帮助我们区分迭代器。(这几个类别皆为全局变量)


那我们如何在迭代器上烙上迭代器类别的印记呢?

一种方法就是使用类型别名:

template
class vector_Iterator
{
public:
	typedef stl_random_access_iterator_tag iterator_category;

	...

protected:
	T* itor;
};

但对于每一个迭代器的实现都如此实现会涌现大量重复代码。为了避免重复,我们单独设置一个类别,专门定义迭代器相关的各种型别,再使迭代器类继承于它:

//型别集装箱,迭代器皆继承此类
template
struct iterator
{
	typedef Category iterator_category;//迭代器类型
	typedef T value_type;//迭代器所指对象类型
	typedef Distance difference_type;//迭代器之间距离类型
	typedef Pointer pointer;//迭代器所指对象的指针型别
	typedef Reference reference;//迭代器所指对象的引用型别
};


注意,在这个类中定义的别名只是作为初始化作用,在迭代器的实现中,我们应为它们设立专属的别名(至少iterator_category应该重新定义为五种迭代器类型中的一种)。


我们再设立一个迭代器萃取装置:

//型别萃取器,类型型别由迭代器自主更改
template//模板参数应设为迭代器
struct stl_iterator_traits
{
	typedef typename Iterator::iterator_category iterator_category;
	typedef typename Iterator::value_type value_type;
	typedef typename Iterator::Distance difference_type;
	typedef typename Iterator::Pointer pointer;
	typedef typename Iterator::Reference reference;
};


让此萃取装置作为外部包装,这样我们就可以隐藏迭代器的内部实现:


//copy算法的内层实现
template
struct _copy_dispatch
{
	OutputIterator operator()(InputIterator first,InputIterator last,OutputIterator result)
	{
		typedef typename stl_iterator_traits::iterator_category iterator_category;
		return _copy(first,last,result,iterator_category());
	}
};

因为原生指针的特殊性和代表性,我们可以为其实现特例化:

//特例化原生指针类型
template
struct stl_iterator_traits
{
	typedef stl_random_access_iterator_tag iterator_category;
	typedef T value_type;
	typedef T* pointer;
	typedef ptrdiff_t diference_type;
	typedef T& reference;
};

template
struct stl_iterator_traits 
{
	typedef stl_random_access_iterator_tag iterator_category;
	typedef T value_type;
	typedef const T* pointer;
	typedef ptrdiff_t diference_type;
	typedef const T& reference;
};

有了itertator_traits技术后,我们可以让拥有更高能力的迭代器完全发挥其性能优势。


你可能感兴趣的:(STL源码)