1. 从STL源码中了解Iterator_trait
以rotate算法为例
template<typename _ForwardIterator>
inline void rotate(_ForwardIterator _first,
_ForwardIterator _middle,
_ForwardIterator _last,)
{
//...
std::_rotate(_first, _middle, _last,
std::__iterator_category(_first));
}
template<typename _Iter>
inline typename iterator_trait<_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)
{
//....
typdef typename iterator_trait<_RandomAccessIterator>::different_type _Distance;
typdef typename iterator_trait<_RandomAccessIterator>::value_type _VlaueType;
_Distance_n = _last - _first;
_Distance_k = _middle - _first;
// ....
for(;;) {
//....
}
}
从上述代码中可以看出,rotate()需要知道iterators的三个associated types,即:
- iterator_trait::iterator_category()
- iterator_trait<_RandomAccessIterator>::different_type __Distance
- iterator_trait<_RandomAccessIterator>::value_type _VlaueType
Iterators必须有能力回答algorithms的提问,这样的提问在C++标准库开发过程中设计出了5种,另外2种从未在C++标准库中被使用过:reference和pointer。
注:typedef typename 的作用
typdef typename iterator_trait<_RandomAccessIterator>::different_type _Distance;
typedef创建了存在类型的别名,而typename告诉编译器iterator_trait<_RandomAccessIterator>::different_type是一个类型而不是一个成员。
2. Iterator的5种associated types
// G4.9
template<typename _Tp>
struct _List_iterator
{
typedef std::bidirectional_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Tp* pointer;
typedef _Tp& reference;
typedef ptrdiff_t difference_type;
}
如上所示,如果 I(iterator)是 class,class iterator 都有能力定义自己的associated type,因此以直接回答算法提问。
template<typename I>
inline void algorithm(I first, I last)
{
//...
I::iterator_category;
I::pointer;
I::reference;
I::value_type;
I::difference_type;
//...
}
如果 I(iterator) 并不是 class,例如它是一个 native pointer(被视为一种退化的iterator),它无法定义自己的associated type,因此并不能回答算法的提问。traits 必须具有分别它获取的 iterator 是 class iterator T 还是native pointer to T。利用partial specialization可达到目的。
3. Itreator_trait源码实现
template <class T>
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;
};
template <class T>
struct iterator_traits<T*> {
typedef typename random_access_iterator_tag iterator_category;
typedef typename T value_type;
typedef typename ptrdiff_t difference_type;
typedef typename T* pointer;
typedef typename T& reference;
};
template <class T>
struct iterator_traits<const T*> {
typedef typename random_access_iterator_tag iterator_category;
typedef typename T value_type;
typedef typename ptrdiff_t difference_type;
typedef typename T* pointer;
typedef typename T& reference;
};
注:const T*类型的Iterator中value_type不是const T,value_type的主要目的是用来声明变量,声明一个无法被复制的变量没有什么用。