2017-06-19 31 views
2

考慮到這種代碼:C++函數模板特殊化和重載

template <class T> 
void f(T p) {   //(1) 
    cout << "Second" << endl; 
} 

template <> 
void f(int *p) {  //(2) 
    cout << "Third" << endl; 
} 


template <class T> 
void f(T* p) {   //(3) 
    cout << "First" << endl; 
} 

呼叫如int *p; f(p);將輸出First

如果聲明的順序改變時,這樣的:

template <class T> 
void f(T* p) {   //(3) 
    cout << "First" << endl; 
} 


template <class T> 
void f(T p) {   //(1) 
    cout << "Second" << endl; 
} 

template <> 
void f(int *p) {  //(2) 
    cout << "Third" << endl; 
} 

相同的呼叫(int *p; f(p);)將輸出Third

我讀到其中函數模板重載需要的地方的方式:第一分辨率只考慮非模板功能底層的基本模板。在選擇「最專業化」之後,如果它是一個模板函數,並且對推導(或明確指定)的參數具有專門化,則調用該專業化。

現在我的問題是:如何確定哪個底層基模板的某個功能是專門化的?在我的例子中,哪個函數模板過載((1)或(3))是(2)專業化?

我的猜測是,當聲明專業化時,已經聲明瞭模板,並從那些最「專業的」(其參數與這個專業化「最接近」)被選擇。它是否正確?另外,您能否指出我在標準中指定的位置?

回答

3

它會打印「第一個」,因爲聲明的順序會影響您實際專用的模板。

你的例子有兩個函數模板,它們重載相同的名字。在第一種情況下,您專門致力於void f(T p),因爲它是目前爲止唯一可見的模板。

在第二種情況下,它是專門的void f(T* p)。所以是的,你的猜測是正確的。具體是在[temp.deduct.decl/1]

在一項聲明,其聲明符-ID是指 函數模板的特化,模板參數推導進行到 查明該聲明指專業化。 具體來說,這是針對顯式實例化,顯式 專業化,和某些朋友聲明。 [...]

而且包括功能模板的部分排序。但是,部分排序僅適用於您引入專業化時可用的函數模板聲明。

,標準警告在[temp.expl.spec/7]

明確的專業化聲明的位置函數模板,[...],可以根據顯式專業化 聲明的相對定位以及它們在如上下文指定的翻譯單元 中的實例化點的相對定位來影響程序是否格式良好 。在寫專業時,請注意 的位置;或者讓它編譯成這樣的嘗試 以點燃它的自焚。

+0

因此,從專業化之前聲明的模板函數中,使用偏序排序來選擇「正確的一個」? – user42768

+0

@ user42768 - 通過模板參數推導*和*部分排序,是的。 – StoryTeller