5

Say I have the following class: (possibly meta-generated)

class MyClass
{
    public:
        myMethod(); 
    ...
}

Assuming a few things here:

1.) I have the class name from somewhere (let's pretend)
2.) I have the names of the class methods somewhere ( std::map< std::string, std::function> ... perhaps? )

So...since I may not know the name of myMethod() until runtime, is there a way to call it using a std::string ? This is assuming that I have the names of a class functions stored somewhere.

MyClass example;

std::string funcName{ findMyMethod() };//get std::string name of myMethod

example.someHowRunMyMethodUsing_funcName_();

I know C++ is generally not suited for introspection-like situations, but I'd like to figure this out.

Thanks!

3
  • Do the methods have same signature ? Commented Jul 10, 2015 at 7:48
  • Many different signatures, but I will have access to their string names. There may end up being some naming conventions to make it easier. Commented Jul 10, 2015 at 15:49
  • So, it seems that you need several maps, one by signature. Commented Jul 10, 2015 at 16:26

4 Answers 4

4

You can do that if you maintain map of std::string -> member function pointers.

std::map<std::string, void (MyClass::*)()> functionMap;
functionMap["myMethod"] = &MyClass::myMethod;

and later

// Get the function name from somewhere.
std::string name = getFunctionName();

// Get the object from somewhere.
MyClass* obj = getObject();

// Check whether there is a function corresponding to the function name.
auto iter = functionMap.find(name);
if ( iter != functionMap.end() )
{
    auto fun = iter->second;
    (obj->*fun)();
}
else
{
    // Deal with missing function.
}
Sign up to request clarification or add additional context in comments.

Comments

3

There are many ways, but using a map of member function pointers is probably among the most general for methods with the same signature.

#include <iostream>
#include <map>
#include <string>
using namespace std;

class My_class
{
public:
    void method_1() { wcout << "method_1\n"; }
    void method_2() { wcout << "method_2\n"; }
    void method_3() { wcout << "method_3\n"; }
};

auto method_name() -> string { return "method_3"; }

auto main() -> int
{
    map<string, void (My_class::*)()> methods =
    {
        { "method_1", &My_class::method_1 },
        { "method_2", &My_class::method_2 },
        { "method_3", &My_class::method_3 },
    };

    My_class example;
    (example.*methods.at( method_name() ))();
}

Supporting different signatures is much harder.

Then you would essentially be into DIY runtime type checking.

Comments

1

There is no built-in generic way to do this in C++.

The closest you can do is use virtual functions in C++ to achieve "late binding" however in that case you need to just through a lot of hoops.

http://www.thegeekstuff.com/2013/06/cpp-virtual-functions/

It is not as flexible as "call by name" that higher level languages like Ruby support.

In a dynamic library / module context you have a few more options using functions like dlopen but these are easier to use in C.

http://linux.die.net/man/3/dlopen

Comments

1

There is COM IDispatch interface, that implements exact the same functionality, so you could create you own analog of this interface and use it with your class.

interface IMyDispatch
{
public:
   virtual bool Invoke(const std::string, void*) = 0;
   virtual ~IMyDispatch() {};
};

///...

class CSomeClass : public IMyDispatch
{
public:
  void DoSomeCoolStuff() { /*some cool stuff here*/ };
public: //IMyDispatch
  bool Invoke(const std::string szName, void* pData)
  {
     if(szName == "DoSomeCoolStuff") //or methods map from the other ansvers
     {
        DoSomeCoolStuff();
        return(true);
     }

     return(false);
  }
}

int main()
{
  CSomeClass *pCl;
  IMyDispatch* pDisp = dynamic_cast<IMyDispatch*>(pCl);
  if(pDisp)
    pDisp->Invoke("DoSomeCoolStuff", nullptr);
}

Comments

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.