[英]Non-type template function pointer to const member function
我正在編寫一個委托類但它沒有采用const成員函數。 這是一個測試用例:
class foo
{
public:
void MemberFunction()
{
printf("non const member function\n");
}
void ConstMemberFunction() const
{
printf("const member function\n");
}
};
template <class C, void (C::*Function)()>
void Call(C* instance)
{
(instance->*Function)();
}
int main (int argc, char** argv)
{
foo bar;
Call<foo,&foo::MemberFunction>(&bar);
Call<foo,&foo::ConstMemberFunction>(&bar);
}
現在編譯器(visual studio 2010)給了我一個錯誤,他無法將const成員函數轉換為非const函數:
2>..\src\main.cpp(54): error C2440: 'specialization' : cannot convert from 'void (__cdecl foo::* )(void) const' to 'void (__cdecl foo::* const )(void)'
2> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
2>..\src\main.cpp(54): error C2973: 'Call' : invalid template argument 'void (__cdecl foo::* )(void) const'
2> ..\src\main.cpp(37) : see declaration of 'Call'
好的,輕松修復(我雖然:P)添加:
template <class C, void (C::*Function)() const>
void Call(C* instance)
{
(instance->*Function)();
}
但現在編譯器完全混淆了(我用它)。 看起來他現在試圖將const函數用於非const成員函數,而將const函數用於const成員函數。
2>..\src\main.cpp(53): error C2440: 'specialization' : cannot convert from 'void (__cdecl foo::* )(void)' to 'void (__cdecl foo::* const )(void) const'
2> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
2>..\src\main.cpp(53): error C2973: 'Call' : invalid template argument 'void (__cdecl foo::* )(void)'
2> ..\src\main.cpp(43) : see declaration of 'Call'
2>..\src\main.cpp(53): error C2668: 'Call' : ambiguous call to overloaded function
2> ..\src\main.cpp(43): could be 'void Call<foo,void foo::MemberFunction(void)>(C *)'
2> with
2> [
2> C=foo
2> ]
2> ..\src\main.cpp(37): or 'void Call<foo,void foo::MemberFunction(void)>(C *)'
2> with
2> [
2> C=foo
2> ]
2> while trying to match the argument list '(foo *)'
2>..\src\main.cpp(54): error C2440: 'specialization' : cannot convert from 'void (__cdecl foo::* )(void) const' to 'void (__cdecl foo::* const )(void)'
2> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
2>..\src\main.cpp(54): error C2973: 'Call' : invalid template argument 'void (__cdecl foo::* )(void) const'
2> ..\src\main.cpp(37) : see declaration of 'Call'
2>..\src\main.cpp(54): error C2668: 'Call' : ambiguous call to overloaded function
2> ..\src\main.cpp(43): could be 'void Call<foo,void foo::ConstMemberFunction(void) const>(C *)'
2> with
2> [
2> C=foo
2> ]
2> ..\src\main.cpp(37): or 'void Call<foo,void foo::ConstMemberFunction(void) const>(C *)'
2> with
2> [
2> C=foo
2> ]
2> while trying to match the argument list '(foo *)'
如果我將重命名第二個Call函數(使用const),它一切正常,但我寧願使用一個函數。
那么,任何人都可以指出我做錯了什么以及如何使這項工作成功?
謝謝!
我想你可以通過從模板類型簽名中刪除函數指針而不是依賴重載來解決這個問題:
template <class C>
void Call(C* ptr, void (C::*function)()) {
(ptr->*function)();
}
template <class C>
void Call(C* ptr, void (C::*function)() const) {
(ptr->*function)();
}
現在使用常規函數重載來選擇應該調用哪兩個函數。 const
成員函數指針將調用第二個版本,而非const
函數將調用第一個版本。 這也意味着您不需要向模板函數顯式提供任何類型信息; 編譯器可以在兩個上下文中推導出C
讓我知道如果(1)這不起作用或(2)這確實有效,但不是你想要的。
希望這可以幫助!
使用VS2010支持的std::bind
或lambdas,以及std::function
,這對你來說將不再是一個問題。
您的問題是成員函數指針是一個不同於const成員函數指針的類型。 我將你的Call
函數修改為:
template< typename C, typename funcptr_t, funcptr_t ptr >
void Call( C *instance )
{
(instance->*ptr)();
}
現在使用額外的模板參數,我可以像這樣調用它:
Call<foo,void (foo::*)(),&foo::MemberFunction>(&bar);
Call<foo,void (foo::*)() const, &foo::ConstMemberFunction>(&bar);
不過,這有點亂。 重載解決方案更好! :-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.