C ++ boost :: bind и boost :: function, обратные вызовы функций-членов класса и оператор ==. Что я делаю неправильно? - PullRequest
1 голос
/ 08 декабря 2010

У меня проблема с использованием boost :: bind и boost :: function и передачей boost :: function в качестве обратного вызова в другой класс.

Вот пример проблемной ситуации:

typedef boost::function<void (bool)> callbackFunction;

class HasCallback
{
public:
 HasCallback() : value(0)
 {
 }

 int value;

 void CallBackFunction(bool changed)
 {
  std::cout << "HasCallback class. CallBackFunction called. Parameter: " << value << std::endl;
 }
};

class ReceivesCallback 
{

public:
 void AddCallback(callbackFunction newFunc)
 {
  callbacks.push_back(newFunc);
 }

 void execute(int &i)
 {
  for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++)
  {
   (*it)(i++);
  }
 }

 void RemoveHandler(callbackFunction oldFunc)
 {
  for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++)
  {
   if((*it) == oldFunc)
   {
    callbacks.erase(it);
    break;
   }
  }

 }

private:
 std::vector<callbackFunction> callbacks;
};


int main()
{
 HasCallback hc;
 ReceivesCallback rc;
 rc.AddCallback(boost::bind(&HasCallback::CallBackFunction, &hc, _1));
 hc.value = 123;



 HasCallback hc2;
 rc.AddCallback(boost::bind(&HasCallback::CallBackFunction, &hc2, _1));
 hc2.value = 321;

 int a = 0;

 rc.RemoveHandler(boost::bind(&HasCallback::CallBackFunction, &hc2, _1));
 rc.execute(a);
}

У меня проблема в том, что это даже не компилируется. Он завершается с ошибкой в ​​ReceivesCallback :: RemoveHandler в строке if ((* it) == oldFunc) с ошибкой, говорящей о том, что существует несколько перегрузок оператора == для того, что я пытаюсь сделать. Я продолжаю искать это и не могу найти, что я делаю неправильно. Кроме того, я продолжаю находить противоречивую информацию, один говорит, что можно сравнить boost :: function-s, а другой - нет. Я могу видеть оператор == функции в boost / function_base.hpp, и я считаю, что это должно сработать, я просто не могу понять, как. Может ли кто-нибудь помочь мне здесь? Я подозреваю, что это не удается, потому что параметры boost :: bind необходимо указать полностью (быть конкретными значениями), но это то, что я не могу получить в разрабатываемом коде, мне просто нужно знать, передан ли обработчик зарегистрирован или нет, так как я привязан к объекту, он должен иметь всю информацию, необходимую для проведения различия.

1 Ответ

1 голос
/ 08 декабря 2010

См. FAQ по Boost.Function для объяснения: Почему я не могу сравнить boost::function объекты с operator== или operator!=? .

Boost.Functions обеспечивает только сравнениеboost::function с произвольным функциональным объектом.Я полагаю, что создание вашего RemoveHandler шаблона функции-члена могло бы решить проблему:

 template<class Functor>
 void RemoveHandler(const Functor &oldFunc)
 {
     for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++)
     {
         if((*it) == oldFunc)
         {
             callbacks.erase(it);
             break;
         }
     }
 }

Здесь oldFunc получает возможность сохранить свой фактический тип без «обертывания» в boost::function.

...