Deferencing pointer leads to using the value of the object indirectly. But I've never really understood what does the "using" means. I started to think the question until my compiler yield an error for the following code
int i = 0, *pi = &i;
decltype(*pi) c; // error: 'c' declared as reference but not initialized.
I looked at the error for a very long time and searched some questions I can only give out the following arguments. I don't know if they are correct or not.
Arguments 1:
1) *p
is an expression that is not a variable (or non-variable expression)
2) dereferencing pointer expression yields a reference, we are in fact using a reference to access the value of the object
Arguments 2:
the dereferencing expression only for which decltype
returns a reference, it is not a general case
Please points out any incorrectness or inaccurate descriptions of the above arguments.
Dereferencing a pointer yields an lvalue expression of the pointed-to type designating the object or function pointed to. It does not yield a reference.* *pi
is an lvalue of type int
.
decltype
(with an exception not relevant here) reports both an expression's type and its value category, the latter being encoded with reference types. Since *pi
is an lvalue, it's encoded as an lvalue reference type, so decltype(*pi)
is int &
: int
for the type, &
for the value category.
Expressions never have reference type because any referenceness is adjusted away "prior to any further analysis".
* This isn't a merely technical distinction: per the direction of core issue 232 and core issue 453, there are valid dereference expressions you can write where binding its result to a reference would cause undefined behavior.
To answer your title question: as T.C. answered too, no. Expressions never have reference type. Given an int a; int &b = a;
, both the expression a
and the expression b
have type int
, and both expressions are lvalues.
1) *p
is an expression that is not a variable (or non-variable expression)
Correct.
2) dereferencing pointer expression yields a reference, we are in fact using a reference to access the value of the object
Dereferencing a pointer gives an lvalue, which decltype
changes into an lvalue reference.
the dereferencing expression only for which decltype returns a reference, it is not a general case
I'm not entirely sure what you mean here. If you mean that when decltype
doesn't produce a reference, having a declaration decltype(...) c;
without an initialiser can be valid, then yes, indeed. If you mean that aside from dereferenced pointers, decltype
never produces a reference type, then no. For instance,
int a;
decltype((a)) b; // not okay - decltype((a)) is int & because (a) is not the name of the
// variable, and the expression (a) is an lvalue
decltype(a) c; // okay - decltype(a) is int because a is the name of the variable
decltype(+a) d; // okay - decltype(+a) is int because the +a is a prvalue of type int
As a matter of fact, standard says following in 8.5.2.1:
The unary * operator performs indirection: the expression to which it
is applied shall be a pointer to an object type, or a pointer to a
function type and the result is an lvalue referring to the object or
function to which the expression points. If the type of the expression
is “pointer to T”, the type of the result is “T”.
So it is not the reference, but decltype()
gives you something which actually has a representation in the C++ types system, and reference is the closest thing to it.