Design Pattern中对迭代器的模式定义:提供一种方法能都依序访问某个聚合物(容器)内所含的各个元素,而又无需暴露该聚合物的内部表述方式。
迭代器是一种相似指针对象,最重要的工做是进行operator*和operator->进行重载,除此以外还有++,==,=这一系列运算符的重载,不可避免地曝光了不少结构的实现细节。因此将迭代器的开发任务交给结构的设计者更加高效。算法
如何获取“迭代器所指对象”的类型?解决办法是使用模板函数参数推导机制。dom
//简单举例 template <class I, class T> void func_impl(I iter,T e) { //T就是迭代器所指之物的类型 。。。 } template <class I> void func(I iter) {//对外接口 func_impl(iter,*iter);//实际工做 }
若是value type要用于函数传回值,使用参数推导就没有做用了,能够经过声明内嵌类型解决。函数
template <class T> struct Iter { typedef T value_type;//内嵌类型 ... }; template <calss I> typename I:value_type func(I iter) { //typename 关键字告诉编译器 value_type表明一个类型 ... }//返回类型I:value_type
这种方法仅限于定义了内嵌类型的class type成员,对于原生指针类型,没法定义内嵌类型。因而引入template partial sepcilization(模板偏特化),即若是class template拥有多个template参数,能够针对一部分参数进行特化,至关于在泛化设计中提供一个特化版本。设计
template <typename T> class C<T*> {}; //T*为原生指针就是T为任何类型的进一步条件限制。 template <class I> struct iterator_traits { typedef typename I::value_type value_type; };//若是I定义了 本身的value_type,能够萃取出value_type;
多了一层间接性能够拥有特化版本:指针
template <class T> struct iterator_traits<T*> { typedef T value_type; }//原生指针如int*类型也能够萃取出value_type; //可是针对指向常数对象的指针,iterator_traits<const int*>::value_type,获取类型是const int,可使用另外一种特化 template <class T> struct iterator_traits<const T*> { typedef T value_type;//类型为T,而非const T };
根据经验,最经常使用到的五种关联类型:value_type,difference type,pointer,reference,iterator category。
value type:迭代器所指对象的类型;code
difference type:两迭代器之间的距离对象
template <class I,calss T> typename iterator_traits::difference_type count(I first,I last,const value &value) { typename iterator_traits::difference_type n = 0; for(;first !=last;++first) if(*first == value) ++n; return n; } //针对原生指针,使用内建类型prtdiff_t template <class T> struct iterator_traits<T*> { typedef prtdiff_t difference_type; };
reference type:迭代器所指对象内容是否容许改变,分为constant iterators和mutable iterators,后者应当返回左值,在C++中使用reference方式返回左值。若是mutable iterator p的value type是T,*p类型是T&。blog
pointer type:reference type返回左值表明p所指内容,而pointer type返回左值表明p所指以内容的地址。继承
iterator_category:首先讨论迭代器的分类接口
直线与箭头表明概念与强化关系,若是算法接收一种迭代器,那么就能够接受强化类型的迭代器。设计算法时,尽可能针对某种迭代器提供明肯定义,针对强化迭代器提供另外一种定义,才能提供最大效率。任何迭代器属于其所类型中最强的那个。
为了实现针对不一样类型迭代器的重载函数,traits应该能萃取出迭代器的类型,以做为算法的参数之一。
42 struct input_iterator_tag {}; 43 struct output_iterator_tag {}; 44 struct forward_iterator_tag : public input_iterator_tag {}; 45 struct bidirectional_iterator_tag : public forward_iterator_tag {}; 46 struct random_access_iterator_tag : public bidirectional_iterator_tag {}; //Input版,模板以算法所能接受的最低阶迭代器类型做为形参 tempalte <class InputIterator,class Distance> inline void __advance(InputIterator &i,Distance n,input_iterator_tag) { while(n--) ++i; } // Forward版,传递调用Input版 tempalte <class ForwardIterator,class Distance> inline void __advance(ForwardIterator &i,Distance n,forward_iterator_tag) { __advance(i,n,input_iterator_tag()); } //Bidirectional版支持两个方向 tempalte <class BidirectionalIterator,class Distance> inline void __advance(BidirectionalIterator &i,Distance n,bidirectional_iterator_tag) { if(n >= 0) while(n--) ++i; else while(n++) --i; } //Random Access版 tempalte <class RandomAccessIterator,class Distance> inline void __advance(RandomAccessIterator &i,Distance n,random_access_iterator_tag) { i+=n; }
最后一个参数用于声明类型,激活重载,并不使用该参数。
//提供上层接口,最后一个参数产生临时对象,在编译时决定调用那个__advance tempalte <class InputIterator,class Distance> inline void advance(InputIterator &i,Distance n) { __advance(i,n,iterator_traits<InputIterator>::iterator_category()); } //定义iterator_category()以下: template <class I> inline typename iterator_traits<I>::iterator_category iterator_category(const &i) { typedef typename iterator_traits<I>::iterator_category category; reutrn category(); } //对于原生指针类型的iterator_category(),是一种RandomAccessIterator template <class T> struct iterator_traits<T*> { typedef rendom_access_iterator_tag iterator_category; }
使用struct继承方式来定义分类标签,有助于消除“单纯传递调用函数”。好比前面的advance()的ForwardIterator版,能够不用写,编译器会调用其父类函数(Input版)。(todo:对OutputIterator定位不明朗,forward_tag并无继承output_tag)
至此,itarator_traits结构包含如下部分:
tempalte <class I> struct iterator_traits { typedef typename I::value_type value_type; typedef typename I::iterator_category iterator_category; typedef typename I::differnce_type difference_type; typedef typename I::pointer pointer; typedef typename I::reference reference; };
tempalte <class Catagory,class T,class Distance = ptrdiff_t,class Pointer = T*,class Reference = &T> struct iterator { typedef Category iterator_category; typedef T value_type; typedef Disatnce difference_type; typedef Pointer pointer; typedef Reference reference; }; //iterator不包含数据,继承时不会有额外开销,通常只需提供前两个参数。 tempalte <class Item> struct ListIterator:public std::iterator<std::forward_iterator_tag,Item> { ... }
迭代器的做用是设计适当的关联类型;设计适当的迭代器是容器的责任。而算法则独立于迭代器和容器。
__type_traits<T>::has_trivial_default_constructor __type_traits<T>::has_trivial_copy_constructor __type_traits<T>::has_trivial_assignment_operator __type_traits<T>::has_trivial_destructor __type_traits<T>::is_POD_type struct __true_type {}; struct __false_type {};