0

我正在尝试将我的代码从 VS2008 移植到 VS2013,但我遇到了一些 std::bind 错误。错误说错误 C2668:'bind':对重载函数的模糊调用。这是一些代码:

// 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对此没有任何问题以及如何防止它(当然,除了重命名函数之外)?

4

1 回答 1

1

我不知道为什么这段代码曾经在 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;
    });
于 2014-11-17T14:47:48.443 回答