Looking into definition of value-categories, I tried a snippet proposed here: https://stackoverflow.com/a/16638081/21691539
template <typename T>
struct value_category {
// Or can be an integral or enum value
static constexpr auto value = "prvalue";
};
template <typename T>
struct value_category<T&> {
static constexpr auto value = "lvalue";
};
template <typename T>
struct value_category<T&&> {
static constexpr auto value = "xvalue";
};
// Double parens for ensuring we inspect an expression,
// not an entity
#define VALUE_CATEGORY(expr) value_category<decltype((expr))>::value
But testing it I don't understand its output in a situation implying references. Here is my "testbench":
#include <iostream>
struct S {
int val;
int& rval = val;
};
int f();
int& rf();
// VALUE_CATEGORY as in previous snippet
#define SHOW_CATEGORY(expr) std::cout << #expr << "\t" << VALUE_CATEGORY(expr) << '\n';
int main() {
SHOW_CATEGORY(f());
SHOW_CATEGORY(rf()); // expecting prvalue, got lvalue
SHOW_CATEGORY(S{}.val);
SHOW_CATEGORY(S{}.rval); // expecting xvalue, got lvalue
}
and the output
f() prvalue
rf() lvalue
S{}.val xvalue
S{}.rval lvalue
In both cases where the expression is related to a reference, I'm getting an unexpected lvalue
.
Is the snippet right and, in this case why? Is it wrong, then what would be the correct value category (and also why)?
NB from https://timsong-cpp.github.io/cppwp/n4861/basic.lval#4.4 I've got that S{}.rval
is not an xvalue
though I'd like to know the rationale.
Is the snippet right and, in this case why?
Yes as explained below.
First S{}.rval
is an lvalue expression as per basic.ref that states:
If
E2
is declared to have type “reference to T”, then E1.E2 is an lvalue of typeT
.
In your example, rval
has int&
which means S{}.rval
is an lvalue expression.
Next the call rf()
is also an lvalue expression. From expr.call:
A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.