Looking into definition of value-categories, I tried a snippet proposed here: /a/16638081/21691539
<code>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
</code>
<code>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
</code>
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”:
<code>#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
}
</code>
<code>#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
}
</code>
#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
}
LIVE
and the output
<code>f() prvalue
rf() lvalue
S{}.val xvalue
S{}.rval lvalue
</code>
<code>f() prvalue
rf() lvalue
S{}.val xvalue
S{}.rval lvalue
</code>
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 rational.