2010-09-16 4 views
5

Теперь я пытаюсь использовать boost bind & mem_fn. Но проблема связана с перегруженной функцией. Как разрешить ошибку компиляции следующих кодов?не может преобразовать параметр 1 из «перегруженной функции» в «...»

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

P.S. Как U известно, станд :: карта имеет 3 перегруженная функция стирания

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

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

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

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

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

+1

Я переместил информацию от своего "ответа" на вопрос, где это должно быть. Если у вас есть дополнительная информация, отредактируйте ее в вопросе. Если вы опубликуете его как ответ, это просто смущает (и, что более важно, люди не будут видеть, если до ответа) – jalf

+0

Ну, вы только заботитесь о VC или нет? –

+0

@George Я обычно использую MSVS, но если у вас есть какая-то идея, расскажите мне что-нибудь. Благодарю. – codevania

ответ

3

std::map s функция-член 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 (см. 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

Thans для вашего ответа. Yeh .. как вы упомянули, стирать функцию-член можно привязать (я сделал это). Но я хочу связать другую перегруженную функцию ... вроде, void erase (iterator _Where) или void erase (iterator _First, iterator _Last). ^^; У тебя есть идея? – codevania

+0

@codevania: Конечно, это абсолютно такая же процедура - просто измените тип, на который вы производите. –

+0

Большое спасибо, Георг. Но выше предложенные коды U не компилируются из-за ошибки типа-cast. – codevania

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)); 
+0

Я вижу ... Правильная подпись: «IF_MAP :: iterator (IF_MAP :: *) (IF_MAP :: iterator)« not »void (IF_MAP :: *) (IF_MAP :: iterator)» – codevania

Смежные вопросы