So I'm trying to make a basic button class, and be able to provide it with a function to call upon click. I started looking up stuff about function pointers and callback functions since I thought that's what I should use.
However, I've gotten stuck with the way I've designed it. As I understand it, in order to allow passing of arbitrary class member functions, I could pass a function pointer to a static member function (of the arbitrary class) along with a void* pointer to my button class, and then upon a click event pass the void* pointer to the static member function to be recast into the correct type and call the correct function.
But what if it turns out the user passed a global function? Should I just create separate functions in order to call static class vs global functions? (Since the global function won't be needing a void* pointer).
Well, if the user of the class wanted a static class member, he would have to pass a void* pointer along with the function (since the static member is intended to only be a wrapper that will recast the void* pointer upon callback).
If the user wanted to pass a global function, he wouldn't pass anything except the function. However, when accepting function pointers I need to distinguish between functions with different arguments.
Basically, I have either static void bar(void*) or void bar().
You should look up boost::function and boost::bind on www.boost.org. That is exactly what you want. They will allow you to abstract away the type of function passed as the callback -- it can be a member function, function object, or free function -- they will all work.
Thanks jsmith, I'm reading the tutorials for them now, and it seems like they're exactly what I was looking for. I don't really understand how I can use them though.. Do you think you could provide an example?
I still don't know how to use them correctly, but here's what I got from reading the documentation..
I can use boost::function to wrap functions more cleanly than using function pointers, but it seems I still need to acknowledge a difference between class and nonclass member functions.
1 2 3 4 5 6
boost::function<int (X*, int)> f;
f = &X::foo;
X x;
f(&x, 5);
boost::bind confused me even more. All I understood is that you can 'ignore' function arguments using it, but it seems like I can only ignore arguments as long as I still have at least one?
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
void free_func( int x, int y ) {
std::cout << x * y << std::endl;
}
struct obj {
explicit obj( int x ) : value( x ) {}
void memberfunc( int y ) const { std::cout << x * y << std::endl; }
};
void do_it( int y, const boost::function<void(int)>& fn )
fn( y );
}
int main() {
obj o( 2 );
boost::function<void(int)> fn( boost::bind( free_func, 2, _1 ) );
do_it( boost::bind( &obj::memberfunc, o, _1 ) );
do_it( 42, fn );
}
Here I've shown how to use boost::bind and boost::function with free functions
and member functions. You can also do same with functors. At the point of
calling foo, yes, I need to know if it's a free function or a member function, but
at the point of invocation, regardless of which it is, the calling convention is the
same -- it is a function that takes one argument.