簡體   English   中英

指向成員函數的指針的模板類型推導

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM