最近我一直在使用新的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
類別除了僅僅MouseMotion
事件之外還希望能夠發送KeyPress
事件。
我想過使用多重繼承。使Input
繼承EventBroadcaster<MouseMotion>
和EventBroadcaster<KeyPress>
。這會導致編譯器錯誤警告模糊函數。在下面的答案Multiple Inheritance Template Class中提供的解決方案確實可以用於受保護的signal
函數,但不適用於公開的connect
函數,該函數在Input
類以外調用。
除了多繼承,我想知道如果variadic模板可以幫助我解決我的問題。我查看了(部分)模板專業化和解包可變參數模板。但一直無法與(優雅的)解決方案。
什麼是支持多種事件類型的最佳方式?
你連接的解決方案怎麼不能用於'connect()'? – 2013-02-22 16:23:59
將下列內容添加到Input類不起作用:'使用EventBroadcaster :: signal; 使用EventBroadcaster :: signal; 使用EventBroadcaster :: connect; 使用EventBroadcaster :: connect;'然而,我只是刪除'使用EventBroadcaster :: connect;'行後的MouseMotion事件。但仍然存在不能連接KeyPress事件的問題。 –
daniel
2013-02-22 16:26:00
不是你的問題的答案,而是'connections.push_back(std :: move(connection));'會更有效率,調用函數可以只是'連接(事件)'沒有額外的括號 – 2013-02-25 13:57:09