2011-08-18 160 views
1

考慮以下設置:C++編譯器如何決定調用哪些函數?

我給定一個接口

template<class T> 
    void FooClass<T>::foo(boost::function<double (int)> f) 
{...} 

我想實現F使用仿函數:

class MyFun { 
    public: double operator()(int a) {do something...;} 
} 

但是沒有在接口定義的另一個功能

template<class T> 
    template <class FunPtr> 
    void FooClass<T>::foo(const FunPtr& f) 
{...} 

當一個FooClass對象被調用時,

MyFun f; 
FooClass<double> fooclass; 
fooclass.foo(f); 

它使用第二個定義,而我希望它調用第一個 - 這可以以某種方式改變嗎?

回答

6

編譯器「preferres」第二個定義,因爲模板版本導致一個精確難擋函數對象參數,而boost::function參數需要隱式轉換被接受(並且在直接重載分辨率之後隱式轉換被認爲是)。你可以實現你想要的只是通過構建一個boost::function對象,然後它傳遞給函數(注意,您可以在同一行中做到這一點,我只是在做它分別爲清楚起見):

boost::function<double (int)> bMyFun(myFunInstance); 
fooClassInstance.foo(bMyFun); 
2

可以明確構建一個boost::function對象,以便第一超載將被優先考慮:

fooclass.foo(boost::function<double (int)>(f)); 

關於你的問題的標題,你想知道重載是如何工作的?當選擇過載時,無模板類型比模板類型更好匹配,但直接匹配的模板類型(FunPtr = MyFun)與隱式轉換(MyFun -> boost::function<double(int)>)匹配的匹配性更好,因此第二次重載在您的原始案例。

(感謝@大衛在我原來的表述指出了一個明顯的錯誤!)

+0

感謝您的回答。我對這些概念並不是很熟悉,所以現在我只想知道在這個具體例子中它是如何工作的。 – Hans

+0

*直到選擇了過載後,纔會考慮潛在的隱式轉換鏈。他們被考慮了,這就是如何找到最好的超載。問題在於,模板版本比任何需要轉換的版本都更好,但重載解析會考慮兩者,然後決定是否使用模板。 –

+0

@David:選擇模板是因爲這是一個更好的匹配 - 如果首先考慮轉換,那麼該函數將被視爲可轉換爲'boost :: function',並且第一次重載會更好匹配,不是嗎? –

相關問題