技术控

    今日:97| 主题:49471
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] STL中的Traits编程技巧

[复制链接]
心痛heartache 发表于 2016-10-5 18:39:19
67 0

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
《STL源码剖析》一书中提到Traits编程技法,它的作用是获取型别(associated type)的特性。这样讲比较抽象,到底什么是相应型别,或者到底什么时候需要用到Traits编程技法呢?先来看一个例子。  
  iterator_traits  

  假设有这么一个函数,接受一个iterator,返回这个iterator所指代的类型,其实这个函数就是实现了typeof(),但是c++里面并没有typeof()操作符。  
           
  1. vector<int> iv = {1, 2, 3, 4, 5};
  2. vector<int>::Iterator it1 = iv.begin(), it2 = iv.end();
  3. template<class iterator>
  4. // ret-type
  5. fun(iterator it)
  6. {
  7. // 函数体
  8. }
复制代码
       那么函数的返回类型的该怎么写呢?再往下看,如果这个Iterator由我们自己来实现(事实上stl的Iterator的实现和这个十分类似)
           
  1. template<class T>
  2. struct MyIter // 为了方便访问成员,用struct
  3. {
  4. typedef T value_type; // 内嵌声明(nested type)
  5. T* ptr;
  6. MyIter (T* p = 0):ptr(p){}
  7. T& operator*() const { return *ptr; }
  8. //...
  9. };
  10. template <class I>
  11. typename I::value_type // 函数返回类型
  12. func(I ite)
  13. {
  14. return *ite;
  15. }
复制代码
     这里要注意一点,返回类型必须加上关键词  typename,编译器并不知道  MyIter<I>::value_type代表的是一个型别或是一个  member function或是一个  data member。关键词  typename  的用意在于告诉编译器这是一个型别,如此才能顺利通过。这样我们就可以通过func函数获取迭代器所指代的类型了。
  但是这样还是有一个问题,并不是所有迭代器都是class type的。比如原生的指针就不是,这样就没有办法为它定义内嵌型别了。现在就轮到traits编程技法发挥作用的时候了:  
           
  1. template <class I>
  2. struct iterator_traits
  3. {
  4. typedef typename I::value_type value_type; // 此处的typename和上文同理,不再赘述。
  5. }
  6. // func可以这么写
  7. template <class I>
  8. typename iterator_traits<I>::value_type
  9. func(I ite)
  10. {
  11. return *ite;
  12. }
复制代码
       现在我们可以利用模板的template partial specialization(偏特化)定义一个偏特化版的iterator_traits专门用于萃取原生指针的型别。
           
  1. template <class T>
  2. struct iterator_traits<T*>
  3. {
  4. typedef T value_type;
  5. }
复制代码
       同理,对于指向常量的指针,我们也可以专门偏特化一个版本来萃取它的型别。
           
  1. template <class T>
  2. struct iterator_traits<const T*>
  3. {
  4. typedef T value_type;
  5. }
复制代码
       __type_traits  

  这里再提一点题外话,《STL源码剖析》提到,stl只对迭代器加以规范,制定出iterator_traits这样的东西,SGI则把这种技法扩大到了迭代器以外,定义了__type_traits。双底线前缀值这是SGI STL内部特有的,不在STL的标准规划之中。
  如果说iterator_traits负责萃取迭代器的特性,那么__type_traits则负责萃取型别的特性。这里所关注的型别特性有一下5个:
  
       
  • has_trivial_default_constructor   
  • has_trivial_copy_constructor   
  • has_trivial_assignment_operator   
  • has_trivial_destructor   
  • is_POD_type  
  有了这些型别特性,我们在对这个型别进行构造、析构、拷贝、赋值等操作时,就可宜采用最有效率的措施。比如对于has_trivial_copy_constructor,那么我只直接通过内存拷贝来实现对象拷贝以提高效率。
  参照iterator_traits的经验,我们希望通过下面这样的方法来获取使用__type_traits          :
                       
  1. __type_traits<T>::has_trivial_default_constructor
  2. __type_traits<T>::has_trivial_copy_constructor
  3. __type_traits<T>::has_trivial_assignment_operator
  4. __type_traits<T>::has_trivial_destructor
  5. __type_traits<T>::is_POD_type
复制代码
                     我们希望上式能够返回给我们一个对象的型别,而不是单纯的bool类型,这样编译器可以通过这个对象的型别来进行参数推导。为此,上述式子应该传回  
           
  1. struct __true_type {};
  2. struct __false_type {};
复制代码
       这是两个空白classes,没有任何成员,我们知道编译器在进行参数推导的时候,并不会真的去生成一个对象,因此,这么做是不会带来额外负担的,却又能够标示真假。
  下面就是SGI的    __type_traits实现:  
           
  1. template <class type>
  2. struct __type_traits
  3. {
  4. typedef __true_type this_dummy_member_must_be_first;
  5. typedef __false_type has_trivial_default_constructor;
  6. typedef __false_type has_trivial_copy_constructor;
  7. typedef __false_type has_trivial_assignment_operator;
  8. typedef __false_type has_trivial_destructor;
  9. typedef __false_type is_POD_type;
  10. }
  11. // 下面是<yupe_traits.h>对C++标量型定义的__type_traits的特化版的一个举例。
  12. // __STL_TEMPLATE_NULL 定义为 template<>
  13. __STL_TEMPLATE_NULL struct __type_traits<char>
  14. {
  15. typedef __true_type has_trivial_default_constructor;
  16. typedef __true_type has_trivial_copy_constructor;
  17. typedef __true_type has_trivial_assignment_operator;
  18. typedef __true_type has_trivial_destructor;
  19. typedef __true_type is_POD_type;
  20. }
复制代码
       如果自己实现一个类,需要告诉STL这个类的特性,那么为这个类也特化一个模板就可以了。
友荐云推荐




上一篇:三分钟搞懂 HTTP Transfer-Encoding
下一篇:Next Generation Server Compression With Brotli
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表