Created
May 19, 2021 15:53
-
-
Save jay-tux/ab547ad6750a34f68ccc9f030ff1c6e5 to your computer and use it in GitHub Desktop.
A simple, customizable, easy-to-use and subscribable event type in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef EVENT_H | |
#define EVENT_H | |
#include <vector> | |
#include <functional> | |
namespace jay { | |
//event class. Supports adding handlers and invoking them | |
template<class ... types> | |
class Event { | |
public: | |
//the cheap callback type; a raw function pointer | |
typedef void (*cheapCall)(types ...); | |
//the expensive callback type; an std::function object | |
typedef std::function<void(types ...)> expCall; | |
//creates a new event | |
Event() : cheapCalls{std::vector<cheapCall>()}, expCalls{std::vector<expCall>()} {} | |
//adds a cheap callback to this event | |
void add(const cheapCall callback) { cheapCalls.push_back(callback); } | |
//adds an expensive callback to this event | |
void add(const expCall callback) { expCalls.push_back(callback); } | |
//invokes the event, calling all handlers | |
void invoke(types ... args) { | |
for(auto callback : cheapCalls) callback(args...); | |
for(auto callback : expCalls) callback(args...); | |
} | |
//invokes the event using the operator | |
Event &operator()(types ... args) { invoke(args...); return *this; } | |
private: | |
std::vector<cheapCall> cheapCalls; | |
std::vector<expCall> expCalls; | |
}; | |
//event exposing wrapper. Keeps actual event hidden from implementers | |
template<class ... types> | |
class ExposedEvent { | |
public: | |
//the event type | |
typedef Event<types ...> eventType; | |
//creates a new exposed event | |
ExposedEvent(eventType &event) : internal{event} {} | |
//adds a cheap callback to the underlying event | |
ExposedEvent &operator+=(const typename eventType::cheapCall callback) { | |
internal.add(callback); | |
return *this; | |
} | |
//adds an expensive callback to the underlying event | |
ExposedEvent &operator+=(const typename eventType::expCall callback) { | |
internal.add(callback); | |
return *this; | |
} | |
private: | |
Event<types...> &internal; | |
}; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In a typical OOP situation (where you'd want to hide the invocation from subscribers), you'll make a
private
field for theEvent
and then expose it to the outside world (and subscribers) through apublic
field containing a matchingExposedEvent
:Subscribers can't fire the event, only the class itself can, but they can still subscribe like so: