简体   繁体   中英

Generic member function pointer

I'm wondering if there's a way in standard C++ (it seems this is not supported but perhaps I didn't look hard) to declare a pointer to any class' member function with the same signature. For example, X and Y have echoX and echoY methods with the same signature

class X{
  int val;
public:
 int echoX(int v)  {
 val = v;
 return v; }
   int getValue() const { return val; }
};

class Y{

   int val;
   public:
   int echoY(int v)  {
   val = v;
   return v;
   }
   int getValue() const { return val; }
};

Some C++ implementations allow this functionality via extensions (eg VCL makes use of the __closure keyword).

typedef int (__closure *IntFunPtr)(int);

Now, it's trivial to write a function that is able to call either X::echoX or Y::echoY

void CallObjectMethod(IntFunPtr fPtr, int val){

    fPtr(val);//this can call any member method that accepts an int and returns an int
}


X x, x1;
CallObjectMethod(&x.echoX,4);
CallObjectMethod(&x1.echoX,20);

Y y, y1;
CallObjectMethod(&y.echoY,10);
CallObjectMethod(&y1.echoY,15);

This functionality can be useful for implementing event handlers, among other things.

Thank you

"For example, X and Y have echoX and echoY methods with the same signature"

Afaik they dont have the same signature, they have an implicit first argument to the class instance. Usually you would choose an std::function to get rid of the first argument.

#include <functional>

class X { public: int echoX(int v) {return v; } };

class Y { public: int echoY(int v) {return v; } };

typedef std::function<int(int)> IntFunction;

int echo(IntFunction func, int v)
{
    return func(v);
}

int main()
{
    int v = 5;
    X x;
    Y y;
    int a = echo(std::bind(&X::echoX, x, std::placeholders::_1), v);
    int b = echo(std::bind(&Y::echoY, y, std::placeholders::_1), v);
}

You could create a generic templated function which accepts the signature you are interested in, pass in the instance of the object and the pointer to the member function. For example:

template<typename T>
void CallObjectMethod(int(T::*func)(int), T& obj, int val)
{
    cout << (obj.*func)(val);
}

Now to call it like you mentioned in your example:

X x, x1;
CallObjectMethod(&X::echoX, x, 10);
CallObjectMethod(&X::echoX, x1, 20);

For object Y you could do something like:

Y y, y1;
CallObjectMethod(&Y::echoY, y, 10);
CallObjectMethod(&Y::echoY, y1, 20);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM