C++ template 学习笔记(第三,四章)
在这一章中主要讲述了class template相关的一些基础知识。主要分为:
1. class template的声明和定义
2. class template的使用
3. class template的特化
4. class template的偏特化
5. class template的预设模版参数
关于这几个方面,根据书上的例子,写了如下代码,注释部分为说明和一些注意事项:
1 #include <iostream> 2 #include <vector> 3 4 template <typename T, typename CONT = std::vector<T> > //模板参数缺省处理,默认为vector容器 5 class Stack //在非特化的主模版声明中,类名后面不能跟尖括号说明类型 6 { 7 private: 8 CONT elems; //储存元素所用容器,在此处我们使用了默认参数 vector 做为容器 9 10 public: 11 void push(T const&); //类模版中的一些成员函数 12 void pop(); 13 T top() const; 14 inline bool empty() const { 15 return elems.empty(); 16 } 17 }; 18 19 template <typename T, typename CONT> //除了特化类模版的类模版的成员函数的定义, 20 //前面需要添加“template <typename T, typename CONT>”说明 21 void Stack<T, CONT>::push (T const& elem) //对于函数定义处,需要使用类模版的类型名 “Stack<T, CONT>::” 来限定 22 { 23 elems.push_back(elem); //末尾添加元素 24 } 25 26 template <typename T, typename CONT> 27 void Stack<T, CONT>::pop() 28 { 29 if (elems.empty ()){ 30 std::cout << "Stack<T, CONT>::pop(): empty stack!" << std::endl; 31 return; 32 } 33 elems.pop_back(); //删除最后一个元素 34 } 35 36 template <typename T, typename CONT> 37 T Stack<T, CONT>::top() const 38 { 39 40 if (elems.empty ()){ 41 std::cout << "Stack<T, CONT>::top(): empty stack!" << std::endl; 42 return; 43 } 44 return elems.back (); //返回最后一个元素的值 45 } 46 47 /* 48 *类模版的偏特化 49 *(在这里尤其需要注意,定义模版的歧义性问题) 50 */ 51 template<typename CONT> //类模版的偏特化,针对double类型的参数声明,将使用此模版 , 52 class Stack<double, CONT> //因此只需接收一个容器类型即可 53 { 54 private: 55 CONT elems; 56 public: 57 void push(double const&); //在此处直接使用 double 类型即可 58 void pop(); 59 double top() const; 60 inline bool empty() const { 61 return elems.empty(); 62 } 63 64 inline void print() 65 { 66 std::cout << "Stack<double, CONT>_ >> " << elems.back() << std::endl; 67 } 68 69 Stack<double, CONT> operator=(Stack<double, CONT> const& stack_to); //运算符重载,在此重载过程中使用了push_front函数 70 //因此,在选用容器时,许选用支持此函数的容器 71 }; 72 73 template<typename CONT> 74 void Stack<double, CONT>::push(double const& elem) 75 { 76 elems.push_back(elem); 77 } 78 79 template<typename CONT> 80 void Stack<double, CONT>::pop() 81 { 82 if (elems.empty()){ 83 std::cout << "Stack<double, CONT>::pop(): empty stack!" << std::endl; 84 return; 85 } 86 elems.pop_back(); 87 } 88 89 template<typename CONT> 90 double Stack<double, CONT>::top() const 91 { 92 if (elems.empty()){ 93 std::cout << "Stack<double, CONT>::top(): empty stack!" << std::endl; 94 return; 95 } 96 return elems.back(); 97 } 98 99 template<typename CONT> 100 Stack<double, CONT> Stack<double, CONT>::operator= (Stack<double, CONT> const& stack_to) 101 { 102 if ((void*)this == (void*) &stack_to) 103 return *this; 104 105 Stack<double, CONT> temp(stack_to); 106 elems.clear(); 107 while (!temp.empty()) 108 { 109 elems.push_front(temp.top()); 110 temp.pop(); 111 } 112 return *this; 113 } 114 115 /* 116 *模版的特化 117 *由于此处对模版的所有参数进行了特化, 118 *因此只需在声明前加 “template<>” 即可 119 *类的声明后面紧跟成员函数声明, 120 *成员函数前面需要使用类模版的类型名“Stack<std::string, std::vector<std::string> >"限定 121 *函数前无需添加 ”template<>" 122 */ 123 template<> 124 class Stack<std::string, std::vector<std::string> > //类模板的特化 125 { 126 private: 127 typename std::vector<std::string> elems; 128 public: 129 void push(std::string const&); 130 void pop(); 131 std::string top() const; 132 inline bool empty() const{ 133 return elems.empty(); 134 } 135 inline void print(){ 136 std::cout << "Stack<std::string, std::vector<std::string> > _>> " << top() << std::endl; 137 } 138 }; 139 140 void Stack<std::string, std::vector<std::string> >::push(std::string const& elem) //成员函数前面需要使用类模版的类型名“Stack<std::string, std::vector<std::string> >"限定 141 //函数前无需添加 ”template<>" 142 { 143 elems.push_back(elem); 144 } 145 146 void Stack<std::string, std::vector<std::string> >::pop() 147 { 148 if (elems.empty()){ 149 std::cout << "Stack<std::string, std::vector<std::string> >::pop(): empty stack!" << std::endl; 150 return; 151 } 152 elems.pop_back(); 153 } 154 155 std::string Stack<std::string, std::vector<std::string> >::top() const 156 { 157 if (elems.empty()){ 158 std::cout << "Stack<std::string, std::vector<std::string> >::top(): empty stack!" << std::endl; 159 return; 160 } 161 return elems.back(); 162 }
对上述代码的使用和测试代码如下:
1 #include "template_3.hpp" 2 #include <deque> 3 #include <stdexcept> 4 #include <cstdlib> 5 using namespace std; 6 7 int main () 8 { 9 10 Stack<int> Stack_int; //使用默认容器vector 11 12 Stack_int.push(1); 13 Stack_int.push(2); 14 Stack_int.push(3); 15 cout << "vector >> " << Stack_int.top() << endl; 16 Stack_int.pop(); 17 cout << "vector >> " << Stack_int.top() << endl; 18 19 20 Stack<int, std::deque<int> > Stack_deque_int; //使用容器deque 21 22 Stack_deque_int.push(1); 23 Stack_deque_int.push(2); 24 Stack_deque_int.push(3); 25 cout << "deque >> " << Stack_deque_int.top() << endl; 26 Stack_deque_int.pop(); 27 cout << "deque >> " << Stack_deque_int.top() << endl; 28 29 Stack<string, vector<string> > Stack_string; 30 Stack_string.push("aaa"); 31 Stack_string.push("bbb"); 32 Stack_string.push("cccc"); 33 Stack_string.print(); 34 Stack_string.pop(); 35 Stack_string.print(); 36 37 Stack<double, deque<double> > Stack_double, Stack_temp; 38 Stack_double.push(1.1111); 39 Stack_double.push(2.2222); 40 Stack_double.push(3.3333); 41 Stack_temp = Stack_double; 42 Stack_temp.print(); 43 Stack_temp.pop(); 44 Stack_temp.print(); 45 return 0; 46 }
以上代码,均在gcc 4.6版本 编译通过~