Skip to main content
GameDev.net gamedev.net
🔒 Locked

C++ Function Pointer Casting

Started by Muzzy A Sep 10, 2014 at 9:14 PM 6 replies 9.3k views
Original Post
Muzzy A
Muzzy A

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();
}
 
Brother Bob
Brother Bob

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.

Muzzy A
Muzzy A

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.

Bacterius
Bacterius

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.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”
Muzzy A
Muzzy A

OK I'll look those up, thanks for the help

SeanMiddleditch
SeanMiddleditch
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 and then adding the forwarding params to the lambda or the placeholders (std::_1, std::_2, etc.) to std::bind.
Sean Middleditch – Game Systems Engineer – Join my team!
Washu
Washu

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 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>
In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
Muzzy A
Muzzy A

Thanks for the help guys, it works exactly the way I wanted.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.