STL Traits编程技法

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()等)

你可能感兴趣的:(traits)