为什么“decltype(i + j)”的结果不是右值参考?

时间:2016-04-21 07:36:02

标签: c++ c++11 rvalue-reference decltype rvalue

我试图给出一个导致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...");
}

2 个答案:

答案 0 :(得分:33)

i + jhere

  

prvalue(&#34;纯rvalue&#34;)表达式是一个没有标识且可以从中移出的表达式。

     

a + b,a%b,a&amp; b,a&lt;&lt; b,以及所有其他内置算术表达式;

不是prvalue expression

  

xvalue(&#34;到期值&#34;)表达式是一个具有标识且可以从中移出的表达式。

xvalue为prvalue产生T,而不是T&&

  

a)如果表达式的值类别是xvalue,则decltype产生T&amp;&amp ;;
  b)如果表达式的值类别是左值,则decltype产生T&amp ;;
  c)如果表达式的值类别是prvalue,则decltype产生T。

您可以按std::move

创建xvalue
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+jprvalue,因此第三种情况适用。这解释了为什么decltype(i + j)int而不是int&&xvaluesprvalues 都绑定到 rvalue引用。

通过检查i+j绑定到lvalue referencervalue 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 是右值参考,但绑定一个。