请看源码:

  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. 关于最新版AFNetworking(3.0)上传多张图片的问题

    最新版的AF已经废弃了很多以前的类,所以很多以前的方法都不能用了,当然最主要还是为了适应ipV6所做的更改.楼主最近正在写多张图片上传,碰到了一些问题,解决之后直接封装了一个方法,废话有点多了,上代码 ...

  2. HDU 1017A Mathematical Curiosity (暴力统计特殊要求个数)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1017 A Mathematical Curiosity Time Limit: 2000/1000 M ...

  3. ios Block详细用法

    ios Block详细用法 ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数的 ...

  4. flume data to hdfs

    flume 开发梳理 flume 数据到hadoop conf/hdfsAgent.conf #配置sources.channels.sinks a1.sources=r1 a1.channels=c ...

  5. 从C语言的volatile关键字,了解C#的volatile机制(转载)

    C#中有一个关键字volatile,一直不太明白到底什么时候才用它,只知道在多线程操作同一个变量的时候要使用volatile关键字,下面看到了一篇C语言关于volatile关键字的介绍,写的很不错,其 ...

  6. UCOS阅读问题累积

    1.#ifdef __cplusplus   extern "C" {  #endif 作用: 一般用于将C++代码以标准C形式输出(即以C的形式被调用),这是因为C++虽然常被认 ...

  7. 关于sharepoint如何做SSO,如何做OOS监视编辑

    应客户需求,需要做sharepoint SSO,以前都是默认的AD验证,如果客户已经有一套SSO系统,验证过SSO之后就能自动登录,而不是浏览器上设置保存用户名密码的AD登陆. 怎么做呢? 首先sha ...

  8. Spring知识点小结汇总

    Spring部分 1.谈谈你对spring IOC和DI的理解,它们有什么区别? IoC Inverse of Control 反转控制的概念,就是将原本在程序中手动创建UserService对象的控 ...

  9. MySQL数据库修改数据表类型(引擎)的方法

    MySQL数据库使用事务,相关数据表必须为InnoDB引擎 查看数据表状态: SHOW TABLE STATUS FROM wawa WHERE NAME='ww_invite_code_temp'; ...

  10. mysql学习记录,CASE WHEN THEN ELSE END用法

    记mysql,case when then else end用法 用法1:搜索函数 SELECT r.order_no, r.golds, r.pay_tool, , ) ) END AS price ...