如何测试表达式是否是临时的?

发布于 2024-11-09 12:33:57 字数 123 浏览 7 评论 0原文

使用以下宏:

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

我应该为问号添加什么?

With the following macro:

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

What should I put for question mark?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

街角卖回忆 2024-11-16 12:33:57

首先我们要澄清:“暂时”是什么意思?

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

我上面提到的第一种“临时变量”实际上是“纯右值表达式”。这些是 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

First we should clarify: What do you mean by "temporary"?

Many people mean different things when they say temporary. Technically, int() is not a temporary, but most people will include them into their own meaning of that term. Technically, given std::string s;, then move(s) isn't a temporary either, but you may want to treat it as one with your macro.

The first kind of "temporaries" I mentioned above are really "prvalue expressions". Those are the std::string("foo") or int() kind of things, but not the move(s) and also (for sure) not the s kind of things. The decltype operator yields a non-reference type for the first kind of "temporaries" I talked about above. For the second kind, move(s), which are xvalues, it will yield an rvalue reference. And for the "non-temporaries", i.e the s cases, it will yield an lvalue reference.

So to summarize, I will define three precise macros, and you can choose from them

#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
左耳近心 2024-11-16 12:33:57

编辑

我意识到我的方法与您所说的代码执行的操作完全相同,只是逻辑上颠倒了:

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

您能否详细说明在何种情况下它会违背您的预期?


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

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

如果 expr 是某种(可能是 const)类型 T 的左值,则 decltype((expr)) 将解析为 T&,并且 T& && 将折叠回 T&

否则,如果 expr 是某种类型 T 的 xvalue,则 decltype((expr)) 将是 T&&代码>和<代码>T&& && 将减少为 T&&

否则,expr 将是某种类型 T 的纯右值,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");

EDIT

I realized that my approach does exactly the same thing as the code you said did not work, only logically inverted:

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

Could you elaborate as to exactly in what kind of a situation it works against your expectations?


You can exploit the reference-collapsing rules like this:

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

If expr is an lvalue of some (possibly const) type T, decltype((expr)) will resolve to T&, and T& && will collapse back to T&.

Otherwise, if expr is an xvalue of some type T, decltype((expr)) will be T&&, and T&& && will reduce to just T&&.

Otherwise, expr will be a prvalue of some type T, decltype((expr)) will yield T, and thus the whole type will be T&&.

Examples:

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");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文