我试图给出一个导致rvalue的操作的简单示例。
这个测试用例应该有效,但令人惊讶的是(对我来说),添加两个int
s的结果不是rvalue(引用)。我在这里缺少什么?
void test(int i, int j)
{
// this assert should pass, but fails:
static_assert(std::is_same<decltype(i + j), int&&>(), "i + j should be a rvalue");
// this assert passed, but should fail:
static_assert(std::is_same<decltype(i + j), int>(), "this assert should fail...");
}
答案 0 :(得分:33)
i + j
是here,
prvalue(&#34;纯rvalue&#34;)表达式是一个没有标识且可以从中移出的表达式。
a + b,a%b,a&amp; b,a&lt;&lt; b,以及所有其他内置算术表达式;
xvalue(&#34;到期值&#34;)表达式是一个具有标识且可以从中移出的表达式。
xvalue为prvalue产生T
,而不是T&&
。
a)如果表达式的值类别是xvalue,则decltype产生T&amp;&amp ;;
b)如果表达式的值类别是左值,则decltype产生T&amp ;;
c)如果表达式的值类别是prvalue,则decltype产生T。
您可以按std::move
:
static_assert(std::is_same<decltype(std::move(i + j)), int&&>(), "std::move(i + j) is a xvalue then this static_assert won't fail");
答案 1 :(得分:5)
基于@ songyuanyao的Answer,我注意到我的错误是检查错误的东西:我的目的是检查i+j
的结果是否绑定到一个右值参考,但我检查了是左值参考。
decltype根据 value category 推断出类型,而不是基于 reference type 绑定的值绑定到:
1)如果表达式的值类别为
xvalue
,则decltype产生T&&
;
2)如果表达式的值类别为lvalue
,则decltype产生T&
;
3)如果表达式的值类别为prvalue
,则decltype产生T
。
如清单所示,自C ++ 11起,rvalues
不会作为最低级别的独特类别存在。它们现在是包含两者的复合类别prvalues
以及xvalues
。写的问题询问表达式是否为rvalue reference
并检查它是否为xvalue
。
从上面的列表中可以清楚地看出i+j
是prvalue
,因此第三种情况适用。这解释了为什么decltype(i + j)
是int
而不是int&&
。 xvalues
和prvalues
都绑定到 rvalue引用。
通过检查i+j
绑定到lvalue reference
或rvalue reference
是否确认绑定到 rvalue reference
:
void foo(const int& f)
{
std::cout << "binds to lvalue reference" << std::endl;
}
void foo(int&& f)
{
std::cout << "binds to rvalue reference" << std::endl;
}
void test(int i, int j)
{
foo(i); // lvalue -> lvalue ref
foo(std::move(i)); // xvalue -> rvalue ref
// (std::move converts the argument to a rvalue reference and returns it as an xvalue)
foo(i + j); // prvalue -> rvalue ref
}
总之: i+j
不是右值参考,但绑定一个。