Skip to content

Instantly share code, notes, and snippets.

@DariusL
Last active September 27, 2020 14:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save DariusL/0b2d9acde176a145d379 to your computer and use it in GitHub Desktop.
Save DariusL/0b2d9acde176a145d379 to your computer and use it in GitHub Desktop.
Generic observer pattern implementation in c++
#pragma once
#include <list>
#include <unordered_map>
#include <functional>
using namespace std;
template<typename... Args>
class Observers
{
public:
using funcs = list<function<void(Args...)>>;
using it = typename funcs::const_iterator;
private:
static unordered_map<int, funcs> observers;
public:
class ObserverScopeRef;
Observers() = delete;
template<typename Observer>
static ObserverScopeRef Register(int ev, Observer &&observer)
{
auto &f = observers[ev];
f.push_back(forward<Observer>(observer));
return ObserverScopeRef(ev, prev(f.end()));
}
static void Notify(int ev, Args... args)
{
try
{
auto &obs = observers.at(ev);
for (auto &o : obs)
o(args...);
}
catch (...){}
}
private:
static void Remove(int key, it iterator)
{
observers[key].erase(iterator);
}
public:
class ObserverScopeRef
{
it iterator;
int key;
bool init;
using Parent = Observers<Args...>;
public:
ObserverScopeRef(int key, it iterator) : key(key), iterator(iterator), init(true){}
ObserverScopeRef() : init(false){}
~ObserverScopeRef()
{
if (init)
Parent::Remove(key, iterator);
}
ObserverScopeRef(ObserverScopeRef&) = delete;
ObserverScopeRef(ObserverScopeRef &&other)
:key(other.key), iterator(other.iterator), init(other.init)
{
other.init = false;
}
ObserverScopeRef& operator=(ObserverScopeRef&) = delete;
ObserverScopeRef& operator=(ObserverScopeRef &&other)
{
if (this != &other)
{
init = other.init;
key = other.key;
iterator = other.iterator;
other.init = false;
}
return *this;
}
};
};
template<typename... Args>
unordered_map<int, typename Observers<Args...>::funcs> Observers<Args...>::observers;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment