Invoking functions with a map question

I’m invokeing some functions with a unordered map by a string:

1
2
3
4
5
6
 MyConstructor() {
    functionMap["Init1"] = &MyClass::Init1;
    functionMap[“Init2”] = &MyClass::Init2; 
  };

std::unordered_map<std::string, void(MyClass::*)()> functionMap;


And to call it I just use:

1
2
if (functionMap.find(CommandArgument) != functionMap.end())
      (this->*(functionMap[CommandArgument]))();


The problem that I am having is this works fine if all the functions are contained in ‘MyClass’ but say I want to call an init function from multiple classes like so:

1
2
3
4
 MyConstructor() {
    functionMap["Init1"] = &MyClass1::Init;
    functionMap[“Init2”] = &MyClass2::Init; 
  };


How can I create my unordered map in order for it to contain different classes and not just “MyClass”. Is this possible?
Last edited on
Do MyClass1 and MyClass2 have a single common base class?
That's what originally my solution would have been, I was thinking that I could use a BaseClass but I still don't know how I could override that in the functionMap.

Is this possible?
Last edited on
For example,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>

class A{
public:
    virtual void f() = 0;
};

class B : public A{
public:
    void f(){
        std::cout << "B::f()\n";
    }
};

class C : public A{
public:
    void f(){
        std::cout << "C::f()\n";
    }
};

typedef void (A::*fp)();

int main(){
    fp array[] = {
        &A::f,
        &A::f,
    };
    B b;
    C c;
    
    (b.*array[0])();
    (c.*array[0])();
    (b.*array[1])();
    (c.*array[1])();
    
    return 0;
}

Note that if it's necessary for some reason, the array can also be populated like this:
1
2
3
4
fp array[] = {
    static_cast<fp>(&B::f),
    static_cast<fp>(&C::f),
};
static_cast<fp>(&B::f) == static_cast<fp>(&C::f) == &A::f
Okay, I see how I can do this with an function pointer array, but I don't see how I can invoke it by using a string (Using the map to have functions mapped to strings).

The way you shown me is good, and thank you!
But it's not generic since I still have to call each array directly from its own class too, and it defeats the purpose of why I have the map. (I have the map since I have a bunch of arguments, I don't want to deal with an if statement).
Doing it with a map is basically the same as what I've shown above. Just declare your map and populate it.
1
2
3
4
5
6
std::map<std::string, fp> map;
map["f"] = &A::f;
map["g"] = &A::g;

B b;
(b.*map["f"])();


But it's not generic since I still have to call each array directly from its own class too
You could use std::function, then.
1
2
3
4
5
6
7
8
B b;
C c;
std::map<std::string, std::function<void()>> map;
map["f1"] = [&b](){ b.f(); };
map["f2"] = [&c](){ c.f(); };

map["f1"]();
map["f2"]();
Note that the std::functions become uncallable if the bound objects go out of scope, so be careful with that. Alternatively, std::shared_ptr could be used:
1
2
3
4
5
6
7
8
auto b = std::make_shared<B>();
auto c = std::make_shared<C>();
std::map<std::string, std::function<void()>> map;
map["f1"] = [b](){ b->f(); };
map["f2"] = [c](){ c->f(); };

map["f1"]();
map["f2"]();
This way, the functions will always stay valid.
Thank you so much!
Topic archived. No new replies allowed.