目录
练习16.5 print函数,打印任意元素类型,任意大小的数组。
练习16.6 模拟接收一个数组实参的begin end标准库函数的实现。
练习16.14 Screen类模板,用非类型模板参数定义Screen的高和宽
练习16.21 DebugDelete类实现,普通类的成员模板。

- template <typename T> // 其实就是代表一个类型而已,也没啥。
- int compare(const T &v1, const T &v2){
- if(v1 < v2) return -1;
- if(v2 < v1) return 1;
- return 0;
- }
模板实现compare函数,用于任意两种相同类型的比较,前提是,此类型支持<运算符。
- template <typename T1, typename T2>
- T1 my_find(const T1& beg,const T1& end,const T2& value){
- for(auto i = beg; i != end; ++i){
- if(*i == value)
- return i;
- }
- return end;
- }
- template <typename T, unsigned int sz> // sz是unsigned类型常量。
- void print(const T (&arr)[sz]){
- for(int i = 0; i != sz; ++i){
- cout<<arr[i]<<" ";
- }
- cout<<endl;
- }
- void test_16_5(){
- int arr1[5] = {1,2,3,4,5};
- print(arr1);
- string arr2[3] = {"aaa","bbb","ccc"};
- print(arr2);
- }
这里用到了非类型模板参数,其中的unsigned int sz就是一个非类型模板参数,可用于模板中需要常量的地方,根据传来的函数实参进行推断此非类型模板参数的模板实参。比如 第一个print中sz = 5,第二个print中sz = 3
- template <typename T, size_t sz>
- T* my_begin(T (&arr)[sz]){
- return &arr[0];
- }
-
- template <typename T, size_t sz>
- T* my_end(T (&arr)[sz]){
- return &arr[0] + sz;
- }
-
- template <typename T, size_t sz>
- const T* my_cbegin(const T (&arr)[sz]){
- const T* ret = &arr[0];
- return ret;
- }
-
- template <typename T, size_t sz>
- const T* my_cend(const T (&arr)[sz]){
- const T* ret = &arr[0] + sz;
- return ret;
- }

- template <typename> class BlobPtr;
- template <typename> class Blob;
- template <typename T>
- bool operator==(const Blob<T>&, const Blob<T>&);
-
- template <typename T>
- class Blob{
- friend class BlobPtr<T>;
- friend bool operator==<T> (const Blob<T>&, const Blob<T>&);
- public:
- using size_type = typename vector<T>::size_type;
- template <typename It> Blob(It t1, It t2);
- // : data(make_shared<vector<T>>(t1,t2)) {}
- Blob(): data(make_shared<vector<T>>()) {}
- Blob(initializer_list<T> il):data(make_shared<vector<T>>(il)) {}
- size_type size()const { return data->size(); }
- bool empty()const { return data->empty(); }
- void push_back(const T& ele) { data->push_back(ele); }
- void push_back(T &&ele) { data->push_back(std::move(ele)); }
- void pop_back();
- T& back();
- const T& back()const;
- T& operator[](size_type i);
- const T& operator[](size_type i)const;
- private:
- shared_ptr<vector<T>> data;
- void check(size_type i, const string& msg)const;
- };
- template <typename T> template <typename It> Blob<T>::Blob(It t1, It t2):data(make_shared<vector<T>>(t1,t2)) {}
- 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>
- const T& Blob<T>::back()const{
- check(0,"beck 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];
- }
-
- template <typename T>
- const T& Blob<T>::operator[](size_type i)const{
- check(i,"subscript out of range");
- return (*data)[i];
- }
-
- template <typename T>
- class BlobPtr
- {
- public:
- BlobPtr(): curr(0) {}
- BlobPtr(Blob<T>& a, size_t sz = 0): wptr(a.data), curr(sz) {} // 仅一个Blob对象作为参数,curr默认为0;
- T& operator*() const{
- auto p = check(curr, "dereference past end");
- return (*p)[curr];
- }
- // prefix
- BlobPtr& operator++();
- BlobPtr& operator--();
- // postfix
- BlobPtr operator ++(int);
- BlobPtr operator --(int);
- private:
- // returns a shared_ptr to the vector if the check succeeds;
- shared_ptr<vector<T>> check(size_t, const string& msg)const;
- weak_ptr<vector<T>> wptr;
- size_t curr;
- };
-
- template <typename T>
- shared_ptr<vector<T>> BlobPtr<T>::check(size_t index, const string& msg)const{
- auto p = wptr.lock();
- if (p) {
- if (p->size() > index) {
- return p;
- } else {
- throw std::out_of_range(msg);
- }
- } else {
- throw "unbind BlobPtr";
- }
- }
-
- // prefix ++
- template <typename T> BlobPtr<T>& BlobPtr<T>::operator++(){
- check(curr, "increment past end of StrBlob");
- ++curr;
- return *this;
- }
- template <typename T> BlobPtr<T>& BlobPtr<T>::operator--(){
- --curr;
- check(-1, "decrease index pass the beg");
- return *this;
- }
-
- template <typename T> BlobPtr<T> BlobPtr<T>::operator++(int){
- BlobPtr ret = *this;
- ++*this; // 利用前置加加检验递增是否合法
- return ret;
- }
-
- template <typename T> BlobPtr<T> BlobPtr<T>::operator--(int){
- BlobPtr ret = *this;
- --*this;
- return ret;
- }
Blob类模板,就是很简单的一个类模板的练习,模拟vector,根据模板实参确定保存的元素类型。剩余的就是一些定义,声明的规则了。还有,比如使用类模板的类型成员,需要声明typename,类模板的模板成员,如Blob类的接收两个迭代器参数的构造函数,就是一个函数模板,定义时,类模板的模板参数列表和函数模板的模板参数列表都需要声明。以及BlobPtr类定义时,在参数的作用域范围内,返回值BlobPtr可以省略模板实参,这都是一些小的规则而已。
- #ifndef C__PRIMER_SCREEN_16_14_H
- #define C__PRIMER_SCREEN_16_14_H
-
- #include<iostream>
- #include<string>
- using namespace std;
- template<int H,int W> class Screen; // 声明这个,下面的<<>>声明才可以
- template<int H,int W> ostream& operator<<(ostream& os, const Screen<H,W>&);
- template<int H,int W> istream& operator>>(istream& is, Screen<H,W>&);
- template <int H, int W>
- class Screen{
- friend ostream& operator<< <H,W>(ostream&,const Screen<H,W>&);
- friend istream& operator>> <H,W>(istream&,Screen<H,W>&);
- public:
- Screen() : contents(W*H,' ') {}
- Screen(char c):contents(W*H, c) {}
- char get()const { return contents[cursor]; } // 隐式内联
- inline char get(int, int)const; // 显式内联
- Screen& clear(char c = bkground);
- private:
- static const char bkground = ' ';
- public:
- Screen& move(int,int);
- Screen& set(char);
- Screen& set(int,int,char);
- Screen& display(ostream& os)
- { do_display(os); return *this; }
- const Screen& display(ostream& os)const
- { do_display(os); return *this;}
- private:
- //实际完成显式的函数
- void do_display(ostream& os)const {os<<contents;}
- int cursor = 0;
- string contents;
- };
- template <int H, int W> inline char Screen<H,W>::get(int r,int c)const{
- return contents[r*W+c];
- }
- template<int H,int W> Screen<H,W>& Screen<H,W>::clear(char c){
- contents = string(H*W,c);
- return *this;
- }
- template <int H,int W> inline Screen<H,W>& Screen<H,W>::move(int r,int c){
- cursor = r*W+c;
- return *this;
- }
-
- template<int H, int W>
- Screen<H,W>& Screen<H, W>::set(char c){
- contents[cursor] = c;
- return *this;
- }
- template<int H,int W>
- Screen<H,W>& Screen<H,W>::set(int r,int col,char ch){
- contents[r*W+col] = ch;
- return *this;
- }
-
- template<int H,int W> ostream& operator<<(ostream& os, const Screen<H,W>& s){
- os<<s.contents;
- return os;
- }
-
- template<int H,int W> istream& operator>>(istream& is, Screen<H,W>& s){
- string t;
- cin >> t;
- s.contents = t.substr(0,H*W);
- return is;
- }
-
- #endif //C__PRIMER_SCREEN_16_14_H
用非类型模板实参确定Screen的高和宽,而不是之前的把高和宽定义为私有数据成员。也是一个练习而已。注意<< >> 运算符重载函数,仍然需要模板,且友元声明时,
friend ostream& operator<< <H,W>(ostream&,const Screen<H,W>&);
friend istream& operator>> <H,W>(istream&,Screen<H,W>&);需要加上<H,W>。还有类模板的声明,以及函数声明。

- template < typename T, typename F = less<T> >
- int compare(const T& v1, const T& v2, F f = F()){
- if(f(v1,v2))
- return -1;
- if(f(v2,v1))
- return 1;
- return 0;
- }
- // 16.19
- template <typename T>
- void print(const T& v){
- for(typename T::size_type sz = 0; sz!=v.size();++sz) {
- cout << v[sz] << " ";
- }
- }
-
- template <typename T>
- void print_2(const T& v){
- for(auto i = v.begin(); i != v.end(); ++i){
- cout<<*i<<" ";
- }
- cout<<endl;
- }
使用类的类型成员

- // 16.1.4
- class DebugDelete
- {
- public:
- explicit DebugDelete(ostream& o = cerr): os(o) {}
- template <typename T> void operator() (T* p)const { cout<<"deleting unique_ptr"<<endl; delete p;}
- private:
- ostream& os;
- };
-
- void test_16_21(){
- int* pi = new int(10);
- DebugDelete d;
- d(pi);
- string* ps = new string("hahaha");
- DebugDelete()(ps);
- }

........
- // 16.1.6 效率与灵活性 test16_28
- template <typename T>
- class Shared_p{
- public:
- Shared_p():p(nullptr), use(nullptr){}
- // shared_p<int> p(new int(1));
- explicit Shared_p(T* pt):p(pt), use(new size_t(1)) {}
- Shared_p(const Shared_p& sp): p(sp.p),use(sp.use){
- if(use) ++*use;
- }
- Shared_p& operator=(const Shared_p& sp);
- ~Shared_p();
- T& operator*() { return *p; }
- T& operator*()const { return *p; }
- private:
- T* p;
- size_t* use;
- };
-
- template<typename T> Shared_p<T>& Shared_p<T>::operator=(const Shared_p& rhs){
- if(rhs.use)
- ++*use;
- if(use && --*use == 0) {
- delete p;
- delete use;
- }
- p = rhs.p;
- use = rhs.use;
- return *this;
- }
-
- template<typename T> Shared_p<T>::~Shared_p(){
- if(use && --*use == 0){
- delete use;
- delete p;
- }
- }
- template <typename T, class... Args>
- Shared_p<T> make_shared(Args&&... args){
- return Shared_p<T>(new T(forward<Args>(args)...));
- }
-
- template <typename T>
- class UP
- {
- public:
- UP():p(nullptr){}
- explicit UP(T* pt):p(pt){}
- UP(const UP&) = delete;
- UP& operator=(const UP&)=delete;
- ~UP(){
- if(p)
- delete p;
- }
- T* release(){
- T* ret = p;
- p = nullptr;
- return ret;
- }
- T* reset(T* new_p = nullptr){
- if(p)
- delete p;
- p = new_p;
- }
- T& operator*() { return *p; }
- T* operator*()const { return *p; }
- private:
- T* p;
- };