C++: Function pointer that holds a method from a specific instance - c++

So I'm currently working on an input manager for a C++ game. I was thinking about doing it as a map<char, list<Listener::method>>, so that when I register a button pressed, I call all the methods registered for the specific key.
Problem is, done like that I have to specify the instance which I want to call the method from. Is there a way to hold inside a variable not only the method but the caller instance?
Something like:
class Foo
{
public:
Foo ();
~Foo ();
void DoSomething();
};
Foo fooObject;
void(Foo::*fPtr)(void) = &fooObject::DoSomething;
(*fPtr)();
And that would call fooObject's DoSomething()
Is it possible?
If not, could someone point me to a Event-Listener pattern? Doesnt have to be overcomplicated or threadsafe. Just the basic structure.

The problem with member function pointers is you need an instance of the class to call them on. You can't achieve this with just a pointer because the pointer only points to the function, and not the additional object you need to pass to the function (remember all member functions have an implicit first parameter that takes the class type).
You can use a std::function to have a function object that holds the object to call and the function to call on it. If you have
std::function<void()> func = [&](){ return fooObject.DoSomething(); }; // Bind with a reference. Use this if the object will live as long as the function to save on a copy
std::function<void()> func = [=](){ return fooObject.DoSomething(); }; // Bind with a copy. Use this if the function will outlive the object
then when you call func using func() it will run the body of he lambda which calls DoSomething on fooObject.
You can also use std::bind to bind a member function pointer to a object to call it on but lambdas are generally preferred as the syntax is easy to use.

Is there a way to hold inside a variable not only the method but the caller instance?
Yes, you can bind method and object together.
Since C++11 you have bind utility.
A minimal example from your concept:
struct Foo {
void foo();
};
void bar() {
// your map
std::map<char, std::function<void()>> actions;
// Bind method and object together inside fn
Foo foo;
auto fn = std::bind(&Foo::foo, &foo);
// Insert fn into map
actions.emplace('f', fn);
// call fn from map! Be careful about object lifetime
actions['f']();
}
Godbolt code
Be careful because the "bind object" (fn in my example) will just store a reference to the object foo. Therefore, if you invoke fn after the object foo has been destroyed you will get an undefined behaviour.
In case you want to take care about object lifetime, you can copy it with a lambda function. For example:
auto fn = [foo]() { foo.foo(); }
Or use a custom structure and store a copied object inside.

There is no such thing as a "method from a specific instance".
You can hold a pointer to a member function of a class. Such pointers are not bound to any specific object.
You can use that function pointer on any object of the class.
Given
class Foo
{
public:
Foo ();
~Foo ();
void DoSomething();
};
Any class can hold a pointer to the DoSomething member function (you're calling it a method).
void(Foo::*fPtr)(void) = &Foo::DoSomething;
You would need an object to be able to call the member function. The calling syntax is a bit obtuse but here it is.
Foo foo = <some function call>;
(foo.*fPtr)();

You could use the bind-functionality to get function object having function parameteras already bound to arguments. By that, you can bind the object reference, which is implicitly the first parameter in any non-static member function, to the respective object for which you'd like to have the callback:
class Foo
{
public:
int x;
Foo (int _x) : x(_x) {} ;
void doSomething() { cout << x << endl; }
};
int main() {
Foo fooObject1(1);
Foo fooObject2(2);
std::function<void ()> fx1 = std::bind(&Foo::doSomething,&fooObject1);
std::function<void ()> fx2 = std::bind(&Foo::doSomething,&fooObject2);
std::vector<std::function<void ()>> callbacks;
callbacks.push_back(fx1);
callbacks.push_back(fx2);
for (auto f : callbacks) {
f();
}
}
Output:
1
2

Related

C++: Store pointer to a member function of an object in another object

I have a class which shall invoke a function specified by the user on certain occasions. Therefore the class has a method void setExternalPostPaintFunction(void(*function)(QPainter&)); that can be used to "register" a function. This function then will be called on that occasion:
class A {
public:
void setExternalPostPaintFunction(void(*function)(QPainter&));
private:
void (*_externalPostPaint)(QPainter&);
bool _externalPostPaintFunctionAssigned;
};
The function pointer is saved in the member variable _externalPostPaint. The implementation of setExternalPostPaintFunction looks like this:
void A::setExternalPostPaintFunction(void(*function)(QPainter&)) {
_externalPostPaint = function;
_externalPostPaintFunctionAssigned = true;
}
Now, this works with normal functions. However, I want to be able to also pass pointers to member functions of objects. From what I know I also have to pass and store the pointer to the object in this case. However, I don't know which type the other object will have. So I guess I'm forced to use templates. I already thought of something like this:
class A {
public:
template <typename T>
void setExternalPostPaintFunction(void(T::*function)(QPainter&), T* object);
private:
void (T::*_externalPostPaint)(QPainter&); //<- This can't work!
bool _externalPostPaintFunctionAssigned;
};
This way I can pass a function pointer and an object pointer to setExternalPostPaintFunction and would probably be able to call the function on the object inside that function. But I'm not able to store it in the variable _externalPostPaint because the type T is only deduced when the function setExternalPostPaintFunction is called, thus I can't have a member variable that depends on this type, since the type of my member variable has to be known when the object is created and apart from that it cannot change, but it would have to in the case when a new function is assigned which possibly could be a member function of an object of different type.
So what is the proper way to do this, or is there any? I'm not super fit with templates and function pointers, so I might have overlooked something.
Anoter option would certainly be to create a functor class with a virtual member function which can be overwritten in a derived class and then pass + store an object pointer of that type instead of the function pointer. But I somehow would prefer my approach if it is somehow possible.
EDIT: SOLUTION
TartanLlama brought me on the right track by suggesting the use of std::function. Here is how I solved it:
class A {
public:
template <typename T>
void setExternalPostPaintFunction(T* object, void(T::*function)(QPainter&)) {
_externalPostPaint = std::bind(function, object, std::placeholders::_1);
_externalPostPaintFunctionAssigned = true;
}
void setExternalPostPaintFunction(std::function<void(QPainter&)> const& function);
private:
std::function<void(QPainter&)> _externalPostPaint;
bool _externalPostPaintFunctionAssigned;
};
As you see, the pointer to the function/member function is stored in an std::function<void(QPainter&)> object now. The advantage is, that an std::function can basically store any callable target. Then there are two overloads: one that can be used for any std::function object that also accepts e.g. a normal function pointer (because the std::function that is expected then is implicitly constructed from that) and one for member functions that have to be called on an object (more for convenience). The latter is implemented as a template. This uses std::bind to create a std::function object of the call of that member function (the user passed) on the object (the user passed).
The overload that takes an std::function is implemented in the source file like this:
void ImageView::setExternalPostPaintFunction(std::function<void(QPainter&)> const& function) {
_externalPostPaint = function;
_externalPostPaintFunctionAssigned = true;
}
Invoking that stored function in the code of class A is now as simple as that:
//canvas is a QPainter instance
if (_externalPostPaintFunctionAssigned) _externalPostPaint(canvas);
The user who wants to register a member function as callback function just has to do the following:
//_imageView is an instance of "A"
//"MainInterface" is the type of "this"
_imageView->setExternalPostPaintFunction(this, &MainInterface::infoPaintFunction);
Or if it's not a member function but just a normal function:
void someFunction(QPainter& painter) {
//do stuff
}
_imageView->setExternalPostPaintFunction(&someFunction);
Or he can explicitly create a std::function object and pass it:
std::function<void(QPainter&)> function = [&](QPainter& painter){ this->infoPaintFunction(painter); };
_imageView->setExternalPostPaintFunction(function);
Works like a charm.
You could use std::function:
class A {
public:
//PostPaintFun can be anything which acts as a function taking a QPainter&
//Could be a lambda, function pointer, functor, etc.
using PostPaintFun = std::function<void(QPainter&)>;
void setExternalPostPaintFunction(PostPaintFun fun);
private:
//Names beginning with an underscore are reserved, don't use them
//Ending with an underscore is fine
PostPaintFun fun_;
bool externalPostPaintFunctionAssigned_;
};
Now you can use member functions like so:
struct B
{
void exec(QPainter&) const;
};
void foo() {
B b;
a.setExternalPostPaintFunction(
[b] (QPainter& p) {b.exec(p);}
);
}
//or inside B
void B::foo() {
a.setExternalPostPaintFunction(
[this] (QPainter&p) {this->exec(p);}
);
}
I have to say I prefer TartanLlama's answer, but here you have something it could work for you.
This might to need some work, but I'm sure you'll get the idea.
struct IFunctionHolder {}; // Used for pointing to any FunctionHolder
typedef IFunctionHolder* functionHolder_ptr; // Alias for IFunctionHolder* .
template<typename Function> // The template for the actual function holders.
struct FunctionHolder: public IFunctionHolder
{
Function function;
};
class A {
public:
template <typename T>
void setExternalPostPaintFunction(void(T::*function)(QPainter&), T* object);
private:
functionHolder_ptr *function_holder; // This memeber can hold eny instantiation of template<> FunctionHolder.
// Instantiate this member wen calling setExternalPostPaintFunction
bool _externalPostPaintFunctionAssigned;
};
You could have some code like this:
A some_a;
void some_a.setExternalPostPaintFunction(&SomeInstance::some_fnunction); // Here take place the instantiation of FunctionHolder.
some_a.function_holder.function(some_painter);

Is there a way to pass a member function to pthread_cleanup_push?

I want to know the way to pass a member function to pthread_clean_push. I don't want to declare the cleanup function as static and pass object's reference to it. Below is the scenario
class Foo{
public:
Foo(string name):name(name){};
void setBar1(){bar1=malloc(4);sleep(20);};
void setBar2(){bar2=malloc(10);sleep(50);};
void cleanBar1(void* arg){free(bar1);};
void cleanBar2(void* arg){free(bar2);};
private:
string name;
void* bar1;
void* bar2;
};
void* myPThread(void* arg){
Foo theFoo(*(string*)(arg));
theFoo.setBar1();
pthread_cleanup_push(&theFoo.cleanBar1,NULL); //what is the correct way to
theFoo.setBar2();
pthread_cleanup_push(&theFoo.cleanBar2,NULL); //pass clean functions?
sleep(100);
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
return NULL;
}
int main(){
string biryani="biryani";
string pappu="pappu";
pthread_t makeBirayani, makePappu;
pthread_create(&makeBiryani,NULL,&myPThread,(void*)&biryani);
pthread_create(&makePappu,NULL,&myPThread,(void*)&pappu);
pthread_join(makeBiryani,NULL);
pthread_join(makePappu,NULL);
return 0;
}
I avoided compile-time error ISO C++ forbids taking the address of a bound member function to form a pointer to member function by using (void(*)(void*))&Foo::cleanBar1 as the argument to pthread_cleanup_push(). But run-time error(segmentation fault) occurs with multiple threads as it has ambiguity in determining the instance to which the cleanup function belongs. How to invoke the member function like here in this scenario? What is the syntax?
Foo::cleanBar1 and Foo::cleanBar2 are non-static member functions, which means that they take an implicit first argument, a pointer to the Foo instance on which they must be invoked (the this pointer). So you cannot pass a pointer to member function to pthread_cleanup_push and get the desired behavior.
You'll need to create a dispatcher function that calls the member function you want, and then pass a pointer to that function to pthread_cleanup_push. This dispatch function could either be a free function, or a static member function of Foo. For instance,
class Foo{
public:
Foo(string name):name(name){}
void setBar1(){bar1=malloc(4);sleep(20);}
void cleanBar1(){free(bar1);}
static void bar1_callback(void *arg)
{
static_cast<Foo*>(arg)->cleanBar1();
}
// ..
private:
string name;
void* bar1;
void* bar2;
};
And then pass it to pthread_cleanup_push as
pthread_cleanup_push(&Foo::bar1_callback, &theFoo);
Now the call to pthread_cleanup_pop will execute Foo::bar1_callback and pass it a pointer to the theFoo instance, which will then invoke the cleanBar1() member function.
The member function needs to know the object for which it is executed. This is why the standard doesn't allow this direct reference.
Just use a lambda-wrapper, like:
pthread_cleanup_push( [](void*a)->void { reinterpret_cast<Foo*>(a)->cleanBar1(NULL);},
&theFoo); //&theFoo will be passed as argument to the function
However you MUST ensure that your theFoo object still exist when the cleanup is called, because you give its adress when you push the cleanup function, and this address will later be used as argument for the cleanup by the lambda function.
From my understanding of the pthread function pthread_cleanup_push function you can pass the address of a free function (or possibly static to the class Foo) to it and a pointer to an object and then route the call to the correct member.
void clean_bar_1(void* arg)
{
Foo* p = static_cast<Foo*>(arg);
p->cleanBar1();
}
And then in myPThread function:
pthread_cleanup_push(&clean_bar_1, &theFoo);
And repeat for the cleanBar2 method.

Function pointer as a member of a class

What's the difference between a class function and global function with regard to function pointers in C++? I'm asking as the Windows CreateThread method doesn't seem to accept the function that the thread code goes in if the function is a class member.
I can pass the function (that the thread code goes in) to the CreateThread message when it is a global method, but once I make it a member of a class I get the error "argument of type [method layout] is incompatible with parameter of type LPTHREAD_START_ROUTINE". ClassName::* is in the middle now; is this affecting it?
What is the way around this?
Member function pointers (DWORD(WINAPI Foo::*)(LPVOID)) are different types than function pointers (DWORD(WINAPI *)(LPVOID)). Member functions have a hidden this parameter, causing a signature mismatch.
The easiest way to do this is to use C++11's <thread> header:
struct Foo {
void threadProc() {}
};
int main() {
Foo foo;
std::thread t{&Foo::threadProc, foo, /*other arguments to threadProc*/};
t.join();
}
If you have to resort to CreateThread, make use of the void * parameter to pass the instance:
struct Foo {
DWORD threadProc() {...}
};
extern "C" DWORD WINAPI proxyThreadProc(LPVOID userData) {
auto foo = static_cast<Foo *>(userData);
if (foo) {foo->threadProc();}
}
int main() {
Foo foo;
CreateThread(..., proxyThreadProc, &foo, ...);
}
The one in your class can now be pretty much whatever you want (like a std::function) and still work, as long as it's called with the right arguments from within the proxy procedure.
yeah, as #chris said there is a hidden pointer of this which will be connected by the end of parameters. when the thread carry out that, it don't know to match with a pointer in the position of the last parameter, then it failed to recover the heap of this function when finished, so It's banned to use non-static member function of class to drive a thread function except for the global function or static member function of class.

C++ Function Pointers to an Object

I'm not sure if this is possible in C++. I know you can pass a pointer to a function or static member function as a parameter. I want a function pointer for a specific object, so that when the function is executed, it is done on the object.
class MyClass
{
public:
MyClass(int id){mId = id;}
void execute(){cout<<mId<<endl;}
private:
int mId;
};
MyClass obj1(1);
MyClass obj2(2);
typedef (Executor)();
Executor ex1 = &obj1::execute();
Executor ex2 = &obj2::execute();
So when ex1 is executed, "1" should be printed and if ex2 is execute, "2" is printed. Is this possible?
The facility that handles this is the function template bind:
auto ex1 = std::bind(&MyClass::execute, obj1);
You can store a bind in a function object:
std::function<void()> ex1 = std::bind(&MyClass::execute, obj1);
Note that by default bind will store obj by value; you can store a reference with ref:
std::function<void()> ex1 = std::bind(&MyClass::execute, std::ref(obj1));
A related facility is mem_fn, which wraps a member function pointer:
void (MyClass::*ex1)() = &MyClass::execute; // raw member function pointer
ex1(obj1);
auto ex1 = std::mem_fn(&MyClass::execute); // mem_fn wrapper
ex1(obj)
However, because mem_fn doesn't bind an instance, you have to supply the instance each time you call it.
In order to avoid writing the class name when binding a member function, you can use a macro:
#define BIND_MEM_FN(o,m) \
std::bind(&std::remove_reference<decltype(o)>::type::m, (o))
A macro is necessary because you can only form a member function pointer from its type and name, and you cannot pass a name (an unqualified-id) to a function.
It's possible, but not the way you describe it.
You can do it the way proposed by the above comments but more elegant and C++ way would be to use functors.
Functor is basically an object which has operator () overloaded.
In your case it can be something like this:
class MyClass
{
public:
MyClass(int id){mId = id;}
void operator()(){cout<<mId<<endl;}
private:
int mId;
};
MyClass obj1(1);
MyClass obj2(2);
obj1();
obj2();
This way your object actually mimics function behavior.
Here you can read more: http://en.wikipedia.org/wiki/Function_object#In_C_and_C.2B.2B
Member function pointers:
typedef void (MyClass::*Executor)();
Executor ex1 = &MyClass::execute;
Executor ex2 = &MyClass::execute;
obj1.*ex1();
obj2.*ex2();
EDIT: Corrected the code as mentioned in the comments.
I made a mistake because I rarely use (member) function pointers indeed. But not because I use std::bind, but because I use polymorphism :)
Actually I don't remember the last time I used a (member) function pointer except in interfacing with OS APIs. Member function pointers are better than non-member function pointers, and std::bind/std::function might be better than member function pointers, but polymorphism is better than all of the above.

Two Classes (A,B) - B to have a pointer to class A non-static method

I have two classes that don't know anything about themselfs class A, class B.
Class A is called the ENGINE,
Class B is called the GUI.
I want GUI class to have a pointer to a function in class ENGINE, so that when an event occurs on GUIControl, it calls ENGINE member function with two parameters (int,int).
Here's how i would like to have it:
class CGUIManager
{
public:
void SetControlCallback(void(*pFunctionPointer)(int,int) );
private:
void (*m_pControlCallbackFunction)(int,int) ;
};
void CGUIManager::SetControlCallback(void(*pFunctionPointer)(int,int) )
{
if(pFunctionPointer)
m_pControlCallbackFunction = pFunctionPointer;
}
class CEngine
{
private:
void GUIControlsCallback(int iControlID, int iControlMessage);
CGUIManager *pGUI;
};
Now while initializing ENGINE, i want to call:
//Set Controls Callback to CEngine Method
pGUI->SetControlsCallback( GUIControlsCallback );
To register a callback within CGUIManager class, that points to a method in CEngine class.
How can i do that?
Thanks in advance.
I would suggest using an interface (or something like that) if you would like it to be oo instead of function pointers ( which must point to a static member btw )
class IGuiCallback
{
public:
virtual void GUIControlsCallback(int iControlID, int iControlMessage)=0;
};
class CGUIManager
{
public:
void SetControlCallback(IGuiCallback*);
private:
IGuiCallback* m_pCallback;
};
class CEngine:public IGuiCallback
{
public:
void GUIControlsCallback(int iControlID, int iControlMessage);
private:
CGUIManager *pGUI;
};
then in engine:
pGUI->SetCallback(this);
There may be some syntax errors in my code but you should get the picture
Pointers-to-member-functions are not function pointers in C++.
To call your callback later (using provided SetControlsCallback signature), the caller need to have a valid instance of CEngine. You can achieve that by binding the pointer to CEngine to GUIControlsCallback:
CEngine* pEngine; // initialized somewhere
pGUI->SetControlsCallback(std::bind1st(pEngine, GUIControlsCallback));
If you use Boost or C++11, you'd better use their versions of bindings (boost::bind or std::bind respectively).
The easiest approach is to use std::function<void(int, int) as the type of the registered callback: this object can be used to call any function [object] which is callable with two ints. In particular, it could call the member function CEngine::GUIControlsCallback(int, int) which actually has three parameters:
the two obvious parameter to the member function of type int
the implicit pointer to the object (which becomes this)
The way this is done is to construct a function object which provides as first parameter a pointer to the CEngine object and takes two integers:
struct CEngine_bind {
CEngine_bind(CEngine* engine): engine_(engine) {}
void operator()(int i0, int i1) { this->engine_->GUIControlsCallback(i0, i1); }
CEngine* engine_;
};
Alternatively, you can use std:bind() which is a create a suitably bound function:
CEngine engine; // ... wherever this object is coming from)
std::function<void(int, int)> callback(std::bind(&CEngine::GUIControlsCallback, &engine,
std::placeholders::_1, std::placeholders::_2));
... and then set the callback object as the callback. This object simply be called passing two integer parameters which will cause the member function on the referenced object to be called:
callback(10, 20);
would call
engine.GUIControlsCallback(10, 20);
The std::function<void(int, int)> is copyable, i.e. you can easily store it in your CGUIManager class.
If you are able to change the interface of the CGUIManager class, I ssugest you generalise it to use boost::function<void(int, int)> (or std::function if writing in C++11) instead of a function pointer.
If you can't, unfortunately you are a victim of bad design. C-style callbacks that use function pointers usually allow for some kind of void* user data parameter to carry any additional information bound to the callback - in this case the your CEngine pointer could be cast to void* and a free function wrapper could be written to cast the void* back to CEngine. However, if you are able to change the callback interface, using boost/STL function is a superior technique.