传递rvalue加注无法绑定到左值

时间:2016-07-27 05:00:45

标签: c++ templates c++11 perfect-forwarding

该计划如下:

#include <iostream>
using namespace std;

template <typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2)
{
      f(t2, t1);
}

void g(int &&i, int &j)
{
      cout << i << " " << j << endl;
}

int main(void)
{
      int i = 1;
      flip2(g, i, 42);
}

编译器抱怨:

error: rvalue reference to type 'int' cannot bind to lvalue of type 'int'

但据我了解,由于T2已使用int进行实例化,因此t2的类型为int&&,因此应将其传递给函数{{ 1}}&#39;的第一个参数(g)。

我的理解有什么不对?

1 个答案:

答案 0 :(得分:5)

f(t2, t1);

t2有一个名字,所以它是一个左值。它的类型是rvalue,但在表达式中它的类型是左值。要将其作为右值引用传递,您需要使用std::forwardmove或者在此处投射不合适,因为T1和T2实际上是通用引用不是左值参考,请参阅编辑)。

#include <iostream>
using namespace std;

template <typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2)
{
      f(std::forward<T2>(t2), std::forward<T1>(t1));
}

void g(int &&i, int &j)
{
      cout << i << " " << j << endl;
}

int main(void)
{
      int i = 1;
        flip2(g, i, 42);
}

http://ideone.com/Aop2aJ

---为什么---

考虑:

template<typename T>
void printAndLog(T&& text) {
    print(text);
    log(text);
}

int main() {
    printAndLog(std::string("hello, world!\n"));
}

当你使用变量的名字时,表达式类型是lvalue(glvalue?); rvalueness被丢弃。否则,在上面的示例中,我们已将text丢失为print()。相反,当我们希望我们的rvalue表现得像一个时,我们必须明确:

template<typename T>
void printAndLog(T&& text) {
    print(text);
    log(std::forward<T>(text));  // if text is an rvalue, give it up.
}

---编辑---

我使用std::forward因为T1&&T2&&是通用引用,而不是右值引用。 https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers