转自:http://blog.csdn.net/my_business/article/details/7891687
介绍traits的文章很多,但感觉大部分文章的说明都很晦涩难懂,把一个并不很复杂的C++模板的应用描述的过于复杂。忍不住想把自己的理解跟大家分享一下,或许我也只是掌握了一点traits的皮毛而已,但也希望这些皮毛能略微抓住你的眼球,带给你一些启发。
首先,介绍traits前,回味一下C++的模板及应用,如果你脑海里浮现出的只是为实现一些函数或类的重用的简单模板应用,那我要告诉你,你out了。最近在整理一些模板的应用方式,有时间的话会写出来分享给大家,本文不会去详细讨论traits以外的模板的各种高级应用。
那么,言归正传,什么是traits?其实它并不是一个新的概念,上个世纪90年代中期就已经被提出,只是到了这个世纪才在各个C++库中被广泛使用,而我也是在这个概念诞生十多年后才接触到它。C++之父Bjarne Stroustrup对traits有如下的描述:
Think of a trait as a small object whose main purpose is to carry information used by another object or algorithm to determine "policy" or "implementation details".

我不知道官方或一些书上是如何去解释traits的,我的理解是:
当函数,类或者一些封装的通用算法中的某些部分会因为数据类型不同而导致处理或逻辑不同(而我们又不希望因为数据类型的差异而修改算法本身的封装时),traits会是一种很好的解决方案。
本以为能很简单的描述它,谁知道还是用了如此长的句子才说明清楚,相当的惭愧。大家只要有个大概的概念就ok了,甚至即使完全没概念也没关系,下面会通过实际代码来说明。
先看这样一个例子。如果有一个模板类Test:
[cpp] view plaincopy
  1. template <typename T>
  2. class Test {
  3. ......
  4. };
假设有这样的需求,类Test中的某部分处理会随着类型T的不同而会有所不同,比如希望判断T是否为指针类型,当T为指针类型时的处理有别于非指针类型,怎么做?
模板里再加个参数,如下?
[cpp] view plaincopy
  1. template <typename T, bool isPointer>
  2. class Test {
  3. ......// can use isPointer to judge whether T is a pointer
  4. };
然后用户通过多传一个模板类型来告诉Test类当前T是否为指针。(Test<int*, true>)
很抱歉,所有的正常点的用户都会抱怨这样的封装,因为用户不理解为什么要让他们去关心自己的模板类型是否为指针,既然是Test类本身的逻辑,为什么麻烦用户呢?
由于我们很难去限制用户在使用模板类时是使用指针还是基本数据类型还是自定义类型,而用常规方法也没有很好的方法去判断当前的T的类型。traits怎么做呢?
定义traits结构:
[cpp] view plaincopy
  1. template <typename T>
  2. struct TraitsHelper {
  3. static const bool isPointer = false;
  4. };
  5. template <typename T>
  6. struct TraitsHelper<T*> {
  7. static const bool isPointer = true;
  8. };
也许你会很困惑,结构体里就一个静态常量,没有任何方法和成员变量,有什么用呢?解释一下,第一个结构体的功能是定义所有TraitsHelper中isPointer的默认值都是false,而第二个结构体的功能是当模板类型T为指针时,isPointer的值为true。也就是说我们可以如下来判断当前类型:
TraitsHelper<int>::isPointer值为false, 可以得出当前类型int非指针类型
TraitsHelper<int*>::isPointer值为true, 可以得出当前类型int*为指针类型
也许看到这里部分人会认为我简直是在说废话,请再自己品味下,这样是否就可以在上面Test类的定义中直接使用TraitsHelper<T>::isPointer来判断当前T的类型了。
[cpp] view plaincopy
  1. if (TraitsHelper<T>::isPointer)
  2. ......
  3. else
  4. ......
再看第二个例子:
还是一个模板类Test:
[cpp] view plaincopy
  1. template <typename T>
  2. class Test {
  3. public:
  4. int Compute(int d);
  5. private:
  6. T mData;
  7. };
它有一个Compute方法来做一些计算,具有int型的参数并返回int型的值。
现在需求变了,需要在T为int类型时,Compute方法的参数为int,返回类型也为int,当T为float时,Compute方法的参数为float,返回类型为int,而当T为其他类型,Compute方法的参数为T,返回类型也为T,怎么做呢?还是用traits的方式思考下。
[cpp] view plaincopy
  1. template <typename T>
  2. struct TraitsHelper {
  3. typedef T ret_type;
  4. typedef T par_type;
  5. };
  6. template <>
  7. struct TraitsHelper<int> {
  8. typedef int ret_type;
  9. typedef int par_type;
  10. };
  11. template <>
  12. struct TraitsHelper<float> {
  13. typedef float ret_type;
  14. typedef int par_type;
  15. };
然后我们再把Test类也更新下:
[cpp] view plaincopy
  1. template <typename T>
  2. class Test {
  3. public:
  4. TraitsHelper<T>::ret_type Compute(TraitsHelper<T>::par_type d);
  5. private:
  6. T mData;
  7. };
可见,我们把因类型不同而引起的变化隔离在了Test类以外,对用户而言完全不需要去关心这些逻辑,他们甚至不需要知道我们是否使用了traits来解决了这个问题。
到这里,再让我们回过来取品味下开始我说的那句话:
当函数,类或者一些封装的通用算法中的某些部分会因为数据类型不同而导致处理或逻辑不同时,traits会是一种很好的解决方案。
是不是有点感觉了?如果还不明白的,麻烦你留言,我会再解释再说明,直到你明白为止,呵呵。
最后,让我们记住它吧,traits,一种模板的应用,非常有用的东东。

C++模板-Traits相关推荐

  1. 模板:什么是Traits

    2019独角兽企业重金招聘Python工程师标准>>> Traits不是一种语法特性,而是一种模板编程技巧.Traits在C++标准库,尤其是STL中,有着不可替代的作用. 如何在编 ...

  2. C++ 模板类型萃取技术 traits

    当函数,类或者一些封装的通用算法中的某些部分会因为数据类型不同而导致处理或逻辑不同(而我们又不希望因为数据类型的差异而修改算法本身的封装时),traits会是一种很好的解决方案.(类型测试发生在编译期 ...

  3. [C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)

    http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/18/2728753.html 1.  主版本模板类 首先我们来看一段初学者都能看 ...

  4. 【effective c++读书笔记】【第7章】模板和泛型编程(3)

    条款46:需要类型转换时请为模板定义非成员函数 对条款24的例子进行模板化: #include<iostream> using namespace std;template<type ...

  5. 疑惑即新知——记一次reverse模板实现过程

    2019独角兽企业重金招聘Python工程师标准>>> 最近学习C++,在实现reverse模板函数的时候,从一个小问题开始,在对这个问题的旁敲侧击当中带起了更多疑惑,顺藤摸瓜之后, ...

  6. effective C++ 条款 47:使用traits classes表现类型信息

    stl主要由"用以表现容器.迭代器和算法"的template构成,但也覆盖若干工具性的templates,其中一个名为advance,将某个迭代器移动某个给定距离: templat ...

  7. C++ 模板偏特化-来自STL的思考

    之前学习STL时接触过一段时间的模板,模板是C++泛型编程编程的基础 STL从头到尾都是模板泛型编程,我觉得用的最巧妙的就是在traits萃取技巧时用到的模板偏特化 先简要回顾一下模板吧,模板主要分为 ...

  8. Effective C++ --7 模板与泛型编程

    上一篇Effective C++ -- 6 继承与面向对象设计 41.了解隐式接口和编译器多态 (1)class和template都支持接口和多态.Class支持显示接口,多态是指virtual引起的 ...

  9. 《STL源码剖析》学习--traits

    在本书迭代器一节提到了Traits编程技法,将其誉为stl源码门匙,在<C++编程思想>一书中,将其列为模板编程中的习语"特征",这里进行总结. traits技术 也往 ...

最新文章

  1. spdlog源码阅读 (1): sinks
  2. Nature:拟南芥微生物组功能研究2细菌基因组测序和分析
  3. 为什么医学影像AI已进入「后深度学习时代」?
  4. Yann LeCun:假如没有深度学习,Facebook就是尘埃
  5. 图解分布式架构的演进过程
  6. 小明分享|基于VSCode Espress IDF软件环境搭建
  7. (转)计算机网络基础知识总结
  8. jQuery 开始动画,停止动画
  9. 结构化编程 —— 顺序、分支(选择)、循环
  10. 程序结构程序设计(四)
  11. MarkDown数学符号(更新中)
  12. 安徽工业大学java实验报告_安徽工业大学java实验报告.doc
  13. 姓名生成---拼音简码(大小写)---拼音全码(大小写)
  14. java pdf 富文本_Java生成pdf,兼富文本
  15. 安装gooreplacer插件为含有googlefonts api的网页提速
  16. 爱快ikuai系统安装配置教程
  17. 数据正态分布化 + 基于回归算法的房价预测(含python代码)
  18. Linux安装视频播放器
  19. destoon7.0第三方短信插件下载 destoon7.0整合云信通短信平台教程
  20. [基本功]支持向量机(SVM)理论知识

热门文章

  1. linux7端口聚合,centos7配置链路聚合
  2. java 接口表单提交_Java http 调用接口提交表单以及文件
  3. python自然语言分析 何翠仪_如何用 Python 中的 NLTK 对中文进行分析和处理?
  4. dataframe 一列的不同值_python数据分析包|Pandas-02之缺失值(NA)处理
  5. 计算机应用技术环境评估,计算机应用教程(第7版)(Windows 7与Office 2007环境)习题解答与上机练习...
  6. android 3.0单元测试,Android Studio 3.0 gradle 3.0.0-beta2打破了Kotlin单元测试覆盖率?
  7. mysql 5.6.27安装图解_Linux下MySQL 5.6.27 安装教程
  8. 【学习笔记】数据链路层——随机访问介质访问控制(ALOHA、CSMA、CSMA/CD、CSMA/CA),截断二进制指数规避算法
  9. jpa多表关联查询_Spring Boot 整合mybatis如何自定义 mapper 实现多表关联查询
  10. oracle10g如何导出dmp,Oracle 10g dmp文件的导入导出