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

时间:2014-11-17 14:31:32

标签: c++ visual-studio-2013 stdbind

我试图将我的代码从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对此没有任何问题以及如何防止它(当然除了通过重命名功能)?

1 个答案:

答案 0 :(得分: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;
    });