2017-08-20 78 views
2

我寫了一個小的函數類,它應該能夠通過隱藏一個靜態包裝函數和一個指向該對象的void指針來調用類成員函數。下面的示例在設置包裝函數時由於錯誤而無法編譯。我想要的是一個類成員指針作爲模板參數。有人知道那裏有什麼問題嗎?類成員函數的C++函子模板

我認爲在調用成員函數時,靜態函數中可能存在另一個問題。我不完全知道如何使用模板語法來做到這一點。最小的例子用C++ 11編譯啓用gcc。

#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

你需要傳遞一個指向'Test'類成員函數的指針,你想調用''Functor'。 '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

這工作正常,但我可以使用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...); 
    } 
}; 

而且使用這種方式:

Functor<void(int)> f; 
Test    t; 

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

f(100); 

也就是說,現在你可以使用成員函數作爲memberCaller模板參數並讓它擦除類型並在調用後在內部使用它。

我也稍微改變了Functor定義,以便使用它作爲:

Functor<void(int)> 

,當你打算與功能型用它那比下面的更明確一點:

Functor<void, int> 

我的兩分錢,至少。


查看上面的例子,並在wandbox上運行。