2015-04-03 45 views
3
//(1) 
template <class T> 
void f(T) {} 

//(2) 
template <class T> 
void f(T*) {} 

//(3) 
template <> 
void f<>(int*) {} 

//(4) 
void f(int*) {} 

int main() 
{ 
    int* p; 
    f(p); // which function will be called? 
    return 0 
} 

我已經知道的行爲:規則來查找這些模板函數重載被稱爲

  • 這取決於是否超載(4)存在。
  • 這取決於(1),(2)和(3)

,我心裏秩序問題(因爲它增加了不確定性和猜測工作時,我寫的代碼),特別是我的聲明的順序知道如果這些是類專業化,那麼順序無關緊要,最專業的類將由編譯器調用。

有人可以向我解釋這是如何工作的?編譯器遵循什麼規則來找到適當的功能專業化?

回答

5

基本規則實際上很簡單:函數和函數模板參與重載解析。顯式函數模板專門化不。

因此,對於調用f(p),編譯器會重載解析以在(1),(2)和(4)之間進行選擇。 (3)是從不考慮過載分辨率

重載解析選擇單個函數或函數模板。 之後就完成了,如果它選擇了功能模板,將會考慮該模板的專業化。

讓我們來分析您提供的不同聲明組合。

  • 如果(4)存在,它將被明確地選擇。當其他條件相同時,非模板函數是比函數模板更好的過載匹配。

  • 比方說,我們只有(1),(2)和(3)按此順序。 (1)和(2)之間選擇重載分辨率。 (2)更好,因爲它更專業。所以函數模板(2)是通過重載分辨率來選擇的。

    然後,編譯器查看模板是否有任何專業化。事實上,—專業化(3),爲T = int。所以選擇這個專業化。

  • 現在,讓我們說順序是(1),(3),(2)。同樣,重載決議在(1)和(2)之間選擇(記住特殊化,其中(3)是永遠不參與重載決議)。 (2)再次被選擇。這一次,(3)是(1)的專門化,對於T = int*。那是因爲(2)在宣佈(3)時還不存在,所以沒有(2)專門化。但(1)不是由重載決議選擇的,所以不考慮。 (2),(3),(1)的順序與(1),(2),(3)相同。順序(2),(1),(3)與(1),(3),(2)相同。 (1)和(2)的相對順序並不重要,它是(3)的位置,它控制着它將專門化的模板。

+0

謝謝您的回答!偉大的迴應。 – Kam 2015-04-03 13:33:12

2

這取決於是否存在過載(4)。

...這是由於重載一個特殊的規則:不在一些模板的特優於函數模板特,如果這些都是重載決議規則,否則無法區分功能。例如。

template <typename T> 
void f(T); // A 

void f(int); // B 

f(4); // Calls B - Conversions of 4 to both parameter types are equivalent 

這也適用於您的樣品:由於參數類型的f<int>(1),f<int*>(2)和f(4)是相同的,(4)必須進行選擇。

一旦(4)消失了,在半序踢:它確定(2)是更專門的,因爲

  • 一些任意類型U不能由T*U匹配不是指針),而

  • 一些任意指針類型V*可以通過T(匹配因爲T將被簡單地推導出V*)。

因此來自(2)的專業化f<int>是更好的匹配。

這取決於申報的順序(1)(2)和(3)

你聲明的名稱f兩個函數模板重載。但是你聲明的明確的專業化可以同時適用於兩者!推導出模板參數,並且可以推導出f(T)f(T*),因爲它們都可以採用指向int的指針。

template <class T> void f(T) {} // (1) 

// Specializes f<int*> from (1), (2) not yet declared 
template <> void f<>(int*) {} 

template <class T> void f(T*) {} // (2) 

或者

template <class T> void f(T) {} // (1) 
template <class T> void f(T*) {} // (2) 

// Specializes f<int> from (2) 
template <> void f<>(int*) {} 

在後者的情況下,(2)被選擇,因爲它比更特化的(1)(根據部分排序的規則)。您可以通過明確提供模板參數來使該專業化毫不含糊,而不是讓它們未指定:

template <> 
void f<int>(int*) {} // Can only specialize (2)