関数の から をstd::multimap
適切な型の にすることに基づくアプローチを次に示します。std::type_index
std::function
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <typeindex>
void freestanding() {
std::cout << "freestanding" << std::endl;
}
void freestandingInt(int iArg) {
std::cout << "freestandingInt " << iArg << std::endl;
}
// Base class for all functions so that we can store all functions
// in a single container.
struct Function {
virtual ~Function() { }
};
// Derived class template for functions with a particular signature.
template <typename T>
struct BasicFunction : Function {
std::function<T> function;
BasicFunction(std::function<T> function) : function(function) { }
};
// Generic container of listeners for any type of function
typedef std::multimap<std::type_index,std::unique_ptr<Function> > Listeners;
template <typename Func>
static void addListener(Listeners &listeners,Func &function)
{
std::type_index index(typeid(Func));
std::unique_ptr<Function>
func_ptr(new BasicFunction<Func>(std::function<Func>(function)));
listeners.insert(Listeners::value_type(index,std::move(func_ptr)));
}
template <typename... Args>
static void callListeners(const Listeners &listeners,Args&&... args)
{
typedef void Func(typename std::remove_reference<Args>::type...);
std::type_index index(typeid(Func));
Listeners::const_iterator i = listeners.lower_bound(index);
Listeners::const_iterator j = listeners.upper_bound(index);
for (;i!=j; ++i) {
const Function &f = *i->second;
std::function<Func> func =
static_cast<const BasicFunction<Func> &>(f).function;
func(std::forward<Args>(args)...);
}
}
struct Dispatcher {
typedef struct Event_ {
Listeners listeners;
} Event;
template<class... Args>
void dispatch(int eventNr, Args&&... args) {
callListeners(events[eventNr].listeners,std::forward<Args>(args)...);
}
std::map<int, Event> events;
};
int main (int argc, char **argv) {
Dispatcher disp;
addListener(disp.events[0].listeners,freestanding);
addListener(disp.events[0].listeners,freestandingInt);
disp.dispatch(0,5);
}
出力:
freestandingInt 5