jac*_*k X 5 c++ language-lawyer c++17
#include <iostream>
struct Test{
Test(int& r):rf(r){
}
int& rf;
};
int main(){
int a = 0;
Test t(a);
decltype(t.rf) b;
}
Run Code Online (Sandbox Code Playgroud)
考虑上面的代码,编译器抱怨这样的代码格式错误,因为b它是引用类型并且没有被初始化。但是根据以下规则,我想知道为什么类型b是引用类型?
dcl.type.simple#4
对于表达式 e,由 decltype(e) 表示的类型定义如下:
- 如果 e 是命名结构化绑定 ([dcl.struct.bind]) 的无括号 id 表达式,则 decltype(e) 是结构化绑定声明规范中给出的引用类型;
- 否则,如果 e 是无括号的 id 表达式或无括号的类成员 access,则 decltype(e) 是由 e 命名的实体的类型。如果没有这样的实体,或者如果 e 命名了一组重载函数,则程序格式错误;
根据expr.ref#4段落所说:
如果 E2 被声明为具有“对 T 的引用”类型,则 E1.E2 是左值;E1.E2 的类型是 T。否则,以下规则之一适用。
这意味着 的类型t.rf是int。我不得不说 [expr.ref] 部分没有说是模糊的,E1.E2仍然是一个参考(表达式E1.E2表示的确切实体是什么?)。它只是说这样的表达式是lvalue,它的类型是引用所指的。
我只在[expr]中找到了一个特殊的规则,那就是:
expr#5
如果一个表达式最初具有类型为“参照T”([dcl.ref],[dcl.init.ref]),类型被调节至T任何进一步分析之前。表达式指定由引用表示的对象或函数,表达式是左值或 x 值,具体取决于表达式。[?注意:在引用的生命周期开始之前或结束之后,行为是未定义的(参见 [basic.life])。?—?尾注?]
是不是说在分析表达式之前t.rf,既然rf是“引用T”的类型,就应该调整为int这样的表达式,即rf指定a它所指的对象。
那么,根据以上这些规则,结果decltype(t.rf)应该是int,为什么编译器认为它是int&?
如果 E2 被声明为具有“对 T 的引用”类型,则 E1.E2 是左值;E1.E2 的类型为 T。否则,适用以下规则之一。
这意味着 t.rf 的类型是 int。
实际上,这意味着表达式 的类型t.rf是 int(类别是左值)。但是命名实体的类型——它是类成员——仍然是对 int 的左值引用,因此这是由decltype(t.rf).
E2 在上下文中定义如下:
[expr.ref]
将 postfix-expression.id-expression 缩写为 E1.E2,...
实体定义为:
[基本.pre]
实体是值、对象、引用、结构化绑定、函数、枚举器、类型、类成员、位域、模板、模板特化、命名空间或包。
实体列表不包括表达式。E2 不是实体。它是一个命名(表示)实体的表达式。