C++模板与泛型编程

模板是C++中泛型编程的基础,一个模板就是一个创建类或函数的蓝图。

函数模板

我们可以定义一个通用的函数模板(function template),而不是为每个类型都定义一个新函数。compare的模板版本如下:

1234567
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),用尖括号包围。
实例化函数模板:

12345
cout << compare(1, 0) << endl; // T为int// 实例化出int compare(const vector<int>&, const vector<int>&)vector<int> vec1{1, 2, 3}, vec2{4, 5, 6};cout << compare(vec1, vec2) << endl; // T为vector<int>

类型参数前必须使用关键字classtypename

123
// 在模板参数列表中,typename和class没有什么不同template <typename T, class U>T calc(const T&, const U&);

类模板

类模板(class template)是用来生成类的蓝图。与函数模板的不同之处是,编译器不能为类模板推断模板参数类型,必须在模板名后面的尖括号中提供额外信息——用来替代模板参数的模板实参列表。

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
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;}

相关推荐