2017-08-20 15 views
2

スタティックラッパー関数とオブジェクトへのvoidポインターを隠すことでクラスメンバー関数を呼び出すことができる小さなFunctorクラスがあります。以下の例は、ラッパー関数を設定する際のエラーのためにコンパイルされません。私が望むのは、テンプレート引数としてのクラスメンバポインタです。誰が何が間違っているか知っていますか?クラスメンバー関数のC++ Functorテンプレート

メンバー関数を呼び出すときに静的関数に別の問題があると思います。テンプレート構文でこれをどうやって行うのか正確には分かりません。最小限の例は、gccを有効にしたC++ 11でコンパイルします。

#include <iostream> 

template<class TReturn, class... TParameter> 
struct Functor { 

    TReturn (*ptr)(void*, TParameter...); 
    void  *object; 

    template<class TObject, class TMemberFunction> 
    static TReturn memberCaller(void *obj, TParameter... params) { 
     TObject *c = static_cast<TObject*>(obj); 
     return (c->*(TObject::TMemberFunction))(params...); 
    } 

    TReturn operator()(TParameter... params) { 
     return ptr(object, params...); 
    } 
}; 

class Test { 
public: 
    void func(int a) { 
     std::cout << a << std::endl; 
    } 
}; 

int main(int argc, const char **argv) { 
    Functor<void, int> f; 
    Test    t; 

    f.object = &t; 
    f.ptr = &Functor<void, int>::memberCaller<Test, Test::func>; 

    f(100); 
} 
+1

'Functor'に呼び出す' Test'クラスのメンバ関数へのポインタを渡す必要があります。 'TMemberFunction'は型名ではありません。実際には 'std :: function'や' fastdelegate'がどのように実装されているかを調べることができます。 – VTT

+0

私は組み込みシステムで使用しているので、この場合は利用可能なstlがないことに言及するのを忘れました。 – Gustavo

+0

関連:https://stackoverflow.com/questions/4298408/5-years-later-is-there-something-better-than-the-fastest-possible-c-delegate –

答えて

1

このような機能はありますか?他のいくつかのエラーを脇に置きます

#include <iostream> 

template<class TObject, class T, class... TParameter> 
struct Functor { 

    using TMemberFunction = T (TObject::*)(TParameter...); 
    TMemberFunction ptr; 
    TObject  *object; 


    T operator()(TParameter... params) { 
     return (object->*ptr)(params...); 
    } 
}; 

class Test { 
public: 
    void func(int a) { 
     std::cout << a << std::endl; 
    } 
}; 

template<typename T> 
class TD; 

int main() 
{ 
    Functor<Test, void , int> f; 
    Test    t; 

    f.object = &t; 
    f.ptr = &Test::func; 

    f(100); 
} 
+0

あなたの答えは質問のように書いてはいけません。そして、おそらくコードをダンプするのではなく、いくつかの説明を追加してください。 – GhostCat

+0

それはうまく動作しますが、1つの特定のクラスに対してのみFunctorを使用できます。クラス型ではなく関数プロトタイプがカウントされる状況があるかもしれません。 – Gustavo

+0

異なるクラスのメンバー関数には異なる型があります。だから私は実際にどのように "クラスの種類はカウントしない" –

2

TMemberFunctionのために、あなたのコードは動作しません:

template<class TObject, class TMemberFunction> 
static TReturn memberCaller(void *obj, TParameter... params) { 
    // ... 
} 

は、メンバ関数へのポインタをキャッチするために使用することはできません。 TMemberFunctionは型でなければならず、そのように使用していません。

ではなく、次のようにあなたは、あなたのクラスを定義することができます

template<class> 
struct Functor; 

template<class TReturn, class... TParameter> 
struct Functor<TReturn(TParameter...)> { 
    TReturn (*ptr)(void*, TParameter...); 
    void  *object; 

    template<class TObject, TReturn(TObject::*TMemberFunction)(TParameter...)> 
    static TReturn memberCaller(void *obj, TParameter... params) { 
     TObject *c = static_cast<TObject*>(obj); 
     return (c->*TMemberFunction)(params...); 
    } 

    TReturn operator()(TParameter... params) { 
     return ptr(object, params...); 
    } 
}; 

そして、このようにそれを使用する:

である、あなたは memberCallerのテンプレートパラメータとして今メンバ関数を使用することができます
Functor<void(int)> f; 
Test    t; 

f.object = &t; 
f.ptr = &Functor<void(int)>::memberCaller<Test, &Test::func>; 

f(100); 

一度呼び出されると型を消去して内部的に使用するようにします。

私も少しようにそれを使用するよう Functorの定義を変更し

Functor<void, int> 
:あなたは関数型とそれを使用する予定のときはもう少し明示的に以下より

Functor<void(int)> 

私の2セントは、少なくとも。


wandbox上の例を参照してください。

関連する問題