Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A issue about the class member access while the nominated data member is of reference type

#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&?

like image 903
xmh0511 Avatar asked Aug 31 '20 02:08

xmh0511


1 Answers

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.

like image 176
eerorika Avatar answered Nov 14 '22 23:11

eerorika