请看源码:

  struct __sfinae_types
{
typedef char __one;
typedef struct { char __arr[]; } __two;
};
template<typename _From, typename _To,
bool = __or_<is_void<_From>, is_function<_To>,
is_array<_To>>::value>
struct __is_convertible_helper
{ static constexpr bool value = is_void<_To>::value; }; template<typename _From, typename _To>
class __is_convertible_helper<_From, _To, false>
: public __sfinae_types
{
template<typename _To1>
static void __test_aux(_To1); template<typename _From1, typename _To1>
static decltype(__test_aux<_To1>(std::declval<_From1>()), __one())
__test(int); template<typename, typename>
static __two __test(...); public:
static constexpr bool value = sizeof(__test<_From, _To>()) == ;
}; /// is_convertible
template<typename _From, typename _To>
struct is_convertible
: public integral_constant<bool,
__is_convertible_helper<_From, _To>::value>
{ };

1.__is_convertible_helper是拥有三个模版参数的类模版,其中最后一个非类型模版参数有默认值。__or_<is_void<_From>, is_function<_To>, is_array<_To>>::value,只要其中任意一个为真,那么结果即为真。

2.__is_convertible_helper<_From, _To, false> 是__is_convertible_helper的偏特化,将bool的值设置为false,也就是说__or_<is_void<_From>, is_function<_To>, is_array<_To>>::value=false时,会转入此模版类。

3.对于为true的情况,is_void<_To>::value直接指示出类型是否可以转换。我们仔细分析一下:

a.is_void<_From>::value为true,则能否转换结果为is_void<_To>::value,from为void,to也为void即可转换。

b.如果is_array<_To>::value,is_function<_To>::value某个为true,则能否转换结果为is_void<_To>::value,在这里必然不能转换。

4.对于为false的情况,关键在于变长函数参数和sizeof表达式的妙用,如果没有这本书《C++设计新思维,泛型编程与设计模式之运用》我根本看不懂这些源码。

a. template<typename _From1, typename _To1> static decltype(__test_aux<_To1>(std::declval<_From1>()), __one()) __test(int);

__test()是一个函数,函数参数类型int,返回值由decltype推导而来,decltype里面是一个逗号表达式,如果__test_aux<_To1>(std::declval<_From1>())是有效的,那么decltype返回__one()的类型。

b.如果表达式是无效的,则__two __test(...)被选择。在编译时,我们可以知道这两个函数一个返回类型__one,一个返回类型__two,一个是单独char,一个是char数组长度为2

c.static constexpr bool value = sizeof(__test<_From, _To>(0)) == 1,调用函数,让编译器选择使用__test(int)还是__test(...),能进行类型转换就选择第一个,然后sizeof就返回值类型长度,指示出是否能进行转换。

一段示例代码,说明一些基本原理。

void convert(double)
{
cout<<"double..."<<endl;
} class H
{
public:
template <typename X> static decltype(convert(X()),string()) hello(int){cout<<"hello..."<<endl;return "c";}
template <typename > static char hello(...){cout<<"..."<<endl;return 'c';} }; int main()
{ cout<<"charSize:"<<sizeof(char)<<endl;
cout<<"stringSize:"<<sizeof(string)<<endl;
cout<<"--------------------"<<endl;
cout<<sizeof(H::hello<string>())<<endl;
cout<<sizeof(H::hello<long>())<<endl;
cout<<"--------------------"<<endl;
H::hello<string>();
H::hello<long>();
H::hello<int>();
H::hello<float>(); }

能转换的类型,sizeof输出8,不能呢过转换输出1,编译器根据语法规则选择哪个函数可以执行。

C++11 type_traits 之is_convertible源码分析的更多相关文章

  1. C++11 type_traits 之is_same源码分析

    请看源码: template<typename _Tp, _Tp __v> struct integral_constant { static const _Tp value = __v; ...

  2. C# DateTime的11种构造函数 [Abp 源码分析]十五、自动审计记录 .Net 登陆的时候添加验证码 使用Topshelf开发Windows服务、记录日志 日常杂记——C#验证码 c#_生成图片式验证码 C# 利用SharpZipLib生成压缩包 Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库

    C# DateTime的11种构造函数   别的也不多说没直接贴代码 using System; using System.Collections.Generic; using System.Glob ...

  3. 【Zookeeper】源码分析目录

    Zookeeper源码分析目录如下 1. [Zookeeper]源码分析之序列化 2. [Zookeeper]源码分析之持久化(一)之FileTxnLog 3. [Zookeeper]源码分析之持久化 ...

  4. Solr4.8.0源码分析(11)之Lucene的索引文件(4)

    Solr4.8.0源码分析(11)之Lucene的索引文件(4) 1. .dvd和.dvm文件 .dvm是存放了DocValue域的元数据,比如DocValue偏移量. .dvd则存放了DocValu ...

  5. 比特币源码分析--C++11和boost库的应用

    比特币源码分析--C++11和boost库的应用     我们先停下探索比特币源码的步伐,来分析一下C++11和boost库在比特币源码中的应用.比特币是一个纯C++编写的项目,用到了C++11和bo ...

  6. string源码分析 ——转载 http://blogs.360.cn/360cloud/2012/11/26/linux-gcc-stl-string-in-depth/

    1. 问题提出 最近在我们的项目当中,出现了两次与使用string相关的问题. 1.1. 问题1:新代码引入的Bug 前一段时间有一个老项目来一个新需求,我们新增了一些代码逻辑来处理这个新需求.测试阶 ...

  7. python基础-11 socket,IO多路复用,select伪造多线程,select读写分离。socketserver源码分析

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  8. 11.深入k8s:kubelet工作原理及源码分析

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 源码版本是1.19 kubelet信息量是很大的,通过我这一篇文章肯定是讲不全的,大家可 ...

  9. JDK源码分析(11)之 BlockingQueue 相关

    本文将主要结合源码对 JDK 中的阻塞队列进行分析,并比较其各自的特点: 一.BlockingQueue 概述 说到阻塞队列想到的第一个应用场景可能就是生产者消费者模式了,如图所示: 根据上图所示,明 ...

随机推荐

  1. Mybatis ,框架

    什么是mybatis MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis使用简单的XML ...

  2. Oracle恢复误删数据

    1.先查出被删除的时间点: select * from flashback_transaction_query where table_name='表名'; 2.根据时间点恢复数据: insert i ...

  3. 一站式学习Redis 从入门到高可用分布式实践

    1:redis 是用c语言来实现的,速度快 持久化 单线程 复杂的数据类型有bitmap和hyperloglog和geo地理信息2:高可用.分布式 v2.8开始支持Redis-Sentinel(哨兵) ...

  4. MySQL学习之用户管理

    用户权限管理 用户权限管理:在不同的项目中给不同的角色(开发者)不同的操作权限,为了保证数据库数据的安全. 简单点说:有的用户可以访问并修改这个数据,而有些用户只能去查看数据,而不能修改数据.就如同博 ...

  5. Java 创建线程的方式

    想必大家在Java面试中经常会被问到有关线程的问题,最常见的莫过于“Java有哪几种创建线程的方式呢?” 稍稍了解过,或者在日常开发中也都会用到以下几种方式: ①继承Thread类(真正意义上的线程类 ...

  6. vue的实例

    vue的实例 创建一个vue实例的写法和创建一个变量一样 var vm = new Vue{{ //我们一般用vm来接收vue的实例,vm是 ViewModel的缩写 }} 然后,我们就可以给vue实 ...

  7. 迪米特法则(LoD)

    如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用.如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用.其根本思想是类之间的松耦合. 类之间的耦合越弱,越有利于 ...

  8. s3c2440系统时钟详解

    一.S3C2440系统时钟体系 S3C2440的时钟控制逻辑可以外接晶振,然后通过内部电路产生时钟源:也可以直接使用内部提供的时钟源,他们通过引脚的设置来选择.时钟逻辑给整个芯片提供了3中时钟:FCL ...

  9. python学习笔记:第20天 多继承、MRO C3算法

    目录 一.多继承 二.旧式类的MRO 三.新式类的MRO 四.super 一.多继承 之前已经学习过了继承,当出现了x是⼀种y的的时候,就可以使⽤继承关系,即"is-a" 关系.在 ...

  10. Django学习之模拟架构页面跳转

    背景知识,需要有一定量的HTTP基础知识 在客户端游览器通过URL向服务端发送请求时,经历了两次过程.一次是URL向服务端发起请求,一次是服务端向客户端回发响应. 由图可知,客户端一共传递两个信息,一 ...