#pragma once #include #include namespace socket { /* Allows casting R(Args...) */ template class Socket; /* A class that represents a socket that can be used to dispatch a function call to different handlers. Handlers can be connected and disconnected from the socket at runtime. */ template class Socket { /* The type of handler function or methods */ using HandlerType = std::function; /* The next handler descriptor to be assigned the descriptor can be used to disconnect a descriptor */ int descriptor; /* Map between descriptors and handlers */ std::map handlers; public: /* Connect a handler to the socket handler: the handler to connect to Returns the handler descriptor */ int connect(HandlerType handler) { // Get the handler descriptor of next handler int hd = descriptor++; // Store the handler handlers[hd] = handler; return hd; } /* Connect a handler to the socket and bind the call to an object, this can be useful if the handler is a method */ template int connect(T *object, R (V::*handler)(Args...)) { auto f = [=](Args... args) { return std::invoke(handler, object, args...); }; return connect(f); } /* Disconnect a handler from the socket hd: the handle descriptor of the handler to disconnect */ void disconnect(int hd) { // Remove the handler from the map handlers.erase(hd); } /* Dispatch a call to all handlers */ void operator()(Args... args) { for (auto &handler : handlers) handler.second(args...); } }; }