容器的迭代器的特征
容器里面的六大部件中的算法和容器是通过iterator来连接的。对于迭代器来说,每个容器的迭代器可能会有不同的特性
这个特性一般会有五个方面
- value_type:迭代器指向的容器中的元素的类型
- difference_type:迭代器之间距离的类型,对于只能前向移动的(iterator++,iterator+3)其移动的距离是unsigned int,对于双向(iterator–)起移动的距离是int。
- pointer:指针类型
- reference:引用类型
- iterator_category;迭代器有前向,双向访问等特征,这个是来标注迭代器的特征的。
traits
萃取机就是相当于包装了访问iterator特性的接口,这个接口被封装成了一个class,通过萃取机来访问当前的容器的iterator。
因为不同容器之间的iterator的访问特性是不一样的,因此是需要特殊设计的。一般的设计分为两种:
- class iterators:将iterator包装成一个单独的类,然后重载++,–等操作符。例如对于list来说,因为存储不同节点之间的物理空间是不连续的,访问前一个节点和后一个节点是需要重载运算符的。这部分对应上图中的lsit::iterator,deque::iterator等
-non-class iterators: iterator就是单独的一个指针,例如对于vector,传进来的就是上图中的T*。
iterator_traits是用来分离class iterators和non-class iterators。如何根据模板传进来的class和non_class来访问这些特性?答案就是通过模板的泛化(针对class)和偏特化(针对non-class)实现.
声明(泛化)
template<class I>
struct iterator_traits{
typedef typename I::iterator_category iterator_category;//(1)迭代器的分类,就是移动性质:前向,双向
typedef typename I::value_type value_type;//(2)迭代器指向的元素的类型
typedef typename I::difference_type difference_type;//(3)两个迭代器之间距离的类型,unsigned int/int
typedef typename I::pointer pointer;//(4)指针
typedef typename I::reference reference;//(5)引用
};
这个泛化根据进来的类去找对应的iterator,例如list,map等
偏特化
//non-class iterators,部分特化
template <class T>
//pointer to T
struct iterator_traits<T *>{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T*;
typedef T&;
};
针对指针的偏特化,相当于特化了<T >.这个就可以处理上面所说的T;同理const T*需要特化的。