在STL中迭代器是容器与泛型算法之间的粘合剂。要想使泛型算法独立于容器,泛型算法必须以迭代器为对外接口,同时要想容器能独立于泛型算法,容器必须有专属的迭代器。
1.oterator_traits
在算法中运用迭代器时,很有可能会用到迭代器的相应型别。假设算法要以“迭代器所指之物的型别(value_type)”定义对象,如何是好?解决办法是利用函数模板的参数推导机制。例如:
但是如果我们要使用value_type作为函数返回值类型,上述方法就行不通了。怎么办?申明内嵌型别是个不错的主意,像这样:
这个方法看起来不错,但是有个隐晦的陷阱:并不是所有的迭代器都是class type,原生指针就不是class,就无法为它定义内嵌型别,但是所有的泛型算法必须能接受原生指针。类模板的偏特化可以解决这个问题:
这就是整个iterator_traits由来。对于任何迭代器,原生指针,const原生指针,只要使用iterator_traits<>都可以萃取出迭代器相应的型别。如下图所示:
整个iterator_traits源代码如下:
struct input_iterator_tag {};
struct output_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 {};
#ifdef __STL_USE_NAMESPACES
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;
};
#endif /* __STL_USE_NAMESPACES */
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
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;
};
template <class T>
struct iterator_traits<T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
template <class T>
struct iterator_traits<const T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
2.__type_traits
iterator_trats负责萃取迭代器特性,__type_traits则负责萃取某一型别的特性,所谓型别特性是指:这个型别是否具有non-trivial defalt ctor , non-trivial copy ctor , non-trivial assignment operator , non-trivial dtor ?如果答案是否定的,我们在对这个型别进行构造,析构,拷贝,赋值等操作时,就可以采取更有效率的措施。因此我们定义了__type_traits.源码如下:
template <class type>
struct __type_traits {
typedef __true_type this_dummy_member_must_be_first;
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_operator;
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type;
};
这是采取了最保守的措施,所有的内嵌型别都被 定义为_false_type,针对每个标量型别,STL都设计了特化版本。