私は単純なイベントシステムに基づいたライブラリに取り組んでいます。
GUI要素(「コントロール」)を操作するには、これらが非常に必要です。たとえば、Window
クラスには「onMouseMove」、「onKeyPress」、「onKeyRelease」などの一連のイベントがあります。ただし、コントロールの基本的なクラスはControl
クラスです。これには、仮想関数の描画(明らかにコントロールを描画する)と、コントロールとメインウィンドウのイベントを接続する仮想関数の接続(Qt Signal-Slot-Conceptと同様に機能)があります。
しかし、Event
クラスはstd::function<...>
サブジェクト(=>スロット)としてポインターを受け取るため、派生コントロールクラスのメンバー関数をウィンドウのイベントに単純に接続することはできません。回避策として、私は次のことを行っています。
class A : public Control {
friend class Window;
public:
A(){
this->eventHandler = [this] () -> void {
if ( someCondition ) this->onSomeCondition.notify();
};
}
Event<> onSomeCondition;
protected:
std::function<void()> eventHandler;
void connect(Window *window){
window->onSomeHigherEvent.attach(&this->eventHandler);
}
void draw(...) const{
drawSome(...);
}
};
std::function<...>
これが基本的に行うことは、コンストラクターのにラムダ関数を割り当て、それstd::function<...>
を選択したイベントにアタッチすることです。
ただし、大きな問題があります。そのクラスのオブジェクトをさらにいくつかインスタンス化するとどうなりますか?次のような通常の関数として、クラスでイベントハンドラーを指定した場合:
void eventHandler() {
if ( someCondition ) this->onSomeCondition.notify();
}
そして、少なくとも次の呼び出しを使用している限り、何らかの理由で機能しないstd::function<...>
usingにその関数を割り当てることができます。std::bind
std::bind(&A::eventHandler, this, std::placeholders::_1); // *this will not work since that's just a (reference to the?) copy to of the object.
とにかく、lambda-function-workaroundは実際にはクラスに組み込まれていないため、時間効率が低いようです。この問題を解決するためのより効率的な方法はありますか?たぶん、特にラムダ関数の問題を解決するのではなく、概念を変更することによってですか?