无法将参数1从'overloaded-function'转换为'...'

时间:2010-09-16 09:22:27

标签: c++ boost function-pointers

现在我尝试使用boost bind& mem_fn。 但是绑定重载函数存在问题。 如何解决以下代码的编译错误?

boost::function< void( IF_MAP::iterator ) > bmf = std::mem_fun1< void, IF_MAP, IF_MAP::iterator >( &IF_MAP::erase );
boost::function< void( IF_MAP::iterator ) > bmf = boost::mem_fn< void, IF_MAP, IF_MAP::iterator >( &IF_MAP::erase );

主要目的是编制以下代码

IF_MAP M;
boost::function< void( IF_MAP::iterator ) > bmf = boost::bind(
    boost::mem_fn< void, IF_MAP, IF_MAP::iterator >( &IF_MAP::erase ),
    &M, _1 );
M.insert( IF_MAP::value_type( 1, 1.f ) ); M.insert( IF_MAP::value_type( 2, 2.f ) );
bmf( 2 );

编译错误消息是这样的......

  

错误C2665:'boost :: mem_fn':2个重载中没有一个可以转换所有参数类型   可能是'boost :: _ mfi :: mf1 boost :: mem_fn :: iterator&gt;(R(__thiscall std :: map&lt; _Kty,_Ty&gt; :: *)(A1))'   或'boost :: _ mfi :: cmf1 boost :: mem_fn :: iterator&gt;(R(__thiscall std :: map&lt; _Kty,_Ty&gt; :: *)(A1)const)'

P.S。 如你所知,std :: map有3个重载的擦除成员函数

  1. void erase(iterator _Where)
  2. size_type erase(const key_type& _Keyval)
  3. void erase(iterator _First, iterator _Last) 第二个功能可以轻松绑定,但其他功能不能。
  4. 修改
    更详细地描述我的问题:

    实际上,我想进行延迟函数调用。 当我遇到函数的返回代码时,那么是时候了,所以应该调用延迟函数。

    现在我正在重构一些遗留代码。现在,我通常会看到这种代码模式。 (实际代码更复杂但几乎相同如下) 重复的erase()调用分散在此函数中。

    typedef map< int, float > IF_MAP;
    
    bool DoAndPopOld( IF_MAP& M, int K )
    {
        IF_MAP::iterator Itr = M.find( K );
        if ( Itr == M.end() ) return false;
    
        if ( K < 10 ) 
        {
            M.erase( Itr ); // erase call is here...
            return false;
        }
    
        if ( 100 < K )
        {
            // Do something
            M.erase( Itr ); // and here...
            return true;
        }
    
        // Do something
        M.erase( Itr ); // and also here!
    
        return true;
    }
    

    所以,我想像这样重构上面的代码......

    class ScopedOutCaller
    {
    private:
        boost::function< void() > F;
    public:
        ScopedOutCaller( boost::function< void() > _F ) : F(_F) {}
        ~ScopedOutCaller() { F(); } // deferred function call
    };
    
    bool DoAndPopNew( IF_MAP& M, int K )
    {
        IF_MAP::iterator Itr = M.find( K );
        if ( Itr == M.end() ) return false;
    
        // Make deferred call, so I do not consider calling erase function anymore.
        ScopedOutCaller SOC( boost::bind( &IF_MAP::erase ), &M, Itr );
    
        if ( K < 10 ) 
        {
            // M.erase( Itr ); <-- unnecessary
            return false;
        }
        if ( 100 < K )
        {
            // Do something
            // M.erase( Itr ); <-- unnecessary
            return true;
        }
    
        // Do something
        // M.erase( Itr ); <-- unnecessary
        return true;
    }
    

    但是,正如我所说的......发生了编译错误。 我想做的事情的长期和短期是如何推迟函数调用。 请告诉我拨打延期电话的方法。 感谢。

2 个答案:

答案 0 :(得分:3)

std::map的成员函数erase()已超载,因此您必须手动消除歧义 - 请参阅Boost.Bind FAQ

E.g。对于size_type erase(const key_type&)重载:

typedef IF_MAP::size_type (IF_MAP::*EraseType2)(const IF_MAP::key_type&);
boost::function<void (const IF_MAP::key_type&)> bmf2;
bmf2 = boost::bind((EraseType2)&IF_MAP::erase, &M, _1);

要选择其他版本,只需更改要投射的类型,例如:

// 1. void erase(iterator position) :
typedef void (IF_MAP::*EraseType1)(IF_MAP::iterator);
boost::function<void (IF_MAP::iterator)> bmf1;
bmf1 = boost::bind((EraseType1)&IF_MAP::erase, &M, _1);

// 3. void erase(iterator first, iterator last) :
typedef void (IF_MAP::*EraseType3)(IF_MAP::iterator, IF_MAP::iterator);
boost::function<void (IF_MAP::iterator, IF_MAP::iterator)> bmf3;
bmf3 = boost::bind((EraseType3)&IF_MAP::erase, &M, _1, _2);

可悲的是Visual Studio在这里不符合C ++ 03(再一次......),你必须使用以下两种形式:

typedef IF_MAP::iterator (IF_MAP::*EraseType1)(IF_MAP::const_iterator);
typedef IF_MAP::iterator (IF_MAP::*EraseType3)(IF_MAP::const_iterator,
                                               IF_MAP::const_iterator);

使用VC8和VC9,你可以使用_HAS_STRICT_CONFORMANCE来解决这个问题,但是这会再次破坏VC10,因为C ++ 0x会将erase()重载更改为Dinkumware使用的表单(参见{{3 }})。
为了便于携带,我会选择使用包装函数来解决这些恼人的问题;但是,如果您只关心VC,请使用我上面提供的类型。

要在块出口处执行生成的仿函数,最简单的方法是使用N3092, 23.4.1或类似的范围保护。例如。对于VC特定演员:

typedef IF_MAP::iterator (IF_MAP::*EraseType)(IF_MAP::const_iterator);
boost::shared_ptr<void> guard(static_cast<void*>(0),
                              boost::bind((EraseType)&IF_MAP::erase, &M, Itr));

答案 1 :(得分:0)

试试这个:

ScopedOutCaller SOC(boost::bind(static_cast< IF_MAP::iterator (IF_MAP::*)(IF_MAP::const_iterator) >(&IF_MAP::erase), &M, Itr));

对于Visual Studio 2005:

ScopedOutCaller SOC(boost::bind(static_cast< IF_MAP::iterator (IF_MAP::*)(IF_MAP::iterator) >(&IF_MAP::erase), &M, Itr));