从 VS2008 移植到 VS2013 时绑定中出现错误 C2668

Error C2668 in bind while porting from VS2008 to VS2013

本文关键字:错误 C2668 绑定 VS2008 VS2013      更新时间:2023-10-16

我正在尝试将我的代码从VS2008移植到VS2013,但遇到一些std::bind的错误。错误显示错误 C2668:"绑定":对重载函数的不明确调用。下面是一些代码:

// Relevant prototypes:
class CLineaPlanta:public SomeBase { /*...*/ };
int SomeBase::TipoLinea()const;
void SomeBase::TipoLinea(int val);
// function paramater: const std::shared_ptr<CLineaPlanta>& lineasBuscar
// function parameter: int tipoLinea;
std::shared_ptr<CLineaPlanta> lineas;
std::remove_copy_if(lineasBuscar.begin(), lineasBuscar.end(),
std::back_inserter(lineas), 
        bind(std::not_equal_to<int>(), bind(&CLineaPlanta::TipoLinea, _1), tipoLinea));

此代码在Visual Studio 2008中有效,但在Visual Studio 2013中给出了上述错误。

显然,编译器很难弄清楚我试图调用哪个版本的TipoLinea()。如果我将getter版本重命名为getTipoLinea,错误就会消失。

以防万一相关,SomeBase 是非抽象的,并且源自 CObject(不确定为什么)和与这部分代码无关的接口。

谁能解释为什么VS2008对此没有任何问题以及如何防止它(当然,除了重命名函数)?

我不知道

为什么这段代码在VS2008中起作用。这可能是 2008 年bind被实现为基于宏的可变参数仿真的结果,其中bind对传递的每个参数数都有几个重载,其中一个参数期望第一个参数是指向具有相同参数数的成员函数的指针。这将允许编译器消除歧义,因为您将一个绑定参数传递给bind,因此它知道函数参数必须有一个参数。

在VS2013中,使用了真正的可变参数,但这可能意味着第一个参数的类型更通用,因此编译器无法再消除歧义。若要进行此编译,需要显式强制转换成员指针:

std::remove_copy_if(lineasBuscar.begin(), lineasBuscar.end(),
    std::back_inserter(lineas), 
    bind(std::not_equal_to<int>(),
         bind(static_cast<int (SomeBase::*)() const>(&CLineaPlanta::TipoLinea),
              _1),
             tipoLinea));

但正如 Neil Kirk 所说,重写为 lambda 更容易:

std::remove_copy_if(lineasBuscar.begin(), lineasBuscar.end(),
    std::back_inserter(lineas),
    [tipoLinea](const std::shared_ptr<CLineaPlanta>& linea) {
        return linea->TipoLinea() != tipoLinea;
    });