Sign in to follow this  
Muzzy A

C++ Function Pointer Casting

Recommended Posts

Hey,

    I'm trying to set up a function pointer so that ANY function can be passed to it as long as it's the same signature.

 

Example

 
// Define a simple function pointer
typedef void (*FuncPointer)();
 
void someFunc()
{
}
 
int main()
{
    FuncPointer func = someFunc;
 
    func();
}
 
// This works no prob
 
 
// Now here is what I want to do
class A
{
public:
    void foo();
};
 

// Define a simple function pointer
typedef void (*FuncPointer)();

 
int main()
{
    // This is what I want to work
    FuncPointer func = A::foo;
 
    // I want it to work without having to define a function pointer like this
   typedef void (A::*FunctionPointer)()
 
/*
    IS THIS POSSIBLE?
*/
 
    func();
}
 

Share this post


Link to post
Share on other sites

Consider the hypothetical call to func() in your last example; what is the value of the this pointer inside A::foo() once func() is called? In other words, which object do you expect the member function to be called on?

 

The moral of the story is: you expect it work work as long as the functions have the same signature, but someFunc() and A::foo() are fundamentally different.

Share this post


Link to post
Share on other sites

I know this, let me clarify

class A
{
public:
    void foo();
};
 

// Define a simple function pointer
typedef void (*Func)();

 
int main()
{
    A obj;

    // This is what I want to work
    Func func = obj.foo;
 
    func();
}
 

I want to be able to have access to that object inside the function that gets called from the function pointer so that I don't have to have some sort of global reference to 'obj'

 

 

you can't typecast it to a 'Func', it gives an error as well.

 

The whole reason is I have a button class which has a function pointer that it calls when the button is clicked, and the function that gets passed to it is a 'void (*Func)()'.  I want to be able to have access to the class that holds that button without having to create some static/global variable to get access to it.

Edited by Muzzy A

Share this post


Link to post
Share on other sites

I want to be able to have access to that object inside the function that gets called from the function pointer so that I don't have to have some sort of global reference to 'obj'

 

You don't, not with standard function pointers like this. Member function pointers are different beasts. In the old C days you would idiomatically do this kind of thing by having your code take a void* "user data" pointer, which would then be passed along to the callback function, so that your callback could have non-global state, which I suppose is what you are trying to achieve. Something like set_callback(func_ptr, &foo) and then use the pointer to your class instance from the callback parameters. In C++, you probably want to use the modern C++ features like std::function, bind, lambdas, etc... which handle all of this and more.

Share this post


Link to post
Share on other sites

The example would become:
 

using FuncWrapper = std::function<void()>;

void someFunc()
{
}

class A
{
public:
    void foo();
};
 
int main()
{
    // free function
    FuncWrapper func = someFunc;
    func();

    // member via lambda
    A obj;
    func = [&](){ obj.foo(); };
    func();

    // member via std::bind (there's also a Boost version if your compiler is ancient)
    func = std::bind(std::mem_fn(&A::foo), &obj);
    func();
}
You can also have std::function, lambdas, or std::bind using arguments and return values by spelling out the signature, e.g. std::function<result_type(param_type1, param_type2)> and then adding the forwarding params to the lambda or the placeholders (std::_1, std::_2, etc.) to std::bind.

 

mem_fn is not needed there, bind already handles the case of member function pointers. 

    func = std::bind(&A::foo, &obj);

is sufficient. Also, let's not forget to add the necessary header include at the start...

#include <functional>
Edited by Washu

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this