在研究值类别的定义时,我尝试了这里提出的一个片段: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
但测试时,我不明白在暗示引用的情况下它的输出。这是我的“测试台”:
#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
}
和输出
f() prvalue
rf() lvalue
S{}.val xvalue
S{}.rval lvalue
在两种情况下,当表达式与引用相关时,我都会得到意外的结果lvalue
。
这段代码正确吗?为什么?如果是错的,那么正确的值类别是什么(以及为什么)?
NB 来自https://timsong-cpp.github.io/cppwp/n4861/basic.lval#4.4我知道这S{}.rval
不是一个xvalue
,但我想知道其理由。
是的,如下所述。
首先
S{}.rval
是一个根据basic.ref的左值表达式,它指出:在您的示例中,
rval
hasint&
表示S{}.rval
是一个左值表达式。接下来,调用
rf()
也是一个左值表达式。从expr.call开始: