应用背景:
例如有下面的函数模板,它用来获取两个变量中较大的一个:
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
注意:
部分显式具体化只能用于类模板,不能用于函数模板