stl之再看迭代器iterator(迭代器相应型别和iterator_traits特性以及traits特性萃取)

迭代器所指之物的型别便是其一。最常用的相应型别有5种,有的时候可以利用template参数推导机制来取得,而并非所有,所以需要更全面的解法。

Traits编程技法

迭代器所指对象的型别,就是迭代器的value type。参数推导机制虽然可用于value type;却非全面可用,如果value type必须要求用于函数的返回值,就不成立。Template参数推导机制推而导之的只是参数,无法推导函数的返回值型别。

声明内嵌型别可以解决返回值型别的问题。

template <class T>
 struct MyIter{
  typedef  T  value_type;
  T* ptr;
  MyIter(T *p=0):ptr(p){}
  T& operator*()const{return *ptr;}
  //....
  };
  
  template<class I>
  typename I::value_type func(I ite)
  {return *ite;}
  //...
  MyIter<int>ite(new int(8));
  cout<<func(ite);

func()的返回型别必须加上typename,T是template的一个参数,在被编译器据西安华之前,编译器对T一无所知,编译器并不知道MyIter<T>::value_type代表的是什么,typename告诉编译器这是一个型别,才能通过编译。

新的问题出现:并不是所有的迭代器都是class type(只有它能够定义内嵌型别,如果无法定义内嵌型别,还是无法解决函数返回值型别的问题);原生指针就不是,所以引出新的解决方案。

TemplatePartial Specialization(偏特化)

  Class template 如果有一个以上的template参数,,可以对其中的某个或者数个进行特化处理,可以再泛型设计中提供一个特化版本,将泛型化版本中某些template参数赋予明确的指定。

模板特化是通过"给模板中的所有模板参数一个具体的类"的方式来实现的.而模板偏特化则是通过"给模板中的部分模板参数以具体的类,而留下剩余的模板参数仍然使用原来的泛化定义"的方式来实现的.

template<class Window>                        //仍然使用原来的泛化定义;
class Widget<Window, MyController>            //MyController是具体的类,是特化定义;
{
    ... 偏特化实现代码 ...
};

模板的偏特化能力很强大.当你实例化一个模板时,编译器会把目前存在的偏特化模板和全特化模板做比较,并找出其中最合适、最匹配的实现.
这样,灵活性就很大.
模板的偏特化机制不能用在函数身上,不论成员函数还是非成员函数.

我们便可以很快找到原生指针的偏特化版本:

template<typename T>

classC<T*>{….}

进入关键部分:

   class template专门用来萃取迭代器的特性,而value type正是迭代器的特性之一。

<pre name="code" class="cpp">template<class I>
struct iterator_traits{
  typedef typename I::value_type value_type ;}

这里所谓的traits就是如果I有自己定义的value type,那么通过这个traits作用,萃取出来的value_type就是I::value_type,换句话说,如果I有自己定义的value type,先前的func函数可以写成这样:

template<class I>

typenameiterator_traits<I>::value_type func(I ite){return *ite;}

中间多了一层间接性,traits可以拥有自己的偏特化版本。令iterator_traits拥有一个偏特化版本:

template<class T>
struct iterator_traits<*T>{
  typedef T value_type ;}

原生指针int*虽然不是一种class type,也可以通过traits特性取其value type。这就解决了之前的问题。

但是,针对指向常数对象的指针,下面这个式子得到的结果:

iterator_traits<constint *>::value_type;

获得的是const int而非int,不是期望的(本来希望利用这种机制,声明一个暂时的变量,使其型别与迭代器的的value type相同,而声明一个无法赋值的暂时变量,没多大用处),所以应该设计一个特化版本:

template<class T>
Struct iterator_traits<T *>{
typedef T value_type;}//萃取出来的应该是T而非const T

特性萃取机traits能够有效运作,每一个迭代器都必须遵循约定,自行以内嵌型别定义的方式定义出相应的型别,这个是stl的一个约定。


 
 


最常用的迭代器相应型别:
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;}

iterators_traits必须对传入型别为pointer以及pointerto-const设计特化版本。

differencetype表示两个迭代器之间的距离。如果一个泛型算法提供技术功能,例如count(),其传回值就必须使用迭代器的difference type

template<class I,class T>
typename iterator_traits<I>::difference_type//这行是函数的返回值
count(I first,I last,,const T& value)
{
  typename iterator_traits<I>::difference_type n=0;
for(;first!=last,++first)
  if(*first!=value)
++n;
return n;}

类似于value typedifference type也设计了两个版本的偏特化版本,pointerpointer-to-const版本。

referencetype pointer type

 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值