本部分包括traits基础以及iterator traits的介绍
一、iterator需要遵循的原则
STL中的iterator是关联algorithms和containers的纽带,algorithms想要通过iterator处理元素,有几个iterator必须要回答给algorithms的问题,比如说iterator指向元素的类型,iterator的类别等等,下面是一个例子:
template<typename _ForwardIterator>
inline void
rotate(_ForwardIterator __first,
_ForwardIterator __middle
_ForwardIterator __last)
{
......
std::__rotate(__first, __middle, __last,
std::__iterator_catagory(__first));
}
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 iterator_traits<_RandomAccessIterator>::value_type _ValueType;
_Distance __n = __last - __first;
_Distance __k = __middle - __first;
......
}
这个例子中,算法中的函数rotate就必须知道迭代器的差的类型,所指元素的类型,以及迭代器本身的类别这三个信息。
所以,所有的iterator定义5个相同的associated types,就可以以一致的方式“告诉”algorithms它需要的这些信息,有5个typedef是所有的iterator都需要定义的,如下图所示:
那么既然有了associated types,我们为什么还需要traits呢?以iterator的associated types为例,假如我们传给algorithms的是native pointer,那么它怎么回答algorithms提出的五个问题呢?这就要引出traits的概念,iterator traits可以统一地处理class iterator和non-class iterator。
二、traits
traits可以理解为一种萃取机制,可以提取出某一些东西的一些相同的特性。比如iterator traits可以统一地处理class iterator和non-class iterator,以统一的方式提取出它们的五个associated types,这是通过模板的偏特化来实现的,如下所示:
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;
};
//partial specialization for regular pointers
template<class T>
struct iterator_traits<T*>{
typedef random_access_iterator_tag iterater_category;
typedef T value_type;
typedef ptrdiff_t difference_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_tag iterater_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
};
注意针对const T*的偏特化版本中的value_type是T而不是const T,这是因为value_type的主要目的是为了声明变量,而声明一个无法被赋值的变量没什么用。