#include <iostream>
struct Test{
Test(int& r):rf(r){
}
int& rf;
};
int main(){
int a = 0;
Test t(a);
decltype(t.rf) b;
}
考虑上面的代码,编译器抱怨这样的代码是不规范的 https://godbolt.org/z/EzEqEx, 因为b
是引用类型并且没有被初始化。但是根据以下规则,我想知道为什么类型b
是引用类型吗?
dcl.type.simple#4 https://timsong-cpp.github.io/cppwp/n4659/dcl.type.simple#4
对于表达式 e,decltype(e) 表示的类型定义如下:
- 如果 e 是命名结构化绑定 ([dcl.struct.bind]) 的无括号 id 表达式,则 decltype(e) 是结构化绑定声明规范中给出的引用类型;
- 否则,如果 e 是不带括号的 id 表达式或不带括号的类成员访问, decltype(e) 是e 命名的实体的类型。如果不存在这样的实体,或者如果 e 命名了一组重载函数,则该程序是格式错误的;
并根据段落内容表达式参考#4 https://timsong-cpp.github.io/cppwp/n4659/expr.ref#4 says:
如果 E2 声明为具有类型“引用 T”,则 E1.E2 是左值;E1.E2的类型为T。否则,适用以下规则之一。
这意味着类型t.rf
is int
。我不得不说 [expr.ref] 部分没有说,这是含糊的,E1.E2
仍然是一个参考(表达式的确切实体是什么E1.E2
表示?)。只是说这样的表达是lvalue
它的类型就是引用所指的类型。
我只在[expr]中找到了一个特殊的规则,那就是:
expr#5 https://timsong-cpp.github.io/cppwp/n4659/expr#5
如果表达式最初具有“对 T 的引用”类型([dcl.ref]、[dcl.init.ref]),则类型将调整为 T在进行任何进一步分析之前. 表达式指定引用所表示的对象或函数,并且表达式是左值或x值,具体取决于表达式。 [ 注意:在引用的生命周期开始之前或结束之后,行为是未定义的(请参阅[basic.life])。 ——《尾注》
这是否意味着在分析表达式之前t.rf
, since rf
类型为“reference to T”,应调整为int
以及这样的表达式,即rf
指定a
它所指的。
所以,根据上述规则,结果decltype(t.rf)
应该int
,为什么编译器认为它是int&
?
如果 E2 被声明为“对 T 的引用”类型,则 E1.E2 是左值; E1.E2 的类型为 T。否则,适用以下规则之一。
这意味着t.rf的类型是int。
事实上,这意味着该类型表达 t.rf
是 int (类别是左值)。但命名的类型entity- 这是类成员 - 仍然是对 int 的左值引用,因此这是由decltype(t.rf)
.
E2 在上下文中定义如下:
[expr.ref]
将 postfix-expression.id-expression 缩写为 E1.E2,...
实体定义为:
[基础.预]
实体是值、对象、引用、结构化绑定、函数、枚举器、类型、类成员、位字段、模板、模板专业化、命名空间或包。
实体列表不包括表达式。 E2不是一个实体。它是命名(表示)实体的表达式。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)