问题描述
在查看 std::forward 的参考页面时,我发现了一些奇怪的东西。该示例将左值作为右值引用传递......但传递给全局函数......并且它编译并运行。我尝试了与成员函数相同的事情,但无法编译。是什么赋予了?我希望在不使用 m = [
[ 1,2,-1,-4,-20],[-8,-3,4,1],[ 3,8,10,1,3],[-4,7,-6]
]
maxsum = 0
for top in range(0,len(m)):
for left in range(0,len(m[0])):
for bottom in range(top,len(m)):
for right in range(left,len(m[0])):
thissum = 0
for row in range(top,bottom+1):
for col in range(left,right+1):
thissum += m[row][col]
maxsum = max(thissum,maxsum)
print(maxsum) # 29
或 std::move
的情况下这两个调用都会失败。
std::forward<T>
解决方法
这是因为 globalDoSomething
的自动模板推导将 T
推断为 int&
。
如果您像对模板类的成员函数那样使用 globalDoSomething<int>(b);
显式实例化模板函数,它也将无法编译。
相反,如果您使用 A<int&> a;
实例化模板类,它将成功编译。
要建立/添加@Patrick Roberts 的答案,来自 template argument deduction
如果 P 是对 cv 非限定模板参数的右值引用 (所谓的转发引用),以及对应的函数调用 参数是一个左值,就地使用了对 A 的左值引用类型 A的扣除
简而言之,虽然 b
是左值,但它确实将 T
推断为 int&
。如示例所示
template<class T>
int f(T&& x) { // x is a forwarding reference
return g(std::forward<T>(x)); // and so can be forwarded
}
int main() {
int i;
f(i); // argument is lvalue,calls f<int&>(int&),std::forward<int&>(x) is lvalue
}
为了测试这个,你可以设置一些不同类型的重载函数并检查
#include <iostream>
#include <utility>
void f(int&& x) {
std::cout << "rvalue reference overload f(" ")\n";
}
void f(const int& x) {
std::cout << "lvalue reference to const overload f(" ")\n";
}
void f(int& x) {
std::cout << "lvalue reference overload f(" ")\n";
}
template <typename T>
void globalDoSomething(T &&data) {
f(data);
}
int main()
{
int b = 0;
globalDoSomething(b);
return 0;
}
输出是
左值引用重载 f()