C++11的std::is_same和std::decay使用与源码解析
C++11的std::is_same和std::decay源码解析
- 1、源码准备
- 2、使用方法
- 2.1、std::is_same使用方法
- 2.2、std::decay使用方法
- 2.3、std::is_same和std::decay配合使用
- 3、源码解析
- 3.1、std::is_same源码解析
- 3.2、std::decay源码解析
- 4、总结
1、源码准备
本文是基于gcc-4.9.0的源代码进行分析,std::is_same和std::decay是C++11才加入标准的,所以低版本的gcc源码是没有这个的,建议选择4.9.0或更新的版本去学习,不同版本的gcc源码差异应该不小,但是原理和设计思想的一样的,下面给出源码下载地址
http://ftp.gnu.org/gnu/gcc
2、使用方法
std::is_same
和std::decay
是C++11新增的两个模板类,功能分别是类型判断和类型朽化。
2.1、std::is_same使用方法
首先通过一个例子看一下std::is_same
的使用方法:
#include <iostream>
#include <type_traits>
#include <stdint.h>int main(int argc, char* argv[])
{std::cout << "第一组,类型的写法完全相同" << std::endl;std::cout << std::is_same<int, int>::value << std::endl; // truestd::cout << std::is_same<double, double>::value << std::endl; // truestd::cout << std::is_same<int32_t, int32_t>::value << std::endl; // truestd::cout << std::is_same<int64_t, int64_t>::value << std::endl; // truestd::cout << std::endl << "第二组,类型相同,但是写法不同(typedef重命名了)" << std::endl;std::cout << std::is_same<short, int16_t>::value << std::endl; // truestd::cout << std::is_same<int, int32_t>::value << std::endl; // truestd::cout << std::is_same<long, int64_t>::value << std::endl; // truestd::cout << std::is_same<unsigned int, uint32_t>::value << std::endl; // truestd::cout << std::endl << "第三组,类型不同" << std::endl;std::cout << std::is_same<char, int>::value << std::endl; // falsestd::cout << std::is_same<double, float>::value << std::endl; // falsestd::cout << std::is_same<float, long>::value << std::endl; // falsestd::cout << std::is_same<double, char>::value << std::endl; // falsestd::cout << std::endl << "第四组,类型其实是一样的,只是省略写法而已" << std::endl;std::cout << std::is_same<char, signed char>::value << std::endl; // falsestd::cout << std::is_same<char, unsigned char>::value << std::endl; // falsestd::cout << std::is_same<short, signed short>::value << std::endl; // truestd::cout << std::is_same<int, signed int>::value << std::endl; // truestd::cout << std::endl << "第五组,类型不同" << std::endl;std::cout << std::is_same<char*, char[]>::value << std::endl; // falsestd::cout << std::is_same<const char, char>::value << std::endl; // falsestd::cout << std::is_same<const char&, const char>::value << std::endl; // falsestd::cout << std::is_same<const int&, int>::value << std::endl; // false
}
上面的结果中,前三组应该是没啥歧义的,因为std::is_same
是可以识别出被typedef
、define
重命名的类型的原始类型的。第四组就有点意思了,除了前面两个以外都是true,说明std::is_same
是可以判断出signed
和signed+类型
是相同的。第五组的话也没什么好说的,类型确实不同。
这里解释一下,从上面的代码中看得出来,
char
既不是unsigned char
也不是signed char
,char
的表达数值范围可能等同于signed char
,也可能等同于unsigned char
,这取决于编译器,一般是等同于signed char
,但这仅仅是范围等同,就像32位机上int
和long
的数值范围是一样的,但并不是同一个类型。
2.2、std::decay使用方法
std::decay
人如其名,就是朽化的意思,主要是对一个类型进行朽化处理,说白一点就是将类型的一些属性比如const
、volatile
、&
(引用)等消除掉,需要注意指针是消不掉。首先通过一个例子看一下std::decay
的使用方法:
#include <iostream>
#include <type_traits>
#include <stdint.h>int main(int argc, char* argv[])
{const int a = 10l;// 报错,const修饰的不能改变//a = 10;std::decay<const int>::type b = 101;// 可以修改b = 10;
}
从上面的例子可以看出经过std::decay
处理之后,const int
的const
属性就没了,这就是std::decay
的一个典型用法
2.3、std::is_same和std::decay配合使用
代码如下,可以看到,经过std::decay
朽化之后,原本使用std::is_same
判断不相同的类型也变得相同了,这里需要注意的是直接使用std::is_same
去判断char*
和char[]
,显示是不相同的,但是经过朽化之后这两个就变得相同了,这个情况原理在后面会讲。
#include <iostream>
#include <type_traits>
#include <stdint.h>int main(int argc, char* argv[])
{std::cout << std::is_same<std::decay<int>::type, std::decay<int>::type>::value << std::endl; // truestd::cout << std::is_same<std::decay<const int>::type, std::decay<int>::type>::value << std::endl; // truestd::cout << std::is_same<std::decay<int&>::type, std::decay<int>::type>::value << std::endl; // truestd::cout << std::is_same<std::decay<const int>::type, std::decay<const volatile int>::type>::value << std::endl; // truestd::cout << std::is_same<std::decay<const volatile int&>::type, std::decay<int>::type>::value << std::endl; // truestd::cout << std::is_same<std::decay<char*>::type, std::decay<char[]>::type>::value << std::endl; // true
}
3、源码解析
3.1、std::is_same源码解析
std::is_same
位于libstdc++-v3\include\std\type_traits
中
template<typename, typename>
struct is_same : public false_type { };template<typename _Tp>
struct is_same<_Tp, _Tp> : public true_type { };
可以看到,代码非常简单,第一个是泛化形式,第二个是偏特化形式,当两个类型相同时,调用的是第二个,而第二个继承的是true_type
,所以此时is_same<_Tp, _Tp>::value
的值就是true
;相反的,当两个类型不同时,调用第一个,此时is_same<_Tp, _Tp>::value
的值就是false
。
3.2、std::decay源码解析
std::decay
位于libstdc++-v3\include\std\type_traits
中
template<typename _Tp>
class decay
{ typedef typename remove_reference<_Tp>::type __remove_type;public:typedef typename __decay_selector<__remove_type>::__type type;
};
可以看到,首先使用了std::remove_reference
将_Tp
的引用属性去除了,关于std::remove_reference
的内容之前在这篇文章《C++11的右值引用、移动语义(std::move)和完美转发(std::forward)详解》中有讲过,这里就不赘述了,大家可以自己去看一下。然后使用了std::__decay_selector
,下面看一下std::__decay_selector
的源码
template<typename _Up, bool _IsArray = is_array<_Up>::value,bool _IsFunction = is_function<_Up>::value>
struct __decay_selector;template<typename _Up>
struct __decay_selector<_Up, false, false>
{ typedef typename remove_cv<_Up>::type __type; };template<typename _Up>
struct __decay_selector<_Up, true, false>
{ typedef typename remove_extent<_Up>::type* __type; };template<typename _Up>
struct __decay_selector<_Up, false, true>
{ typedef typename add_pointer<_Up>::type __type; };
可以看到共有三种偏特化形式:
- 第一种就是当
_Up
既不是数组形式也不是可调用实体形式时匹配,使用了std::remove_cv
去除了_Up
的const
和volatile
属性。关于std::remove_cv
可以看一下这篇文章《C++11的std::ref、std::cref源码解析》,里面有详细介绍 - 第二种就是当
_Up
是数组时匹配,使用了std::remove_cv
去除了_Up
的数组属性,只留下个数组名指针,这就是为什么前面使用std::decay
之后char*
和char[]
会显示相同的原因了。
template<typename _Tp>
struct remove_extent
{ typedef _Tp type; };template<typename _Tp, std::size_t _Size>
struct remove_extent<_Tp[_Size]>
{ typedef _Tp type; };template<typename _Tp>
struct remove_extent<_Tp[]>
{ typedef _Tp type; };
- 第三种就是当
_Up
是可调用实体时匹配,使用了std::add_pointer
去除了_Up
的引用属性,代码与前面的那些原理是一样的,这里就不细讲了,大家可以自己去看一下源代码的实现。
综上可得std::decay
其实就是利用模板特化机制来实现对类型进行筛选,将原始的、没有经过其它属性修饰的类型提取出来,以达到朽化类型的作用。
4、总结
本文先是介绍了C++11新增的std::is_same
和std::decay
这两个模板类的作用与使用方法,然后通过对源码进行分析,我们知道了这两个模板类的实现其实并不复杂,都是借助了模板特化机制来实现的,其实不止这两个,C++标准库的type_traits
文件里面的内容基本都是使用类似的方法来实现的。
最后,如果大家觉得本文写得好的话麻烦点赞收藏关注一下谢谢,也可以关注该专栏,以后会有更多优质文章输出的。
C++11的std::is_same和std::decay使用与源码解析相关推荐
- C++的std::is_same与std::decay
一.背景 有一个模板函数,函数在处理int型和double型时需要进行特殊的处理,那么怎么在编译期知道传入的参数的数据类型是int型还是double型呢? #include <iostream& ...
- The Wide and Deep Learning Model(译文+Tensorlfow源码解析) 原创 2017年11月03日 22:14:47 标签: 深度学习 / 谷歌 / tensorf
The Wide and Deep Learning Model(译文+Tensorlfow源码解析) 原创 2017年11月03日 22:14:47 标签: 深度学习 / 谷歌 / tensorfl ...
- 面试官系统精讲Java源码及大厂真题 - 11 HashSet、TreeSet 源码解析
11 HashSet.TreeSet 源码解析 更新时间:2019-09-16 19:37:35 成功的奥秘在于目标的坚定. --迪斯雷利 引导语 HashSet.TreeSet 两个类是在 Map ...
- [源码解析] 深度学习分布式训练框架 horovod (11) --- on spark --- GLOO 方案
[源码解析] 深度学习分布式训练框架 horovod (11) - on spark - GLOO 方案 文章目录 [源码解析] 深度学习分布式训练框架 horovod (11) --- on spa ...
- 学生HTML个人网页作业作品 ~ 超级英雄11页面网页设计成品~ 学生网页设计作业源码
学生HTML个人网页作业作品 ~ 超级英雄11页面网页设计成品~ 学生网页设计作业源码 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从下手?网页要求的总数量 ...
- Apache IoTDB源码解析(0.11.2版本):Session的源码解析
1. 声明 当前内容主要为解析Apache IoTDB 0.11.2版本的Session的源码解析 通过前面的Apache Thrift的Demo,可以发现iotdb中的server是使用了thrif ...
- C++演示std :: sort(),std :: reverse()的函数(附完整源码)
@[TOC](C++演示std :: sort(),std :: reverse()的函数) C++演示std :: sort(),std :: reverse()的函数完整源码(定义,实现,main ...
- Linux0.11内核源码解析-setup.s
学习资料: Linux内核完全注释 操作系统真像还原 极客时间-Linux内核源码趣读 Linux0.11内核源码 ->setup程序将system模块从0x10000~0x8ffff整块向下移 ...
- Linux0.11内核源码解析-bootsect.s
学习资料: Linux内核完全注释 操作系统真像还原 极客时间-Linux内核源码趣读 Linux0.11内核源码 ->上电 ->80x86架构CPU会自动进入实模式 ->从地址0x ...
- 阿里 双11 同款,流量防卫兵 Sentinel go 源码解读
作者 | 于雨 apache/dubbo-go 项目负责人 本文作者系 apache/dubbo-go 项目负责人,目前在 dubbogo 项目中已内置可用 sentinel-go,如果想单独使用可 ...
最新文章
- 2022-2028年中国塑料网格板行业市场行情动态及发展趋向分析报告
- 【linux】Valgrind工具集详解(九):Memcheck检查的内容和方法
- iOS中UISearchBar(搜索框)使用总结
- 去除菜单项的加速键--‘’符号
- JQuery-Table斑马线
- JQuery七个常犯的错误
- Java包装类型对象比较相等性注意事项
- 刷题记录 kuangbin带你飞专题五:并查集
- ppp协议 服务器,详解PPP及PPPoE协议
- 深度解析《软文广告经典案例300》
- 『IT视界』 [原创评论]揪出"程序员"身上的"六宗罪"
- MySQL数据库安全配置规范操作
- SpringCloud学习一
- HTML+CSS静态页面网页设计作业——我的家乡-四川成都(4页) HTML+CSS+JavaScript
- 工作篇 之 解决谷歌地图与 NestedScrollView 滑动冲突
- 虚拟机DEDECMS织梦建站
- 【MATLAB】理解采样频率和信号频率的关系
- 下载工具:aria2c
- 虚拟天文台主节点成功上云
- 帕斯卡分布/负二项分布
热门文章
- win10默认壁纸_Win10系统待机锁频壁纸怎么提取?
- Hou的图像显著性计算模型
- android 跳转公众号,app直接跳转公众号
- 湘潭大学 计算机学院程诗婕,2019 CCF CCSP分赛区竞赛决出金银铜奖
- CorelDRAW_X6使用汇总
- 学习笔记 - excel筛选分组
- [学习报告]《LeetCode零基础指南》(第五讲) 指针-gyro
- 终于!疫情之下,第一批企业没能熬住面临倒闭,员工被遣散,没能等来春暖花开!
- excel两列数据对比找不同_对比excel,轻松学习python数据分析
- WinPE (老毛桃最终修改版) V09.11 硬盘安装操作系统详细图解