12.19 StrBlob及其伴随类StrBlobPtr

StrBlob.h

#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <memory>

class StrBlobPtr;

class StrBlob {
   friend class StrBlobPtr;
public:
   typedef std::vector<std::string>::size_type size_type;
   StrBlob();
   StrBlob(std::initializer_list<std::string> il);
   StrBlob(const StrBlob &obj)
   		: data(new std::vector<std::string>(*obj.data)) {}
   StrBlob &operator=(const StrBlob &rhs) {
   		data = rhs.data;
   		return *this;
   }
   size_type size() { return data->size(); }
   const size_type size() const { return data->size(); }
   bool empty() { return data->empty(); }
   void push_back(const std::string &s) { data->push_back(s); }
   void push_back(std::string &&s) {data->push_back(std::move(s));}
   void pop_back();
   std::string& front();
   const std::string& front() const;
   std::string& back();
   const std::string& back() const;
private:
   std::shared_ptr<std::vector<std::string>> data;
   void check(size_type i, const std::string &msg) const;

   friend class StrBlobPtr;
   StrBlobPtr begin(); // 不建议将实现写在此处,会造成"incomplete type is not allowed" error
   StrBlobPtr end();
};

StrBlob.cpp

#include "stdafx.h"
#include <stdexcept> // out_of_range
#include "StrBlob.h"
#include "StrBlobPtr.h" // 需要include头文件来保证StrBlobPtr构造函数的定义存在

StrBlob::StrBlob() {
   data = std::make_shared<std::vector<std::string>>();
}

StrBlob::StrBlob(std::initializer_list<std::string> il) {
   data = std::make_shared<std::vector<std::string>>(il);
}

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

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

const std::string& StrBlob::front() const {
   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::back() const {
   check(0, "back on empty StrBlob");
   return data->back();
}

StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); }
StrBlobPtr StrBlob::end() { return StrBlobPtr(*this, data->size()); }

StrBlobPtr.h

#pragma once
#include <memory>
#include <vector>
#include "StrBlob.h" // 有#program once的存在,不用担心重复定义的问题

class StrBlobPtr
{
public:
   StrBlobPtr():curr{0}{}
   StrBlobPtr(StrBlob &a, size_t sz = 0)
      : wptr(a.data), curr(sz){}
   ~StrBlobPtr() {};
   std::string &deref() const;
   StrBlobPtr &incr();
   friend bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs);
private:
   std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
   std::weak_ptr<std::vector<std::string>> wptr;
   std::size_t curr;
};

StrBlobPtr.cpp

#include "stdafx.h"
#include "StrBlobPtr.h"
#include <exception>

std::string & StrBlobPtr::deref() const {
   auto p = check(curr, "Dereference past the end");
   return (*p)[curr];
}
StrBlobPtr & StrBlobPtr::incr() {
   check(curr, "Increment past the end");
   ++curr;
   return *this;
}

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

bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs) {
   auto lp = lhs.wptr.lock(), rp = rhs.wptr.lock();
   if (lp == rp) {
      return (!lp || lhs.curr == rhs.curr);
   }
   else {
      return false;
   }
}

main.cpp

int main()
{
   ifstream f("test.txt");
   if (f) {
      string tmp;
      StrBlob s;
      while (f >> tmp) {
         s.push_back(tmp);
      }
      cout << "Read all word" << endl;
      cout << "Show them" << endl;
      for (StrBlobPtr p = s.begin();
         !eq(p, s.end());
         p.incr()) {
         cout << p.deref() << " ";
      }
      cout << endl;
   }
   else {
      cout << "Read file error" << endl;
      exit(1);
   }
   return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值