StrBlob.h

#include<string>
#include<vector>
#include<memory>
#iclude<initializer_list>
#inlude<stdexcept>


#ifndef STRBLOB__H
#define STRBLOB__H


class StrBlob {
    public:
        friend class StrBlobPtr;// so in StrBlobPtr can use StrBlob instance access StrBlob private member

        typedef std::string::size_type size_type;

        StrBlob(): data(std::make_shared<std::vector<std::string>>()) {}
        StrBlob(const std::initializer_list<std::string> &li): data(std::make_shared<std::vector<std::string>>(li)) {}

        size_type size()  const {return data->size();}
        bool      empty() const {return data->empty();}

        void push_back(const std::string &str) { data->push_back(str);}
        void pop_back();

        std::string& front() const;
        std::string& back() const;

    private:
        std::shared_ptr<std::vector<std::string>> data;
        void check(const size_type &i, const std::string &msg) const;
};

class StrBlobPtr {
    public:
        StrBlobPtr(): curr(0) {};
        StrBlobPtr(StrBlob &sb, const size_t &sz) : w_ptr(sb.data), curr(sz) {}

        std::string& deref();
        void incr();

    private:
        std::shared_ptr<std::vector<std::string>> check(const std::string &msg) const;
        std::weak_ptr<std::vector<std::string>> w_ptr;
        size_t curr;
};

#endif

StrBlob.cpp

#include<StrBlob.h>

void StrBlob::pop_back() {
    check(0, "pop_back is out of range");
    data->pop_back();
}

std::string& StrBlob::front() const {
    check(0, "front is out of range");
    return data->front();
}

std::string& StrBlob::back() const {
    check(0, "back is out of range");
    return data->back();
}

void StrBlob::check(const std::string& msg) const {
    if(i>=data->size())
        throw std::out_of_range(msg);
}


std::string& StrBlobPtr::deref() {
    std::shared_ptr<std::vector<std::string>> ptr = w_ptr.check("deref");
    return (*ptr)[curr];
}

void StrBlobPtr::incr() {
    check("increase");
    ++curr;
}


std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(const std::string &msg) const {
    std::shared_ptr<std::vector<std::string>> ptr = w_ptr.lock();
    if(!ptr)
        throw std::runtime_error("unbound StrBlobPtr");
    if(curr >= ptr->size())
        throw std::out_of_range(msg);
    return ptr;
}

感觉StrBlobPtr就是强行使用weak_ptr,并没有实际的用途,除非StrBlob对象销毁了,shared_ptr指针data销毁了,weak_ptr指针w_ptr的check操作才会起到作用,但是不明白为什么不直接使用StrBlob对象来访问data,而要StrBlobPtr来访问呢?

ifstream is("map.dat");
string line;
StrBlob sb;
StrBlobPtr sbp(sb, 0);

while(getline(is, line)) {
    sb.push_back(line);
}

cout<<sb.front()<<endl;
cout<<sb.back()<<endl;

//for(size_t i=0; i != sb.size(); ++i) { // 必须要借助sb才知道什么时候结束,除非让报out_of_range的异常
//    cout<<sbp.deref()<<endl;
//    sbp.incr();
//}

while(1) {
    try {
        cout<<sbp.deref()<<endl;
        sbp.incr();
    } catch(out_of_range e) {
        cout<<e.what()<<endl;
        break;
    } catch(runtime_error e) {
        cout<<e.what()<<endl;
        break;
    }
}
12-21 18:59