design problem? callbacks to class vs global functions?

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).

Sorry if this doesn't make any sense.
How could you distinguish the static member against the global function?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <iomanip>
#include <typeinfo>

class foo{
public:	
	static void bar(){}
};
void bar(){}

int main(int argc, char *argv[]) {
	std::cout << typeid(bar).name() << ' ' << typeid(foo::bar).name() << std::endl;
	std::cout << std::boolalpha << (typeid(bar) == typeid(foo::bar)) << std::endl;
	return 0;
}
Output:
FvvE FvvE
true
Last edited on
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?
Here's an example (warning: not compiled):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#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.

Last edited on
Topic archived. No new replies allowed.