[英]function template explicit specialization
在本文中 ,他們說(c)明確專門化(b)。 我懷疑為什么我們不能說這是(a)的明確專業化? 因為我們可以為任何特定類型專門化模板。 所以雖然專注於int *,但為什么他們說(c)明確專門化(b)。
template<class T> // (a) a base template
void f( T );
template<class T> // (b) a second base template, overloads (a)
void f( T* ); // (function templates can't be partially
// specialized; they overload instead)
template<> // (c) explicit specialization of (b)
void f<>(int*);
任何評論都有助於理解事物。
如果(b)不存在,則(c)確實是(a)的有效專業化。 實際上,只是改變源代碼行的順序,以便(c)在編譯器看到(b)之前出現,將使它成為(a)的特化!
請考慮以下代碼:
int main()
{
int a;
f(&a);
return 0;
}
現在把自己放在編譯器的鞋子里。 您需要使用int*
參數找到匹配的函數f
。 你是做什么?
f
的非模板函數,並查看是否存在與參數類型匹配的任何函數(在本例中為int*
)。 f<T>
和f<T*>
。 請注意,與類不同,函數模板不能部分專用,因此就編譯器而言,這些是完全獨立的重載。 f<T*>
基本模板是更好的匹配,因此您使用T=int
實例化它。 現在,如果您已經看過f<int*>
,那么您可以使用它,否則您將生成該函數。 現在這是有趣的事情。 如果我們更改原始代碼的順序,請轉到
template<class T> void f( T ); // (i)
template<> void f<>(int*); // (ii)
template<class T> void f( T* ); // (iii)
那么編譯器現在看到(ii)作為(i)的特化 - 因為它按順序處理事物,並且在它達到(ii)時它不知道(iii)存在了! 但由於它僅匹配基礎模板,因此它決定(iii)是比(i)更好的匹配 - 現在(iii)沒有任何特化,因此您獲得默認實例化。
這一切都讓人很困惑,有時甚至會讓最有經驗的C ++程序員絆倒。 所以基本規則是: 不要專門化函數模板,而是使用普通函數重載 。 一個普通的舊的非模板
void f(int*);
在其他事情之前會匹配,並避免這一切混亂。
編輯: nm請求在評論中引用標准。 我擔心我只有C ++ 03版本,但是這里有:
第4.7.3.3段: “明確專門化的函數模板或類模板的聲明應在聲明明確專業化的范圍內。” 。
這就是為什么在上面的例子中,(ii)不能被視為(iii)的明確專業化,因為(iii)還不在范圍內。
第4.8.3節: “當寫入對[函數]名稱的調用時...對每個函數模板執行模板參數推導(14.8.2)和檢查任何顯式模板參數(14.3)以查找模板參數值(如果有的話),可以與該函數模板一起使用,以實例化可以使用調用參數調用的函數模板特化。“
換句話說,(正如我所讀到的,無論如何)它始終會查看每個基本模板,無論如何 - 提供明確的專業化沒有任何區別。
同一段落繼續: “對於每個函數模板,如果參數推導和檢查成功,則使用模板參數(推斷和/或顯式)來實例化單個函數模板特化,該特殊化被添加到候選函數集中。用於重載分辨率。 “
因此,只有在這一點(我讀到它)才會考慮顯式特化。
最后,也許最重要的是在這種情況下,第13.3.3節涉及選擇過載集中的“最佳可行功能”。 兩個項目是相關的:
F1優於F2,如果: “F1和F2是功能模板特化,F1的功能模板比F2模板更專業,根據14.5.5.2中描述的偏序規則” 。 這就是f<T*>
版本在嘗試匹配f(int*)
時在f<T>
版本之前被選中的原因 - 因為它是一個“更專業”的模板
F1優於F2,如果: “F1是非模板函數,F2是函數模板特化” ,這是我在原始答案結束時的建議的基礎。
唷!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.