zoukankan      html  css  js  c++  java
  • 模板类之间的友元关系实现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

  • 相关阅读:
    一起学windows phone7开发(二十四. Task 补遗)
    一起学windows phone7开发(二十.一 正式版中新增的 Panorama 和 Pivot Project)
    一起学WP7 XNA游戏开发(四. Input)
    一起学WP7 XNA游戏开发(五. Sound)
    一起学windows phone7开发(二十一.三 Map 控件深入学习)
    Daisy.wp7.Controls自定义的控件库
    一起学windows phone7开发(二十二.使用系统资源)
    一起学习Windows Phone7开发(二十三 Windows Phone7 Toolkit 补遗)
    一起学windows phone7开发(二十一.一 Silverlight bing map控件与 Pone7 map控件的比较)
    第一次试验报告
  • 原文地址:https://www.cnblogs.com/wuchanming/p/3948381.html
Copyright © 2011-2022 走看看