一、函数模板存在的类型问题

template<class T1,class T2>
void fun(T1 a, T2 b)
{(T1 or T2?)y = a + b;
}

语句y = a+b,其实我们并不知道y应该为什么类型,我们可以写成T1或者T2甚至可能是其类型。但是具体准确的写成哪一个呢?我们并不确定,因为用函数模板产生函数实体跟传入实参的类型有关,如果我们调用的时候是fun(int, double)那么按道理来说,结果应该是double,当然,如果我们用T1(在这里即int)也可以接收,只不过降低了结果的精确度。如果调用的时候是fun(short, int)那么结果准确类型的话,就是int类型的。甚至如果我们调用函数时fun(char , short),那么结果准确类型应该是int类型(在这里加法运算会导致自动整数提升),这个时候既不是T1类型,也不是T2类型。除此之外,我们可能重载结构体或者类的"+"运算符,这会导致结果的类型更复杂多变。
C++11提出decltype关键字来解决这个问题。

二、decltype关键字

1.decltype基本用法和作用

int main()
{int x = 10;decltype(x) y1;//int类型short a = 2;char b = 1;decltype(a + b) y2;//int类型double c = 1;decltype(x + c) y3;//double类型return 0;
}

相当于decltype会自动推演类型,这一点我觉得和auto挺相像的。
那么我们的模板类就可以写成下面这样。

template<class T1,class T2>
void fun(T1 a, T2 b)
{decltype(a+b) y = a + b;
}

这样y类型就是精确的类型了。
即decltype的使用格式是:decltype (expression) y;即定义一个变量y,类型和expression类型相同。expression可以是变量也可以是表达式。
编译器为了确定类型,会遍历一个核对表。

(1)如果expression是一个没有用括号括起来的标识符,则y与这个标识符类型相同。
举例:
int a;
decltype(a) y;
那么y就是和a类型相同,是int类型,包括const限定符。
举例:
const int a = 10;
decltype(a) y = 20;
decltype(a) y2(20);
注意上面decltype两种用法都可,但是一定得给初始值,因为y和y2也是const int类型,所以一定得给初始值。
(2)如果expression是一个左值并且用括号括起来了,那么y是这个标识符类型的引用。
举例:
int a;
decltype ((a)) y1(x1);
const int b = 10;
decltype((b)) y2(x2);
注意在这里y1就是类型为int& 类型的变量,x1是给y1初始化的,x1一定是个左值,且肯定不能是const。y2是类型为const int& 类型的变量,x2是给y2初始化的。
总结来说,expression再加个括号,那么decltype定义的变量类型就是expression类型的引用。引用我们都知道,一定需要初始化,初始化规则和我们平常使用引用初始化规则都一样。
(3)如果expression是一个函数调用,那么y与函数返回值类型相同,注意在这里并没有实施调用函数,只是编译器根据函数返回值类型推出来变量y应该的类型。
举例:
int fun(){return 0;}
decltype(fun()) y1;
decltype((fun())) y2;
注意y1和y2都是与fun函数返回类型相同的类型,即int。并不会因为多加了括号而变成int&。也就是上面的第二点对于函数并不适用。
(4)如果上面的都不符合,那么y和表达式expression类型相同。
举例:
int a = 10;
int& b = a;
int& c = a;
float d = 10;
decltype(a+b) y1;
decltype(b+c) y2;
decltype(a+d) y3;
a+b为int类型,所以y1是int类型。
b+c也是int类型,所以y2是int类型。
a+d是float类型,所以y3是float类型。
模板函数内部的变量类型用C++11新增的关键字decltype解决了。但是函数返回类型呢?
比如:

template<class T1,class T2>
? fun(T1 a,T2 b)
{return x + y;
}

函数返回值类型是什么?我们并不确定,刚才讲了decltype,难道可以这样写?:

template<class T1,class T2>
decltype(x+y) fun(T1 a,T2 b)
{return a + b;
}

答案是不行!因为此时还没有执行函数体,还不知道x和y变量,编译器看不见x和y,没办法使用。我们可以用auto。在这里auto是一个占位符,表示后置返回类型提供的类型。编译器会在编译期间将auto替换为正确类型。而decltype是关键字。这也是它们俩的不同点。

template<class T1,class T2>
auto fun(T1 a,T2 b)->decleype(x+y)
{return a + b;
}

这种写法是我在书上看的,但是我们其实不用这么麻烦,可以直接这样写:

template<class T1,class T2>
auto fun(T1 a,T2 b)
{return a + b;
}

因为auto是占位符,没有什么其他特殊作用,是编译器编译期间推导出来类型,将auto替换为了正确推导出来的类型。auto除了占位这个作用,其他事情都是编译器做的。
其实我们前面说的decltype做的事情,我们可以用auto占位,让编译器编译期间将auto替换掉。
比如:
int a = 10;
float b = 20;
auto x1 = a;
auto x2(a+b);
auto x2 = (a+b);
发现auto可以基本替代掉decltype的作用。只不过定义变量使用auto占位时,必须给出变量的初始值或者表达式,这样编译器才会有推导变量类型的依据,才能用正确类型替换掉占位符auto。

C++11新增的关键字decltype(auto)相关推荐

  1. C++14尝鲜:decltype 和 decltype(auto)

    decltype decltype是C++11新增的关键字,主要用于提取变量和表达式的类型. decltype的语法形式为:decltype(e),这里e是一个表达式,而decltype(e)是一个类 ...

  2. C++11 新增关键字decltype学习

    decltype 是 C++11 新增的一个关键字,它和 auto 的功能一样,都用来在编译时期进行自动类型推导. decltype 是"declare type"的缩写,译为&q ...

  3. 【C++】C++11新增关键字详解

    目录 一.auto 1.auto 用来声明自动变量,表明变量存储在栈(C++11之前) 2.auto用于推断变量类型示例(C++11) 3.声明或定义函数时作为函数返回值的占位符,此时需要与关键字 d ...

  4. C++起始(内联函数,宏的优缺点,const关键字,auto关键字(C++11)基于范围的for循环(C++11). 指针空值nullptr(C++11))

    内联函数 概念 以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销, 内联函数提升程序运行的效率 函数前增加inline关键字将其改成内联函数,在编 ...

  5. C/C++中涉及存储方式的关键字:auto,static,register,extern2009-01-22 11:23auto关键字:

    C/C++中涉及存储方式的关键字:auto,static,register,extern 2009-01-22 11:23 auto关键字: auto对象和变量被存储在栈中,它的生命周期仅存在于它的声 ...

  6. C++11新特性之decltype关键字的使用

    一.decltype关键字介绍 decltype关键字与auto关键字相似,但又有不同之处:auto关键字是在编译时通过已经初始化的变量来确定auto所代表的类型.换句话说,auto修饰的表达式必须是 ...

  7. C++11精要学习:decltype的功能与使用

    文章目录 获取表达式的类型 推导规则 返回类型后置 高级用法 获取表达式的类型 在编写程序的过程中,我们可能会有一种需求,就是希望可以根据一个变量的类型,来定义具有相同类型的变量.例如定义int x ...

  8. C++-关键字:auto

    C++98 auto 早在C++98标准中就存在了auto关键字,那时的auto用于声明变量为自动变量,自动变量意为拥有自动的生命期,这是多余的,因为就算不使用auto声明,变量依旧拥有自动的生命期: ...

  9. C++11新特性之decltype类型推导

    ​ 目录 一.decltype关键字 二.decltype的推导规则 1.表达式为单独变量 2.表达式为函数调用 3.表达式为左值,或者被()包围 三. decltype的应用 在前面一章,小编已经对 ...

最新文章

  1. 0x21.搜索 - 树与图的遍历、拓扑排序
  2. (三)WebGIS前端地图显示之根据地理范围换算出瓦片行列号的原理(核心)
  3. 【转】:Andriod开发环境搭建 (1)
  4. dede mysql x_认识Dede的mysql数据库结构功能
  5. Java扑克牌(多线程)
  6. 微信小程序_(表单组件)button组件的使用
  7. Java为什么能跨平台运行
  8. Linux64位steam,这下没得玩了! Steam无奈抛弃Linux用户
  9. c/c++_消除非标准警告
  10. 大快DKH大数据网络爬虫安装教程(详细图文步骤)
  11. pgpool-II3.1 的内存泄漏(五)
  12. 什么是编译性语言、解释性语言和脚本语言
  13. 推荐几个好的粉碎文件的软件?这3款软件让你彻底摆脱无法删除文件的烦恼
  14. 《看清你的思维图谱》读书笔记
  15. 建筑竞赛获奖项目解析国外教程
  16. 11款产品原型设计工具
  17. pytorch中保存、载入权重
  18. vulnhub Loly: 1
  19. 阿里的面试官都喜欢问哪些问题?
  20. Jlink使用技巧系列教程索引

热门文章

  1. 织梦wap.php绑定域名,dedecms织梦cms 手机站移动端 绑定设置独立M或wap域名的方法...
  2. [系统安全] 二十三.逆向分析之OllyDbg动态调试复习及TraceMe案例分析
  3. [数据库] MySQL基础知识之日期判断及添加排序序号
  4. 【数据结构与算法】之深入解析“单词接龙”的求解思路与算法示例
  5. SwiftUI之深入解析如何定制视图的动画和转场
  6. 中国大学MOOC 计算机组成原理第4章 测试(中)
  7. LDC1000学习资料
  8. 【STM32】随机数发生器相关函数和类型
  9. 【Linux网络编程】循环服务器之TCP模型
  10. [Qt教程] 第19篇 2D绘图(九)图形视图框架(上)