上一篇讲到traits的类型萃取,可将迭代器相关的类型获取用于变量声明和函数返回等操作。对于原生指针和const指针可以采用偏特化技术进行处理。
在STL中,对迭代器除了封装类型信息以外,还有一些其他的信息,这篇文章介绍一下。
STL中,迭代器中的类型包括以下五种:
template <class _Iterator>
struct iterator_traits {
typedef typename _Iterator::iterator_category iterator_category;
typedef typename _Iterator::value_type value_type;
typedef typename _Iterator::difference_type difference_type;
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
第一种类型:value_type
这个前面介绍过,就是获取迭代器指向元素的类型。
第二种类型: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;
}
当然,因为原生指针并没有这个类型信息,需要对其特化。
template <class I>
class iterator_traits<I*> {
typedef ptrdiff_t difference_type;
}
template <class I>
class iterator_traits<const I*> {
typedef ptrdiff_t difference_type;
}
其中的ptrdiff_t是一个C++内置类型 【typedef long int ptrdiff_t】
第三种类型:reference
这个类型就是迭代器封装对象的引用,是为了解决对指针进行解引用时返回什么类型对象的问题。
这个类型一般用在*运算符重载,让所有指针有相同的表现形式。
第四种类型:pointer
这个类型就是迭代器封装对象的地址,主要用于->运算符重载。
对于智能指针,我们一般需要重载下面两个运算符:
T& operator*() const { return *ptr; } // T& is reference type
T* operator->() const { return ptr; } // T* is pointer type
因此,为了对迭代器和原生指针有一个相同的表现形式,在iterator_traits中加入了:
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
同样需要对const指针和原生指针特化:
template<class T>
struct iterator_traits<T*> {
typedef typename T* pointer;
typedef typename T& reference;
}
template<class T>
struct iterator_traits<const T*> {
typedef typename const T* pointer;
typedef typename const T& reference;
}
第五种类型:iterator_category
最后一种类型,其作用是按照迭代器的移动特性和能够在该迭代器上实施的操作对迭代器进行分类,主要是为了效率。
STL中的迭代器有五种类型:
单向移动只读迭代器 input iterator
单向移动只写迭代器 output iterator
单向移动读写迭代器 forwarditerator
双向移动读写迭代器 bidirectional iterator
随机访问迭代器 random access iterator
前四种属于单步移动迭代器,最后一种属于双向移动迭代器。
在STL提供的各种算法中,遍历元素需要用到advance()函数,而具体实现时需要根据迭代器的不同类型调用各自类型迭代器的advance()实现。
这种类型判断放在运行时确定效率肯定不高。
因此最好是能够在编译期就确定好函数该调用哪一个。
所以,STL中的实现是这样的:
template <class InputIterator, class Distance>
void advance(InputIterator& i, Distance n) {
// Forward the correct messages
__advance(i, n, type_traits<i>::iterator_category());
}
另外,STL为我们提供了一个标准的迭代器壳。
template <class Category,
class T,
class Distance = ptrdiff_t
class Pointer = T*
class Reference = T&>
struct iterator {
typedef Category iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
};
避免了一些复杂的typedef声明。
参考:
http://www.cppblog.com/nacci/archive/2005/11/03/911.aspx
在此感谢。