Fer*_*eak 21 c++ decltype language-lawyer c++14
鉴于:
decltype(auto) f1()
{
int x = 0;
return x; // decltype(x) is int, so f1 returns int
}
decltype(auto) f2()
{
int x = 0;
return (x); // decltype((x)) is int&, so f2 returns int&
}
Run Code Online (Sandbox Code Playgroud)
(摘自Scott Meyer的Effective Modern C++).
现在,如果我找到了正确的段落,则第7.1.5.2节 C++标准的简单类型说明符[dcl.type.simple]说:
如果e是id-expression或类成员访问(5.2.5 [expr.ref]),则decltype(e)被定义为由e命名的实体的类型
而该部分的例子是:
struct A { double x; }
const A* a = new A();
decltype((a->x)); // type is const double&
Run Code Online (Sandbox Code Playgroud)
现在,我想知道为什么被decltype((x))推断出来是int&在书中.
Tar*_*ama 10
相关标准引用如下:
N4140 [dcl.type.simple]/4:对于表达式e,表示的类型decltype(e)定义如下:
- 如果e是未加密码的id-expression或未加括号的类成员访问(5.2.5),
decltype(e)则是名为的实体的类型e.如果没有这样的实体,或者如果e命名了一组重载函数,那么该程序就会形成错误;- 否则,如果
e是decltype(e)x值T&&,T则是e的类型;- 否则,如果
e是左值,decltype(e)是T&,这里T是e的类型 ;- 否则,
decltype(e)是的类型e.
由于x是一个左值,并且表达括弧,则第三个规则使用,所以decltype((x))是int&.
decltype 返回变量的声明类型,或表达式的"类型"(添加一些引用以指示l/r值).
这使它可用于两个不同的目的.有时这会造成混乱,但事实就是如此.
令牌x是一个变量.变量的类型是int.
令牌(x)是不变量,而是含有只是一个变量(真微不足道)的表达.因此,表达式的类型(由decltype确定)(x)是int&.
表达式的类型x(如果你可以说服decltype给你;你不能)也是int&,但是decltype(ACTUAL_VAR_NAME)评估变量类型的规则是"胜利".
现在,以上都不是真的.实际的事实是标准的引用,它描述了编译器应该通过哪些步骤来确定decltype返回的类型.但这是一个有效的谎言,一个(如果标准的措辞证明有错误)可能表明标准在它不同意时有一个错误.
§7.1.6.4[dcl.spec.auto](草案n3797)
- ...如果占位符是decltype(auto)类型说明符,则函数的声明类型或函数的返回类型应仅为占位符.根据7.1.6.2中的描述确定为变量或返回类型推导出的类型,就好像初始化器是decltype的操作数一样.
§7.1.6.2[dcl.type.simple]
- 对于表达式e,由decltype(e)表示的类型定义如下:
- 如果e是未表示的id-expression或未加密的类成员访问(5.2.5),则decltype(e)是e命名的实体的类型.如果没有这样的实体,或者e命名了一组过载的功能,那么该程序就会形成错误;
- 否则,如果e是x值,则decltype(e)是T &&,其中T是e的类型;
- 否则,如果e是左值,则decltype(e)是T&,其中T是e的类型;
- 否则,decltype(e)是e的类型
xis是一个未加括号的id-expression,因此返回类型推导为以下类型x:int
(x)是不是一个未加括号标识表达,这样的规则并不适用.但是,它是一个(带括号的)左值表达式.因此推导出的类型是T&其中T是的类型x:int&
[dcl.spec.auto]/7强制要求,粗略地说,返回类型是通过应用于语句中decltype的表达式获得的return.因此,正如评论所暗示的那样,我们正在寻找decltype((x)).恶魔般的规则介入:
需要注意的是,因为表达式的第一点不适用的括号.因此,我们得到int&.
decltype普通标识符和括号标识符的应用之间的区别在相应论文的修订版6中引入.参见修订版5,§2.3:
表示的类型
decltype(e)定义如下:
- 如果
e是形式(e1),decltype(e)则定义为decltype(e1).
这背后的理由大概如下:编写(x),程序员打算decltype不将操作数视为名称而是表达式 - 考虑其值类别.
| 归档时间: |
|
| 查看次数: |
974 次 |
| 最近记录: |