-1

I have read several posts about this, but can't seem to find exactly what i am looking for with example code if anyone could give me some help i would highly appreciate it.

in my header i have:

void addEvent(void (*func)(Pack  *));

void triggerEvents(Pack * );

std::list<void(*)(Pack *)> eventList;

and in cpp file

void DNetwork::addEvent(void (*func)(Pack *)){
    eventList.push_back(func);
}

void DNetwork::triggerEvents(Pack * pack){
    for (std::list<void (*)( Pack *)>::iterator it = eventList.begin(); it !=         eventList.end() ;it++ ){
        (*it)(pack);
    } 
}

This works fine with free functions, but when i try to add a member function to this list i get an error. Does anyone know how to store a member function (from random class objects) inside a pointer?

  • Yap: `ReturnType (TheClass::*memberPointer)(arguments, ...) = &TheClass::aMemberFunction;` –  Jun 25 '13 at 18:19
  • See C++ FAQ section 33: http://www.parashift.com/c++-faq/pointers-to-members.html – aschepler Jun 25 '13 at 18:21
  • Yes, but i want to be able to store function pointers from different classes as well. Is it possible to have a parent class for the class i want to use which can take the functions so that the list will be: something like this std::list eventList; – dag roger stokland rui Jun 25 '13 at 18:22
  • 2
    Take a look at std::function – Jiwan Jun 25 '13 at 18:25
  • duplicate of http://stackoverflow.com/questions/130322/how-do-you-pass-a-member-function-pointer?rq=1 – kfsone Jun 28 '13 at 03:33

4 Answers4

3

The simple solution is using type erasure on the function/function pointer type, for which the easier way is just using std::function<>:

std::list<std::function<void (Pack*)>;

Then you can initialize the function objects with either a free function or a member function (by means of std::bind to bind the member-function with an object on which to call it) or even function objects (types that offer an operator()).

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
1

For member function you need a bind. A member function is a "normal function" that has an implicit parameter of its class. So you need a binder. If you use c++11 you can use std::bind and std::function or you can use boost::bind and boost::function for non c++11 code.

typedef std::function< void ( Pack* ) > MyFunction;
void addEvent( MyFunction f );
void triggerEvents( Pack* );
std::list< MyFunction > eventList;

void DNetwork::addEvent( MyFunction f )
{
    eventList.push_back( f );
}

void DNetwork::triggerEvents( Pack *pack )
{
    for ( auto it = eventList.begin(); it != eventList.end(); it++ )
    {
        (*it)(pack);
    } 
}

Now if I have the class A with the method doA( Pack* ) I will write:

A a;
Pack pack;
DNetwork d;
d.addEvent( std::bind( &A::doA, &a, &pack ) );

Or even better you can use Boost.Signal or you can use the Publisher/Subcriber Pattern

Edit As @DavidRodríguez-dribeas suggest: The bind should not take the &pack argument, as the argument to the member function is provided at the place of call in triggerEvents. The correct way is:

A a;
Pack pack;
DNetwork d;
d.addEvent( std::bind( &A::doA, &a, std::placeholders::_1 ) );
d.triggerEvents( &pack );
Elvis Dukaj
  • 7,142
  • 12
  • 43
  • 85
-1

You could do an overload such as:

std::list<void(*)(Pack *)> eventList;
void addEvent(void (*func)(Pack  *));
template<typename T>
void addEvent(void (T::*func)(Pack  *));
namespace Abstraction {
    template<typename T>
    void abstractlyAddEvent( T, std::list<void(*)(Pack *)> *eventList );
}
-2

If I'm understanding your problem you get the error when you try to add a function to the list in addEvent?

If you're adding a pointer to a non-static member function of a class ensure it has the right syntax... for example a function pointer to a a member function in TestClass would look like:

void * (TestClass:: *) ()
sedavidw
  • 11,116
  • 13
  • 61
  • 95
  • 1
    This not resolve the problem. We need just a simple way to bind to ordinary function and method. So it's juast function + bind – Elvis Dukaj Jun 25 '13 at 19:02