J'ai fait cela avec std :: function et std :: bind ..
J'ai écrit cette classe EventManager qui stocke un vecteur de gestionnaires dans un unordered_map qui mappe les types d'événement (qui sont simplement const unsigned int, j'ai une grande énumération à la portée de l'espace de noms) à un vecteur de gestionnaires pour ce type d'événement.
Dans ma classe EventManagerTests, j'ai configuré un gestionnaire d'événements, comme ceci:
auto delegate = std::bind(&EventManagerTests::OnKeyDown, this, std::placeholders::_1);
event_manager.AddEventListener(kEventKeyDown, delegate);
Voici la fonction 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;
}
Voici la définition du type EventHandler:
typedef std::function<void(Event *)> EventHandler;
Puis de retour dans EventManagerTests :: RaiseEvent, je fais ceci:
Engine::KeyDownEvent event(39);
event_manager.RaiseEvent(1, (Engine::Event*) & event);
Voici le code pour 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);
}
);
}
}
Cela marche. Je reçois l'appel dans EventManagerTests :: OnKeyDown. Je dois supprimer les vecteurs au moment du nettoyage, mais une fois que je le fais, il n'y a pas de fuites. Le déclenchement d'un événement prend environ 5 microsecondes sur mon ordinateur, ce qui est vers 2008. Pas vraiment très rapide, mais. Aussi longtemps que je le sais et que je ne l'utilise pas dans du code ultra chaud.
J'aimerais l'accélérer en lançant mes propres std :: function et std :: bind, et peut-être en utilisant un tableau de tableaux plutôt qu'une unordered_map de vecteurs, mais je n'ai pas tout à fait compris comment stocker une fonction membre pointeur et appelez-le à partir d'un code qui ne sait rien de la classe appelée. La réponse de Eyelash semble très intéressante.