2017-10-11 5 views
3

のリスナー - 変更することはできません)関数ポインタとvoid*を受け入れます。以下は例です:バインドクラスメソッドと関数ポインタとして渡し、私は(サードパーティ)の引数の関数としての私のクラスのメソッドを渡したい

#include <functional> 

typedef void(*pfnc) (void*); 

struct Foo 
{ 
    static void static_foo(void*) 
    { 
    } 

    void foo(void*) 
    { 
    } 

    void listner(pfnc f, void* p) 
    { 
     f(p); 
    } 

    void test() 
    { 
     listner(static_foo); // works with static method 

     auto f = [](void*) {}; 
     listner(f); // works with lambda 

     std::function<void(void*)> stdf = std::bind(&Foo::foo, this, std::placeholders::_1); 
     listner(stdf); // does not compile with not static method 
    } 
}; 

残念ながら私の解決策はコンパイルされません。私は何を変えなければならないのですか?

+1

関数ポインタに状態がありません。あなたは 'void *'パラメータを使わなければなりません。プラス面では、私が出会った他の特定のC APIとは異なり、パラメータが存在します。 – chris

+1

'listener'メソッドが' pfnc'だけを受け入れることは確かですか?通常、このようなメソッドは、ハンドラメソッドへのコールバックの際に渡されるユーザ指定の 'void *'パラメータを受け取ります... –

+0

私は通常、メソッドを呼び出すためにこれを取得するラムダを使用します。 –

答えて

1

リスナーAPIは、コールバック信号の外観から、「ユーザー定義データ」としてvoidへのポインタを取ります。あなたはFooにハンドラにルーティングするために、データと小さなステートレスプロキシ機能としてthisを渡すことができます。

typedef void(*pfnc) (void*); 

struct Foo 
{ 
    static void static_foo(void*) 
    { 
    } 

    void foo() 
    { 
    } 

    void listner(pfnc f, void* user_data) 
    { 

     // eventually calls 
     f(user_data); 
    } 

    void test() 
    { 
     listner(static_foo, nullptr); // works with static method 

     auto f = [](void*) { 
     }; 
     listner(f, nullptr); // works with lambda 

     listner([](void* pv) 
     { 
      reinterpret_cast<Foo*>(pv)->foo(); 
     }, this); 
    } 

}; 
0

例えば、質問では、メンバ関数ポインタを渡すことも可能であろう。もちろん、そのメンバが呼び出されるインスタンスを知っていなければなりません。呼び出し元関数がメンバー関数でもある場合は、thisを使用して、ポインタを介して渡されたメンバ関数を呼び出すことができます。これらは昔ながらの機能

とほぼ同等であるため、

struct Foo 
{ 
    static void static_foo(void*) 
    { 
    } 

    void foo(void*) 
    { 
    } 

    void listner(pfnc f) 
    { 
    } 

    void listner(void(Foo::*f)(void*)) 
    { 
     (this->*f)(nullptr); // call member function pointer for this 
    } 

    void test() 
    { 
     listner(static_foo); // works with static method 

     auto f = [](void*) {}; 
     listner(f); // works with lambda 

     listner(&Foo::foo); // pass pointer to member function 
    } 
}; 
0

あなたの例では、静的メンバ関数で「働く」ことがキャプチャレスラムダあるので、それはまた、あなたが提供ラムダでの作品 "これは関数ポインタ(Passing lambda as function pointer) に変換することができますが、chrisのように、関数ポインタには状態がありません。つまり、キャプチャするものを格納する場所がないためです。 。

同じことがバインドになります。このようなオブジェクトは状態を持っているので、std :: functionに格納できますが、プレーンな(ステートレスな)関数ポインタに格納することはできません。他の人のように最後に

あなたは、納得していないよstdf.target_type()があなたに伝え何を見ているとtypeid(static_foo).name() とそれを比較した場合あなたはまた、STDの戻り値の型を見てすることができます::バインド

、あなたは、あなたのオブジェクトをユーザーデータ、つまり、void *に入れなければならないと言っています。 std :: functionをパラメータとしてヘルパー関数でラップすることができるかどうか調べる価値があります。

関連する問題