我们先来定义一个普通的模板类
1 template<class T> 2 struct Test 3 { 4 Test(){ cout << "模板类" << endl; } 5 };
我们再来调用一下:
1 int main() 2 { 3 Test<char> t1; 4 Test<int> t2; 5 Test<int *> t3; 6 return 0; 7 }
输出的结果1:
模板类
模板类
模板类
如果我们这样写,再增加一个模板类
1 template<class T> 2 struct Test 3 { 4 Test(){ cout << "模板类" << endl; } 5 }; 6 7 template<> 8 struct Test<int> 9 { 10 Test(){ cout << "全特化" << endl; } 11 };
再来调用一下,调用代码同上!
输出的结果2:
模板类
全特化
模板类
其中template<>开头的模板类就是全特化的模板类,根据全特化模板的定义就知道,全特化的时候没有类型参数,即template<(这里是空)>。由于全特化版本的模板类与Test<int> t2;调用时更接近,所以会用这个模板来实例化一个类。
那什么是偏特化模板类,先看如下定义:
1 template<class T> 2 struct Test 3 { 4 Test(){ cout << "模板类" << endl; } 5 }; 6 7 template<> 8 struct Test<int> 9 { 10 Test(){ cout << "全特化" << endl; } 11 }; 12 13 template<class T> 14 struct Test<T*> 15 { 16 Test(){ cout << "偏特化" << endl;} 17 };
再次调用,输出结果3:
模板类
全特化
偏特化
我们看一下,第三个模板类的定义,会发现它很特别,它既有类型参数。但又需要对其进行特化(这里是特化成指针类型),当你给的是指针类型的时候,会调用这个模板,而不是普通模板。这就是部分特化,也称偏特化。有的人可能会想到,我这样写不也行么:
template<class T*> struct Test { Test(){ cout << "型别是指针!" << endl;} };
对不起,这段代码可以通过编译,但是在你实例化一个类的时候,即Test<int *> t;的时候就编译不同过了!所以必须要用到偏特化!当然,我上面写的是偏特化的一种,当这样的时候也是偏特化:
template<class T> struct Test<int,T> { }
这个偏特化的例子中,一个参数被绑定到int类型,而另一个参数仍未绑定需要由用户指定。这也是偏特化。而且更好理解!还有一点要注意的是,我们在写全特化类模板和偏特化类模板的时候,都必须给出一个普通类模板的定义,如果不定义普通模板而只定义全特化模板或者偏特化模板编译时会报错:对不起,XXX不是一个模板!