I made this simple event system:
template<typename Func, typename Args>
class Event
{
public:
static void dispatch(Args args) noexcept
{
for (auto listener : listeners)
listener.second(args);
}
static void attach(const std::string& id, Func func) noexcept
{
listeners.insert({ id, func });
}
static void dettach(const std::string& id) noexcept
{
listeners.erase(id);
}
private:
static std::unordered_map<std::string, Func> listeners;
};
template<typename Func, typename Args>
std::unordered_map<std::string, Func> Event<Func, Args>::listeners;
What I wanted to do is to let me create any sort of event without needing to do a lot more code.
so for example in this code, if I want to add a KeyEvent, for example, I could do this:
struct KeyArguments {
int key;
int state;
};
class KeyEvent : public Event<std::function<void(const KeyArguments&)>, KeyArguments>
{
};
And to use such code:
KeyArguments args;
args.key = Key::A;
args.state = State::KeyUp;
KeyEvent::attach("new", func);
KeyEvent::attach("new2", [](KeyArguments args) { std::cout << "The key that was pressed is " << args.key;});
KeyEvent::dispatch(args);
KeyEvent::dettach("new2");
KeyEvent::dispatch(args);
I also wanted to make the design reachable from anywhere in the code, this is why I used static keyword, and this is the part that doesn't really "feel" good.
Should I really be using static in this case? Is there any cons in using such design?
I feel like using templatefor this case is a bit overkill. For each event create a "new" class (the struct doesn't bother me). Do you think there is a way around that? Is it as bad as I think it is?
EDIT: The design goal was to create an event system that anyone could attach to and get notified when the specific event has happened.
For example in a game we would like to distribute an event for KeyPress, so the event system (in the engine) would let the game programmer attach the Player::input function to it, and if he would like, Menu::input as well. Both of them will get notified when a KeyPress event has happened.
KeyEventclass. \$\endgroup\$attachthan the one defined in yourEventclass. 2) You didn't explain what you want, but usually an event manager uses the id to raise a specific event i.e. call all the function pointers registered for a specific event id. Here, yourdispatchfunction doesn't use thestd::stringkey in themap. So when you dispatch events, the class will dispatch all the events with the same parameters (all the function pointers that this class stored), whatever the name of the event is. \$\endgroup\$KeyEvent(in a game) will call every function that attached to it to let them know a key was pressed. \$\endgroup\$