7

使用以下宏:

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

问号应该填什么?

4

2 回答 2

12

首先我们要澄清:你所说的“临时”是什么意思?

很多人说临时的意思不同。从技术上讲,int()这不是暂时的,但大多数人都会将它们包含在他们自己的含义中。从技术上讲, given std::string s;, thenmove(s)也不是临时的,但您可能希望将其与宏视为一个。

我上面提到的第一种“临时”实际上是“prvalue 表达式”。那些是std::string("foo")int()类型的东西,但不是move(s)而且(肯定)不是s那种东西。该decltype运算符为我上面谈到的第一种“临时”产生了一个非引用类型。对于第二种move(s)xvalues,它将产生一个右值引用。对于“非临时人员”,即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
于 2011-05-24T17:40:47.170 回答
5

编辑

我意识到我的方法与您所说的代码完全一样,它不起作用,只是逻辑上颠倒了:

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

您能否详细说明它在哪种情况下会与您的预期相反?


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

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

Ifexpr是某个(可能是 const)类型的左值Tdecltype((expr))将解析为T&T& &&并将折叠回T&

否则, ifexpr是某种类型的 xvalue Tdecltype((expr))将会是T&&,并且T&& &&会减少到 just T&&

否则,expr将是某种类型的纯右值Tdecltype((expr))将 yield 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");
于 2011-05-24T11:31:06.273 回答