map of member function pointers

Hello,
I need some help on this problem :

I would like to be able to register pointers to member functions (with a defined signature; lets say : <int, std::string>) of different classes without knowing in advance those classes. So as long as the class have a member function with the good arguments, I want to be able to add a pointer to this member function into a container (the same for all classes).

As I know that all the registered functions wait for the same arguments, I don't care to know what is the class, because all I will need is these member function. But as the signature is different I don't know of to achieve this container of member function pointers.


I need this for an Event driven system. The member function of any kinds of objects (so they are unknown in advance... and even if the were known, I can't register each type of object to the EventDispatcher class) can register as a listener for a specific event on the EventDispatcher, and if this event is fired then we call back the registered member function with the Event as argument.


Let's try with a simple example :

Lets imagine two classes MyClassA and MyClassB that both have a member function with the same arguments ( int, std::string).

I would like to be able to add the pointers to those member functions in the same container.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class MyClassA
{
	public:
		MyClassA(){};
		~MyClassA(){};

		void myMemberFunctionA( int, std::string ) {};
};


class MyClassB
{
	public:
		MyClassB(){};
		~MyClassB(){};

		void myMemberFunctionB( int, std::string ) {};
};

/* Here is my problem ...
Compiler request me to define the container with a specific class name
(here MyClassA for the purpose of the example)... but I would like to be
able to add member function pointers of any kind of classes as long as
the member function signature is (int, std::string)
*/
// map < key, pair< memberFunction_ptr, classInstance_ptr > >
std::map< int, std::pair< void(MyClassA::*)(int, std::string), MyClassA* > > myMap; 


// This does work
MyClassA a;
myMap.insert( myMap.size()+1, std::make_pair( &MyClassA::myMemberFunctionA, &a ) )

// This does NOT work (as myMap is not defined using MyClassB)
MyClassB b;
myMap.insert( myMap.size()+1, std::make_pair( &MyClassB::myMemberFunctionB, &b ) )


Indeed I could add MyClassC, MyClassD etc member function pointers later as long as the member function signature is still the same.


Do you have any idea, or clue the help me with this ?
Thank you
Use boost::bind and boost::function.

1
2
3
4
5
6
7
typedef boost::function<void(int, std::string const&)> Callback;
std::map< int, Callback > myMap;
MyClassA* a = new MyClassA;
MyClassB* b = new MyClassB;

myMap.insert( std::make_pair( 42, boost::bind( &MyClassA::myMemberFunctionA, a ) );
myMap.insert( std::make_pair( 99, boost::bind( &MyClassB::myMemberFunctionA, b ) );


Well in fact I try to do it without boost.

I keep boost as the last solution, but I try to avoid dependency to the maximum (even if boost if a fabulous lib) ;).
Last edited on
Then two other options are to invent your own boost::bind and boost::function or use type erasure (http://www.cplusplus.com/forum/articles/18756/) to create a polymorphic map.
Do the member functions in the map belong to different classes? Like any other function, you can cast member function pointers to void*, but the values of those void* only make sense in context with the class. You could try the following:

Create a virtual CallMemberFunc class that has a member function that takes whatever parameters your member functions use, and returns whatever value your member functions should return, and then create a sub class of it for all classes you need. Then just let the sub classes call the member functions you want in the function from the super class, and return it's return value. That is the simplest way I can think off to do this without boost... though it will force you to create a bunch of pretty useless classes.
hanst99:

Yes, OP's example shows different classes. But you cannot safely cast just any member function pointer to void*.

Your second idea is essentially the same as the type erasure proposal I made, except for two things: first, it does
not require the user to create classes that are related via a base class, and second, with type erasure the compiler is
generating the useless classes for you.
Hello,
thank you very much for your help.

I will try to use the type erasure described by jsmith. This do match almost all my needs, and I tried to do something similar without success.

Indeed I will have to modify it a bit as I only need the member function pointer not a copy of them. And I will have to add an override of the "operator <" as I finally decided to store them in a std::set. (I need to find a nice way to compare member function for this override... but I'm not sure I can use their address to avoid duplications as the member function doesn't seem to have an address as non member functions or static functions ).

I will come back here later to report if this solution was the good one or not.
Last edited on
Topic archived. No new replies allowed.