一、为什么要有模板?
将类型参数化,可以实现算法与类型的分离,编写针对类型更加抽象的函数或者类。
二、函数模板
通用定义:
template<typename 类型形参1, ...>
返回类型 函数模板名 (形参表) { ... }
特化定义:
template<>
返回类型 函数模板名<类型实参1, ...> (形参表) { ... }
三、类模板
通用定义:
template<typename 类型形参1, ...>
class 类模板名 { ... };
全类特化:
template<>
class 类模板名<类型实参1, ...> { ... };
成员特化:
template<>
返回类型 类模板名<类型实参1, ...>::成员函数名 (形参表) { ... }
四、局部特化
五、非类型参数和缺省参数
1.非类型参数的实参仅限于常量或者常量表达式。
2.无论类型参数还是非类型参数都可以带有缺省值,而且和函数的缺省参数一样,模板的缺省参数也必须靠右。
六、有关模板的其它问题
1.从模板继承
2.向模板派生
3.模板中模板成员
1)模板型成员变量
2)模板型成员函数
3)模板型成员类型
4.模板型模板实参
七、容器和迭代器
arg.cpp
#include <iostream> using namespace std; template<typename T> class A { public: A (const T& t) : m_t (t) {} T m_t; }; template<typename X, typename Z, template<typename T> class Y> class B { public: B (const X& i, const Z& s) : m_i (i), m_s (s) {} Y<X> m_i; Y<Z> m_s; }; int main (void) { B<int, string, A> b (100, "hello"); cout << b.m_i.m_t << ' ' << b.m_s.m_t << endl; return 0; }
array.cpp
#include <iostream> using namespace std; template<typename T = int, size_t S = 5> class Array { public: T& operator[] (size_t i) { return m_array[i]; } const T& operator[] (size_t i) const { return const_cast<Array&> (*this) [i]; } size_t size (void) const { return S; } friend ostream& operator<< (ostream& os, const Array& arr) { for (size_t i = 0; i < arr.size (); ++i) os << '(' << arr.m_array[i] << ')'; return os; } private: T m_array[S]; }; int main (void) { const /*volatile*/ int x = 3, y = 7; Array<int, x+y> arr; for (size_t i = 0; i < arr.size (); ++i) arr[i] = i; cout << arr << endl; Array<Array<int, 4>, 3> m; for (size_t i = 0; i < m.size (); ++i) for (size_t j = 0; j < m[i].size (); ++j) m[i][j] = i * m[i].size () + j; cout << m << endl; Array<double> a2; Array<> a3; return 0; }
cmp.cpp
#include <iostream> #include <cstring> using namespace std; // 通用模板 template<typename T> class Comparator { public: Comparator (T x, T y) : m_x (x), m_y (y) {} T min (void) const { return m_x < m_y ? m_x : m_y; } T max (void) const { return m_x > m_y ? m_x : m_y; } private: T m_x; T m_y; }; /* // 针对char*的全模板特化 template<> class Comparator<char*> { public: Comparator (char* x, char* y) : m_x (x), m_y (y) {} char* min (void) const { return strcmp (m_x, m_y) < 0 ? m_x : m_y; } char* max (void) const { return strcmp (m_x, m_y) > 0 ? m_x : m_y; } private: char* m_x; char* m_y; }; */ // 针对char*的成员函数特化 template<> char* Comparator<char*>::min (void) const { return strcmp (m_x, m_y) < 0 ? m_x : m_y; } template<> char* Comparator<char*>::max (void) const { return strcmp (m_x, m_y) > 0 ? m_x : m_y; } int main (void) { cout << "输入两个整数:" << flush; int nx, ny; cin >> nx >> ny; Comparator<int> cn (nx, ny); cout << "最小值:" << cn.min () << endl; cout << "最大值:" << cn.max () << endl; cout << "输入两个字符串:" << flush; string sx, sy; cin >> sx >> sy; Comparator<string> cs (sx, sy); cout << "最小值:" << cs.min () << endl; cout << "最大值:" << cs.max () << endl; cout << "输入两个字符串:" << flush; char cx[256], cy[256]; cin >> cx >> cy; Comparator<char*> cc (cx, cy); cout << "最小值:" << cc.min () << endl; cout << "最大值:" << cc.max () << endl; return 0; }
inher.cpp
#include <iostream> using namespace std; template<typename T> class A { public: A (const T& t) : m_t (t) {} T m_t; }; template<typename T, typename Y> class B : public A<T> { public: B (const T& t, const Y& y) : A<T> (t), m_y (y) {} Y m_y; }; int main (void) { B<int, string> b (100, "hello"); cout << b.m_t << ' ' << b.m_y << endl; return 0; }
inter.cpp
#include <iostream> using namespace std; template<typename T> class A { public: class B {}; }; template<typename T> void foo (void) { typename A<T>::B b; } int main (void) { foo<int> (); return 0; }
list.cpp
#include <iostream> #include <stdexcept> #include <cstring> using namespace std; // 双向线性链表容器模板 template<typename T> class List { public: // 构造、析构、拷贝构造、拷贝赋值 List (void) : m_head (NULL), m_tail (NULL) {} ~List (void) { clear (); } List (const List& that) : m_head (NULL), m_tail (NULL) { for (Node* node = that.m_head; node; node = node->m_next) push_back (node->m_data); } List& operator= (const List& that) { if (&that != this) { List list (that); swap (m_head, list.m_head); swap (m_tail, list.m_tail); } return *this; } // 获取首元素 T& front (void) { if (empty ()) throw underflow_error ("链表下溢!"); return m_head->m_data; } const T& front (void) const { return const_cast<List*> (this)->front (); } // 向首部压入 void push_front (const T& data) { m_head = new Node (data, NULL, m_head); if (m_head->m_next) m_head->m_next->m_prev = m_head; else m_tail = m_head; } // 从首部弹出 void pop_front (void) { if (empty ()) throw underflow_error ("链表下溢!"); Node* next = m_head->m_next; delete m_head; m_head = next; if (m_head) m_head->m_prev = NULL; else m_tail = NULL; } // 获取尾元素 T& back (void) { if (empty ()) throw underflow_error ("链表下溢!"); return m_tail->m_data; } const T& back (void) const { return const_cast<List*> (this)->back (); } // 向尾部压入 void push_back (const T& data) { m_tail = new Node (data, m_tail); if (m_tail->m_prev) m_tail->m_prev->m_next = m_tail; else m_head = m_tail; } // 从尾部弹出 void pop_back (void) { if (empty ()) throw underflow_error ("链表下溢!"); Node* prev = m_tail->m_prev; delete m_tail; m_tail = prev; if (m_tail) m_tail->m_next = NULL; else m_head = NULL; } // 删除所有匹配元素 void remove (const T& data) { for (Node* node = m_head, *next; node; node = next) { next = node->m_next; if (equal (node->m_data, data)) { if (node->m_prev) node->m_prev->m_next = node->m_next; else m_head = node->m_next; if (node->m_next) node->m_next->m_prev = node->m_prev; else m_tail = node->m_prev; delete node; } } } // 清空 void clear (void) { for (Node* next; m_head; m_head = next) { next = m_head->m_next; delete m_head; } m_tail = NULL; } // 判空 bool empty (void) const { return ! m_head && ! m_tail; } // 获取大小 size_t size (void) const { size_t count = 0; for (Node* node = m_head; node; node = node->m_next) ++count; return count; } // 插入输出流 friend ostream& operator<< (ostream& os, const List& list) { for (Node* node = list.m_head; node; node = node->m_next) os << *node; return os; } private: // 节点 class Node { public: Node (const T& data = 0, Node* prev = NULL, Node* next = NULL) : m_data (data), m_prev (prev), m_next (next) {} friend ostream& operator<< (ostream& os, const Node& node) { return os << '(' << node.m_data << ')'; } T m_data; // 数据 Node* m_prev; // 前指针 Node* m_next; // 后指针 }; bool equal (const T& a, const T& b) const { return a == b; } Node* m_head; // 头指针 Node* m_tail; // 尾指针 public: // 正向迭代器 class Iterator { public: Iterator (Node* head = NULL, Node* tail = NULL, Node* node = NULL) : m_head (head), m_tail (tail), m_node (node) {} bool operator== (const Iterator& it) const { return m_node == it.m_node; } bool operator!= (const Iterator& it) const { return ! (*this == it); } Iterator& operator++ (void) { if (m_node) m_node = m_node->m_next; else m_node = m_head; return *this; } const Iterator operator++ (int) { Iterator old = *this; ++*this; return old; } Iterator& operator-- (void) { if (m_node) m_node = m_node->m_prev; else m_node = m_tail; return *this; } const Iterator operator-- (int) { Iterator old = *this; --*this; return old; } T& operator* (void) const { return m_node->m_data; } T* operator-> (void) const { return &**this; } private: Node* m_head; Node* m_tail; Node* m_node; friend class List; }; Iterator begin (void) { return Iterator (m_head, m_tail, m_head); } Iterator end (void) { return Iterator (m_head, m_tail); } Iterator insert (Iterator loc, const T& data) { if (loc == end ()) { push_back (data); return Iterator (m_head, m_tail,m_tail); } else { Node* node = new Node (data, loc.m_node->m_prev, loc.m_node); if (node->m_prev) node->m_prev->m_next = node; else m_head = node; node->m_next->m_prev = node; return Iterator (m_head, m_tail, node); } } Iterator erase (Iterator loc) { if (loc == end ()) throw invalid_argument ("无效迭代器!"); if (loc.m_node->m_prev) loc.m_node->m_prev->m_next = loc.m_node->m_next; else m_head = loc.m_node->m_next; if (loc.m_node->m_next) loc.m_node->m_next->m_prev = loc.m_node->m_prev; else m_tail = loc.m_node->m_prev; Node* next = loc.m_node->m_next; delete loc.m_node; return Iterator (m_head, m_tail, next); } }; // 针对const char*的特化 template<> bool List<const char*>::equal (const char* const& a, const char* const& b) const { return strcmp (a, b) == 0; } // 测试用例 int main (void) { try { List<int> list1; list1.push_front (20); list1.push_front (10); list1.push_back (30); list1.push_back (40); cout << list1 << endl; cout << list1.front () << ' ' << list1.back () << endl; list1.pop_front (); list1.pop_back (); cout << list1 << endl; ++list1.front (); --list1.back (); cout << list1 << endl; list1.push_back (21); list1.push_back (25); list1.push_back (21); list1.push_back (21); cout << list1 << endl; list1.remove (21); cout << list1 << endl; List<int> list2 = list1; cout << list2 << endl; list2.back () = 100; cout << list2 << endl; cout << list1 << endl; list2 = list1; cout << list2 << endl; list2.front () = 100; cout << list2 << endl; cout << list1 << endl; cout << list1.size () << endl; list1.clear (); cout << list1 << endl; cout << boolalpha << list1.empty () << endl; // List<string> list3; List<const char*> list3; list3.push_back ("beijing"); list3.push_back ("tianjin"); list3.push_front ("tianjin"); list3.push_back ("shanghai"); list3.push_back ("beijing"); cout << list3 << endl; list3.remove (string ("beijing").c_str ()); cout << list3 << endl; for (List<const char*>::Iterator it = list3.begin (); it != list3.end (); ++it) cout << *it << ' '; cout << endl; List<const char*>::Iterator it = list3.begin (); it++; it = list3.insert (it, "chongqing"); cout << list3 << endl; list3.erase (it); cout << list3 << endl; } catch (exception& ex) { cout << ex.what () << endl; return -1; } return 0; }
max.cpp
#include <iostream> using namespace std; int max_int (int x, int y) { return x > y ? x : y; } string max_str (string x, string y) { return x > y ? x : y; } int main (void) { cout << "输入两个整数:" << flush; int nx, ny; cin >> nx >> ny; cout << "最大值:" << max_int (nx, ny) << endl; cout << "输入两个字符串:" << flush; string sx, sy; cin >> sx >> sy; cout << "最大值:" << max_str (sx, sy) << endl; return 0; }
max2.cpp
#include <iostream> #include <typeinfo> #include <cstring> using namespace std; // 函数模板/模板函数 template<typename T> T Max (T x, T y) { cout << typeid (T).name () << endl; return x > y ? x : y; } // 模板特化 template<> char* Max<char*> (char* x, char* y) { return strcmp (x, y) > 0 ? x : y; } template<typename T> void foo (void) { T t; cout << typeid (t).name () << endl; } int main (void) { cout << "输入两个整数:" << flush; int nx, ny; cin >> nx >> ny; cout << "最大值:" << Max (nx, ny) << endl; cout << "输入两个字符串:" << flush; string sx, sy; cin >> sx >> sy; cout << "最大值:" << Max (sx, sy) << endl; cout << "输入两个字符串:" << flush; char cx[256], cy[256]; cin >> cx >> cy; cout << "最大值:" << Max (cx, cy) << endl; /* foo<int> (); foo<double> (); foo<string> (); */ return 0; }
memb1.cpp
#include <iostream> using namespace std; template<typename T> class A { public: A (const T& t) : m_t (t) {} T m_t; }; template<typename T, typename Y> class B { public: B (const T& t, const Y& y) : m_a (t), m_y (y) {} A<T> m_a; Y m_y; }; int main (void) { B<int, string> b (100, "hello"); cout << b.m_a.m_t << ' ' << b.m_y << endl; return 0; }
memb2.cpp
#include <iostream> using namespace std; template<typename T> class A { public: A (const T& t) : m_t (t) {} /* template<typename Y> void print (const Y& y) { cout << m_t << ' ' << y << endl; } */ template<typename Y> void print (const Y& y); T m_t; }; template<typename T> template<typename Y> void A<T>::print (const Y& y) { cout << m_t << ' ' << y << endl; } int main (void) { A<int> a (100); a.print<string> ("hello"); return 0; }
memb3.cpp
#include <iostream> using namespace std; template<typename T, typename Y> class A { public: A (const T& t, const Y& y) : m_t (t), m_b (y) {} /* template<typename X> class B { public: B (const X& x) : m_x (x) {} X m_x; }; */ template<typename X> class B; T m_t; B<Y> m_b; }; template<typename T, typename Y> template<typename X> class A<T, Y>::B { public: B (const X& x) : m_x (x) {} X m_x; }; int main (void) { A<int, string> a (100, "hello"); cout << a.m_t << ' ' << a.m_b.m_x << endl; return 0; }
part.cpp
#include <iostream> using namespace std; template<typename T1, typename T2> class A { public: A (void) { cout << "A<T1,T2>" << endl; } }; template<typename T1> class A<T1, int> { public: A (void) { cout << "A<T1,int>" << endl; } }; template<> class A<int, int> { public: A (void) { cout << "A<int,int>" << endl; } }; template<typename T> class B { public: B (void) { cout << "B<T>" << endl; } }; template<typename T> class B<T*> { public: B (void) { cout << "B<T*>" << endl; } }; template<typename T> class B<T[]> { public: B (void) { cout << "B<T[]>" << endl; } }; template<typename T1, typename T2, typename T3> class C { public: C (void) { cout << "C<T1,T2,T3>" << endl; } }; template<typename T1, typename T2> class C<T1, T2, T2> { public: C (void) { cout << "C<T1,T2,T2>" << endl; } }; template<typename T1> class C<T1, T1*, T1*> { public: C (void) { cout << "C<T1,T1*,T1*>" << endl; } }; int main (void) { // 特化程度高的优先 A<double, double> a1; A<double, int> a2; A<int, int> a3; // 针对指针和数组的特化优先 B<char> b1; B<char*> b2; B<char[]> b3; // 匹配度高的特化优先 C<char, short, long> c1; C<char, short, short> c2; C<char, char*, char*> c3; return 0; }
shape.cpp
#include <iostream> using namespace std; template<typename BASE> class Shape : public BASE { public: void draw (void) const { BASE::draw (); } }; class Rect { public: void draw (void) const { cout << "绘制矩形..." << endl; } }; class Circle { public: void draw (void) const { cout << "绘制圆形..." << endl; } }; int main (void) { Shape<Rect> shape1; shape1.draw (); Shape<Circle> shape2; shape2.draw (); return 0; }