I have implemented a class called MethodMap that allows me to store member function pointers of a class and call them at runtime using a key string. The member function can take any parameters or not at all. The class looks like this:
template <typename T, typename... Args>
class MethodMap {
private:
std::unordered_map<std::string, std::function<void(T*, Args...)>> method_map;
public:
void Insert(const std::string& key, void (T::* method)(Args...)) {
method_map[key] = [method](T* obj, Args... args) { (obj->*method)(args...); };
}
void Call(const std::string& key, T* instance, Args&&... methodArgs) const {
auto it = method_map.find(key);
if (it != method_map.end()) {
auto& func = it->second;
// use tuple to store and forward the arguments
std::tuple<Args...> arg_tuple(std::forward<Args>(methodArgs)...);
std::apply(func, std::tuple_cat(std::make_tuple(instance), arg_tuple));
return;
}
std::cerr << "Error: method '" << key << "' not found" << std::endl;
}
};
The Insert method inserts a member function pointer to the map, and the Call method calls the member function with the given key and arguments.
It works well, but I realized that I need to create a different instance of MethodMap for every member function pointer that takes different arguments. For example, if I have the following member functions:
class MyClass {
public:
void Method1(int x);
void Method2(double d);
void Method3(int x, const std::string& s);
void Method4();
};
I would need to create a different instance of MethodMap for each member function pointer because they have different argument lists. For example:
MethodMap<MyClass> methodmap;
MyClass myClass;
methodmap.Insert("key", &MyClass::Method4);
methodmap.Call("key", &myClass);
MethodMap<MyClass, int> methodmapWithParameters;
methodmapWithParameters.Insert("key", &MyClass::Method1);
methodmapWithParameters.Call("key", &myClass, 1);
Is there a way to handle this with a single instance of MethodMap?
I did encounter similar questions, but in all of them the parameters given were always the same and I'm having trouble to generalize this myself.
MyClass(i.e., static would do) or do you plan to have multiple instances?member_base_ptrthat is virtual, and that one can store in your map as pointer (ideally some kind of managed pointer so that it is properly released), from that you can extend amember_ptrwith the types you need. In youCallyou look up for thatmember_base_ptrand try to do adynamic_castto thatmember_ptrif it is successful, you then can forward the call to that one.methodmapWithParameters.Call("key", &myClass, 1);is correct, ormethodmapWithParameters.Call("key", &myClass, 1, 2, 3, 49);is correct, ormethodmapWithParameters.Call("key", &myClass, "what", "is", "going". "on")is correct?