12.1.1
#include<iostream>
#include<fstream>
#include<vector>
#include<memory>
#include<string>
using namespace std;
class StrBlob {
public:
typedef vector<string>::size_type size_type;
StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> il) : data(make_shared<vector<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();
const string& front() const;
string& back();
const string& back() const;
private:
shared_ptr<vector<string>> data;
void check(size_type i, const string& smg) const;
};
int main(int argc, char* argv[])
{
StrBlob d({ "2020,7,13", });
cout << d.size() << endl;
d.push_back("2020,7,14");
cout << d.size() << endl;
d.pop_back();
cout << d.size() << endl;
return 0;
}
void StrBlob::check(size_type i, const string& msg) const
{
if (i >= data->size())
throw out_of_range(msg);
}
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
return data->pop_back();
}
string&
StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
const string&
StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
string&
StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const string&
StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
12.1.6
head.h
#include <memory>
#include <vector>
#include <string>
class StrBlobPtr; //友元必须提前声明
class StrBlob {
friend class StrBlobPtr;
public:
typedef std::vector<std::string>::size_type size_type;
StrBlob() :data(std::make_shared<std::vector<std::string>>()) { }
StrBlob(std::initializer_list<std::string>il) :data(std::make_shared<std::vector<std::string>>(il)) { }
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
void push_back(const std::string& t) { data->push_back(t); }
void pop_back();
std::string& front();
std::string& back();
const std::string& front() const;
const std::string& back() const;
StrBlobPtr begin();
StrBlobPtr end();
StrBlobPtr cbegin() const;
StrBlobPtr cend() const;
private:
std::shared_ptr<std::vector<std::string>> data;
void check(size_type i, const std::string& msg) const;
};
class StrBlobPtr {
public:
StrBlobPtr() : curr(0) { }
StrBlobPtr(const StrBlob& a, size_t sz = 0) :
wptr(a.data), curr(sz) { }
bool operator != (const StrBlobPtr& q) { return q.curr != curr; }
std::string& deref() const;
StrBlobPtr& incr();
private:
std::shared_ptr<std::vector<std::string>>
check(std::size_t i, const std::string& msg) const;
std::weak_ptr<std::vector<std::string>> wptr;
std::size_t curr;
};
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
std::string&
StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
std::string&
StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const std::string&
StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
const std::string&
StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
void StrBlob::check(size_type i, const std::string& msg) const
{
if (i >= data->size())
throw std::out_of_range(msg);
}
StrBlobPtr StrBlob::begin()
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
StrBlobPtr StrBlob::cbegin() const
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::cend() const
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
std::string&
StrBlobPtr::deref() const
{
auto p = check(curr, "dereferemce past end");
return (*p)[curr];
}
StrBlobPtr&
StrBlobPtr::incr()
{
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
std::shared_ptr<std::vector<std::string>>
StrBlobPtr::check(std::size_t i, const std::string& msg) const
{
auto ret = wptr.lock();
if (!ret)
throw std::runtime_error("unbound StrBlobPtr");
if (i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
cpp
#include<iostream>
#include<memory>
#include"head.h"
using namespace std;
int main(int argc, char* argv[])
{
const StrBlob b{ "It", "is", "a", "Test" };
StrBlobPtr q(b);
for (q = b.cbegin(); q != b.cend(); q.incr())
cout << q.deref() << " ";
return 0;
}