zoukankan      html  css  js  c++  java
  • Traits编程技法

        迭代器所指对象的型别,称为该迭代器的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 {  ...  }
  • 相关阅读:
    总结Linq或者lamdba的写法
    JObject 用法 、JProperty 用法、JArray 用法 Linq 转 Json
    System.DateTime.Now 24小时制。
    将springboot jar应用打包成镜像并在docker运行成容器
    RPC框架——简单高效hessian的使用方式
    WebService—规范介绍和几种实现WebService的框架介绍
    Java三大体系JavaEE、JavaSE、JavaME的区别
    JavaEE体系架构
    JavaEE 技术体系
    注解之@CookieValue
  • 原文地址:https://www.cnblogs.com/lulu10922/p/7985177.html
Copyright © 2011-2022 走看看