Home > database >  C method resolution by name
C method resolution by name

Time:04-14

I am wondering if there is a way in C to write a function that will resolve object methods based on the method name alone (specific examples below). Run time or compile time resolution (such as templates) would both be acceptable. I have read a little bit about template metaprogramming, but I was hoping I might get some info as to whether that is even the appropriate direction for my problem before delving to deep into that.

Essentially, I am trying to write a function that will call non-static methods of a passed in object, such as this psuedocode:

exampleFunction(Object myObject, ObjectMethod myObjectMethod) {
    // do some stuff here

    myObject.myObjectMethod(arguments);

    // do some more stuff here
}

In this case, I cannot hard-code a method into exampleFunction and simply have every object that I call it with have that method name. I must have the flexibility to call exampleFunction with a variety of methods, and have each of those methods properly resolve. Further, I must be able to resolve methods, and those methods must be non-static. In my case, I must be able to modify internal, private object members on the method call. Without going into the details, these constraints are an artifact of the system I am working on that I cannot change.

As I previously stated, both compile time and run time solutions are acceptable. So something like this with templates would work perfectly well in my case as well:

template <ObjectMethodName methodName>
exampleFunction(Object myObject) {
    // do some stuff here

    myObject.methodName(arguments);

    // do some more stuff here
}

Any thoughts on whether this is possible, as well as information on possible implementation would be appreciated.

CodePudding user response:

You can make exampleFunction a function template that has the first parameter of type of the object, the second parameter can be a reference to a pointer to a member function and the third parameter is a function parameter pack that denotes the arguments to be passed when calling the member function.

#include <iostream>

class Actions {
  public:
    Actions(){}
    void doSmthg(){
        std::cout<<"do something called"<<std::endl;
    }
    void multipleArgs(int, int)
    {
        std::cout<<"multiple int args called"<<std::endl;
    }
};
class Entity
{
    public:
    void func(double)
    {
        std::cout<<"func called"<<std::endl;
    }
};
template<typename T, typename Callable, typename... Args>
void exampleFunction(T obj, const Callable& callable, const Args&... args){
    std::cout<<"exampleFunction called"<<std::endl;
    //call the function on the passed object
    (obj.*callable)(args...);
}


int main()
{
    Actions action;
    
    exampleFunction(action, &Actions::doSmthg); //calls doSmthg member function with 0 arguments 
    exampleFunction(action, &Actions::multipleArgs, 5,7);//calls multipleArgs member function with 2 int arguments
    
    Entity e;
    exampleFunction(e, &Entity::func,4.4); //calls func member function 
}

Demo

The output of the above program is:

exampleFunction called
do something called
exampleFunction called
multiple int args called
exampleFunction called
func called

CodePudding user response:

It's possible to pass a pointer-to-member-function as a template parameter.

Here is one example approach.

#include <iostream>

struct Foo {
    void print() {
        std::cout << "Foo\n";
    }

    void printVal(int val) {
        std::cout << "val = " << val << "\n";
    }
};

template <auto F, typename T, typename... Args>
void exampleFunc(T& obj, Args&&... args) {
    (obj.*F)(args...);
}

int main()
{
    Foo foo;
    exampleFunc<&Foo::print>(foo);
    exampleFunc<&Foo::printVal>(foo, 5);
}

Using auto template parameters requires c 17.

  • Related