如何在C++中通过编程方式判断表达式为prvalue、lvalue或xvalue
如何在C++中区分xvalue和prvalue?
我们已经能区分lvalue和rvalue,现在想进一步区分右值范畴里的xvalue和prvalue,先看你给出的宏实现:
#include <iostream> #include <type_traits> using namespace std; #define IS_XVALUE(expr) (is_rvalue_reference<decltype((expr))>{}) #define IS_PRVALUE(expr) (!is_reference<decltype((expr))>{}) #define IS_LVALUE(expr) (is_lvalue_reference<decltype((expr))>{}) int main() { int a = 0; int &b = a; int &&c = 3; cout << IS_LVALUE(a); // true cout << IS_LVALUE(b); // true cout << IS_LVALUE(c); // true cout << IS_PRVALUE(3); // true cout << IS_XVALUE(move(a)); // true }
你的宏实现是正确的
C++里表达式的值类别和decltype((expr))的结果有明确对应关系:
- 左值(lvalue)表达式:
decltype((expr))会得到左值引用类型,所以IS_LVALUE的判断逻辑成立 - 将亡值(xvalue)表达式:
decltype((expr))会得到右值引用类型,IS_XVALUE的判断完全正确 - 纯右值(prvalue)表达式:
decltype((expr))会得到非引用类型,IS_PRVALUE通过“是否不是引用类型”判断,逻辑没问题
测试用例里的结果也符合规则:比如命名的右值引用c本身是左值(所有命名变量都是左值表达式),所以IS_LVALUE(c)返回true,这是正确的;std::move(a)生成xvalue,3是prvalue,对应的判断结果都没问题。
非宏的实现方式
宏存在多次求值、缺乏类型安全等问题,推荐用模板函数+完美转发实现,代码如下:
#include <iostream> #include <type_traits> // 判断是否为左值表达式 template<typename T> constexpr bool is_lvalue(T&&) { return std::is_lvalue_reference_v<T>; } // 判断是否为xvalue表达式 template<typename T> constexpr bool is_xvalue(T&&) { return std::is_rvalue_reference_v<T>; } // 判断是否为prvalue表达式 template<typename T> constexpr bool is_prvalue(T&&) { return !std::is_reference_v<T>; } int main() { int a = 0; int &b = a; int &&c = 3; std::cout << is_lvalue(a); // true std::cout << is_lvalue(b); // true std::cout << is_lvalue(c); // true std::cout << is_prvalue(3); // true std::cout << is_xvalue(std::move(a)); // true }
这个实现利用了C++的完美转发规则:
- 传入左值时,模板参数
T会被推导为左值引用类型 - 传入xvalue时,
T会被推导为右值引用类型 - 传入prvalue时,
T会被推导为非引用类型
通过std::is_lvalue_reference_v等类型特性就能准确判断表达式的 value category。
内容的提问来源于stack exchange,提问作者oyyko
相关产品推荐
相关产品推荐

