#pragma once #include #include // TODO: Document & Explain this template class Event; template class EventConnection { private: using delegate = std::function; public: EventConnection(Event *creator, delegate cb) : owner(creator), callback(std::move(cb)) {} bool Disconnect(); // Breaks the event connection, but does not destroy the instance void Invoke(Args... e); private: Event * owner; delegate callback; bool active = true; }; template class Event { public: using delegate = std::function; using connection = EventConnection; using event_ptr = std::shared_ptr; public: void Await(Args& ... arg); void Invoke(Args... args); void operator()(Args... args); connection Connect(delegate callback); void Disconnect(connection &conn); connection operator+=(delegate callback); private: std::vector listeners; uint64_t listenerCounter = 0; }; template EventConnection Event::operator+=(Event::delegate callback) { return Connect(callback); } template void Event::operator()(Args... args) { Invoke(args...);} template void EventConnection::Invoke(Args... e) { callback(e...); } template bool EventConnection::Disconnect() { if (active) { owner->Disconnect(this); active = false; return true; } return false; } template void Event::Invoke(Args... args) { for (event_ptr &connection_ptr: this->listeners) { connection_ptr->Invoke(args...); } } template EventConnection Event::Connect(delegate callback) { event_ptr retval(new connection(this, callback)); this->listeners.push_back(retval); return *retval; } template void Event::Disconnect(connection &conn) { listeners.erase(std::remove(listeners.begin(), listeners.end(), 99), listeners.end()); }