泛型編程是指獨立與任何類型的方式編寫代碼。泛型編程和麪向對象編程,都依賴與某種形式的多態。面向對象編程的多態性在運行時應用於存在繼承關係的類,一段代碼能夠能夠忽略基類和派生類之間的差別。在泛型編程中,編寫的代碼能夠用做多種類型的對象。面向對象編程所依賴的多態性稱爲運行時多態性,泛型編程所依賴的多態性稱爲編譯時多態性或參數式多態性。 html
1 template<typename T> 2 inline bool isEqual(const T& t1, const T& t2) { 3 return t1 == t2; 4 }
1 const size_t MAXSIZE = 100; 2 template<class T> 3 class Stack{ 4 private: 5 T elements[MAXSIZE]; 6 public: 7 //others 8 };
1 template<typename T,int X = 5> 2 inline bool isEqualToX(const T& a) { 3 return a == X; 4 } 5 6 template<class T,int MAXSIZE=100> 7 class Stack { 8 private: 9 T elements[MAXSIZE]; 10 public: 11 //others 12 };
有時爲了須要,針對特定的類型,須要對模板進行特化,也就是特殊處理。 例如,stack類模板針對bool類型,由於實際上bool類型只須要一個二進制位,就能夠對其進行存儲,使用一個字或者一個字節都是浪費存儲空間的.。特化必須在同一命名空間下進行,能夠特化類模板也能夠特化函數模板,但類模板能夠偏特化和全特化,而函數模板只能全特化。模板的偏特化是指須要根據模板的某些但不是所有的參數進行特化。嚴格的來講,函數模板並不支持偏特化,但因爲能夠對函數進行重載,因此能夠達到相似於類模板偏特化的效果。模板實例化時會優先匹配」模板參數」最相符的那個特化版本。template < >告訴編譯器這是一個特化的模板。ios
1 template<class T,int MAXSIZE=100> 2 class Stack { 3 private: 4 T elements[MAXSIZE]; 5 public: 6 //others 7 }; 8 9 //template specializations aim at bool 10 template<> 11 class Stack<bool>{ 12 13 };
1 template<typename T> 2 inline bool isEqual(const T t1, const T t2) { 3 return t1 == t2; 4 } 5 6 //針對int型的指針作特化 7 template<> 8 inline bool isEqual(const int* p1,const int* p2){ 9 return *p1 == *p2; 10 }
類模板的偏特化,例如c++標準庫中的類vector的定義,這個偏特化的例子中,一個參數被綁定到bool類型,而另外一個參數仍未綁定須要由用戶指定。c++
1 template <class T, class Allocator> 2 class vector { // … // }; 3 template <class Allocator> 4 class vector<bool, Allocator> { //…//};
函數模板的偏特化,嚴格的來講,函數模板並不支持偏特化,但因爲能夠對函數進行重載,因此能夠達到相似於類模板偏特化的效果。根據重載規則,對(a)進行重載。若是將(a)稱爲基模板,那麼(b)稱爲對基模板(a)的重載,而非對(a)的偏特化。C++的標準委員會仍在對下一個版本中是否容許函數模板的偏特化進行討論。
template <class T> void f(T); (a)
template < class T> void f(T*); (b)編程
3.1 隱式實例化。在使用模板函數和模板類時,不存在指定類型的模板函數和模板類的實體時,由編譯器根據指定類型參數隱式生成模板函數或者模板類的實體稱之爲模板的隱式實例化。函數模板隱式實例化指的是在發生函數調用的時候,若是沒有發現相匹配的函數存在,編譯器就會尋找同名函數模板,若是能夠成功進行參數類型推演,就對函數模板進行實例化。類模板隱式實例化指的是在使用模板類時纔將模板實例化。函數
3.2 顯示實例化。顯示實例化也稱爲外部實例化。在不發生函數調用的時候將函數模板實例化,或者在不適用類模板的時候將類模板實例化稱之爲模板顯示實例化。對於函數模板而言,不論是否發生函數調用,均可以經過顯示實例化聲明將函數模板實例化,定義函數模板爲:template函數返回類型 函數模板名<實際類型列表>(函數參數列表),顯示實例化爲template void func<int>(const int&);類模板的顯示實例化,對於類模板而言,不論是否生成一個模板類的對象,均可以直接經過顯示實例化聲明將類模板實例化,定義類模板格式爲:template class 類模板名<實際類型列表>,顯示實例化爲template class theclass<int>;優化
3.3 匹配規則spa
(1) 類模板的匹配規則。最優化的優於次特化的,即模板參數最精確匹配的具備最高的優先權,每一個類型均可以用做普通型(a)的參數,但只有指針類型才能用做(b)的參數,而只有void*才能做爲(c)的參數。.net
template <class T> class vector{//…//}; // (a) 普通型
template <class T> class vector<T*>{//…//}; // (b) 對指針類型特化
template <> class vector <void*>{//…//}; // (c) 對void*進行特化指針
(2) 函數模板的匹配規則。非模板函數具備最高的優先權。若是不存在匹配的非模板函數的話,那麼最匹配的和最特化的函數具備高優先權rest
template <class T> void f(T); // (d)
template <class T> void f(int, T, double); // (e)
template <class T> void f(T*); // (f)
template <> void f<int> (int) ; // (g)
void f(double); // (h)
bool b;
int i;
double d;
f(b); // 以 T = bool 調用 (d)
f(i,42,d) // 以 T = int 調用(e)
f(&i) ; // 以 T = int* 調用(f)
f(d); // 調用(g)
參考:http://www.cnblogs.com/qicosmos/p/4325949.html
可變參數模板是C++11新增的特性之一,它對參數高度泛化,他能表示0到任意個數、任意類型的參數。可變模板參數以前會帶有省略號,把帶省略號的參數稱爲「參數包」,它裏面包含了0到N(N>=0)個模版參數。咱們沒法直接獲取參數包args中的每一個參數的,只能經過展開參數包的方式來獲取參數包中的每一個參數,這是使用可變模版參數的一個主要特色。可變模版參數和普通的模版參數語義是一致的,因此能夠應用於函數和類,便可變模版參數函數和可變模版參數類,然而,模版函數不支持偏特化,因此可變模版參數函數和可變模版參數類展開可變模版參數的方法還不盡相同。
1 #include <iostream> 2 using namespace std; 3 //遞歸終止函數 4 void print() 5 { 6 cout << "empty" << endl; 7 } 8 //展開函數 9 template <class T, class ...Args> 10 void print(T head, Args... rest) 11 { 12 cout << "parameter " << head << endl; 13 print(rest...); 14 } 15 16 17 int main(void) 18 { 19 print(1,2,3,4); 20 return 0; 21 }
1 template <class T> 2 void printarg(T t) 3 { 4 cout << t << endl; 5 } 6 7 template <class ...Args> 8 void expand(Args... args) 9 { 10 int arr[] = {(printarg(args), 0)...}; 11 } 12 13 expand(1,2,3,4);
可變參數模板類的參數包展開的方式和可變參數模板函數的展開方式不一樣,可變參數模板類的參數包展開須要經過模板特化和繼承方式去展開,展開方式比可變參數模板函數要複雜。可變參數模板類是一個帶可變模板參數的模板類,好比C++11中的元祖std::tuple就是一個可變模板類,它的定義以下,這個可變參數模板類能夠攜帶任意類型任意個數的模板參數。
1 template< class... Types > 2 class tuple; 3 std::tuple<int> tp1 = std::make_tuple(1); 4 std::tuple<int, double> tp2 = std::make_tuple(1, 2.5); 5 std::tuple<int, double, string> tp3 = std::make_tuple(1, 2.5, 「」); 6 std::tuple<> tp;//可變參數模板的模板參數個數能夠爲0個,因此下面的定義也是也是合法的:
參考