fork download
  1. /*
  2.  * This file contains code from "C++ Primer, Fifth Edition", by Stanley B.
  3.  * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the
  4.  * copyright and warranty notices given in that book:
  5.  *
  6.  * "Copyright (c) 2013 by Objectwrite, Inc., Josee Lajoie, and Barbara E. Moo."
  7.  *
  8.  *
  9.  * "The authors and publisher have taken care in the preparation of this book,
  10.  * but make no expressed or implied warranty of any kind and assume no
  11.  * responsibility for errors or omissions. No liability is assumed for
  12.  * incidental or consequential damages in connection with or arising out of the
  13.  * use of the information or programs contained herein."
  14.  *
  15.  * Permission is granted for this code to be used for educational purposes in
  16.  * association with the book, given proper citation if and when posted or
  17.  * reproduced. Any commercial use of this code requires the explicit written
  18.  * permission of the publisher, Addison-Wesley Professional, a division of
  19.  * Pearson Education, Inc. Send your request for permission, stating clearly
  20.  * what code you would like to use, and in what specific way, to the following
  21.  * address:
  22.  *
  23.  * Pearson Education, Inc.
  24.  * Rights and Permissions Department
  25.  * One Lake Street
  26.  * Upper Saddle River, NJ 07458
  27.  * Fax: (201) 236-3290
  28. */
  29.  
  30. #ifndef STRBLOB_H
  31. #define STRBLOB_H
  32. #include <vector>
  33. #include <string>
  34. #include <initializer_list>
  35. #include <memory>
  36. #include <stdexcept>
  37.  
  38. // forward declaration needed for friend declaration in StrBlob
  39. class StrBlobPtr;
  40.  
  41. class StrBlob {
  42. friend class StrBlobPtr;
  43. public:
  44. typedef std::vector<std::string>::size_type size_type;
  45.  
  46. // constructors
  47. StrBlob() : data(std::make_shared<std::vector<std::string>>()) { }
  48. StrBlob(std::initializer_list<std::string> il);
  49.  
  50. // size operations
  51. size_type size() const { return data->size(); }
  52. bool empty() const { return data->empty(); }
  53.  
  54. // add and remove elements
  55. void push_back(const std::string &t) { data->push_back(t); }
  56. void pop_back();
  57.  
  58. // element access
  59. std::string& front();
  60. std::string& back();
  61.  
  62. // interface to StrBlobPtr
  63. StrBlobPtr begin(); // can't be defined until StrBlobPtr is
  64. StrBlobPtr end();
  65. private:
  66. std::shared_ptr<std::vector<std::string>> data;
  67. // throws msg if data[i] isn't valid
  68. void check(size_type i, const std::string &msg) const;
  69. };
  70.  
  71. // constructor
  72. inline
  73. StrBlob::StrBlob(std::initializer_list<std::string> il):
  74. data(std::make_shared<std::vector<std::string>>(il)) { }
  75.  
  76. // StrBlobPtr throws an exception on attempts to access a nonexistent element
  77. class StrBlobPtr {
  78. friend bool eq(const StrBlobPtr&, const StrBlobPtr&);
  79. public:
  80. StrBlobPtr(): curr(0) { }
  81. StrBlobPtr(StrBlob &a, size_t sz = 0): wptr(a.data), curr(sz) { }
  82.  
  83. std::string& deref() const;
  84. StrBlobPtr& incr(); // prefix version
  85. StrBlobPtr& decr(); // prefix version
  86. private:
  87. // check returns a shared_ptr to the vector if the check succeeds
  88. std::shared_ptr<std::vector<std::string>>
  89. check(std::size_t, const std::string&) const;
  90.  
  91. // store a weak_ptr, which means the underlying vector might be destroyed
  92. std::weak_ptr<std::vector<std::string>> wptr;
  93. std::size_t curr; // current position within the array
  94. };
  95.  
  96. inline
  97. std::string& StrBlobPtr::deref() const
  98. {
  99. auto p = check(curr, "dereference past end");
  100. return (*p)[curr]; // (*p) is the vector to which this object points
  101. }
  102.  
  103. inline
  104. std::shared_ptr<std::vector<std::string>>
  105. StrBlobPtr::check(std::size_t i, const std::string &msg) const
  106. {
  107. auto ret = wptr.lock(); // is the vector still around?
  108. if (!ret)
  109. throw std::runtime_error("unbound StrBlobPtr");
  110.  
  111. if (i >= ret->size())
  112. throw std::out_of_range(msg);
  113. return ret; // otherwise, return a shared_ptr to the vector
  114. }
  115.  
  116. // prefix: return a reference to the incremented object
  117. inline
  118. StrBlobPtr& StrBlobPtr::incr()
  119. {
  120. // if curr already points past the end of the container, can't increment it
  121. check(curr, "increment past end of StrBlobPtr");
  122. ++curr; // advance the current state
  123. return *this;
  124. }
  125.  
  126. inline
  127. StrBlobPtr& StrBlobPtr::decr()
  128. {
  129. // if curr is zero, decrementing it will yield an invalid subscript
  130. --curr; // move the current state back one element}
  131. check(-1, "decrement past begin of StrBlobPtr");
  132. return *this;
  133. }
  134.  
  135. // begin and end members for StrBlob
  136. inline
  137. StrBlobPtr
  138. StrBlob::begin()
  139. {
  140. return StrBlobPtr(*this);
  141. }
  142.  
  143. inline
  144. StrBlobPtr
  145. StrBlob::end()
  146. {
  147. auto ret = StrBlobPtr(*this, data->size());
  148. return ret;
  149. }
  150.  
  151. // named equality operators for StrBlobPtr
  152. inline
  153. bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
  154. {
  155. auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
  156. // if the underlying vector is the same
  157. if (l == r)
  158. // then they're equal if they're both null or
  159. // if they point to the same element
  160. return (!r || lhs.curr == rhs.curr);
  161. else
  162. return false; // if they point to difference vectors, they're not equal
  163. }
  164.  
  165. inline
  166. bool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
  167. {
  168. return !eq(lhs, rhs);
  169. }
  170. #endif
  171.  
  172.  
  173. //
  174. // main.cpp
  175. // Exercise 12.5
  176. //
  177. // Created by Steven Wiseman on 26/02/2025.
  178. //
  179.  
  180. #include <iostream>
  181. using std::cout; using std::endl;
  182.  
  183. //#include "StrBlob.h"
  184.  
  185. int main()
  186. {
  187. StrBlob b1;
  188. {
  189. StrBlob b2 = { "a", "an", "the" };
  190. b1 = b2;
  191. b2.push_back("about");
  192. cout << b2.size() << endl;
  193. }
  194. cout << b1.size() << endl;
  195.  
  196. for (auto it = b1.begin(); neq(it, b1.end()); it.incr())
  197. cout << it.deref() << endl;
  198.  
  199. return 0;
  200. }
  201.  
  202.  
  203.  
Success #stdin #stdout 0.01s 5288KB
stdin
Standard input is empty
stdout
4
4
a
an
the
about