Jis
Jis

Reputation: 127

map to a function pointer with different number of arguments and varying datatypes

In my code, I have several class, each with different methods. For example:

class A {
public:
    int sum(int a, int b);
    bool isScalable(double d);
}

class B {
public:
    std:string ownerName();
}

My aim is to create a map of all the function names as below

std::map<std::string, FnPtr> myMap;

// Add the newly implemented function to this map
myMap["sum"] = &A::sum;
myMap["isScalable"] = &A::isScalable;
myMap["myMap"] = &B::myMap;

The issue is I am not aware how I can define FnPtr. Can you please help me out.

Upvotes: 0

Views: 196

Answers (1)

einpoklum
einpoklum

Reputation: 131586

As comments suggest, it is unlikely you really want to do this.

Assuming that you do, however - perhaps you should reconsider whether C++ is the right language for the task. Another language which has better runtime reflection facility might be more appropriate; perhaps an interpreted language like Python or Perl. Those are typically much more convenient when you need to look up class methods by name at runtime.

If it has to be C++, then perhaps you should relax the class structure somewhat. Use a single class for both A's and B's (lets call it MyCommonObj); and have the class hold a map of strings to function pointers. As for these functions' signatures - It's probably a good idea not to make the member functions, but freestanding ones. In that case, perhaps your function pointer type would be:

using generic_function = std::any (*)(std::vector<std::any>);

That's pretty generic - for storage and for invocation. If you have this map, you can easily look up your function name and pass the arguments. However, you might need to also keep additional information about what type your arguments should be, otherwise you'll always be passing strings. ... which is also an option, I suppose:

using generic_function = std::any (*)(std::vector<std::string>);

Now if the A and B members in your example are really non-static like you listed them, i.e. they use instance fields, then these generic functions must also always take a reference or pointer to an instance of MyCommonObj:

using generic_function = std::any (*)(MyCommonObj&, std::vector<std::string>);

Finally, note that code using this type, and run-time lookup of function names etc - will not be very performant.


If you're not using C++17 and don't have access to std::any, you can either:

  • Use boost::any from the Boost libraries.
  • Use an any-emulator library (which exist on GitHub)
  • Use a union of all the types you actually use, e.g. union {int i; double d;} - but then you'll need to protect yourself against passing values of the wrong type.

Upvotes: 1

Related Questions