STL迭代器之迭代器绑定器:Iterator Traits

Iterators有不同的类型,每种类型都代表着不同的能力,它在重载某个行为时,是有用的,甚至有必要。通过iterators tags和iterator traits 重载可以实现。对于么一个iterator类型STL都提供一个 terator tag ,这个 terator tag 能被做一个 ’table”.
namespace std {
struct output_iterator_tag {
};
struct input_iterator_tag {
};
struct forward_iterator_tag
: public input_iterator_tag {
};
struct bidirectional_iterator_tag
: public forward_iterator_tag {
};
struct random_access_iterator_tag
: public bidirectional_iterator_tag {
};
}
如果要写一个泛型代码,你也许不仅需要iterator category ,例如你可能需要迭代器引用的类型,所以STL提供了一个特殊的面板结构体来定义iterator traits ,这个结构体包含了所有关于an iterator 的信息。它被用于定义一个iterator类型的正常的接口。 
namespace std {
template <class T>
struct iterator_traits {
typedef typename T::value_type value_type;
typedef typename T::difference_type difference_type;
typedef typename T::iterator_category iterator_category;
typedef typename T::pointer pointer;
typedef typename T::reference reference;
};
}
这个结构体的模板参数是 iterator.
这个结构体有两个有点:
1.         它保证一个 iterator 提供了所有的类型定义。
2.         它能被特殊的迭代器特化或部分特化。
例如
namespace std {
template <class T>
struct iterator_traits<T*> {
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef random_access_iterator_tag iterator_category;
typedef T* pointer;
typedef T& reference;
};
}
因此对于任何指向 T 的指针类型,它都是 random access iterator  种类。

怎么写一个泛型函数。
如果你写泛型函数没有用到 iterator_traits ,它的实现很简单。例如:
template <class OutPutIterator>
void display(OutPutIterator start,OutPutIterator end)
{
    while(start!=end)
         {
                   cout<<*start<<" ";
                   ++start;
         }
         cout<<endl;
}
这个使用于任何顺序容器。

但有的时候能用到,为了不同 iterator 种类,你一定要有以下两步:
Step 1. 让你的模板函数调用另一个函数,该函数增加了一个iterator category参数。
例如:
template <class Iterator>
inline void foo (Iterator beg, Iterator end)
{
foo (beg, end,std::iterator_traits<Iterator>::iterator_category());
}





Step2
为每一个 iterator 种类实现一个函数实现:
template <class BiIterator>
void foo (BiIterator beg, BiIterator end,
std::bidirectional_iterator_tag)
{
...
}
//foo() for random access iterators
template <class RaIterator>
void foo (RaIterator beg, RaIterator end,
std::random_access_iterator_tag)
{
}

看下 advance() 函数的实现过程。
template <class Iterator>
typename std::iterator_traits<Iterator>::difference_type
distance (Iterator pos1, Iterator pos2)
{
return distance (pos1, pos2,std::iterator_traits<Iterator>::iterator_category());
}
//distance() for random access iterators
template <class RaIterator>
typename std::iterator_traits<RaIterator>::difference_type
distance (RaIterator pos1, RaIterator pos2,
std::random_access_iterator_tag)
{
return pos2 - pos1;
}
//distance() for input, forward, and bidirectional iterators
template <class InIterator>
typename std::iterator_traits<lnIterator>::difference_type
distance (Inlterator pos1, InIterator pos2,
std::input_iterator_tag)
{
typename std::iterator_traits<lnIterator>::difference_type d;
for (d=0; pos1 != pos2; ++pos1, ++d) {
;
}
return d;
}


如何定义一个 iterator
在定义自己的 iterator 时,你需要提供iterator traits。
有两种方法;
1.       提供必要的 iterator_traits 的五种类型。
2.       提供 iterator_traits 结构体的特化。
对于第一种方法, STL 提供了一个基类 iteratoe<>, 它用于类型的定义。你可以这样:
class MyIterator
: public std::iterator <std::bidirectional_iterator_tag,
type, ptrdiff_t, type*, type&> {
...
};
第一个参数是the iterator category, 第二个参数是元素类型type,第三个是差值类型(difference type),第四个是指针类型(pointer type),第五个是引用类型(reference type),最后三个是可选的,它们默认的类型: ptrdif_f_t,  type *,  and  type &
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值