1

I would like to write a C#-like C++ event class like this :

template< typename ListenerType >
class Event
{
private:

    std::vector< ListenerType * > m_aListeners;

public:

    void operator += ( ListenerType * pListener )
    {
        m_aListeners.push_back( pListener );
    }

    void operator -= ( ListenerType * pListener )
    {
        std::vector< ListenerType * >::reverse_iterator revIter = m_aListeners.rbegin();
        for( ; revIter != m_aListeners.rend(); ++revIter )
            if( revIter == pListener )
            {
                m_aListeners.remove( revIter );
                break;
            }
    }
};

class DataReceivedEvent : public Event< DataReceivedListener >
{
public:

    void Trigger( const byte_t * pData )
    {
        for( size_t nI = 0; nI < m_aListeners.size(); ++nI )
            m_aListeners[ nI ]->OnDataReceived( pData );
    }
}

The problem is that it forces me to write a Trigger method that always does the same thing (iterate and call handlers) for each event type since different events can have a different list of parameter, and for each event, the associated handler type has a mehod with a specific name.

I don't know much about C++11, but i have the feeling that it would be possible to avoid rewritting the Trigger method for each event type using templates. But i can't use C++11, so i wonder if there is a way, using older C++ version, to do that, in a type safe way.

EDIT : I thought about creating a hierarchy of event data classes, i.e template< typename ListenerType >::Data and DataReceivedEvent::Data : public template< typename ListenerType >::Data so that i can have a Trigger method always taking a single argument, i.e virtual void Trigger( const Data * pData ). But I still have the problem that it needs to call a specific method in the event listener.

Virus721
  • 8,061
  • 12
  • 67
  • 123
  • Can you use Boost? Because then you can use [Boost function](http://www.boost.org/doc/libs/1_59_0/doc/html/function.html) and [Boost bind](http://www.boost.org/doc/libs/1_59_0/libs/bind/doc/html/bind.html) libraries. – Some programmer dude Oct 21 '15 at 09:23
  • @JoachimPileborg Thanks for your previous comment (http://stackoverflow.com/questions/14189440/c-class-member-callback-simple-examples/14189561#14189561). It seems to be supported in VS2005 so I will have a look at this. And I do not want to use boost because my targeted platforms are Android (which is OK) and Windows CE (which is not very well supported by boost). – Virus721 Oct 21 '15 at 09:27
  • Ho unfonrtunately function and bind are not supported by VS2005 :( But maybe i can still find a compatible way to do it with what exists in `` – Virus721 Oct 21 '15 at 09:40

1 Answers1

0

You can use templates and operator overloading for this as well. When you assume that the ListenerType implements the operator() you can implement it like this (the example also uses variadic templates. You can use arbitrary amount of arguments):

#include <vector>
#include <iostream>

template< typename ListenerType >
class Event
{
private:

    std::vector< ListenerType * > m_aListeners;

public:

    void operator += ( ListenerType * pListener )
    {
        m_aListeners.push_back( pListener );
    }

    void operator -= ( ListenerType * pListener )
    {
        auto revIter = m_aListeners.rbegin();
        for( ; revIter != m_aListeners.rend(); ++revIter )
            if( revIter == pListener )
            {
                m_aListeners.remove( revIter );
                break;
            }
    }

    template<typename... Params>
    void operator()(Params... data) {
        for (auto l : m_aListeners) {
            (*l)(data...);
        }
    }
};

class DataReceivedListener {
public:

    void operator()(const char* pData) {
        std::cout << pData << std::endl;
    }

};

class DataReceivedEvent : public Event< DataReceivedListener >
{
public:
};


int main() {

    DataReceivedEvent e;
    DataReceivedListener l1;
    DataReceivedListener l2;
    e += &l1;
    e += &l2;

    e("Hello");
}

Unfortunately, C++11 does not introduces Concepts. If you had this (constraints in C#) you would get some more help by the compiler.

schrieveslaach
  • 1,689
  • 1
  • 15
  • 32