C++ std::bind 到 std::function,VS2015 到底哪里出了问题?

C++ std::bind to std::function, what went wrong in VS2015?

我是 VS2013 的用户,我经常按如下方式使用初始化,它工作得很好:

MyClass::MyClass myRoutine(){
    std::function<double(double)> oFunc = std::bind(&Myclass::myfunction, this, std::placeholders::_1);
}

MyClass::MyClass myfunction(double & inX){
    return 0;
}

我决定升级到VS2015,但是编译报错:

error C2440: 'initializing': cannot convert from 'std::_Binder<std::_Unforced,double (__thiscall MyClass::* )(double &),MyClass *const ,const std::_Ph<1> &>' to 'std::function<double (double)>'

发生了什么事?

函数签名不匹配:double(double) vs double(double&)。因此编译错误。其中一项需要更改,例如:

double MyClass::myfunction(double inX){
    return 0;
}

您的函数通过引用获取其参数 (double &),而您正试图将其分配给具有按值获取签名的函数 (double)。

这很可能是由于一致性错误而在 VS2013 中编译的(可能与临时 MSVC 扩展的非常量引用有一些奇怪的交互)。基本上它不是有效的 C++ 代码。 VS2015 在标准支持和一致性方面领先于以前的 VSes(VS2017 更是如此),因此此错误代码不再编译。

无论如何,std::bind 几乎完全被 lambdas 淘汰了,VS2010+ 应该会支持它。他们产生更好的代码,更好 warnings/errors,更容易编写和调试。

例如,您的代码可以这样重写:

std::function<double(double)> oFunc = [this](double x){ return myfunction(x); };

如果你真的想通过引用传递,或者像这样:

std::function<double(double &)> oFunc = [this](double &x){ return myfunction(x); };

注意它是多么的简短。