Code
#include <iostream>
int main()
{
int a=3;
int *p=&a;
decltype (a) k1;
decltype (*p) k2;
return 0;
}
Output
Declaration of reference variable 'k2' requires an initializer
Explanation given to such phenomena is " decltype
returns a reference type for expression that yield objects that can stand on the LHS of the assignment"
see what *p
yields value of of the object it points means 3
and what a
yields value of itself which is 3
.
Now we talk manipulatively that *p
refers to object a
then a
also refers to a
itself.
So I am not digesting the explanation given for such phenomena.
CodePudding user response:
a
is an unparenthesised id expression.
*p
is not an id expression. It is an indirection operation.
decltype
behaves differently when the operand is an unparenthesised id expression than when the operand is not an unparenthesised id expression.
decltype
of an unparenthesised id expression doesn't yield a reference type but rather the type of the entity named by the id expression. The type of the entity named by a
is int
.
decltype
of a non-unparenthesised-id-expression may yield either an lvalue reference or an rvalue reference or a non-reference depending on the value category of the expression. *p
is an lvalue expression, so decltype (*p)
yields an lvalue reference i.e. int&
.
see what *p yields value of of the object it points means 3 and what a yields value of itself which is 3.
There is no difference between the expressions a
and *p
in regards to what the expressions themselves yield. They are both lvalue expressions of the same type and name the same object.
The distinction is that one is an unparenthesised id-expression and thus applies for the exceptional case of decltype
while the other is not.
CodePudding user response:
According to cppreference for
decltype ( expression )
If the argument is any other expression of type T, and if the value category of expression is lvalue, then decltype yields T&;
So now lets look at your example. In particular, we have :
decltype (*p) k2;
The "thing" inside the parenthesis ()
is an expression. That is, *p
is an expression. Now there are two important thing:
- The type of this expression is
int
. - The value category of this expression is an lvalue.
And so according to the above quoted statement, the result will be T& or int&
in our case.
And since we must always initialize a reference, so you get the said error.
CodePudding user response:
Reference in its essence is not so different from a pointer. They are both referring to the object in memory. But I believe you already know that.
The thing with decltype is that it returns reference in this case. As pointed out in another answer here and mentioned here,
*p
is the built-in indirection expression which is an lvalue. So decltype does this:
b) if the value category of expression is lvalue, then decltype yields T&;
You can also verify this:
std::cout << "*p and int are the same type? " << std::boolalpha
<< std::is_same_v<decltype(*p), int> << '\n'
<< "*p and int& are the same type? "
<< std::is_same_v<decltype(*p), int&> << '\n';