複製鏈接
請複製以下鏈接發送給好友

模板特化

鎖定
C++中的模板特化不同於模板的實例化,模板參數在某種特定類型下的具體實現稱為模板的特化。模板特化有時也稱之為模板的具體化,分別有函數模板特化和類模板特化。 [1] 
中文名
模板特化
外文名
Template Specialization
領    域
計算機編程
編程語言
C++

模板特化函數模板特化

函數模板特化是在一個統一的函數模板不能在所有類型實例下正常工作時,需要定義類型參數在實例化為特定類型時函數模板的特定實現版本。查看如下例子。
#include <iostream>
using namespace std;
template<typename T> T Max(T t1,T t2){
    return (t1>t2)?t1:t2;
}
 
typedef const char* CCP;
template<> CCP Max<CCP>(CCP s1,CCP s2){
    return (strcmp(s1,s2)>0)?s1:s2;
}
int main(){
//調用實例:int Max<int>(int,int)
    int i=Max(10,5);
    //調用顯示特化:const char* Max<const char*>(const char*,const char*)
    const char* p=Max<const char*>("very","good");
    cout<<"i:"<<i<<endl;
    cout<<"p:"<<p<<endl;
}
程序正常編譯運行結果:
i:10
p:very
在函數模板顯示特化定義(Explicit Specialization Definition)中,顯示關鍵字template和一對尖括號<>,然後是函數模板特化的定義。該定義指出了模板名、被用來特化模板的模板實參,以及函數參數表和函數體。在上面的程序中,如果不給出函數模板Max<T>在T為const char*時的特化版本,那麼在比較兩個字符串的大小時,比較的是字符串的起始地址的大小,而不是字符串的內容在字典序中先後次序。
1.1.1使用函數重載替代函數模板特化
除了定義函數模板特化版本外,還可以直接給出模板函數在特定類型下的重載形式(普通函數)。使用函數重載可以實現函數模板特化的功能,也可以避免函數模板的特定實例的失效。例如,把上面的模板特化可以改成如下重載函數。 [1] 
typedef const char* CCP;
CCP Max(CCP s1,CCP s2){
    return (strcmp(s1,s2)>0)?s1:s2;
}
程序運行結果和使用函數模板特化相同。但是,使用普通函數重載和使用模板特化還是有不同之處,主要表現在如下兩個方面:
(1)如果使用普通重載函數,那麼不管是否發生實際的函數調用,都會在目標文件中生成該函數的二進制代碼。而如果使用模板的特化版本,除非發生函數調用,否則不會在目標文件中包含特化模板函數的二進制代碼。這符合函數模板的“惰性實例化”準則。
(2)如果使用普通重載函數,那麼在分離編譯模式下,應該在各個源文件中包含重載函數的申明,否則在某些原文件中就會使用模板實例化,而不是重載函數。

模板特化類模板特化

類模板特化類似於函數模板的特化,即類模板參數在某種特定類型下的具體實現。考察如下代碼。
#include <iostream>
using namespace std;
 
template<typename T>class A{
    T num;
public:
    A(){
        num=T(6.6);
    }
    void print(){
        cout<<"A'num:"<<num<<endl;
    }
};
 
template<>class A<char*>{
    char* str;
public:
    A(){
        str="A' special definition ";
    }
    void print(){
        cout<<str<<endl;
    }
};
 
int main(){
    A<int> a1; //顯示模板實參的隱式實例化
    a1.print();
    A<char*> a2;//使用特化的類模板
    A2.print();
}
程序輸出結果如下:
A'num:6
A' special definition
參考資料
  • 1.    陳剛.C++高級進階教程.湖北武漢:武漢大學出版社,2008:225-228