Сравнение указателей функций, сохраненных как boost :: function

У меня есть список объектов boost :: function, и я пытаюсь найти конкретный, чтобы я мог удалить его из списка. Эффективно функция регистрируется (помещается в вектор), и я хочу иметь возможность отменить ее регистрацию (поиск в векторе и удаление указателя на соответствующую функцию). Вот код:

#include <string>
#include <vector>

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>

class DummyClass
{
public:
std::string Data;
};
typedef boost::shared_ptr<DummyClass> DummyClassPtrType;

class UpdaterClass
{
public:
void handle(DummyClassPtrType Dummy);
};

class ManagerClass
{
public:
typedef boost::function<void (DummyClassPtrType Dummy)> HandlerFunctionType;
typedef std::vector<HandlerFunctionType> HandlerFunctionListType;
//
HandlerFunctionListType HandlerFunctionList;
void registerHandler(HandlerFunctionType Handler)
{
HandlerFunctionList.push_back(Handler);
}
void unRegister(HandlerFunctionType Handler)
{
// find the function pointer in the list and delete it from the list if found
HandlerFunctionListType::iterator HandlerIter = HandlerFunctionList.begin();
while (HandlerIter != HandlerFunctionList.end())
{
if (*HandlerIter == Handler) // error C2666: 'boost::operator ==' : 4 overloads have similar conversions
{
HandlerIter = HandlerFunctionList.erase(HandlerIter);
break;
}
else
{
++HandlerIter;
}
}
}
};

int main()
{
ManagerClass Manager;
UpdaterClass Updater;
Manager.registerHandler(boost::bind(&UpdaterClass::handle, &Updater, _1));
Manager.unRegister(boost::bind(&UpdaterClass::handle, &Updater, _1));
return 0;
}

Компилятору (VS2008 SP1) не нравится строка:

if (*HandlerIter == Handler)

и я не могу понять, как этого добиться.

1

Решение

В дополнение к ответу Якка, другим обычным способом реализации этого является сохранение итератора для элемента в контейнере (этот итератор действует по «токену», о котором говорит Якк).

Поскольку вы, возможно, удаляете и добавляете другие элементы перед тем, как удалять конкретный элемент, вы должны выбрать контейнер, который не делает недействительными его итераторы при вставке / удалении. std::vector явно не подходит для этого, но std::list является.

Ваш registerHandler Функция просто должна вернуть итератор, возвращенный std::list::insert, а также unregisterHandler будет просто вопрос вызова HandlerFunctionList.erase(iteratorToken);,

Единственным недостатком этой реализации является то, что, в отличие от Yakk, он не использует словарь для хранения токенов, поэтому он не может заранее проверить действительность токена и что-то пойдет не так, если пользователь передаст неверный итератор вашему unregisterHandler,

Однако положительным моментом является повышение производительности, поскольку он полностью избегает использования промежуточного словаря.

Выбери свой яд.

2

Другие решения

При регистрации обратных вызовов строите токены (я обычно использую направляющие или int) и вернуть их вызывающей стороне.

Вызывающий, желающий удалить обратный вызов, должен использовать этот токен для выполнения запроса.

Это позволяет зарегистрировать один и тот же указатель на функцию дважды, среди прочего, с разными идентификаторами.

Если вы используете 64-битные целые числа и просто ослепляете с приращением каждого токена, и вы регистрируете 1 миллион функций на каждый кадр, и вы работаете со скоростью 1000 кадров в секунду, и вы оставляете свой код работающим в течение 100 тысяч лет, обтекание не произойдет. В 1 миллион лет это будет. Решите, используете ли вы полный гид или int в результате чего вы ищете пробелы и перерабатываете их, стоит.

Другой вариант заключается в использовании std::unique_ptr<char>( new char() ) злоупотреблять кучей и сделать свой токен void*,

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector