我最近一直在玩新的 C++11 标准,并决定创建一个基本的事件处理系统。下面的代码提供了我当前实现的一个小例子。
#include <functional>
#include <vector>
#include <iostream>
template <typename Event>
class EventBroadcaster
{
public:
typedef std::function<void(const Event&)> Connection;
void connect(Connection&& connection)
{
connections.push_back(std::move(connection));
}
void signal(const Event& event)
{
for (const auto& connection : connections)
{
connection(event);
}
}
private:
std::vector<Connection> connections;
};
struct MouseMotion
{
int x = 0;
int y = 0;
};
class Input : public EventBroadcaster<MouseMotion>
{
public:
void process()
{
MouseMotion mouseMotion;
mouseMotion.x = 10;
mouseMotion.y = 20;
signal(mouseMotion);
}
};
int main()
{
int x = 0;
int y = 0;
Input input;
input.connect([&](const MouseMotion& e){
x += e.x;
y += e.y;
});
input.process();
std::cout << x << "," << y << std::endl; // Output: 10,20
return 0;
}
Input
如果该类只广播单个事件,上述解决方案确实可以很好地工作。然而,可能存在Input
类希望能够发送KeyPress
事件而不仅仅是MouseMotion
事件的情况。
我考虑过使用多重继承。同时Input
继承EventBroadcaster<MouseMotion>
和EventBroadcaster<KeyPress>
。这会导致编译器错误警告不明确的函数。以下答案多重继承模板类中提供的解决方案确实适用于受保护的signal
函数,但不适用于在类外调用的公共connect
函数Input
。
除了多重继承,我想知道可变参数模板是否可以帮助我解决问题。我已经查看了(部分)模板专业化和解包可变参数模板。但是一直无法提供(优雅的)解决方案。
支持多种事件类型的最佳方式是什么?