應用背景:
例如有下面的函數模板,它用來獲取兩個變量中較大的一個:
template<class T> const T& Max(const T& a, const T& b){ return a > b ? a : b; }
請讀者注意a > b
這條語句,>
能夠用來比較 int、float、char 等基本類型數據的大小,但是卻不能用來比較結構體變量、對象以及數組的大小,因為我們並沒有針對結構體、類和數組重載>
。
另外,該函數模板雖然可以用於指針,但比較的是地址大小,而不是指針指向的數據,所以也沒有現實的意義。
讓模板能夠針對某種具體的類型使用不同的算法(函數體或類體不同),這在 C++ 中是可以做到的,這種技術稱為模板的顯示具體化(Explicit Specialization)。
一.函數模板的顯式具體化
#include <iostream> #include <string> using namespace std; typedef struct { string name; int age; float score; } STU; template<typename T> const T& Max(const T &a, const T &b); template<> const STU& Max<STU>(const STU &a, const STU &b); ostream & operator<<(ostream &out, const STU &stu); int main() { int a = 10; int b = 20; cout<<Max(a,b)<<endl; STU stu1 = {"Jack",16,95.5}; STU stu2 = {"Mike",17,90.0}; cout<<Max(stu1,stu2)<<endl; return 0; } template<typename T> const T& Max(const T &a, const T &b) { return a > b ? a : b; } template<> const STU& Max<STU>(const STU &a, const STU &b) { return a.score > b.score ? a : b; } ostream & operator<<(ostream &out, const STU &stu) { out<<stu.name<<", "<<stu.age<<", "<<stu.score; return out; }
運行結果:
20
Jack,16,95.5
語法格式為:
template<> const STU& Max(const STU& a, const STU& b);
二.類模板顯式具體化
#include <iostream> #include <string> using namespace std; template<typename T1, typename T2> class Point { public: Point(T1 x, T2 y):m_x(x), m_y(y){} public: T1 getX() const {return m_x;} void setX(T1 x) {m_x = x;} T2 getY() const {return m_y;} void setY(T2 y) {m_y = y;} void display() const; private: T1 m_x; T2 m_y; }; // 這里要帶上模板頭 template<typename T1, typename T2> void Point<T1,T2>::display() const { cout<<"x="<<m_x<<", y="<<m_y<<endl; } // 類模板顯式具體化(針對字符串類型的顯式具體化) template<> class Point<char *, char *> { public: Point(char *x, char *y):m_x(x), m_y(y){} public: char* getX() const {return m_x;} void setX(char *x) {m_x = x;} char *getY() const {return m_y;} void setY(char *y) {m_y = y;} void display() const; private: char *m_x; char *m_y; }; // 注意!這里不能帶模板頭template<> void Point<char*, char*>::display() const { cout<<"x="<<m_x<<", y="<<m_y<<endl; } int main() { (new Point<int,int>(10,20))->display(); (new Point<int, char*>(20,"jack"))->display(); (new Point<char*,char*>("java","android"))->display(); return 0; }
運行結果:
x =10, y = 20
x = 20, y = jack
x = java, y = android
需要注意的是:在類模板的具體化中,成員方法的實例化是不能帶模板頭template<>的。
三.部分顯式具體化
#include <iostream> using namespace std; // 類模板 template<typename T1, typename T2> class Point { public: Point(T1 x, T2 y):m_x(x), m_y(y){} public: T1 getX() const {return m_x;} void setX(T1 x){m_x = x;} T2 getY() const {return m_y;} void setY(T2 y){m_y = y;} void display() const; private: T1 m_x; T2 m_y; }; template<typename T1, typename T2> void Point<T1,T2>::display() const { cout<<"x="<<m_x<<", y="<<m_y<<endl; } template<typename T2> class Point<char*, T2> { public: Point(char *x, T2 y):m_x(x), m_y(y){} public: char *getX() const {return m_x;} void setX(char *x){m_x = x;} T2 getY() const {return m_y;} void setY(T2 y){m_y = y;} void display() const; private: char *m_x; T2 m_y; }; // 部分顯式具體化還是需要加上模板頭 template<typename T2> void Point<char*,T2>::display() const { cout<<"x="<<m_x<<" | y="<<m_y<<endl; } int main() { (new Point<int,int>(10,20))->display(); (new Point<char*,int>("jack",10))->display(); (new Point<char*,char*>("java","android"))->display(); return 0; }
運行結果:
x = 10, y = 20
x = jack | y = 10
x = java | y = android
注意:
部分顯式具體化只能用於類模板,不能用於函數模板