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;
}