传递右值加注不能绑定到左值
passing rvalue raises cannot bind to lvalue
程序如下:
#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&&
,所以应该允许传递给函数g
的第一个参数 (int &&
).
我的理解有什么问题吗?
f(t2, t1);
t2
有一个名字,所以它是一个左值。它的 type 是右值,但在表达式中它的类型是左值。为了将其作为右值引用传递,您需要使用 std::forward
(move
否则此处的转换不合适,因为 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);
}
--- 为什么 ---
考虑:
template<typename T>
void printAndLog(T&& text) {
print(text);
log(text);
}
int main() {
printAndLog(std::string("hello, world!\n"));
}
当你使用变量名时,表达式类型是左值(glvalue?);右值性被丢弃。否则在上面的例子中,我们会把 text
输给 print()
。相反,当我们希望我们的右值表现得像一个时,我们必须明确:
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
程序如下:
#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&&
,所以应该允许传递给函数g
的第一个参数 (int &&
).
我的理解有什么问题吗?
f(t2, t1);
t2
有一个名字,所以它是一个左值。它的 type 是右值,但在表达式中它的类型是左值。为了将其作为右值引用传递,您需要使用 std::forward
(move
否则此处的转换不合适,因为 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);
}
--- 为什么 ---
考虑:
template<typename T>
void printAndLog(T&& text) {
print(text);
log(text);
}
int main() {
printAndLog(std::string("hello, world!\n"));
}
当你使用变量名时,表达式类型是左值(glvalue?);右值性被丢弃。否则在上面的例子中,我们会把 text
输给 print()
。相反,当我们希望我们的右值表现得像一个时,我们必须明确:
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