1

I hope to use map library to call a function by a string with the function name, I've tested the following example and everything are working well.

#include <string>
#include <iostream>

using namespace std;

typedef void (*pFunc)();
map<string, pFunc> strFuncMap;

void func1()
{
    printf("this is func1!\n");
}

void buildMap()
{
    strFuncMap["func1"] = &func1;// 
}

void callFunc(const std::string& str)
{
    (*strFuncMap[str])();
}

int main()
{
    buildMap();

    callFunc("func1");
    return 0;
}

However, as I define all these things in a class, there is a compiler error occur:

#include <map>
#include <string>
#include <iostream>

using namespace std;

class theClass {
public:
    typedef void (*pFunc)();
    map<string, pFunc> strFuncMap;

    void func1()
    {
        printf("this is func1!\n");
    }

    void buildMap()
    {
        strFuncMap["func1"] = &func1;// a value of type cannot be assigned to an entity of type
    }

    void callFunc(const std::string& str)
    {
        (*strFuncMap[str])();
    }
};


int main()
{
    theClass a;
    a.buildMap();

    a.callFunc("func1");
    return 0;
}

I've tried to solve this problem for a couple of hours. Or is there any other way to use string to call function in a class? I will very appreciate if someone can help me. THANKS!!

1
  • Thank you so much! I found the mistake I did Commented Jul 10, 2021 at 1:33

2 Answers 2

3

Your code doesn't work because func1 is a member function and the syntax for member functions is different.

You need a map of member function pointers (offsets)

typedef void (theClass::*pFunc)();
map<string, pFunc> strFuncMap;

Then you can store the pointer with

strFuncMap["func1"] = &theClass::func1;

And you need an object to call a member function

(this->*strFuncMap[str])();

The final code:

#include <map>
#include <string>
#include <iostream>

using namespace std;

class theClass {
public:
    typedef void (theClass::*pFunc)();
    map<string, pFunc> strFuncMap;

    void func1()
    {
        printf("this is func1!\n");
    }

    void buildMap()
    {
        strFuncMap["func1"] = &theClass::func1;
    }

    void callFunc(const std::string& str)
    {
        (this->*strFuncMap[str])();
    }
};


int main()
{
    theClass a;
    a.buildMap();

    a.callFunc("func1");
    return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much! I will use your final code!
And if various objects and classes are involved, one would need do type erasure hacks in way similar to what some frameworks do for signal-slot architecture.
1
typedef void (*pFunc)();

This declares pFunc to be the type of function pointers. That is, the type of pointers to functions which exist at the top-level. This excludes member functions, lambda functions, and functors. Consider

using pFunc = std::function<void()>

Now your type will correctly accept anything that can reasonably be interpreted as a callable object. Note that member functions still need to be wrapped in a lambda, since you're closing around this.

strFuncMap["func1"] = [this]() { this->func1(); };

1 Comment

Thank you so much! I found the mistake I did

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.