CTTCG 附录 B Value Categories
对于变量而言,其括号表达式的值类别是左值引用。但由于 decltype 有特殊效果,直接对变量 x 使用 decltype(x) 并不遵循这一点,为此可以按照下面说的使用 decltype((x))。
With the keyword decltype (introduced in C++11), it is possible to check the value category of any C++ expression. For any expression
x,decltype((x))(note the double parentheses) yields:
typeifxis a prvaluetype&ifxis an lvaluetype&&ifxis an xvalueThe double parentheses in
decltype((x))are needed to avoid producing the declared type of a named entity in case where the expressionxdoes indeed name an entity (in other cases, the paren-theses have no effect). For example, if the expressionxsimply names a variablev, the construct without parentheses becomesdecltype(v), which produces the type of the variablevrather than a type reflecting the value category of the expressionxreferring to that variable.
例子:
#include <iostream>
template<typename T>
struct value_category {
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";
};
// Get value category of an expression
#define VALUE_CATEGORY(expr) value_category<decltype((expr))>::value
#define PRINT(expr) printf("(%s) : %s\n", #expr, VALUE_CATEGORY(expr))
int main() {
PRINT(4); // prvalue
int x;
int &y = x;
int &&z = (int &&)x;
PRINT(x); // lvalue
PRINT(y); // lvalue
PRINT(z); // lvalue
PRINT(x+1); // prvalue
}