3

C# スタイルのイベントを提供するように設計されたeventクラス テンプレートを作成しました。イベント インスタンスはクラスのパブリック メンバーとして格納され、所有者クラスにさまざまなイベントを提供します。例えば:

template<typename SENDER , typename ARGS>
class event{ .... };

struct foo
{
    event<foo,int> event_a;
    ...

    void do_work()
    {
        int data;

        ....

        event_a.raise_event( *this , a );
    }
};

void on_event_a(foo& , int&) { std::cout << "On event_a of class foo!" << std::endl; }

struct bar
{
    void on_event_a(int&) { std::cout << "Catching an event with a member function!"; }
};


int main()
{
    int argumment;

    foo foo_instance;
    bar bar_instance;

    foo.event_a.add_handler( [](foo& , int& ) { std::cout << "Lambda!" << std::endl; } );
    foo.event_a.add_handler( on_event_a );
    foo.event_a.add_handler( bar_instance , &bar::on_event_a );

    foo_instance.do_work();
}

出力は次のとおりです。

ラムダ!
クラス foo の event_a で!
メンバー関数でイベントキャッチ!

今、そのメカニズムを使用して、freeglut を OO スタイルでラップしたいと考えています。具体的には、さまざまな freeglut イベント (ウィンドウのサイズ変更、キーボード入力、マウスの動きなど) を管理するクラスを作成したくありません。
私の最初のアイデアは、クラス コンストラクターを使用して、freeglut コールバックごとに 1 つのラムダを登録することでした。ラムダは、次のように、コールバックの引数を適切なイベントにバイパスします。

class freeglut_events
{
    event<freeglut_events> repaint_event;

    freeglut_events()
    {
        glutDisplayFunc( [&](){ repaint_event.raise_event( *this ); } );                
    }
};

しかし、これは次のコンパイラ エラーにつながります (私は Visual Studio 2012 を使用しています)。

'[]lambda() -> void' から 'void(*)()' への有効な変換はありません

私が理解しているのは、ラムダがローカルデータをキャプチャするため、登録関数が期待するグローバル関数ポインタの署名とラムダの署名が正確に等しくないということです。

私の質問は次のとおりです:これを達成するための他のエレガントな方法はありますか?

4

1 に答える 1

2

まあ、あなたはそれをすることはできません。関数ポインタに変換できるのは非キャプチャ ラムダのみであり、glutDisplayFuncは関数ポインタ パラメータ、つまりvoid (*func)(void).

この回答も参照してください: glutDisplayFunc に 1 つの引数 (ポインター) を渡しますか?

于 2013-10-12T22:12:10.640 に答える