не может преобразовать параметр 1 из 'перегруженной функции' в '...' - PullRequest
5 голосов
/ 16 сентября 2010

Теперь я пытаюсь использовать 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': ни одна из двух перегрузок не может преобразовать все типы аргументов: 'boost :: _ mfi :: mf1 boost :: mem_fn :: iterator> (R (__thiscall std ::map <_Kty, _Ty> :: *) (A1)) 'или' boost :: _ mfi :: cmf1 boost :: mem_fn :: iterator> (R (__thiscall std :: map <_Kty, _Ty> :: *) (A1) const) '

PS Как вы знаете, std :: map имеет 3 перегруженных функции стирания члена

  1. void erase(iterator _Where)
  2. size_type erase(const key_type& _Keyval)
  3. void erase(iterator _First, iterator _Last) 2-ю функцию можно легко связать, но другие нет.

Редактировать
Чтобы описать мой вопрос более подробно:

На самом деле, я хочу сделать отложенный вызов функции.Когда я встречаю код возврата функции, тогда пришло время выйти за рамки, так что должна быть вызвана отложенная функция.

Теперь я выполняю рефакторинг некоторых устаревших кодов.В настоящее время я обычно вижу такой шаблон кодов.(Фактические коды более сложные, но почти такие же, как показано ниже) Дублированные 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 ]

3 голосов
/ 16 сентября 2010

std::map s функция-член erase() перегружена, поэтому вы должны устранить неоднозначность вручную - см. Boost.Bind FAQ .

Например, для перегрузки 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);

Sadly VisualStudio не соответствует 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 (см. N3092, 23.4.1 ).
Дляпереносимость я бы использовал вместо этого функцию-обертку, чтобы обойти эти раздражающие проблемы;однако, если вы заботитесь только о VC, просто используйте типы, которые я предоставил выше.

Для выполнения результирующих функторов при выходе из блока, самый простой способ - использовать Boosts shared_ptr или аналогичную областьохранник.Например, для конкретного броска 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));
0 голосов
/ 17 сентября 2010

Попробуйте это:

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));
...