《STL源码剖析》读书笔记------第3 章 迭代器概念与traits编程技法

45 篇文章 0 订阅
6 篇文章 0 订阅

迭代器相应型别(associated types):

value_type:指迭代器所指对象的型别。

difference_type:用来表示两个迭代器之间的距离,因此它也可以用来表示一个容器的最大容量。

reference_type:对一个mutable iterator(允许改变所指对象之内容)进行提领操作时得到的型别。

pointer_type:传回一个pointer,指向迭代器所指之物。

iterator_category:迭代器相应型别。


Partial Specialization(偏特化)的意义

根据书上的意思,偏特化版不一定是对template参数U或V或T(或某种组合)指定某个参数值,而是“所谓Partial specialization的意思是提供另一份template定义式,而其本身仍为templatized”。《泛型思维》一书对partial specialization的定义是:“针对(任何)template参数更进一步的条件限制所设计出来的一个特化版本”。由此,面对以下这么一个class template:

template<typename T>

class C {......} ; //这个泛化版本允许(接受)T为任何型别

根据“针对(任何)template参数更进一步的条件限制”,我们便很容易接受它有一个形式如下的partial specialization:

template<typename T>

class C<T*>  {.....} ;  //这个特化版本仅适用于“T为原生指针”的情况。“T为原生指针”便是“T为任何型别”的一个更进一步的条件限制。

因此,有了这项技巧就可以为原生指针设计特化版本的迭代器,可以解决原生指针无法定义“内嵌型别”的问题。


“特性萃取机”traits:榨取各个迭代器的特性(相应型别)

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 ;
}

迭代器相应型别之一:iterator_category:

根据移动特性与施行操作,迭代器被分为五类:

1、Input Iterator:这种迭代器所指的对象,不允许外界改变。只读(read only)。

2、Output Iterator :只写(write only)。

3、Forward Iterator:允许“写入型”算法(例如replace())在此种迭代器所形成的区间上进行读写操作。

4、Bidirectional Iterator:可双向移动。某些算法需要逆向走访某个迭代器区间(例如逆向拷贝某范围内的元素),可以使用Bidirectional Iterators。

5、Random Access Iterator:前四种迭代器都只供应一部分指针算术能力(前三种支持operator++,第四种再加上operator--),第五种则涵盖所有指针算术能力,包换p+n,p-n,p[n],p1-p2,p1<p2。


迭代器的分类与从属关系(非继承关系),所谓concept(概念)与refinement(强化)的关系

Input Iterator                 Output Iterator


             Forward Iterator

   

            Bidirectional Iterator

                 

           Random Access Iterator


特性萃取机的设计考虑如下:如果traits有能力萃取出迭代器的种类,我们便可利用这个“迭代器类型”相应型别作为advanced()等函数的第三参数。这个相应型别一定必须是一个class type,不能只是数值号码类的东西,因为编译器需依赖它(一个型别)来进行重载决议(overloaded resolution)。


五种迭代器类型:

//五个作为标记用的型别(tag types)

struct input_iterator_tag{ } ;

structoutput_iterator_tag { } ;

structforward_iterator_tag : public input_iterator_tag { } ;

structbidirectional_iterator_tag : public forward_iterator_tag { } ;

structrandom_access_iterator_tag : public bidirectional_iterator_tag { } ;

 

iterator_traits与迭代器型别配合工作如下:

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 BidiectionalIterator,class Distance>
inline void __advance(BidiectionalIterator &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 ;	
}

每个__advance()的最后一个参数都只声明型别,并未指定参数名称,因为它纯粹只是用来激活重载机制,函数之中根本i不使用该参数。对于上述函数,只需要再添加一个对外开放的上层控制接口,调用上述各个重载的__advance()。这一上层接口只需两个参数,当它准备将工作转给上述的__advance时,才自行添加上第三个参数:迭代器类型。因此,这个上层函数必须有能力从它所获得的迭代器中推导出其类型-------这份工作自然是traits机制:

//声明为InputIterator的原因是,命名规则以算法所能接受之最低阶迭代器类型,来为其迭代器型别参数命名。
template<class InputIterator,class Distance> 
inline void advance(InputIterator &i , Distance n) 
{
	//最后一个参数生成一个临时对象,触发重载机制,然后调用相应的__advance函数
	__advance(i,n,iterator_traits<InputIterator>::iterator_category()) ; 
}


------------

traits利用“内嵌型别”的编程技巧与编译器的template参数推导功能,增强C++未能提供关于型别认证方面的能力,弥补C++不为强型别语言的遗憾。除此之外,SGI STL还将这种技巧扩大到迭代器之外,那就是所谓的__type_traits。iterator_traits负责萃取迭代器的特性,__type_traits则负责萃取型别(type)的特性。我们所关注的型别特性是指:这个型别是否具备non-trivial default ctro?是否具备non-trivial copy ctor?是否具备non-trivial assignment opertor?是否具备non-trivial dtor?如果答案是否定的,我们在对这个型别进行构造、析构、拷贝、赋值等操作时,就可以采用最有效率的措施(例如根本不调用身居高位,不谋实事的那些construct,destructor),而采用内存直接处理操作如malloc、memcpy等等,获得最高效率。由于和traits机制相近,此读书笔记就不再重复写出来了,详情请参考《STL源码剖析》








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值