C++模板與泛型編程


模板是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; // 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

1
2
3
// 在模板參數列表中,typename和class沒有什么不同
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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM