C++ STL和泛型编程(二)---- 迭代器的设计原则和Iterator Traits的作用与设计

C++ STL和泛型编程(二)---- 迭代器的设计原则和Iterator Traits的作用与设计

一、Iterator遵循的原则

算法在对容器进行操作时,是通过Iterators去操作的,所以算法在操作使用Iterators时需要知道其的一些性质!即 Algorithms提问,Iterators回答

如:rotate()算法对iterators操作时,需要知道其的三个associated types

template<typename _Iter>
inline typename iterator_traits<_Iter>::iterator_category __iterator_category(const _Iter&){
	return typename iterator_traits<_Iter>::iterator_category();
}

template<typename _RandomAccessIterator>
void __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, random_access_iterator_tag){
	...
	typedef typename iterator_traits<_RandomAccessIterator>::difference_type _Distance;
	typedef typename iteraor_traits<_RandomAccessIterator>::value_type _ValueType;
	_Distance __n = __last - _first;
	_Distance __k = __middle - __first;
	...
	for(;;){
		if(__k < __n - __k){
			if(__is_pod(_Value Type_)&& __k == 1){
				_ValueType __t = _GLIBCXX_MOVE(*__p);
			}
		}
	}
	...
};


template<typename _ForwardIterator>
inline void rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last){
	...
	std::__rotate(__first, __middle, __last, std::__iterator_category(__first));
}


- typename的使用:

一般情况下都是typedef + 原类型名 + 原类型新别名,而这里却是typedef + typename + 原类型名 + 原类型新别名说明链接如下
因为如果不加typename,编译器可能会不知道 iteraor_traits<_RandomAccessIterator>::value_type 表示的是一个成员变量还是一个类型名;而加了关键字typename后,则告知编译器,其是一个类型,即是为iteraor_traits<_RandomAccessIterator> 这个类中所嵌套的value_type类型而定义一个叫 _ValueType 的别名。
如:return typename iterator_traits<_Iter>::iterator_category () 中,告诉编译器返回的是一个iterator_traits<_Iter>类中所嵌套的iterator_category类型的临时变量因为后面的小括号)。

链接
typename的使用由来

执行过程:
1.算法inline void rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last)调用成员函数std::__rotate(__first, __middle, __last, std::__iterator_category(__first)),而其中的第三传入参数调用inline typename iterator_traits<_Iter>::iterator_category __iterator_category(const _Iter&)来获取第一个关联属性__iterator_category即迭代器的分类,即调用何种操作如++或–或增减xx的iterator。
2.紧接着第三参数处理返回后,进入void __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, random_access_iterator_tag)函数内部,即获取第二、三个关联属性iterator_traits<_RandomAccessIterator>类中嵌套的difference_type类型和value_type类型,并为difference_type类型value_type类型分别定义别名 _Distance_ValueType
3._ValueType 是指容器中所存放元素的类型,如vector容器中存放了100万个string类型的容器,则_ValueType就是string。
4._Distance 是指两个iterator的距离用什么类型来表示,如距离用int型表示则_Distance就是int。
5.所以本例中,出现了3种associated types,另外两种referencepointer 在C++标准库种从未使用。而且由上例可知,iterators必须有能力回答algortihms的提问。因而在C++标准库的开发过程中iterators要设计出5种associated types以便满足algorithms的提问。

- Iterator必须提供5种associated types:

// G2.9下
template<class T, class Ref, class Ptr>
struct __list_iterator{ // 选用链表作为例子
	typedef bidirectional_iterator_tag iterator_category; //(1) 注:这里bidirectional_iterator_tag也是标准库内置定义的类型,表示是双向的类型。
	typedef T value_type; //(2)
	typedef Ptr pointer; //(3)
	typedef Ref reference; //(4)
	typedef ptrdiff_t difference_type; //(5) 注:这里的ptrdiff_t是一个内置类型,如long,表明两个iterator的距离这么长就足够了。若选择链表里面放元素,当链表头跟尾的距离超出ptrdiff_t这个类型所能表示的范围,则元素过多设计失效!!
};

// G4.9下
template<typename _Tp>
struct __list_iterator{
	typedef std::bidirectional_iterator_tag iterator_category; //(1) 
	typedef _Tp value_type; //(2)
	typedef _Tp* pointer; //(3)
	typedef _Tp& reference; //(4)
	typedef ptrdiff_t difference_type; //(5) 
};

template<typename I>
inline void algorithm(I first, I last){
...
	I::iterator_category
	I::pointer
	I::reference
	I::value_type
	I::difference_type
...
}

二、Traits(特性、特征、特质)----萃取机

由上可知,上面讨论的都是当iterator均是class时因为内部设计了5种associated types,所以其可对algorithm的提问做出相应的回答。当若当terator不是classs而是自然指针如native pointer时(可看成退化的iterator),其无法回答上述五个问题,则此时需要引入Traits(萃取机)。

在这里插入图片描述Iterator Traits充当中介,用来分离class iterators和non-class iterators!!

在这里插入图片描述执行过程:
一、因为加入了中介Traits(萃取机),所以algorithm要提问v1的value_type时,先通过iterator_traits::value_type;
二、此时模板参数I为class iterator则进入(1),即进入class iterator的value_type中去取得其associated type;
三、若模板参数I为pointer to T或pointer to const T即非class iterator则进入(2)或(3),此时由于iterator不是class只是native pointer,所以无法回答algorithm提出返回value_type的问题。iterator_traits则帮忙回答,如进行typedef T value_type来告诉algorithm此时v1的value_type。

完整的iterator_traits:

template<class T>
struct iterator_traits{
	typedef typename I::iterator_category iterator_category;
	typedef typename I::value_type value_type;
	typedef typename I::difference_type defference_type;
	typedef typename I::pointer pointer;
	typedef typename I::reference reference;
};

// partial specialization for regular pointers
template<class T>
struct iterator_traits<T*>{
	typedef random_access_iterator_taq iterator_category;
	typedef T value_type;
	typedef ptrdiff_t defference_type;
	typedef T* pointer;
	typedef t& reference;
};

// partial specialization for regular const pointers
template<class T>
struct iterator_traits<const T*>{
	typedef random_access_iterator_taq iterator_category;
	typedef T value_type;
	typedef ptrdiff_t defference_type;
	typedef T* pointer;
	typedef t& reference;
};

由上可知,
1.当传入algorithm的传入参数为class iterator时,则调用的是泛化版本的iterator_traits,此时是通过I类中所嵌套的value_type类型来定义别名value_type的类型。比如以__list_iterator<int>为例子,则是通过 __list_iterator<int>类中嵌套的int的类型来定义别名value_type ,此时算法得到的回答是value_type就是int型
2.当传入参数为非class iterator即regular pointers或regular const pointers时,则调用的是偏特化版本的iterator_traits<T*>或iterator_traits<const T*>,直接用所传入的模板参数T的类型来定义别名value_type的类型。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值