简介
参见C++primer第十四章第六节的习题
类说明
这个类是一个指向StrBlob类的指针,只不过不同于普通指针,该类的数据成员有一个weak_ptr,在构造函数中,我们将该指针指向shared_ptr指向的内容,不过该指针并不会像shared_ptr那样,为use_count加一。
由于 weak_ptr 所指向的对象可能不存在,因此使用了一个 check() 来检查该类在进行操作前的合法性,在该函数中,我们用到了 lock() 函数用来检验,如果存在,则返回一个指向该对象的 shared_ptr 指针,否则报错。
关于算术运算符,我起初定义的是非成员函数,但是该类的算术运算符并不需要如此,原因是我们并不会对两个指针做加法,这样没有意义,我们只会对指针做偏移,所以该算术运算符就相当于是++,–的一个扩大版而已。与非成员函数一样,我们同样利用复合运算符来实现算术运算符。
下面是代码:
/*
===========================================================================
C++ Primer 5th Exercise Answer Source Code
StrBlob, StrBlobPtr
If you have questions, try to connect with me: pence<1477364283@qq.com>
===========================================================================
*/
#pragma once
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <memory>
#include <algorithm>
#include <utility>
#include "StrVec.h"
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::istringstream;
using std::ostringstream;
using std::map;
using std::set;
using std::ifstream;
using std::getline;
using std::shared_ptr;
using std::size_t;
class StrBlobPtr;
class StrBlob
{
public:
friend class StrBlobPtr;
friend bool operator==(const StrBlob&, const StrBlob&);
friend bool operator!=(const StrBlob&, const StrBlob&);
friend bool operator<(const StrBlob&, const StrBlob&);
friend bool operator>(const StrBlob&, const StrBlob&);
friend bool operator<=(const StrBlob&, const StrBlob&);
friend bool operator>=(const StrBlob&, const StrBlob&);
using size_type = vector<string>::size_type;
/*构造函数*/
StrBlob(); //默认构造函数
StrBlob(std::initializer_list<string> list);
/*拷贝构造函数*/
StrBlob(const StrBlob& rCopy):data(std::make_shared<vector<string>>(*rCopy.data)){}
/*拷贝赋值运算符*/
StrBlob& operator= (const StrBlob & rCopy)
{
data = std::make_shared<vector<string>>(*rCopy.data);
return *this;
}
/*重载下标运算符*/
string& operator[](std::size_t n)
{
check("out of range", n);
return (*data)[n];
}
const string& operator[](std::size_t n) const
{
check("out of range", n);
return (*data)[n];
}
/*成员函数*/
bool empty() { return data->empty(); }
void push_back(const string& str) { data->push_back(str); }
void pop_back();
StrBlobPtr begin();
StrBlobPtr end();
size_type size() { return data->size(); }
string& front();
string& back();
const string& front() const;
const string& back() const;
unsigned count() const { return data.use_count(); }
private:
shared_ptr<vector<string>> data;
void check(const string& wmsg, size_type idx) const;
};
class StrBlobPtr
{
public:
friend bool operator==(const StrBlobPtr&, const StrBlobPtr&);
friend bool operator!=(const StrBlobPtr& lhs, const StrBlobPtr& rhs);
friend bool operator<(const StrBlobPtr& lhs, const StrBlobPtr& rhs);
friend bool operator>(const StrBlobPtr& lhs, const StrBlobPtr& rhs);
friend bool operator<=(const StrBlobPtr&, const StrBlobPtr&);
friend bool operator>=(const StrBlobPtr&, const StrBlobPtr&);
/*constructor*/
StrBlobPtr() = default;
StrBlobPtr(StrBlob& DataSource, size_t curr = 0) : pData(DataSource.data), idx(curr) {}
/*subscript operator*/
string& operator[](std::size_t n);
const string& operator[](std::size_t n) const;
/*increment decrement operator*/
StrBlobPtr& operator++();
StrBlobPtr& operator--();
StrBlobPtr operator++(int);
StrBlobPtr operator--(int);
StrBlobPtr operator+(size_t) const;
StrBlobPtr operator-(size_t) const;
StrBlobPtr& operator+=(size_t);
StrBlobPtr& operator-=(size_t);
/*members*/
StrBlobPtr& increase();
string& deref() const;
unsigned count() const { return pData.use_count(); }
private:
shared_ptr<vector<string>> check(size_t index, const string& msg) const;
std::weak_ptr<vector<string>> pData;
size_t idx = 0;
};
/*StrBlobPtr subscript operator*/
inline string& StrBlobPtr::operator[](std::size_t n)
{
auto sharedPvector = check(n, "the access is cross the border");
return (*sharedPvector)[n];
}
inline const string& StrBlobPtr::operator[](std::size_t n) const
{
auto sharedPvector = check(n, "the access is cross the border");
return (*sharedPvector)[n];
}
/*increment, decrement operator*/
inline StrBlobPtr& StrBlobPtr::operator++()
{
check(idx, "the increment past end of StrBlobPtr");
++idx;
return *this;
}
inline StrBlobPtr& StrBlobPtr::operator--()
{
--idx;
check(idx, "the decrement past begin of StrBlobPtr");
return *this;
}
inline StrBlobPtr StrBlobPtr::operator++(int)
{
StrBlobPtr ret = *this;
++* this;
return ret;
}
inline StrBlobPtr StrBlobPtr::operator--(int)
{
StrBlobPtr ret = *this;
--* this;
return ret;
}
inline StrBlobPtr StrBlobPtr::operator+(size_t n) const
{
StrBlobPtr tmp = *this;
tmp += n;
return tmp;
}
inline StrBlobPtr StrBlobPtr::operator-(size_t n) const
{
StrBlobPtr tmp = *this;
tmp -= n;
return tmp;
}
inline StrBlobPtr& StrBlobPtr::operator+=(size_t n)
{
idx += n;
check(idx, "the access is out of range!");
return *this;
}
inline StrBlobPtr& StrBlobPtr::operator-=(size_t n)
{
idx -= n;
check(idx, "the access is out of range!");
return *this;
}
#include "StrBlob.h"
/****************************************
* *
*class StrBlob *
* *
*****************************************/
StrBlob::StrBlob() :data(std::make_shared<vector<string>>()) {}
StrBlob::StrBlob(std::initializer_list<string> list) : data(std::make_shared<vector<string>>(list)) {}
/*overload operators*/
bool operator==(const StrBlob& lhs, const StrBlob& rhs)
{
if (*lhs.data == *rhs.data)
{
return true;
}
return false;
}
bool operator!=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(lhs == rhs);
}
bool operator<(const StrBlob& lhs, const StrBlob& rhs)
{
return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->begin());
}//return *lhs.data < *rhs.data;
bool operator>(const StrBlob& lhs, const StrBlob& rhs)
{
return rhs < lhs;
}
bool operator<=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(lhs > rhs);
}
bool operator>=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(lhs < rhs);
}
void StrBlob::check(const string& wmsg, size_type idx) const
{
if (idx >= data->size())
{
throw std::out_of_range(wmsg);
}
}
const string& StrBlob::back() const
{
//this指针为一个指向const对象的常量指针,形如 const int* const p,因此当p想转换为非底层const的指针时,是不允许的
//所以也需要为check定义const版本
check("back on empty vector", 0);
return data->back();
}
const string& StrBlob::front() const
{
check("front on empty vector", 0);
return data->front();
}
string& StrBlob::back()
{
check("back on empty vector", 0);
return data->back();
}
string& StrBlob::front()
{
check("front on empty vector", 0);
return data->front();
}
void StrBlob::pop_back()
{
check("pop_back on empty vector", 0);
return data->pop_back();
}
StrBlobPtr StrBlob::begin()
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
return StrBlobPtr(*this, size());
}
/****************************************
* *
*class StrBlobPtr *
* *
*****************************************/
/*overload operators*/
bool operator!=(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
if (lhs.idx != rhs.idx)
{
return true;
}
return false;
}
bool operator==(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
return !(lhs != rhs);
}
bool operator>(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
return lhs.idx > rhs.idx;
}
bool operator<(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
return lhs.idx < rhs.idx;
}
bool operator<=(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
return lhs.idx <= rhs.idx;
}
bool operator>=(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
return lhs.idx >= rhs.idx;
}
shared_ptr<vector<string>> StrBlobPtr::check(size_t index, const string& msg) const
{
auto sData = pData.lock();
if (!sData)
{
throw std::runtime_error("unbound StrBlobPtr");
}
else if (sData->size() <= index)
{
throw std::out_of_range(msg);
}
return sData;
}
StrBlobPtr& StrBlobPtr::increase()
{
check(idx, "operating cross-border");
++idx;
return *this;
}
string& StrBlobPtr::deref() const
{
auto sData = check(idx, "the deref is cross-border");
return (*sData)[idx];
}