Loss of reference

18 hours ago 3
ARTICLE AD BOX

I am studying c++, but currently I can not solve the following issues yet, so be patient. Basically I am trying to create a event emitter similar to the nodejs, but there is some flaw related to loss of reference in my current code. The code is the following:

// emitter.cc // ------------------------------------------------------ #include "event/emitter.h" namespace game { void Emitter::on(std::string eventName, Listener *listener) { std::list<Listener *> *listenersByEventName; try { listenersByEventName = listeners.at(eventName); } catch (const std::out_of_range &ex) { listenersByEventName = new std::list<Listener *>; listeners.insert({eventName, listenersByEventName}); } listenersByEventName->push_back(listener); }; void Emitter::off(std::string eventName, Listener *listener) { try { std::list<Listener *> listenersByEventName = *listeners.at(eventName); std::list<Listener *>::iterator iterator = listenersByEventName.begin(); while (iterator != listenersByEventName.end()) { if ((*iterator)->name == listener->name) { iterator = listenersByEventName.erase(iterator); break; } iterator++; } } catch (const std::out_of_range &ex) { // do nothing } }; void Emitter::emit(Event event) { try { std::list<Listener *> listenersByEventName = *listeners.at(event.name); for (auto listener : listenersByEventName) { listener->function(event); } } catch (const std::out_of_range &ex) { // do nothing } }; } // namespace game // emitter.h // ------------------------------------------------------ #pragma once #include <functional> #include <list> #include <map> #include <stdexcept> #include <string> #include "event/event.h" #include "event/listener.h" namespace game { class Emitter { public: std::map<std::string, std::list<Listener *> *> listeners; void on(std::string eventName, Listener *listener); void off(std::string eventName, Listener *listener); void emit(Event event); }; } // namespace game // unit test file main.cc // ------------------------------------------------------ TEST_CASE("Emitter should work properly", "[event][emitter]") { game::Emitter emitter; std::string eventName0 = "event-0"; std::string listenerName0 = "listener-0"; std::map<std::string, int> calls = {{listenerName0, 0}}; game::Listener *listener0 = new game::Listener{ "listener-0", [calls, listenerName0](game::Event event) mutable { calls[listenerName0]++; }}; SECTION("when adding a listener") { emitter.on(eventName0, listener0); REQUIRE(emitter.listeners.size() == 1); }; SECTION("when emitting a event") { REQUIRE(emitter.listeners.size() == 1); <= Issue here !0 == 1 game::Event event{eventName0, {}}; emitter.emit(event); REQUIRE(calls[listenerName0] == 1); <= Issue here !0 == 1 }; SECTION("when removing a listener") { emitter.off(eventName0, listener0); REQUIRE(emitter.listeners.size() == 0); }; delete listener0; }

The issue is at the unit test. Basically emitter map losses its reference to a std::list, I think. How to solve this? Obs: As I didn't study destructors, the code is not releasing the allocated std::list.

Read Entire Article