模板是C++中泛型编程的基础,一个模板就是一个创建类或函数的蓝图。
函数模板
我们可以定义一个通用的函数模板(function template)
,而不是为每个类型都定义一个新函数。compare的模板版本如下:
1 2 3 4 5 6 7
| template <typename T> int compare(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
| #include <iostream> using std::cout; using std::endl; #include <string> using std::string; #include <memory> 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; }
|