且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

有关提名数据成员为引用类型时类成员访问的问题

更新时间:2023-01-17 17:44:40



如果E2被声明为对T的引用类型,则E1.E2为左值; E1.E2的类型为T。否则,将应用以下规则之一。


这意味着t.rf的类型为int。


实际上,这表示表达式 t.rf 的类型>是整数(类别是左值)。但是名为 entity 的类型(它是类成员)仍然是对int的左值引用,因此是 decltype(t.rf)$给出的类型。 c $ c>。


E2在上下文中的定义如下:


[expr.ref]


将postfix-expression.id-expression缩写为E1.E2,...


实体定义为:


[basic.pre]


实体是值,对象,引用,结构化绑定,函数,枚举数,类型,类成员,位域,模板,模板专业化,名称空间或包。


实体列表不包含表达式。 E2不是实体。这是一个命名(表示)实体的表达式。


#include <iostream>
struct Test{
    Test(int& r):rf(r){

    }
    int& rf;
};
int main(){
   int a = 0;
   Test t(a);
   decltype(t.rf) b;  
}

Consider the above code, the compiler complains such a code is ill-formed, because b is of reference type and it's not be initialized. However according to the following rules, I wonder why the type of b is a reference type?
dcl.type.simple#4

For an expression e, the type denoted by decltype(e) is defined as follows:

  • if e is an unparenthesized id-expression naming a structured binding ([dcl.struct.bind]), decltype(e) is the referenced type as given in the specification of the structured binding declaration;
  • otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access, decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;

And according to what the paragraph expr.ref#4 says:

If E2 is declared to have type "reference to T", then E1.E2 is an lvalue; the type of E1.E2 is T. Otherwise, one of the following rules applies.

It means that the type of t.rf is int. I have to say it is vague that the section [expr.ref] does not say, E1.E2 is still a reference(what is the exactly entity the expression E1.E2 denotes?). It just say such an expression is lvalue and its type is what the reference refer to.

I only find a special rule in [expr], that is:
expr#5

If an expression initially has the type "reference to T" ([dcl.ref], [dcl.init.ref]), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression. [ Note: Before the lifetime of the reference has started or after it has ended, the behavior is undefined (see [basic.life]).  — end note ]

Does it mean that before analyzing the expression t.rf, since rf has the type "reference to T", it should be adjusted to int and such an expression, namely rf designates a to which it refers.

So, According to these above rules, the result of decltype(t.rf) should be int, why the compiler consider it as int&?

if E2 is declared to have type "reference to T", then E1.E2 is an lvalue; the type of E1.E2 is T. Otherwise, one of the following rules applies.

It means that the type of t.rf is int.

Indeed, it means that the type of the expression t.rf is int (and category is lvalue). But the type of the named entity - which is the class member - is still lvalue reference to int and hence that is the type given by decltype(t.rf).

E2 is defined in the context as such:

[expr.ref]

Abbreviating postfix-expression.id-expression as E1.E2, ...

Entity is defined as:

[basic.pre]

An entity is a value, object, reference, structured binding, function, enumerator, type, class member, bit-field, template, template specialization, namespace, or pack.

The list of entities doesn't include expressions. E2 is not an entity. It is an expression that names (denotes) an entity.