私はC++を学び、私がよく知っている他の言語のさまざまなイディオムを実装しようとしています。C++のテンプレートイベント型を持つセントラルイベントディスパッチャ
最近、複数のオブジェクトがN個の引数を取るイベントを登録でき、EventDispatcher :: dispatch(event_name)を1回呼び出すと登録されたすべてのイベントコールバックが呼び出される中央のEventDispatcherを実装しようとしました。
まず、イベントのテンプレートクラスを作成しました。私は次の例のようなイベントを定義することができ、この構造により
template <typename ..._args>
class Event
{
public:
//Alias for template callback
using _callback = std::function<void(_args...)>;
//Ctor & Dtor
explicit Event(std::string const& name, _callback const& cb) : _name(name), _cbFunc(cb) {}
~Event() {}
//Accessors
std::string const& getName() const { return this->_name; }
//Methods
void trigger(_args... a) { this->_cbFunc(a...); }
private:
//Event identifier
std::string _name;
//Event callback - can't be changed inside event.
_callback const _cbFunc;
};
:
void testCallback(int a) {
std::cout << a << std::endl;
}
Event<int> _event("TestEvent", std::bind(&testCallback, _1));
_event.trigger(20); //This will actually output 20 to the console.
私は、隣にやりたいように定義されるべきEventDispatcherクラスがあります。
class EventDispatcher
{
public:
EventDispatcher();
~EventDispatcher();
void registerEvent(**Event of any type**);
void dispatchEvent(std::string const& eventName, ....args);
private:
std::map<std::string, std::vector<**Event of any type**>> _eventList;
};
を
私はこのように電話をかけることができます。
EventDispatcher _dispatcher;
_dispatcher.registerEvent(_event); //event defined in the previous example.
_dispatcher.dispatchEvent("TestEvent", 20); //this should call event's trigger() method with arguments passed to it actually.
私は、中央ディスパッチャを実装し、それをテンプレート化イベントのインスタンスを登録し、その後は、dispatchEvent(...)に可変数の引数を渡すと、それはすべてのトリガー作ることができる持ってする方法を見つけ出すことができませんでしたがテンプレート化されたイベントのベクトルのイベント。
どうすればこのような機能を実現できますか?このようなシステムを実装するC++の方法から、私の思考のプロセスが正しいのか、それとも遠いのでしょうか?あらゆるヒントを歓迎します。
間違ったタイプの引数を使用してイベントにディスパッチしようとするとどうなりますか? A.DLLの型に右値を取るイベントを登録し、B.DLLの型のインスタンスで呼び出すとどうなりますか? 2つのスコープのいずれかにB.DLLタイプからA.DLLタイプへの変換演算子がある場合はどうなりますか?これらは3つの異なる質問です。コンパイル時に型エラーが発生すると、型の不一致が発生したときに異なるシグネチャを扱う中央のディスパッチャが必要なのはなぜですか? – Yakk
私はC++で初心者で、勉強したいと言ったような、すばらしい質問です。私がセントラルイベントディスパッチャを使用する理由は、それを使用できるようにすることです。別のクラスでは、例えばメインアプリケーションモジュールの「ディスパッチャ」に登録できます。他にどんな選択肢がありますか? – Alaminut