zoukankan      html  css  js  c++  java
  • 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()等)

  • 相关阅读:
    Hibernate 学习-3
    Hibernate反向工程使用心得
    MyEclipse中自动整合Spring3+Hibernate/JPA
    jsp页面不显示问题
    jstl获取当前系统时间的方法
    js实现12小时时钟
    从servlet跳到jsp页面,并用jstl 进行判断和显示方法
    jsp调用js文件时出现乱码
    常见异常总结
    js实现表单验证
  • 原文地址:https://www.cnblogs.com/baiyideng/p/3696038.html
Copyright © 2011-2022 走看看