Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ store a pointer to a member function of unknown class

I want to store a pointer to an object and a pointer to it's method of known signature. If I know the class then this pointer have type:

int (MyClass::*pt2Member)(float, char, char)

But how can i store the pointer if i don't know the type?

I want to do something like this:

myObject.callThisFuncLater(&otherObject, &otherObject::method)

How can i store a pointer to method method in myObject and call it later ?

like image 548
Andrew Avatar asked Oct 16 '11 19:10

Andrew


2 Answers

The easiest way to do it if you have access to the TR1 STL library extensions (available on gcc and Visual Studio 2008 and onwards is. std::function and std::bind can be used to wrap an invocation which can be called later. This functionality is also available in boost function and boost bind:

#include <functional>

class MyClass {
public:
  template<typename T> callThisFuncLater(T& otherObject,
                                         int(T::*)(float, char, char) method) {
    return storedInvocation_ = std::bind(otherObject, 
                                  method, 
                                  std::placeholders::_1,   // float
                                  std::placeholders::_2,   // char
                                  std::placeholders::_3);  // char
  }

  int callStoredInvocation(float a, char b, char c) {
    storedInvocation_(a, b, c);
  }

private:
  std::function<int(float, char, char)> storedInvocation_;
};
like image 148
Brian Coleman Avatar answered Sep 19 '22 09:09

Brian Coleman


There is no simple way of doing this as originally built into the language or standard library (although, it has recently been added). If you're familiar with Boost, they include a solution for this - Boost.Function.

If for some reason, however, you're unable or unwilling to use Boost, there is a generic way of doing this using templates (which, admittedly, is rather similar to Boost's solution):

class FncPtr
{
public:
    virtual int call(float, char, char) = 0;
};

template <typename T>
class ClassFncPtr : public FncPtr
{
     int (T::*pt2Member)(float, char, char);
     T *inst;
public:
     ClassFncPtr(T* who, int (T::*memfunc)(float,char,char))
         : inst(who), pt2Member(memfunc)
     {
     }
     int call(float a, char b, char c)
     {
         return (inst->*pt2Member)(a,b,c);
     }
};

template <typename T>
FncPtr * makeFuncPointer(T* who, int (T::*memfunc)(float,char,char))
{
    return new ClassFncPtr<T>(who,memfunc);
}

You can also subclass FncPtr to be able to use non-class functions, if you'd like.

like image 34
Nate Avatar answered Sep 21 '22 09:09

Nate