【问题标题】: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() 会产生编译时错误。这种绑定仅适用于模板吗?为什么?我们可以在没有模板的情况下以某种方式做到这一点吗?

【问题讨论】:

    标签: c++ c++11 lvalue rvalue


    【解决方案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

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

    【讨论】:

    猜你喜欢
    • 2014-01-02
    • 1970-01-01
    • 2017-12-06
    • 2014-10-31
    • 2017-04-13
    • 2011-02-14
    • 2018-09-30
    • 1970-01-01
    相关资源
    最近更新 更多