基本信息
文件名称:详解C++17中的decltype类型推导.docx
文件大小:19.01 KB
总页数:8 页
更新时间:2025-05-21
总字数:约5.25千字
文档摘要

详解C++17中的decltype类型推导

目录引子标准演进C++11C++14放宽对不完整类型的限制decltype(auto)C++17总结

引子

在编程过程中,有时我们需要根据表达式的类型来声明变量,尤其是在涉及模板编程和泛型编程时,经常会遇到这样的问题:(1)、有些泛型类型由模板参数决定,但是却很难或根本无法表示;(2)、需要在编译时确定变量的类型。

除此之外,我们知道auto在自动类型推导时,会忽略类型的修饰符。如此会导致auto推导的类型会与原表达式的类型存在不一致问题。

为了更好的解决这些问题,从C++11标准开始,C++引入了decltype关键字,其作用是让编译器在编译时识别表达式的类型,方便的的进行类型推导,同时也解决泛型编程和模板编程中变量类型表示的问题。

标准演进

decltype是declaretype的缩写。C++11标准引入了decltype的核心功能和推导规则,C++11以后的各标准都本别对C++11自定的规则进行扩容和改进。具体演进过程如下所示:

C++11:引入关键字,并引入decltype的核心功能,用于根据表达式推导出变量的类型;C++14:引入两个重要改进引入decltype(auto)语法,此语法可用于函数返回值类型的推导。基于decltype(auto)语法,函数的返回值类型可通过函数体的返回值表达式来推导,从而简化函数返回值类型的声明。放宽了对不完整类型的限制:在C++11中,如果decltype推导的表达式结果是一个不完整类型,那么会导致编译错误。而在C++14中,对不完整类型的处理更加宽松,允许使用decltype推导不完整类型的变量。C++17:decltype(atuo)支持非类型模板形参占位符。

C++11

引入关键字,并引入decltype的核心功能,用于根据表达式推导出变量的类型;当使用decltype(e)推导表达式e(类型为T)的类型时,C++11标准定义decltype的推导规则如下:

如果是一个未加括号的标识符表达式或类成员访问,那么decltype(e)的推导结果为e类型T;假如不存在这样的实体或e是一组重载函数,那么decltype(e)无法推导。而且推导过程const/volatile限定符会被忽略;如果e是一个可调用对象,那么decltype(e)推导为可调用对象返回值的类型;如果e是一个左值,decltype(e)推导为T。const/volatile限定符不能忽略;如果e是一个将亡值,decltype(e)推导为T,const/volatile限定符不可忽略;如decltype(e)无法命中上述4情况,decltype(e)将会推导为e的类型T;

为了让大家更形象的理解这5条规则,下面我们通过一些示例来说明这五条推导规则。

示例1:未加括号标识符表达式

intx=42;

decltype(x)y;//推导结果是int,满足第1条规则

示例2:加括号的标识符表达式

intx=42;

decltype((x))y=x;//推导结果是int,满足第三条规则

示例3:未加括号的类成员访问

structMyClass{

intmember;

constMyClassobj;

decltype(obj.member)result=obj.member;//推导结果是int,忽略const/volatile限定符,满足第1条规则

示例4:加括号的类成员访问

structMyClass{

intmember;

constMyClassobj;

decltype((bj.member))result=obj.member;//推导结果是constint,const/volatile限定符不能忽略,满足第3条规则

示例5:可调用对象表达式

intadd(inta,intb)

returna+b;

decltype(add(1,2))result;//推导结果是int,满足第2条规则

示例6:将亡值

intx=42;

decltype(std::move(x))result=std::move(x);//推导结果为int,std::move(x)为将亡值

示例7:右值表达式

intx=42;

decltype(x+1)result;//推导结果是int(右值表达式x+1的类型是int)

示例8:右值引用变量