私は最近、新しい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
多重継承に加えて、可変個引数テンプレートが私の問題を解決できるかどうか疑問に思いました。(部分的な)テンプレートの特殊化と可変個引数テンプレートの解凍を見てきました。しかし、(エレガントな)ソリューションを提供することはできませんでした。
複数のイベントタイプをサポートするための最良の方法は何でしょうか?