如何测试表达式是否为临时表达式

How to test whether expression is a temporary?

本文关键字:表达式 是否 何测试 测试      更新时间:2023-10-16

使用以下宏:

#define ASSERT_IF_TEMP(expr) static_assert(?, "Is temporary!");

我应该把什么作为问号?

首先我们应该澄清:"临时"是什么意思?

很多人说"暂时"是指不同的意思。从技术上讲,int()不是暂时的,但大多数人会将其纳入该术语的含义中。从技术上讲,给定std::string s;,那么move(s)也不是临时的,但您可能希望将其与宏视为一个。

我上面提到的第一种"临时性"实际上是"prvalue表达式"。这些是std::string("foo")int()类的东西,但不是move(s),也(当然)不是s类的东西。decltype运算符为我上面谈到的第一类"临时"生成了一个非引用类型。对于第二种move(s),即x值,它将产生一个右值引用。对于"非临时性",即s情况,它将产生左值引用。

总之,我将定义三个精确的宏,你可以从中选择

#define IS_LVALUE(...) std::is_lvalue_reference<decltype((__VA_ARGS__))>::value
#define IS_XVALUE(...) std::is_rvalue_reference<decltype((__VA_ARGS__))>::value
#define IS_PRVALUE(...) !std::is_reference<decltype((__VA_ARGS__))>::value

编辑

我意识到我的方法做的事情和你说的不起作用的代码完全一样,只是逻辑上颠倒了:

std::is_lvalue_reference<decltype((expr))>::value

你能详细说明在什么情况下它会违背你的期望吗?


你可以像这样利用引用折叠规则:

std::is_rvalue_reference<decltype((expr))&&>::value

如果expr是某个(可能是常量)类型T的左值,则decltype((expr))将解析为T&,而T& &&将折叠回T&

否则,如果expr是某种类型T的x值,则decltype((expr))将是T&&,并且T&& &&将减少到仅T&&

否则,expr将是某个类型T的prvalue,decltype((expr))将产生T,因此整个类型将是T&&

示例:

template <typename T>
struct is_rvalue : std::is_rvalue_reference<T&&>
{};
struct x {};
x a; const x b{};
static_assert(is_rvalue<decltype((x()))>::value, "x() is an rvalue");
static_assert(!is_rvalue<decltype((a))>::value, "a is an lvalue");
static_assert(!is_rvalue<decltype((b))>::value, "b is an lvalue");
static_assert(is_rvalue<decltype((std::move(a))>::value, "std::move(a) is an rvalue");