C++ Primer(第5版) 练习 13.26

练习 13.26 对上一题中描述的StrBlob类,编写你自己的版本。

环境:Linux Ubuntu(云服务器)
工具:vim

 

代码块
class StrBlobPtr;

class StrBlob{
    friend class StrBlobPtr;

    public:
	typedef vector<string>::size_type size_type;
	StrBlob();
	StrBlob(StrBlob &s): data(make_shared<vector<string>>(*s.data)) {}
	StrBlob &operator= (StrBlob &s);
	StrBlob(initializer_list<string> il);
	size_type size() const { return data->size(); }
	bool empty() const { return data->empty(); }
	void push_back(const string &t) { data->push_back(t); }
	void pop_back();
	string &front();
	string &back();
	string &front() const;
	string &back() const;

    StrBlobPtr begin();
    StrBlobPtr end();

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

StrBlob& StrBlob::operator= (StrBlob &s){
	auto newdata = make_shared<vector<string>>(new vector<string>(*s.data));
	data = newdata;
}

void StrBlob::pop_back(){
	check(0, "pop_back on empty StrBlob");
	data->pop_back();
}

string& StrBlob::front(){
	check(0, "front on empty StrBlob");
	return data->front();
}

string& StrBlob::back(){
	check(0, "back on empty StrBlob");
	return data->back();
}

string& StrBlob::front() const{
	check(0, "front on empty StrBlob");
	return data->front();
}

string& StrBlob::back() const{
	check(0, "back on empty StrBlob");
	return data->back();
}

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

class StrBlobPtr{
    public:
    StrBlobPtr(): curr(0) {}
    StrBlobPtr(StrBlob &s, size_t sz = 0): wptr(s.data), curr(sz) {}
    string &deref() const;
    StrBlobPtr &incr();

    private:
    shared_ptr<vector<string>> check(size_t, const string &) const;
    weak_ptr<vector<string>> wptr;
    size_t curr;
};

shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const {
    auto ret = wptr.lock();
    if(!ret){
        throw runtime_error("unbound StrBlobPtr");
    }
    if(i >= ret->size()){
        throw out_of_range(msg);
    }
    return ret;
}

string &StrBlobPtr::deref() const{
    auto p = check(curr, "dereference past end");
    return (*p)[curr];
}

StrBlobPtr &StrBlobPtr::incr(){
    check(curr, "increment past end of StrBlobPtr");
    ++curr;
    return *this;
}

StrBlobPtr StrBlob::begin(){
    return StrBlobPtr(*this);
}

StrBlobPtr StrBlob::end(){
    auto ret = StrBlobPtr(*this, data->size());
    return ret;
}
04-28 09:10