I am trying to write a simple dispatcher, the user code can attach callbacks to it. Each event has a known signature, and the user code will need to call dispatch with the right number and argument types. This is managed by the variadic arguments. But, freestandingInt is not accepted, as the vector is not of the right type. How to make it generic?
Follows a minimal example
void freestanding() {
std::cout << "freestanding" << std::endl;
}
void freestandingInt(int iArg) {
std::cout << "freestandingInt " << iArg << std::endl;
}
struct Dispatcher {
typedef struct Event_ {
std::vector<std::function<void()> > listeners;
} Event;
template<class... Args>
void dispatch(int eventNr, Args&&... args) {
for (auto listener: events[eventNr].listeners) {
std::function<void()> f(std::bind(listener, std::forward<Args>(args)...));
f();
}
}
std::map<int, Event> events;
};
int main (int argc, char **argv) {
Dispatcher disp;
disp.events[0].listeners.push_back(freestanding);
disp.dispatch(0); // OK
// error here
//disp.events[1].listeners.push_back(freestandingInt);
}
Here is an approach based on making a
std::multimap
from thestd::type_index
of the function to astd::function
of the appropriate type:Output:
Additional approach is using std::bind
more on that in this amazing post: https://oopscenities.net/2012/02/24/c11-stdfunction-and-stdbind/