Zrobiłem to za pomocą std :: function i std :: bind ..
Napisałem tę klasę EventManager, która przechowuje wektor programów obsługi w unordered_map, która mapuje typy zdarzeń (które są po prostu const unsigned int, mam ich duże wyliczenie w zakresie przestrzeni nazw) do wektora programów obsługi dla tego typu zdarzenia.
W mojej klasie EventManagerTests konfiguruję procedurę obsługi zdarzeń, taką jak ta:
auto delegate = std::bind(&EventManagerTests::OnKeyDown, this, std::placeholders::_1);
event_manager.AddEventListener(kEventKeyDown, delegate);
Oto funkcja AddEventListener:
std::vector<EventHandler>::iterator EventManager::AddEventListener(EventType _event_type, EventHandler _handler)
{
if (listeners_.count(_event_type) == 0)
{
listeners_.emplace(_event_type, new std::vector<EventHandler>());
}
std::vector<EventHandler>::iterator it = listeners_[_event_type]->end();
listeners_[_event_type]->push_back(_handler);
return it;
}
Oto definicja typu EventHandler:
typedef std::function<void(Event *)> EventHandler;
Następnie w EventManagerTests :: RaiseEvent robię to:
Engine::KeyDownEvent event(39);
event_manager.RaiseEvent(1, (Engine::Event*) & event);
Oto kod dla EventManager :: RaiseEvent:
void EventManager::RaiseEvent(EventType _event_type, Event * _event)
{
if (listeners_.count(_event_type) > 0)
{
std::vector<EventHandler> * vec = listeners_[_event_type];
std::for_each(
begin(*vec),
end(*vec),
[_event](EventHandler handler) mutable
{
(handler)(_event);
}
);
}
}
To działa. Otrzymuję wezwanie w EventManagerTests :: OnKeyDown. Muszę usunąć wektory, przyjść na czas czyszczenia, ale kiedy to zrobię, nie ma wycieków. Podniesienie zdarzenia zajmuje na moim komputerze około 5 mikrosekund, czyli około 2008 roku. Nie do końca superszybkie, ale. W porządku, o ile wiem o tym i nie używam go w bardzo gorącym kodzie.
Chciałbym to przyspieszyć, zwijając własne std :: function i std :: bind i być może używając tablicy tablic zamiast unordered_map wektorów, ale nie do końca wymyśliłem, jak przechowywać funkcję składową wskaźnik i wywołaj go z kodu, który nic nie wie o wywoływanej klasie. Odpowiedź rzęs wygląda bardzo interesująco.