模板的定義:模板就是實現代碼重用機制的一種工具,它可以實現類型參數化,即把類型定義爲參數, 從而實現了真正的代碼可重用性。
模版可以分爲兩類,一個是 函數模版 ,另外一個是 類模版。
#include <iostream>
using namespace std;
//模板函數
template<typename T>
void add(T num1, T num2) {
cout << num1 << " + " << num2 << " = "<< num1 + num2 << endl;
}
//模板類
template<typename T>
class Test_Class {
public:
static void multi(T num1, T num2) {
cout << num1 << " * " << num2 << " = "<< num1 * num2 << endl;
}
};
int main(){
//Test 1
int num1 = 1;
int num2 = 2;
add<int>(num1, num2);
Test_Class<int>::multi(num1, num2);
//Test 2
double num3 = 3.1;
double num4 = 4.2;
add<double>(num3, num4);
Test_Class<double>::multi(num3, num4);
return 0;
}
結果:
函數模板是可以被重載的(類模板不能被重載),也就是說允許存在兩個同名的函數模板,還可以對它們進行實例化,使它們具有相同的參數類型。
//函數模板
template <typename T>
int fun(T){
return 1;
}
//函數模板的重載
template <typename T>
int fun(T*){
return 2;
}
int main(){
cout << fun<int*>((int*)0) << endl;
cout << fun<int>((int*)0) << endl;
return 0;
}
特化
前面提到函數模板能被重載,而類模板不可以,我們可以通過特化來實現相似的效果,從而可以透明地獲得具有更高效率的代碼。
特化也分爲了兩種,全特化和偏特化。
不能將特化和重載混爲一談
全特化和偏特化都沒有引入一個全新的模板或者模板實例。它們只是對原來的泛型(或者非特化)模板中已經隱式聲明的實例提供另一種定義。
在概念上,這是一個相對比較重要的現象,也是特化區別於重載模板的關鍵之處。
全特化
全特化是模板的一個唯一特例,指定的模板實參列表必須和相應的模板參數列表一一對應。
//該程序用來演示全特化類
#include <iostream>
using namespace std;
template<typename T1, typename T2>
class A{
public:
void function(T1 value1, T2 value2){
cout<<"value1 = "<<value1<<endl;
cout<<"value2 = "<<value2<<endl;
}
};
template<>
class A<int, double>{ // 類型明確化,爲全特化類
public:
void function(int value1, double value2){
cout<<"intValue = "<<value1<<endl;
cout<<"doubleValue = "<<value2<<endl;
}
};
int main(){
A<int, double> a;
a.function(12, 12.3);
return 0;
}
偏特化
偏特化感覺像是介於普通模板和全特化之間,只存在部分的類型明確化,而非將模板唯一化。
再次劃重點 函數模板不能被偏特化。
偏特化類樣例:
#include <iostream>
using namespace std;
template<typename T1, typename T2>
class A{
public:
void function(T1 value1, T2 value2){
cout<<"value1 = "<<value1<<endl;
cout<<"value2 = "<<value2<<endl;
}
};
template<typename T>
class A<T, double>{ // 部分類型明確化,爲偏特化類
public:
void function(T value1, double value2){
cout<<"Value = "<<value1<<endl;
cout<<"doubleValue = "<<value2<<endl;
}
};
int main(){
A<char, double> a;
a.function('a', 12.3);
return 0;
}
偏特化的特殊例子
//這段代碼是STL源碼中的一部分
template <class Iterator>
struct iterator_traits {
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};
/*
* 偏特化版本,我們可以看到他的唯一不同之處就是T*,這也是偏特化的一種
*/
template <class T>
struct iterator_traits<T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
模板類調用優先級
對主版本模板類、全特化類、偏特化類的調用優先級從高到低進行排序是:
全特化類>偏特化類>主版本模板類
這樣的優先級順序對性能也是最好的。
重點總結
類模板和函數模板都可以被全特化;
類模板能偏特化,不能被重載;
函數模板全特化,不能被偏特化。
原文鏈接