Blob类
1 #include<iostream> 2 #include<initializer_list> 3 #include<vector> 4 using namespace std; 5 6 template <typename T> 7 class Blob { 8 public: 9 typedef typename vector<T>::size_type size_type; 10 11 Blob(); 12 Blob(initializer_list<T> il); 13 size_type size() const { return data->size(); } 14 bool empty() const { return data->empty(); } 15 void push_back(const T &t) { data->push_back(t); } 16 void push_back(T &&t) { data->push_back(std::move(t)); } 17 void pop_back(); 18 T& back(); 19 T& operator[](size_type i); 20 21 private: 22 shared_ptr<vector<T>> data; 23 void check(size_type i, const string &msg) const; 24 }; 25 26 template <typename T> 27 void Blob<T>::check(size_type i, const string &msg) const 28 { 29 if (i >= data->szie()) 30 throw out_of_range(msg); 31 } 32 33 template <typename T> 34 Blob<T>::Blob() : data(make_shared<vector<T>>()) {} 35 36 template <typename T> 37 Blob<T>::Blob(initializer_list<T> il) : data(make_shared<vector<T>>(il)) {} 38 39 template <typename T> 40 T& Blob<T>::back() 41 { 42 check(0, "back on empty Blob"); 43 return data->back(); 44 } 45 46 template <typename T> 47 T& Blob<T>::operator[](size_type i) 48 { 49 check(i, "subscript out of range"); 50 return (*data)[i]; 51 } 52 53 template <typename T> 54 void Blob<T>::pop_back() 55 { 56 check(0, "pop_back on emppty Blob"); 57 data->pop_back(); 58 }
BlobPtr类
头文件
1 /********BlobPtr*********/ 2 3 #ifndef BLOBPTR_H 4 #define BlOBPTR_H 5 #include<iostream> 6 #include<initializer_list> 7 #include<string> 8 #include<memory> 9 #include<vector> 10 using namespace std; 11 12 template <typename> class BlobPtr; //前置声明, 在Blob申明友元所需要的 13 template <typename> class Blob; //前置申明,运算符==中的参数所需要的 14 template <typename T> 15 bool operator==(const Blob<T>&, const Blob<T>&); 16 17 template <typename T> 18 class Blob { 19 friend class BlobPtr<T>; 20 friend bool operator ==<T>(const Blob<T>&, const Blob<T>&); 21 public: 22 typedef typename vector<T>::size_type size_type; 23 24 Blob(); 25 Blob(initializer_list<T> il); 26 size_type size() const { return data->size(); } 27 bool empty() const { return data->empty(); } 28 void push_back(const T &t) { data->push_back(t); } 29 void push_back(T &&t) { data->push_back(std::move(t)); } 30 void pop_back(); 31 T& back(); 32 T& operator[](size_type i); 33 34 BlobPtr<T> begin() { return BlobPtr<T>(*this); } 35 BlobPtr<T> end() 36 { 37 auto ret = BlobPtr<T>(*this, data->size()); 38 return ret; 39 } 40 private: 41 shared_ptr<vector<T>> data; 42 void check(size_type i, const string &msg) const; 43 }; 44 45 template <typename T> 46 void Blob<T>::check(size_type i, const string &msg) const 47 { 48 if (i >= data->szie()) 49 throw out_of_range(msg); 50 } 51 52 template <typename T> 53 Blob<T>::Blob() : data(make_shared<vector<T>>()) {} 54 55 template <typename T> 56 Blob<T>::Blob(initializer_list<T> il) : data(make_shared<vector<T>>(il)) {} 57 58 template <typename T> 59 T& Blob<T>::back() 60 { 61 check(0, "back on empty Blob"); 62 return data->back(); 63 } 64 65 template <typename T> 66 T& Blob<T>::operator[](size_type i) 67 { 68 check(i, "subscript out of range"); 69 return (*data)[i]; 70 } 71 72 template <typename T> 73 void Blob<T>::pop_back() 74 { 75 check(0, "pop_back on emppty Blob"); 76 data->pop_back(); 77 } 78 79 template <typename T> 80 bool operator==(const Blob<T> &lhs, const Blob<T> &rhs) 81 { 82 if (rhs.size() != lhs.size()) 83 return false; 84 for (size_t i = 0; i != lhs.size(); +i) 85 if (lhs[i] != rhs[i]) 86 return false; 87 return true; 88 } 89 90 /******************************************************************/ 91 92 template <typename T> 93 bool operator==(const BlobPtr<T>&, const BlobPtr<T>&); 94 95 template <typename T> 96 class BlobPtr { 97 friend bool operator==<T>(const BlobPtr<T>&, const BlobPtr<T>&); 98 public: 99 BlobPtr() : curr(0) {} 100 BlobPtr(Blob<T> &a, size_t sz = 0) : wptr(a.data), curr(sz) {} 101 102 T& operator*() const; 103 104 BlobPtr& operator++(); //前置运算符 105 BlobPtr& operator--(); //前置运算符 106 BlobPtr operator++(int); //后置运算符 107 BlobPtr operator--(int); //后置运算符 108 private: 109 shared_ptr<vector<T>> check(size_t, const string &) const; 110 weak_ptr<vector<T>> wptr; 111 size_t curr; //数组当前的位置 112 }; 113 114 template <typename T> 115 shared_ptr<vector<T>> BlobPtr<T>::check(size_t i, const string &msg) const 116 { 117 auto ret = wptr.lock(); 118 if (!ret) 119 throw std::runtime_error("unbound BlobPtr"); 120 if (i >= ret->size()) 121 throw std::out_of_range(msg); 122 return ret; 123 } 124 125 template <typename T> 126 T& BlobPtr<T>::operator*() const 127 { 128 auto p = check(curr, "dereference past end"); 129 return (*p)[curr]; 130 } 131 132 template <typename T> 133 BlobPtr<T> BlobPtr<T>::operator++(int) //++后置运算符 134 { 135 BlobPtr ret = *this; 136 ++*this; 137 return ret; 138 } 139 140 template <typename T> 141 BlobPtr<T> BlobPtr<T>::operator--(int) //--后置运算符 142 { 143 BlobPtr ret = *this; 144 --*this; 145 return ret; 146 } 147 148 template <typename T> 149 BlobPtr<T>& BlobPtr<T>::operator++() //++前置运算符 150 { 151 check(curr, "increment past end of BlobPtr"); 152 ++curr; 153 return *this; 154 } 155 156 template <typename T> 157 BlobPtr<T>& BlobPtr<T>::operator--() //--前置运算符 158 { 159 --curr; //如果是0,则继续递减它产生一个无效下标 160 check(curr, "decrement past begin of BlobPtr"); 161 return *this; 162 } 163 164 template <typename T> 165 bool operator == (const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) 166 { 167 return (lhs.wptr.lock().get() == rhs.wptr.lock().get()) && lhs.curr == rhs.curr; 168 } 169 170 template <typename T> 171 bool operator!=(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) 172 { 173 return !(rhs == lhs); 174 } 175 #endif
主函数
1 #include<iostream> 2 #include<string> 3 #include"BlobPtr.h" 4 using namespace std; 5 6 int main() 7 { 8 Blob<string> b1; 9 cout << b1.size() << endl; 10 { 11 Blob<string> b2 = { "a", "an", "the" }; 12 b1 = b2; 13 b2.push_back("about"); 14 cout << b1.size() << " " << b2.size() << endl; 15 } 16 cout << b1.size() << endl; 17 for (auto p = b1.begin(); p != b1.end(); ++p) 18 cout << *p << " "; 19 return 0; 20 }
输出结果:
成员模板
1. 若外围类定义也是类模板,则在类体外定义成员模板时,它接收二个模板形参集:一个是外围类的,另一个是自身的:
1 template<typename T1> 2 struct string 3 { 4 // 成员模板函数 5 template<typename T2> 6 int compare(const T2&); 7 8 // 构造函数亦可为模板 9 template<typename T2> 10 string(const std::basic_string<T2>& s) { /*...*/ } 11 }; 12 13 // string<T1>::compare<T2> 的类外定义 14 template<typename T1> // 对于外围类模板 15 template<typename T2> // 对于成员模板 16 int string<T1>::compare(const T2& s) { /* ... */ }
2. 可以声明拥有相同名称的非模板成员函数和模板成员函数。在冲突的情况下(某些模板特化准确匹配非模板函数的签名),该名称的使用及类型指代非模板成员,除非提供显式模板实参列表。
1 #include<iostream> 2 using namespace std; 3 4 template<typename T> 5 struct A 6 { 7 void f(int); // 非模板成员 8 9 template<typename T2> 10 void f(T2); // 成员模板 11 }; 12 13 template <typename T> 14 void A<T>::f(int) 15 { 16 cout << "非模板成员" << endl; 17 } 18 19 // 模板成员定义 20 template <typename T> 21 template <typename T2> 22 void A<T>::f(T2) 23 { 24 cout << "成员模板" << endl; 25 } 26 27 int main() 28 { 29 A<char> ac; 30 ac.f('c'); // 调用模板函数 A<char>::f<char>(int) 31 ac.f(1); // 调用非模板函数 A<char>::f(int) 32 ac.f<>(1); // 调用模板函数 A<char>::f<int>(int) 33 return 0; 34 }
运行结果:
3. 举例
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 struct Printer 7 { 8 ostream& os; 9 Printer(ostream& os): os(os) {} 10 11 template<typename T> 12 void operator()(const T& obj) { os << obj << ' '; } // 成员模板 13 }; 14 15 int main() 16 { 17 vector<int> v = { 1,2,3 }; 18 for_each(v.begin(), v.end(), Printer(cout)); 19 string s = "abc"; 20 for_each(s.begin(), s.end(), Printer(cout)); 21 }
运行结果:
for_each源码:
1 template<typename InputIterator, typename Function> 2 Function for_each(InputIterator beg, InputIterator end, Function f) 3 { 4 while(beg != end) 5 f(*beg++); 6 }