Analisando a definição de categorias de valor, tentei um trecho proposto aqui: 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
Mas testando-o não entendo sua saída em uma situação que implique referências. Aqui está meu "banco de testes":
#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
}
e a saída
f() prvalue
rf() lvalue
S{}.val xvalue
S{}.rval lvalue
Nos dois casos em que a expressão está relacionada a uma referência, estou recebendo um arquivo lvalue
.
O trecho está correto e, neste caso, por quê? Está errado, então qual seria a categoria de valor correta (e também por quê)?
NB de https://timsong-cpp.github.io/cppwp/n4861/basic.lval#4.4 Eu entendi, S{}.rval
mas xvalue
gostaria de saber o motivo.
Sim, conforme explicado abaixo.
A primeira
S{}.rval
é uma expressão lvalue conforme basic.ref que afirma:No seu exemplo,
rval
hasint&
que significaS{}.rval
é uma expressão lvalue.Em seguida, a chamada
rf()
também é uma expressão lvalue. De expr.call :