I am confused about the wording for std::decay
on cppreference. They say it applies "lvalue to rvalue." I know std::decay
removes referenceness, so is this what they mean by that? If so, why is a non-reference type called an rvalue?
I think cppreference is just using the term a bit loosely and makes an assumption that the reader is aware of the connection between refererence kinds and value categories.
Normally an implicit conversion is something that is applied to an expression, not to a type.
A conversion is something like "An lvalue/xvalue/prvalue expression of type T
may be converted to an lvalue/xvalue/prvalue expression of type U
." followed by a specification of how the result of the conversion is determined.
Notably, types of expressions (i.e. T
and U
) are never reference types. However, there is a canonical mapping from the value category (lvalue/xvalue/prvalue) to reference kinds:
lvalue <-> lvalue reference
xvalue <-> rvalue reference
prvalue <-> no reference
And with that translation there is an analogues meaning for a conversion on a type that matches exactly what you would get when applying decltype
to the expression before and after the conversion.
An lvalue-to-rvalue conversion is a conversion from a non-function, non-array lvalue or xvalue of type cv T
to a prvalue of either type cv T
if T
is a class type or T
if T
is not a class type.
So in terms of the type analogy this means that cv T&
and cv T&&
are transformed to cv T
if T
is a class type and to T
if T
is a non-function non-array non-class type. And in all other situations no transformation is applied (at least not due to the lvalue-to-rvalue conversion part of the explanation of std::decay
).
Of course, because cv
qualifiers are removed in a second step, this means effectively simply that references and cv-qualifiers are removed. However, for function and array types std::decay
behaves slightly differently, because it applies the array-to-pointer and function-to-pointer conversion with the same analogy and therefore produces a function pointer or an element pointer instead of a function type or array type (however ref/cv-qualified). The description on cppreference makes it clear that std::decay
reflects the behavior of these implicit conversions on type and value category.
In the above cv
is any combination of const
and volatile
(or neither).