C++模板-Traits

转自: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,一种模板的应用,非常有用的东东。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509381.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis中SqlMapConfig.xml配置文件的使用

文章目录SqlMapConfig.xml中配置的内容和顺序如下properties&#xff08;属性)SqlMapConfig.xml引用如下typeAliases&#xff08;类型别名)mybatis支持别名&#xff1a;自定义别名mappers&#xff08;映射器)Mapper引入映射器的几种方法:1.通过resource属性引入classpath路径的…

数据结构实验之数组三:快速转置

题目描述 转置运算是一种最简单的矩阵运算&#xff0c;对于一个m*n的矩阵M( 1 < m < 10000,1 < n < 10000 )&#xff0c;它的转置矩阵T是一个n*m的矩阵&#xff0c;且T( i , j )M( j , i )。显然&#xff0c;一个稀疏矩阵的转置仍然是稀疏矩阵。你的任务是对给…

主流服务器框架总结

libevent 编辑Libevent 是一个用C语言编写的、轻量级的开源高性能网络库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff0c;不如 ACE 那么臃肿庞大&#xff1b;源代码相当…

Mybatis输入映射和输出映射

Mapper.xml映射文件中定义了操作数据库的sql&#xff0c;每个sql是一个statement&#xff0c;映射文件是mybatis的核心。输入参数映射parameterType(输入类型)传递简单类型&#xff1a;如&#xff1a;<select id"queryUserById" parameterType"Integer"…

树结构练习——排序二叉树的中序遍历

题目描述 在树结构中&#xff0c;有一种特殊的二叉树叫做排序二叉树&#xff0c;直观的理解就是——(1).每个节点中包含有一个关键值 (2).任意一个节点的左子树&#xff08;如果存在的话&#xff09;的关键值小于该节点的关键值 (3).任意一个节点的右子树&#xff08;如果存在的…

陈硕知乎专栏

https://www.zhihu.com/people/giantchen/answers

Mybatis动态sql的使用

通过mybatis提供的各种标签方法实现动态拼接sql。 为什么用if标签? UserMapper.xml配置sql&#xff0c;如下&#xff1a; <!-- 根据条件查询用户 --> <select id"queryUserByWhere" parameterType"user" resultType"user">SELEC…

面向对象设计之CRC卡片

1.什么是 CRC card&#xff1f; CRC (Class-Responsibility-Collaborator) Card是目前比较流行的面向对象分析建模方法。在CRC建模中&#xff0c;用户、设计者、开发人员都有参与&#xff0c;完成对整个面向对象工程的设计。 CRC卡是一个标准索引卡集合&#xff0c;包括三个部分…

川藏线徒搭

http://www.mafengwo.cn/i/6296156.html

删数问题

Problem Description 键盘输入一个高精度的正整数n&#xff08;≤100位&#xff09;&#xff0c;去掉其中任意s个数字后剩下的数字按照原来的左右次序组成一个新的正整数。编程对给定的n与s&#xff0c;寻找一种方案&#xff0c;使得剩下的数字组成的新数最小。Input 输入有多组…

面试70问 经典回答

http://group.cnblogs.com/topic/37628.html

Mybatis整合spring

整合思路 1、SqlSessionFactory对象应该放到spring容器中作为单例存在。 2、传统dao的开发方式中&#xff0c;应该从spring容器中获得sqlsession对象。 3、Mapper代理形式中&#xff0c;应该从spring容器中直接获得mapper的代理对象。 4、数据库的连接以及数据库连接池事务…

最少拦截系统

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹…

云计算的理解

原文&#xff1a;http://www.chinacloud.cn/show.aspx?id15917&cid17 老叟发现&#xff0c;即使是一些搞计算机的人&#xff0c;也不了解“云”是什么。于是&#xff0c;俺卖车之余就写了一篇科普&#xff1a; 到底什么是云(云计算) 有很多关于云的介绍。然而&#xff0c;…

什么是Springmvc以及如果编写第一个入门程序

Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来,如下图&#xff1a; Springmvc处理流程 入门程序 创建web工程 springMVC是表现层框架&#xff0c;需要搭建web工程开发。 如下图创建动态web工程&#xff1a; 输入…

迷瘴

Problem Description 通过悬崖的yifenfei&#xff0c;又面临着幽谷的考验—— 幽谷周围瘴气弥漫&#xff0c;静的可怕&#xff0c;隐约可见地上堆满了骷髅。由于此处长年不见天日&#xff0c;导致空气中布满了毒素&#xff0c;一旦吸入体内&#xff0c;便会全身溃烂而死。幸好y…

驳斥《沙盒用于数据防泄密是重大技术原理性失误》

http://blog.ifeng.com/article/30786929.html 最近网上出现了一篇名为《沙盒用于数据防泄密是重大技术原理性失误》的文章&#xff0c;经作者鉴定&#xff0c;是某不良公司攻击技术领先的竞争对手苏州深信达公司的软文。该公司为何主动公开攻击竞争对手&#xff0c;可能和最近…

windows驱动开发学习

序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼.本人从事驱动开发时间不长也不短,大概也就3~4年时间.大多数人都认为会驱动开发的都是牛人,高手之类的.其实高…

Springmvc架构详解

框架结构 框架结构如下图&#xff1a; 架构流程 1、 用户发送请求至前端控制器DispatcherServlet 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3、 处理器映射器根据请求url找到具体的处理器&#xff0c;生成处理器对象及处理器拦截器(如果有则生成)一…

区间覆盖问题

用i来表示x坐标轴上坐标为[i-1&#xff0c;i]的长度为1的区间&#xff0c;并给出n&#xff08;1≤n≤200&#xff09;个不同的整数&#xff0c;表示n个这样的区间。 现在要求画m条线段覆盖住所有的区间&#xff0c;条件是&#xff1a;每条线段可以任意长&#xff0c;但是要求所…