迭代器所指对象的型别,称为该迭代器的value type。value type是迭代器相应型别的一种。想要知道迭代器的value type,下面是一种办法:
1 template <class T> 2 struct MyIter{ 3 typedef T value_type; 4 T* ptr; 5 //.... 6 }; 7 8 template <class I> 9 typename I::value_type 10 func(I ite) 11 { return *ite; }
但当func参数为原生指针时上述办法就不适用了。偏特化可以解决,所谓partial specialization的意思是提供另一份template的定义,其本身仍为templatized。
1 template<typename T> 2 class C { ... }; 3 4 //特化版本,使用于T为原生指针 5 template<typename T> 6 class C<T*> { ... };
专门定义一个class template用来萃取迭代器的特性:
1 template <class I> 2 struct iterator_traits { 3 typedef typename I::value_type value_type; 4 };
这样使用iterator_traits<I>::value_type,实际上就是I::value_type,使用:
1 template <class I> 2 typename iterator_traits<I>::value_type 3 func(I ite) 4 { return *ite; }
可以针对原生指针提供一个特化版本:
1 template <class T> 2 struct iterator_traits<T*> { 3 typedef T value_type; 4 };
故即使原生指针int*不是一种class type,仍可以通过iterator_traits<int*>::value_type萃取出其value type。
根据经验,最常用到的迭代器相应型别有五种:
1 template <class I> 2 struct iterator_traits { 3 typedef typename I::iterator_category iterator_category; 4 typedef typename I::value_type value_type ; 5 typedef typename I::difference_type difference_type ; 6 typedef typename I::pointer pointer ; 7 typedef typename I::reference reference ; 8 };
iterator_traits必须针对传入之型别为pointer及pointer-to-const者,设计特化版本。
iterator_category
迭代器可以分为五类:
Input Iterator:只读。
Output Iterator:只写。
Forward Iterator
Bidirectional Iterator
Random Access Iterator
上述的迭代器前两种往后依次强化,即后者支持前者支持的操作,且支持新的操作(前三种支持operator++,第四个加上operator--,最后一个涵盖所有指针的能力)。设计算法时,针对某种迭代器提供一个明确的定义,并针对更强化的某种迭代器提供另一种定义。例如,有个算法可以接受Forward Iterator,Random Access Iterator给它当然也可以接受,但由于算法在实现时只使用了Forward Iterator支持的操作,没有使用Random Access Iterator支持的更加便捷的操作,会导致效率低,故应该再定义一个Random Access Iterator版本的。
定义五个classes,代表五种迭代器类型:
1 struct input_iterator_tag { }; 2 struct output_iterator_tag { }; 3 struct forward_iterator_tag : public input_iterator_tag { }; 4 struct bidirectional_iterator_tag : forward_iterator_tag { }; 5 struct random_access_iterator_tag : bidirectional_iterator_tag { };
定义以下重载函数:
1 template <class InputIterator, class Distance> 2 inline void __advance(InputIterator& i, Distance n, input_iterator_tag) 3 { 4 while (n--) ++i; 5 } 6 7 template <class BidirectionalIterator, class Distance> 8 inline void __advance(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag) 9 { 10 if (n >= 0) 11 while (n--) ++i; 12 else 13 while (n++) --i; 14 } 15 16 template <class RandomAccessIterator, class Distance> 17 inline void __advance(BidirectionalIterator& i, Distance n, random_access_iterator_tag) 18 { 19 i += n; 20 }
每个__advance()的最后一个参数都只声明参数的类型,并未制定参数名称,因为它只是用来激活重载,函数里用不到该参数。接下来需要一个对外的接口,它接受两个参数,当它准备调用__advance()时,加上第三个参数:迭代器类型,这个工作要依赖于traits机制:
1 template <class InputIterator, class Distance> 2 inline void advance(InputIterator& i, Distance n) 3 { 4 __advance(i, n, iterator_traits<InputIterator>::iterator_category()); 5 }
traits除了上面提供的class的迭代器类型,针对指针的特化版本:
1 template <class T> 2 struct iterator_traits<T*> { 3 ... 4 typedef random_access_iterator_tag iterator_category ; 5 }; 6 7 template <class T> 8 struct iterator_traits<const T*> { 9 ... 10 typedef random_access_iterator_tag iterator_category ; 11 };
STL算法的一个命名规则:以算法所能接受之最低阶迭代器类型,来为其迭代器型别参数命名。
__type_traits
STL只对迭代器加以规范,制定出iterator_traits,SGI把这种技法进一步扩大,于是有了__type_traits:
1 template <class type> 2 struct __type_traits { 3 typedef __true_type this_dummy_member_must_be_first; 4 typedef __false_type has_trivial_default_constructor; 5 typedef __false_type has_trivial_copy_constructor; 6 typedef __false_type has_trivial_assignment_operator; 7 typedef __false_type has_trivial_destructor; 8 typedef __false_type is_POD_type; 9 };
特化版本:
1 template <class type> 2 struct __type_traits<char> { 3 typedef __true_type has_trivial_default_constructor; 4 typedef __true_type has_trivial_copy_constructor; 5 typedef __true_type has_trivial_assignment_operator; 6 typedef __true_type has_trivial_destructor; 7 typedef __true_type is_POD_type; 8 }; 9 10 template <class type> 11 struct __type_traits<signed char> { 12 typedef __true_type has_trivial_default_constructor; 13 typedef __true_type has_trivial_copy_constructor; 14 typedef __true_type has_trivial_assignment_operator; 15 typedef __true_type has_trivial_destructor; 16 typedef __true_type is_POD_type; 17 }; 18 19 template <class type> 20 struct __type_traits<unsigned char> { 21 typedef __true_type has_trivial_default_constructor; 22 typedef __true_type has_trivial_copy_constructor; 23 typedef __true_type has_trivial_assignment_operator; 24 typedef __true_type has_trivial_destructor; 25 typedef __true_type is_POD_type; 26 }; 27 28 template <class type> 29 struct __type_traits<short> { 30 typedef __true_type has_trivial_default_constructor; 31 typedef __true_type has_trivial_copy_constructor; 32 typedef __true_type has_trivial_assignment_operator; 33 typedef __true_type has_trivial_destructor; 34 typedef __true_type is_POD_type; 35 }; 36 37 template <class type> 38 struct __type_traits<unsigned short> { 39 typedef __true_type has_trivial_default_constructor; 40 typedef __true_type has_trivial_copy_constructor; 41 typedef __true_type has_trivial_assignment_operator; 42 typedef __true_type has_trivial_destructor; 43 typedef __true_type is_POD_type; 44 }; 45 46 //后面省略int, unsigned int, long, unsigned long, float, double, long double, T*.....
使用示例:
1 template <class T> inline void copy(T* source, T* destination, int n){ 2 copy(source, destination, __type_traits<T>::has_trivial_copy_constructor()); 3 } 4 5 template <class T> inline void copy(T* source, T* destination, int n, __false_type) 6 { ... } 7 8 //拷贝一个数组,其元素具有trivial copy constructors,可借助memcpy() 9 template <class T> inline void copy(T* source, T* destination, int n, __true_type) 10 { ... }