不能在成员函数中将左值绑定到右值,但在全局函数中可以

问题描述

在查看 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()

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...