[英]Template type deduction for a pointer to member function
我有一個與Morpheus提出的問題非常相似的問題,在下面的問題中:
Richard Corden提出的解決方案要求用戶明確指定函數參數類型,以區分它們的重載。 但是,此解決方案似乎不適用於具有相同類型的不同數量的參數的重載。
考慮這個例子(源自原始問題):
template <typename T>
class A
{
public:
template<class Arg1>
void connect(void (T::*f)(Arg1))
{
//Do some stuff
}
template<class Arg1, class Arg2>
void connect(void (T::*f)(Arg1,Arg2))
{
//Do some stuff
}
void connect(void (T::*f)())
{
//Do some stuff
}
};
class GApp
{
public:
void foo() {}
void foo(double d) {}
void foo(double d1, double d2) {}
};
int main ()
{
A<GApp> a;
a.connect (&GApp::foo); // foo () - OK
a.connect<double> (&GApp::foo); // foo (double) - FAIL
a.connect<double,double> (&GApp::foo); // foo (double,double) - OK
}
GNU G ++ 3.4.5和MSVC 2008不編譯上面的代碼,兩者都提供類似的錯誤消息:
test.cpp: In function `int main()':
test.cpp:36: error: call of overloaded `connect(<unknown type>)' is ambiguous
test.cpp:7: note: candidates are: void A<T>::connect(void (T::*)(Arg1)) [with Arg1 = double, T = GApp]
test3.cpp:13: note: void A<T>::connect(void (T::*)(Arg1, Arg2)) [with Arg1 = double, Arg2 = double, T = GApp]
我知道一些可以使其編譯的變通方法,比如將指針指定給完全相同類型的變量(例如void (GApp::*tmp)(double) = &GApp::foo;
)或者,使用更多調用connect函數時的表達形式(例如connect((void (GApp::*)(double))(&GApp::foo));
)。
但是,我更喜歡第一種解決方案,並想知道它為什么不起作用。
先感謝您!
對於a.connect<double> (&GApp::foo)
, foo(double)
和foo(double, double)
將匹配connect
的重載與one,並分別與兩個模板參數匹配(在兩個參數的情況下)版本,將推導出第二個模板參數,第一個參數由您明確提供)。
如果你想消除模棱兩可的情況,我建議你傳遞確切的類型,這樣就不會出現任何意外。 而不是那些重載,為什么不有一個重載
template<typename MType, typename T>
void connect(MType T::*f)
{
//Do some stuff
}
a.connect<void()> (&GApp::foo);
a.connect<void(double)> (&GApp::foo);
a.connect<void(double, double)> (&GApp::foo);
最后一次調用connect
應該在你的代碼中正常工作。 然后,您可以在connect
單獨模板時剖析類型MType
,以獲取參數和返回類型。
原始代碼的問題在於您明確定義了錯誤的部分。 當你指定一個模板參數列表時,即使你指定了一個模板參數列表,編譯器也會嘗試推導出第二個模板參數,然后它會立即運行到模糊狀態,因為它不知道你是否想要使用(double,double)或(雙)變異。
讓編譯器推導出它們,而不是定義模板參數,而是明確指定要使用哪個foo()函數:
int main()
{
A<GApp> a;
a.connect (&GApp::foo); // foo () - OK
a.connect( ( void (GApp::*)(double) )&GApp::foo); // foo (double) - OK
a.connect( ( void (GApp::*)(double, double) ) &GApp::foo); // foo (double,double) - OK
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.