C ++事件模板类

时间:2015-10-21 09:10:44

标签: c++ class templates events

我想写一个类似C#的C ++事件类:

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 );
    }
}

问题在于它迫使我编写一个Trigger方法,它总是为每个事件类型做同样的事情(迭代和调用处理程序),因为不同的事件可以有不同的参数列表,并且对于每个事件,关联的处理程序类型有一个具有特定名称的方法。

我对C ++ 11了解不多,但我觉得可以避免使用模板为每种事件类型重写Trigger方法。 但我不能使用C ++ 11,所以我想知道是否有一种方法,使用较旧的C ++版本,以类型安全的方式做到这一点。

编辑:我考虑创建一个事件数据类的层次结构,即template< typename ListenerType >::DataDataReceivedEvent::Data : public template< typename ListenerType >::Data,这样我就可以使用一个Trigger方法始终采用单个参数,即virtual void Trigger( const Data * pData )。但我仍然遇到需要在事件监听器中调用特定方法的问题。

1 个答案:

答案 0 :(得分:0)

您也可以使用模板和运算符重载。当您假设ListenerType实现operator()时,您可以像这样实现它(该示例也使用variadic templates。您可以使用任意数量的参数):

#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");
}

不幸的是,C ++ 11没有引入Concepts。如果你有这个(constraints in C#),你会得到编译器的更多帮助。