练习16.9
函数模板:一个函数模板就是一个公式,可用来生成针对特定类型的函数版本
类模板:类模板是用来生成类的蓝图的
练习16.10
当一个类模板被实例化后,他的每个实例都形成一个独立的类。
练习16.11
1 template<typename elemType> class ListItem; 2 template<typename elemType> class List { 3 public: 4 List<elemType> (); 5 List<elemType>(const List<elemType> &); 6 List<elemType>& operator=(const List<elemType> &); 7 ~List(); 8 void insert(ListItem<elemType> *ptr, elemType value); 9 private: 10 ListItem<elemType> *front, *end; 11 };
ListItem类的类型没有说明;
练习16.12
1 #include <iostream> 2 #include <string> 3 #include <utility> 4 #include <memory> 5 #include <vector> 6 #include <list> 7 8 using namespace std; 9 10 template <typename T> class BlobPtr; 11 12 template<typename T> class Blob { 13 friend class BlobPtr<T>; 14 public: 15 typedef vector<string>::size_type size_type; 16 Blob(); 17 Blob(initializer_list<T> il); 18 size_type size() const { return data->size(); } 19 bool empty() const { return data->empty(); } 20 void push_back(const T &t) { data->push_back(t); } 21 void push_back(T&& t) { data->push_back(std::move(t)); } 22 void pop_back(); 23 T& front(); 24 T& back(); 25 T& operator[](size_type i); 26 private: 27 shared_ptr<vector<T>> data; 28 void check(size_type i, const string &msg) const; 29 }; 30 31 template <typename T> class BlobPtr { 32 public: 33 BlobPtr() : curr(0) {} 34 BlobPtr(Blob<T> &a, size_t sz = 0) : wptr(a.data), curr(sz) {} 35 T& deref() const; 36 BlobPtr<T>& incr(); 37 private: 38 shared_ptr<vector<T>> check(size_t, const string&) const; 39 weak_ptr<vector<T>> wptr; 40 size_t curr; 41 }; 42 43 int main() 44 { 45 Blob<string> b1; 46 b1.push_back("asdasd"); 47 cout << b1.front() << endl; 48 BlobPtr<string> b(b1); 49 auto p = b.deref(); 50 cout << p << endl; 51 b1.pop_back(); 52 system("pause"); 53 return 0; 54 } 55 56 template<typename T> 57 Blob<T>::Blob() : data(make_shared<vector<T>>()){} 58 59 template<typename T> 60 Blob<T>::Blob(initializer_list<T> il) : data(make_shared<vector<T>>(il)) {} 61 62 template<typename T> 63 void Blob<T>::pop_back() 64 { 65 check(0, "pop_back on empty Blob"); 66 data->pop_back(); 67 } 68 69 template<typename T> 70 T & Blob<T>::front() 71 { 72 check(0, "front on empty Blob"); 73 return data->front(); 74 // TODO: 在此处插入 return 语句 75 } 76 77 template<typename T> 78 T & Blob<T>::back() 79 { 80 check(0, "back on empty Blob"); 81 return data->back(); 82 // TODO: 在此处插入 return 语句 83 } 84 85 template<typename T> 86 T & Blob<T>::operator[](size_type i) 87 { 88 check(i, "subscript out of range"); 89 return (*data)[i]; 90 // TODO: 在此处插入 return 语句 91 } 92 93 template<typename T> 94 void Blob<T>::check(size_type i, const string & msg) const 95 { 96 if (i >= data->size()) 97 throw out_of_range(msg); 98 } 99 100 template<typename T> 101 T & BlobPtr<T>::deref() const 102 { 103 auto p = check(curr, "dereference past end"); 104 return (*p)[curr]; 105 // TODO: 在此处插入 return 语句 106 } 107 108 template<typename T> 109 BlobPtr<T> & BlobPtr<T>::incr() 110 { 111 check(curr, "increment past end of BlobPtr<T>"); 112 ++curr; 113 return *this; 114 // TODO: 在此处插入 return 语句 115 } 116 117 template<typename T> 118 shared_ptr<vector<T>> BlobPtr<T>::check(size_t i, const string &msg) const 119 { 120 auto ret = wptr.lock(); 121 if (!ret) 122 throw runtime_error("unbound BlobPtr<T>"); 123 if (i >= ret->size()) 124 throw out_of_range(msg); 125 return ret; 126 }
练习16.13
将BlobPtr设置为Blob的友元
练习16.14、练习16.15
1 #include <iostream> 2 #include <string> 3 #include <utility> 4 #include <memory> 5 #include <vector> 6 #include <list> 7 8 using namespace std; 9 10 template <typename T> class Screen { 11 friend istream& operator>><T> (istream& is, Screen<T>& s); 12 friend ostream& operator<<<T> (ostream& os, const Screen<T>& s); 13 public: 14 Screen() = default; 15 private: 16 T height; 17 T width; 18 }; 19 20 template <typename T> 21 istream& operator>> (istream& is, Screen<T>& s); 22 template <typename T> 23 ostream& operator<< (ostream& os, const Screen<T>& s); 24 25 int main() 26 { 27 Screen<double> s1; 28 cin >> s1; 29 cout << s1; 30 system("pause"); 31 return 0; 32 } 33 34 template<typename T> 35 istream & operator >> (istream & is, Screen<T>& s) 36 { 37 is >> s.height >> s.width; 38 if (!is) 39 s = Screen<T>(); 40 return is; 41 // TODO: 在此处插入 return 语句 42 } 43 44 template<typename T> 45 ostream & operator<<(ostream & os, const Screen<T>& s) 46 { 47 os << s.height << " " << s.width; 48 return os; 49 // TODO: 在此处插入 return 语句 50 }
练习16.16
1 #include <iostream> 2 #include <string> 3 #include <utility> 4 #include <memory> 5 #include <vector> 6 #include <list> 7 8 using namespace std; 9 10 template <typename T> class Vec { 11 public: 12 Vec() : elements(nullptr), first_free(nullptr), cap(nullptr) {} 13 Vec(const Vec<T>& v); 14 Vec<T>& operator==(Vec<T>& v); 15 ~Vec(); 16 void push_back(const T&); 17 size_t size() const { return first_free - elements; } 18 size_t capacity() const { return cap - elements; } 19 T* begin() const { return elements; } 20 T* end() const { return first_free; } 21 private: 22 static allocator<T> alloc; 23 void chk_n_alloc() 24 { 25 if (size() == capacity()) reallocate(); 26 } 27 pair<T*, T*> alloc_n_copy(const T*, const T*); 28 void free(); 29 void reallocate(); 30 T* elements; 31 T* first_free; 32 T* cap; 33 }; 34 35 template <typename T> allocator<T> Vec<T>::alloc; 36 37 int main() 38 { 39 Vec<string> v1; 40 v1.push_back("sda"); 41 cout << v1.size() << endl; 42 system("pause"); 43 return 0; 44 } 45 46 template<typename T> 47 Vec<T>::Vec(const Vec<T>& v) 48 { 49 auto newdata = alloc_n_copy(v.begin(), v.end()); 50 elements = newdata.first; 51 first_free = cap = newdata.second; 52 } 53 54 template<typename T> 55 Vec<T> & Vec<T>::operator==(Vec<T>& v) 56 { 57 auto data = alloc_n_copy(v.begin(), v.end()); 58 free(); 59 elements = data.first; 60 first_free = cap = data.second; 61 return *this; 62 // TODO: 在此处插入 return 语句 63 } 64 65 template<typename T> 66 Vec<T>::~Vec() 67 { 68 free(); 69 } 70 71 template<typename T> 72 void Vec<T>::push_back(const T &s) 73 { 74 chk_n_alloc(); 75 alloc.construct(first_free++, s); 76 } 77 78 template<typename T> 79 pair<T*, T*> Vec<T>::alloc_n_copy(const T *b, const T *e) 80 { 81 auto data = alloc.allocate(e - b); 82 return { data, uninitialized_copy(b, e, data) }; 83 } 84 85 template<typename T> 86 void Vec<T>::free() 87 { 88 if (elements) 89 for (auto p = first_free; p != elements;) 90 alloc.destroy(--p); 91 alloc.deallocate(elements, capacity()); 92 } 93 94 template<typename T> 95 void Vec<T>::reallocate() 96 { 97 auto newcapacity = size() ? 2 * size() : 1; 98 auto newdata = alloc.allocate(newcapacity); 99 auto dest = newdata; 100 auto elem = elements; 101 for (size_t i = 0; i != size(); ++i) 102 alloc.construct(dest++, std::move(*elem++)); 103 free(); 104 elements = newdata; 105 first_free = dest; 106 cap = elements + newcapacity; 107 }