为什么decltype(auto)未返回左值引用,加完美转发lambda后结果不同?
C++类型推导规则对应说明
1. 无lambda版本foo返回int的核心原因
你对decltype的基础规则存在误解:
decltype作用于无括号的纯变量名时,推导结果是变量的声明类型,而非根据表达式值类别推导的引用类型。这里a的声明类型是int,所以decltype(a)就是int,不是int&- 只有
decltype((a))(变量名额外包裹一层括号)时,才会按表达式的值类别推导:a是左值,所以decltype((a))结果为int&decltype(auto)作为返回值的推导规则为:直接将decltype(return后表达式)作为返回类型。无lambda版本中return的是无括号的变量a,所以返回类型推导为int,符合标准规则。
2. 加入完美转发lambda后返回int&的规则组合
该结果是「转发引用推导」+「std::forward规则」+「decltype(auto)推导」共同作用的结果:
2.1 转发引用的参数推导
调用identity(a)时,a是int类型的左值:
- 转发引用
auto&& i接收左值时,auto会被推导为int& - 参数
i的类型为int& &&,经过引用折叠后最终为int&
2.2 std::forward的返回值规则
std::forward<decltype(i)>(i)中模板参数为int&:
- 按照
std::forward的定义,模板参数为左值引用类型时,返回值就是对应类型的左值引用,即int&
2.3 外层foo的返回值推导
此时return后的表达式identity(a)是类型为int&的左值表达式:
decltype(auto)以decltype(identity(a))作为返回类型,结果为int&,与你观察到的结果一致。
额外提醒:第二个版本的foo返回了局部变量a的引用,属于悬垂引用,是未定义行为,实际开发中需要规避。
内容的提问来源于stack exchange,提问作者bradgonesurfing
相关产品推荐
相关产品推荐

