左值绑定到右值引用

Posted

技术标签:

【中文标题】左值绑定到右值引用【英文标题】:lvalue binding to rvalue reference 【发布时间】:2013-06-15 18:09:23 【问题描述】:

我试图了解左值如何绑定到右值引用。考虑这段代码:

#include <iostream>

template<typename T>
void f(T&& x) 
    std::cout << x;


void g(int&& x) 
    std::cout << x;


int main() 
    int x = 4;
    f(x);
    g(x);
    return 0;

虽然调用 f() 没问题,但调用 g() 会产生编译时错误。这种绑定仅适用于模板吗?为什么?我们可以在没有模板的情况下以某种方式做到这一点吗?

【问题讨论】:

【参考方案1】:

由于T 是一个模板参数,T&amp;&amp; 成为一个转发引用。由于引用折叠规则,对于左值,f(T&amp; &amp;&amp;) 变为 f(T&amp;),对于右值,f(T &amp;&amp;) 变为 f(T&amp;&amp;)

【讨论】:

这是有道理的。但是假设我不需要模板,那么有没有办法获得通用引用,比如上面的例子?为此,我稍微编辑了问题。 @r.v 您可以为左值 (void g(int&amp;)) 提供第二个重载 g,或者您可以使用std::move移动左值。 是的,这些是可能的解决方案,但我希望我们得到一些符合通用参考的东西:给定类型 T(固定,非模板),我可以在一次调用中同时匹配 T& 和 T&& (没有重载),然后使用转发等。这肯定有助于减少一些冗余代码。 @r.v 抱歉,但不包括我建议的内容,如果没有模板,这是不可能的。 :( 顺便说一句,完美转发非常适合模板。 没问题,谢谢。我认为我们在这里有一个合法的用例。【参考方案2】:

0x499602D2 已经回答了您的问题;不过,对您的代码进行以下更改可能会提供进一步的见解。

我在f 中添加了一个static_assert 来检查推导的类型:

#include <type_traits>

template<typename T>
void f(T&& x) 
    static_assert(std::is_same<T&&, int&>::value,"");
    std::cout << x;

断言确实没有失败,所以fx 的类型最终是int&amp;(在这个特定示例中)。

我改变了gmain 中的调用方式:

g(std::move(x));

现在代码已编译,程序按预期工作并打印44

希望这有助于理解右值引用。

【讨论】:

已经有一个模板:std::is_rvalue_reference

以上是关于左值绑定到右值引用的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 11 中将非 const 左值引用绑定到右值是不是有效?(修改)

error C2662 无法将左值绑定到右值 —— 变量永远是左值,即使它的类型为右值引用

std::forward vs std::move 同时将左值绑定到右值引用

VS2012 error C2664: “std::make_pair”:无法将左值绑定到右值引用

通用引用的语法

允许将右值绑定到非常量左值引用吗?