首页 > 代码库 > 模板类之间的友元关系实现Blob和BlobPtr

模板类之间的友元关系实现Blob和BlobPtr

16.12编写你自己版本的Blob和BlobPtr模板,包含书中未定义的多个const成员。

Blob.h(注意,成员函数的声明和定义要放在一个头文件中)

/*记住,模板的头文件中通常既包括声明也包括定义。函数模板和类模板成员函数的定义通常放在头文件中,不能分开放。。。。谨记*/#ifndef BLOB_H#define BLOB_H#include<iostream>#include<vector>#include<string>#include<memory>#include<initializer_list>using namespace std;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:    typedef T value_type;    typedef typename vector<T>::size_type size_type;    Blob();    Blob(initializer_list<T> il);    BlobPtr<T> begin() { return *this;}    BlobPtr<T> end() { auto ret=BlobPtr<T>(*this,this->size()); return ret;}    size_type size() const { return data->size();}    bool empty() const { return data->empty();}    void push_back(const T &t) { data->push_back(t);}    void push_back(T &&t) { data->push_back(std::move(t));}    void pop_back();    T& front();    T& back();    const T& front() const;    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>Blob<T>::Blob():              data(std::make_shared<std::vector<T>>()) { }template<typename T>Blob<T>::Blob(initializer_list<T> il):data(make_shared<vector<T>>(il)) {}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");    data->pop_back();}template <typename T>T& Blob<T>::front(){    check(0,"front");    return data->front();}template<typename T>T& Blob<T>::back(){    check(0,"back");    return data->back();}template<typename T>const T& Blob<T>::front() const{    check(0,"front");    return data->front();}template<typename T>const T& Blob<T>::back() const{    check(0,"back");    return data->back();}template<typename T>T& Blob<T>::operator[](size_type i){    check(i,"out_of_range");    return (*data)[i];}template<typename T>const T& Blob<T>::operator[](size_type i) const{    check(i,"out_of_range");    return (*data)[i];}template <typename T>bool operator==(const Blob<T> &lhs,const Blob<T> &rhs){    if(rhs.size()!=lhs.size())        return false;    for(size_t i=0;i!=lhs.size();+i)        if(lhs[i]!=rhs[i])            return false;    return true;}template <typename T>ostream operator<<(ostream &os,const Blob<T> &a){    os<<"<";    for(size_t i=0;i!=a.size();++i)        os<<a[i]<<" ";    os<<">";    return os;}template <typename T>bool operator==(const BlobPtr<T>&,const BlobPtr<T>&);template <typename T> class BlobPtr{friend bool operator==<T>    (const BlobPtr<T>&,const BlobPtr<T>&);public:    BlobPtr():curr(0){}    BlobPtr(Blob<T> &a,size_t sz=0):wptr(a.data),curr(sz){}    T& operator*() const    {        auto p=check(curr,"dereference past end");        return (*p)[curr];    }    BlobPtr& operator++();    BlobPtr& operator--();    BlobPtr& operator++(int);    BlobPtr& operator--(int);private:    shared_ptr<vector<T>> check(size_t,const string &) const;    weak_ptr<vector<T>> wptr;    size_t curr;};template <typename T>shared_ptr<vector<T>> BlobPtr<T>::check(size_t i,const string &msg) const{    auto ret=wptr.lock();    if(!ret)        throw runtime_error("unbind BlobPtr");    if(i>=ret->size())        throw out_of_range(msg);    return ret;}template <typename T>BlobPtr<T>& BlobPtr<T>::operator++(){    check(curr,"++");    ++curr;    return *this;}template <typename T>BlobPtr<T>& BlobPtr<T>::operator--(){    --curr;    check(curr,"--");    return *this;}template <typename T>BlobPtr<T>& BlobPtr<T>::operator++(int){    auto ret=*this;    ++*this;    return ret;}template <typename T>BlobPtr<T>& BlobPtr<T>::operator--(int){    auto ret=*this;    --*this;    return ret;}template <typename T>bool operator==(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs){    return (lhs.wptr.lock().get()==rhs.wptr.lock().get())&&lhs.curr==rhs.curr;}template <typename T>bool operator!=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs){    return !(rhs==lhs);}#endif // BLOB_H

main.cpp

#include "Blob.h"int main(){    Blob<string> b1; // empty Blob    cout << b1.size() << endl;    {  // new scope        Blob<string> b2 = {"a", "an", "the"};        b1 = b2;  // b1 and b2 share the same elements        b2.push_back("about");        cout << b1.size() << " " << b2.size() << endl;    } // b2 is destroyed, but the elements it points to must not be destroyed    cout << b1.size() << endl;    for(auto p = b1.begin(); p != b1.end(); ++p)        cout << *p << endl;    return 0;}

16.14 编写Screen类模板,用非类型参数定义Screen的高和宽。

16.15为你的Screen模板实现输入和输出运算符。Screen类需要哪些友元来令输入和输出运算符正确工作。

#include<iostream>#include <string>using namespace std;//模板非类型参数,友元一定要前置声明template <unsigned H,unsigned W>class Screen;template <unsigned H,unsigned W>ostream& operator<<(ostream &os,const Screen<H,W> &s);template <unsigned H,unsigned W>istream& operator>>(istream &is,Screen<H,W> &s);template <unsigned H,unsigned W>class Screen{friend ostream& operator<< <H,W> (ostream &os,const Screen<H,W> &s);friend istream& operator>> <H,W> (istream &is,Screen<H,W> &s);public:    typedef string::size_type pos;    Screen()=default;    Screen(pos ht,pos wd,char c):height(ht),width(wd),contents(ht*wd,c){}    char get() const    {        return contents[cursor];    }    inline char get(pos ht,pos wd) const;    Screen &move(pos r,pos c);private:    pos cursor=0;    pos height=H;    pos width=W;    string contents;};template<unsigned H,unsigned W>char Screen<H,W>::get(pos ht,pos wd) const{    pos row=ht*width;    return contents[row+wd];}template <unsigned H,unsigned W>Screen<H,W>& Screen<H,W>::move(pos r,pos c){    pos row=r*width;    cursor=row+c;    return *this;}template <unsigned H,unsigned W>ostream& operator<<(ostream &os,const Screen<H,W> &s){    os<<s.cursor<<" "<<s.height<<" "<<s.width<<" "<<s.contents[s.cursor]<<endl;    return os;}template <unsigned H,unsigned W>istream& operator>>(istream &is,Screen<H,W> &s){    is>>s.cursor>>s.height>>s.width>>s.contents;    return is;}int main(){}

16.16

模板类之间的友元关系实现Blob和BlobPtr