traits编程技法大量运用于STL实现中。通过它在一定程度上弥补了C++不是强型别语言的遗憾,增强了C++关于型别认证方面的能力。
traits编程技法是利用“内嵌型别”的编程技法和编译器的template参数推导功能实现的。
iterator_traits
1.对于class type要求其“内嵌型别”
要求与STL兼容的容器,其迭代器必须定义一下五种型别:
iterator_category 迭代器类型
value_type 迭代器所指对象类型
difference_type 迭代器间的距离类型
pointer
reference
2.对于非class type(如:原生指针)需要使用template partial specialization(偏特化)
1 //class type的“内嵌型别”
2 template <class _Iterator>
3 struct iterator_traits {
4 typedef typename _Iterator::iterator_category iterator_category;
5 typedef typename _Iterator::value_type value_type;
6 typedef typename _Iterator::difference_type difference_type;
7 typedef typename _Iterator::pointer pointer;
8 typedef typename _Iterator::reference reference;
9 };
10
11 //对原生指针的偏特化
12 template <class _Tp>
13 struct iterator_traits<_Tp*> {
14 typedef random_access_iterator_tag iterator_category;
15 typedef _Tp value_type;
16 typedef ptrdiff_t difference_type;
17 typedef _Tp* pointer;
18 typedef _Tp& reference;
19 };
20
21 //对const指针的偏特化
22 template <class _Tp>
23 struct iterator_traits<const _Tp*> {
24 typedef random_access_iterator_tag iterator_category;
25 typedef _Tp value_type;
26 typedef ptrdiff_t difference_type;
27 typedef const _Tp* pointer;
28 typedef const _Tp& reference;
29 };
iterator中为什么要引入traits机制?
提高效率
对效率的至极追求贯穿整个STL设计,traits机制的引入是为了实现 同一方法用于不同类型时调用对该类型最高效的版本 以提高效率。
例如 advance():
1 //用于input_iterator的版本
2 template <class _InputIter, class _Distance>
3 inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) {
4 while (__n--) ++__i;
5 }
6
7 //用于 bidirectional_iterator的版本
8 template <class _BidirectionalIterator, class _Distance>
9 inline void __advance(_BidirectionalIterator& __i, _Distance __n,
10 bidirectional_iterator_tag) {
11 __STL_REQUIRES(_BidirectionalIterator, _BidirectionalIterator);
12 if (__n >= 0)
13 while (__n--) ++__i;
14 else
15 while (__n++) --__i;
16 }
17
18 //用于 random_access_iterator的版本
19 template <class _RandomAccessIterator, class _Distance>
20 inline void __advance(_RandomAccessIterator& __i, _Distance __n,
21 random_access_iterator_tag) {
22 __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);
23 __i += __n;
24 }
25
26 //advance方法的对外接口
27 template <class _InputIterator, class _Distance>
28 inline void advance(_InputIterator& __i, _Distance __n) {
29 __STL_REQUIRES(_InputIterator, _InputIterator);
30 __advance(__i, __n, iterator_category(__i));
31 }
SGI STL中迭代器之外的 __type_traits
STL只对迭代器进行了traits规范,制定类iterator_traits。SGI
把这种规范扩大到类迭代器之外,也就是__type_traits(__前缀表示是SGI 内部使用的,不在STL规范内)。
iterator_traits负责萃取iterator特性,而__type_traits则负责萃取一下五种型别(type)特性:
has_trivial_default_constructor 是否有平凡的默认构造函数
has_trivial_copy_constructor 是否有平凡的拷贝构造函数
has_trivial_assignment_operator 是否有平凡的分配操作
has_trivial_destructor 是否有平凡的析构函数
is_POD_type 是否为POD类型(POD:Plain Old Data)
如果class内含指针成员,并对它进行内存动态分配,那么这个class就需要实现自己的 non-trivial-xxx。
上述特性应该响应我们“真”或“假”,但却不能是bool值,因为我们要利用其响应来进行参数推导,而编译器只有面对class
object形式的参数时才能进行参数推导,因此响应应该是带有“真”“假”性质的不同类。SGI STL中如下定义:
1 struct __true_type {
2 };
3
4 struct __false_type {
5 };
1 template <class _Tp>
2 struct __type_traits {
3 typedef __true_type this_dummy_member_must_be_first;
4 /* Do not remove this member. It informs a compiler which
5 automatically specializes __type_traits that this
6 __type_traits template is special. It just makes sure that
7 things work if an implementation is using a template
8 called __type_traits for something unrelated. */
9
10 /* The following restrictions should be observed for the sake of
11 compilers which automatically produce type specific specializations
12 of this class:
13 - You may reorder the members below if you wish
14 - You may remove any of the members below if you wish
15 - You must not rename members without making the corresponding
16 name change in the compiler
17 - Members you add will be treated like regular members unless
18 you add the appropriate support in the compiler. */
19
20
21 typedef __false_type has_trivial_default_constructor;
22 typedef __false_type has_trivial_copy_constructor;
23 typedef __false_type has_trivial_assignment_operator;
24 typedef __false_type has_trivial_destructor;
25 typedef __false_type is_POD_type;
26 };
为保守起见都定义为__false_type
在SGI STL的Type_traits.h中对C++ 内建的bool/char/signed char/unsigned
char等标记为__true_type。
为什么要引入__type_triats?
答案还是提高效率
对于标记为__true_type的型别,对其对象进行构造/析构/拷贝/赋值等操作时就可以采用最有效率的措施。(如:不必调用高层次的constructor/destructor,而采用内存直接处理操作malloc()/memcpy()等)
STL Traits编程技法,码迷,mamicode.com