Iterator Traits(迭代器特性)
迭代器可以区分为不同的类型,每个类型都有特定的迭代器功能。
根据迭代器类型,将操作行为重载,将会很有用,也很必要!
透过迭代器标志(tags)和迭代器特性(traits,由<iterator>提供)可以实现这样的重载.
STL为每周迭代器都提供了一个迭代器标志(iterator tags),用来作为迭代器的标签(label)
namespace
{
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
{
};
}
请注意,这里使用了继承,所有我们可以说:
任何Forward迭代器都是一种(is-a) input迭代器
STL提供了一种特殊的template结果来定义所谓的迭代器特性(traits)
其包含迭代器的相关特性,为迭代器应具备的所有类型定义(包括迭代器类型、元素类型等)提供一致的接口
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;
};
}
这里,T表示迭代器类型。有了它,我们就可以写任何运用迭代器类型或者元素类型等特征
的泛型程序代码:
typename std::iterator_traits<T>::value_type;
迭代器类型如下:
通过iterator_traits返回某个具体迭代器的value等,见下面
template <class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&> struct iterator { typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference; typedef Category iterator_category; };
这个iterator_traits有两个优点:
1.能确保每一个迭代器提供所有必要的性别定义
2.能针对特定的迭代器进行特化(specialization)
如:以一般指针作为迭代器时的特化版本:
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;
};
}
通过iterator_traits我们就可以编写这样的泛型函数:
根据迭代器类型定义采用不同的功能实现
如算法内部要定义一个临时变量tmp(其中T为迭代器类型):
另一个例子,元素的环形移动:
template <class ForwardIterator>
void shift_left(ForwardIterator beg,ForwardIterator end)
{
if(beg != end)
{
value_type tmp(*beg);
//我认为应该是 typename std::iterator_traits<ForwardIterator>::value_type tmp(*beg);
//...
}
}
运用迭代器类型:
如果你希望针对不同的迭代器采用不同的实现方案,你需要按下面两步来走:
1.让你的template函数将迭代器类型作为附加参数,调用另一个函数:
template <class iterator>
inline void foo(intertor beg,intertor end)
{
foo(beg,end,
std::iterators_traits<intertor>::iterator_category());
}
2.针对不同的迭代器类型实现上述所调用的函数。
template <class BIDirectionIterator>
void foo(BIDirectionIterator beg,BIDirectionIterator end,
std::bidirectional_iterator_tag)
{
//...
}
template <class RandomAccessIterator>
void foo(RandomAccessIterator beg,RandomAccessIterator end,
std::random_access_iterator_tag)
{
//...
}
实例:实现迭代器辅助函数 distance()
对于随机迭代器,只是简单的运用operator-
对其他类型的迭代器,必须一步一步的前进到区间终点
(因此,必须保证其实迭代器前进一定能够到达终止迭代器)
template <class iterator>
typename std::iterators_traits<intertor>::difference_type
distance(intertor pos1,intertor pos2)
{
return distance(pos1,pos2,
std::iterators_traits<intertor>::iterator_category());
}
///对随机迭代器的实现版本
template <class RandomAccessIterator>
typename std::iterators_traits<RandomAccessIterator>::difference_type
void distance(RandomAccessIterator pos1,RandomAccessIterator pos2,
std::random_access_iterator_tag)
{
return pos2-pos1;
}
///对input迭代器的实现版本
template <class InputIterator>
typename std::iterators_traits<InputIterator>::difference_type
void distance(InputIterator pos1,InputIterator pos2,
std::input_iterator_tag)
{
typename std::iterators_traits<InputIterator>::difference_type dist;
for(dist=0;pos1!=pos2;++pos1,++dist)
{
}
return dist;
}
注意:第二个实现的distance函数使用的是input迭代器,
所有该版本对Forward迭代器、BiDirectional迭代器都生效。