The rules of the specifier decltype
are here: https://en.cppreference.com/w/cpp/language/decltype
Your case falls into any expression (third item), because *p
is not a id-Expression, neither a class membership access, and yes any expression.
If the argument is any other Expression of type T
, and
a. if the value Category of Expression is xvalue, then decltype yields T&&
;
b. if the value Category of Expression is lvalue, then decltype yields T&
;
c. if the value Category of Expression is prvalue, then decltype yields T
.
The value category of the expression *p
(indirect expression) is defined as a lvalue:
The following Expressions are lvalue Expressions:
- …
*p
, the built-in indirection Expression;
So the kind where decltype(*p)
results comes from rule 3.b.: if the value Category of Expression is lvalue, then decltype yields T&
, where T
is the type of expression *p
, which in that case is int
. Replacing, we have int&
as the resulting type.