事件模板类

C++ Event template class

本文关键字:事件      更新时间:2023-10-16

我想写一个类似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,这样我就可以有一个触发器方法总是采用单个参数,即virtual void Trigger( const Data * pData )。但是我仍然有一个问题,它需要在事件侦听器中调用一个特定的方法。

您也可以使用模板和操作符重载。当您假设ListenerType实现operator()时,您可以这样实现它(该示例还使用可变模板)。你可以使用任意数量的参数):

#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没有引入概念。如果你有这个(c#中的约束),你会从编译器那里得到更多的帮助。