模板是C++中泛型編程的基礎,一個模板就是一個創建類或函數的藍圖。
函數模板
我們可以定義一個通用的函數模板(function template)
,而不是為每個類型都定義一個新函數。compare的模板版本如下:
1 2 3 4 5 6 7
|
template <typename T> int (const T &v1, const T &v2) { if (v1 < v2) return -1; if (v2 < v1) return 1; return 0; }
|
模板定義以關鍵字template
開始,后跟一個模板參數列表(template parameter list)
,這是一個逗號分隔的一個或多個模板參數(template parameter)
,用尖括號包圍。
實例化函數模板:
1 2 3 4 5
|
cout << compare(1, 0) << endl;
vector<int> vec1{1, 2, 3}, vec2{4, 5, 6}; cout << compare(vec1, vec2) << endl;
|
類型參數前必須使用關鍵字class
或typename
:
1 2 3
|
template <typename T, class U> T calc(const T&, const U&);
|
類模板
類模板(class template)
是用來生成類的藍圖。與函數模板的不同之處是,編譯器不能為類模板推斷模板參數類型,必須在模板名后面的尖括號中提供額外信息——用來替代模板參數的模板實參列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
using std::cout; using std::endl; #include <string> using std::string; #include <memory> 大專欄 C++模板與泛型編程/>using std::shared_ptr; using std::make_shared; #include <vector> using std::vector;
using std::initializer_list; using std::out_of_range;
template <typename T> class Blob { public: typedef T value_type; typedef typename vector<T>::size_type size_type; Blob(); Blob(initializer_list<T> il); size_type size() const { return data->size(); } bool empty() const { return data->empty(); } void push_back(const T &t) { data->push_back(t); } void push_back(T &&t) { data->push_back(move(t)); } void pop_back(); T &back(); T &operator[](size_type i); private: shared_ptr<vector<T>> data; void check(size_type i, const string &msg) const; };
template <typename T> Blob<T>::Blob(): data(make_shared<vector<T>>()) { }
template <typename T> Blob<T>::Blob(initializer_list<T> il): data(make_shared<vector<T>>(il)) { }
template <typename T> void Blob<T>::check(size_type i, const string &msg) const { if (i >= data->size()) throw out_of_range(msg); }
template <typename T> void Blob<T>::pop_back() { check(0, "pop_back on empty Blob"); data->pop_back(); }
template <typename T> T &Blob<T>::back() { check(0, "back on empty Blob"); return data->back(); }
template <typename T> T &Blob<T>::operator[](size_type i) { check(i, "subscript out of range"); return (*data)[i]; }
int main() { Blob<int> squares = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; for (size_t i = 0; i != squares.size(); ++i) squares[i] = i * i; cout << squares.back() << endl; return 0; }
|