Skip to content

Instantly share code, notes, and snippets.

@thai-ng
Created August 22, 2017 17:49
Show Gist options
  • Save thai-ng/aa033a633e5425b3a5c51328bc16fc5e to your computer and use it in GitHub Desktop.
Save thai-ng/aa033a633e5425b3a5c51328bc16fc5e to your computer and use it in GitHub Desktop.
#include <vector>
#include <iostream>
#include <memory>
#include <algorithm>
#include <type_traits>
using namespace std;
class EventHandler
{
public:
template <typename Instance,
typename Function,
typename = enable_if_t<is_member_function_pointer_v<Function>>>
EventHandler(Instance i, Function f) : self_(new model<Instance, Function>(i, f)) {}
void operator() ()
{
(*self_)();
}
bool operator== (const EventHandler& other) const
{
return (*self_) == (*(other.self_));
}
private:
struct concept_t
{
virtual ~concept_t() = default;
virtual void operator() () = 0;
virtual bool operator== (const concept_t& other) const = 0;
};
template <typename I, typename F>
struct model : concept_t
{
model(I x, F f) : instance_(move(x)), function_(move(f)) {}
void operator() () override
{
(instance_->*function_)();
}
bool operator== (const concept_t& other) const override
{
if (typeid(*this) == typeid(other))
{
auto o = static_cast<const model&>(other);
return instance_ == o.instance_ && function_ == o.function_;
}
return false;
}
I instance_;
F function_;
};
unique_ptr<concept_t> self_;
};
class Event
{
public:
void addEventHandler(EventHandler handler)
{
if (find(begin(handlers), end(handlers), handler) == end(handlers))
{
handlers.emplace_back(move(handler));
}
else
{
cout << "Handler already exist\n";
}
}
void fire()
{
for (auto& handler : handlers)
{
handler();
}
}
private:
vector<EventHandler> handlers;
};
class Actor
{
int id;
public:
Actor(int i) : id(i) {}
void DoTheThing()
{
cout << "Actor "<< id << " doing the thing\n";
}
void DoAnotherThing()
{
cout << "Actor " << id << " doing another thing!\n";
}
};
void doTheThing()
{
cout << "Free do the thing\n";
}
int main()
{
auto actor1 = make_unique<Actor>(1);
auto actor2 = make_unique<Actor>(2);
Event myEvent;
myEvent.addEventHandler(EventHandler(actor1.get(), &Actor::DoTheThing));
myEvent.addEventHandler(EventHandler(actor2.get(), &Actor::DoTheThing));
myEvent.addEventHandler(EventHandler(actor1.get(), &Actor::DoTheThing));
// myEvent.addEventHandler(EventHandler(actor1.get(), &doTheThing)); // Error: Not a member function
myEvent.fire();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment