模板函數重載
例子:
template<typename T> //(a):主模板
void f(T t)
{
cout << "template 1/n";
}
int main(int argc, char *argv[])
{
int *p = new int(2);
f(p);
f(*p);
system("PAUSE");
return 0;
}
如果只有上面這一個函數模板,main中的兩個調用自然都匹配這個模板。如果增加一個模板:
template<typename T> //(b):主模板,重載了(a)
void f(T *t)
{
cout << "template 2/n";
}
那麼f(p)調用(b),f(*p)調用(a)。如果再增加一個特化模板:
template<> void f<int *>(int *t) //(c):(a)的特化
{
cout << "template 3/n";
}
出乎意料,f(p)還是調用(b),f(*p)還是調用(a)。這是因爲重載決議時只考慮主模板。
如果將(b)也特化:
template<> void f<int>(int *t) //(d):(b)的特化
{
cout << "template 5/n";
}
這時f(p)調用的時(d),f(*p)調用的是(a)。
如果提供一個普通函數:
void f(int *p) //(e):普通函數
{
cout << "no template/n";
}
此時f(p)調用(e)。
準則:函數模板特化並不參與重載決議。只有在某個主模板被重載決議選中的前提下,其特化版本纔有可能被使用。而且,編譯器在選擇主模板的時候並不關心它是否有某個特化版本。
準則:如果一個普通的非模板函數跟一個函數模板在重載解析的參數匹配中表現一樣好的話,編譯器會選擇普通函數。
更多內容請參考《Exceptional C++ Style》第7條。