My Project
pelVector.hpp
1 
10 #ifndef PEL_Vector_HPP_INCLUDED
11 #define PEL_Vector_HPP_INCLUDED
12 
13 #include <cstddef>
14 #include <string>
15 #include <initializer_list>
16 #include <stdexcept>
17 #include <utility>
18 #include <algorithm>
19 #include <fstream>
20 #include <istream>
21 #include <iostream>
22 #include <sstream>
23 #include "./cereal/cereal.hpp"
24 
25 namespace pel {
26 
27 template<typename T> // T must be a type
28 class Vector {
29  T* v_, // start of allocation
30  * space_, // end of sequence, start of expansion
31  * last_; // end of allocated memory space
32 
33  void rangeCheck(std::size_t i) {
34  if (i >= size())
35  throw std::out_of_range{"Out of range index"};
36  }
37 
38  public:
40  // construction/copy/destruction:
41 
42  Vector() // create empty Vector
43  : v_{new T[0]}, space_{v_}, last_{v_} { }
44 
45  Vector(std::size_t size, T const& val)
46  : v_{new T[size]}, space_{v_ + size}, last_{space_}
47  {
48  try {
49  for (std::size_t i = 0; i < size; ++i)
50  v_[i] = val;
51  }
52  catch (...) {
53  delete[] v_;
54  throw;
55  }
56  }
57 
58  Vector(std::initializer_list<T> const& list)
59  : v_{new T[list.size()]}, space_{v_ + list.size()}, last_{space_}
60  {
61  try {
62  auto p = v_;
63  for (auto q = list.begin(); q != list.end(); ++p, ++q)
64  *p = *q;
65  }
66  catch (...) {
67  delete[] v_;
68  throw;
69  }
70  }
71 
72  Vector(Vector<T> const& vec) // copy constructor
73  : v_{new T[vec.size()]}, space_{v_ + vec.size()}, last_{space_}
74  {
75  try {
76  for (std::size_t i = 0; i < vec.size(); ++i)
77  v_[i] = vec[i];
78  }
79  catch (...) {
80  delete[] v_;
81  throw;
82  }
83  }
84 
85  Vector<T>& operator=(Vector<T> const& vec) { // copy assignment operator
86  // copy-and-swap idiom (strong exception safety guarantee):
87  Vector<T> tmp{vec};
88  std::swap(v_, tmp.v_);
89  std::swap(space_, tmp.space_);
90  std::swap(last_, tmp.last_);
91  return *this;
92  } // local tmp Vector is destroyed at this point
93 
94  ~Vector() { delete[] v_; } // destructor
95 
97  // modifiers:
98 
99  void push_back(T const& val) { // strong exception safety guarantee
100  if (space_ == last_) { // capacity exhaustion
101  auto const sz = size(), // original size
102  // new capacity
103  cp = (sz)? static_cast<std::size_t>(1.5*sz) : 2;
104  T* newBlock = new T[cp];
105  try {
106  for (std::size_t i = 0; i < sz; ++i)
107  newBlock[i] = v_[i];
108  }
109  catch (...) {
110  delete[] newBlock;
111  throw;
112  }
113  delete[] v_;
114  v_ = newBlock;
115  space_ = v_ + sz;
116  last_ = v_ + cp;
117  }
118  *space_ = val;
119  ++space_;
120  }
121 
122  void popBack() { // calling popBack() on an empty container is undefined
123  --space_;
124  *space_ = T{};
125  }
126 
127  // iterator position must be valid and dereferenceable
128  T* erase(T* position) { // basic exception safety guarantee
129  for (T* p = position + 1; p != space_; ++p)
130  *(p - 1) = *p;
131  popBack();
132  return position;
133  }
134 
135  T* insert(T* position, T const& val) {
136  if (space_ != last_ && position == space_) {
137  *space_ = val;
138  ++space_;
139  } else if (space_ != last_) { // basic guarantee; more efficient
140  *space_ = *(space_ - 1);
141  ++space_;
142  // copy the elements in [position,space_-2) to range ending at
143  // space_-1. The elements are copied in reverse order (the last
144  // element is copied first), but their relative order is preserved
145  auto it1 = space_ - 1,
146  it2 = space_ - 2;
147  while (position != it2)
148  *(--it1) = *(--it2);
149  *position = val;
150  } else { // strong safety guarantee trivially satisfied
151  std::size_t const n = position - v_;
152  // increase the alloc
153  auto const sz = size(),
154  cp = (sz)? static_cast<std::size_t>(1.5*size()) : 2;
155  T* newBlock = new T[cp];
156  try {
157  for (std::size_t i = 0; i < n; ++i)
158  newBlock[i] = v_[i];
159  newBlock[n] = val;
160  for (std::size_t i = n; i < sz; ++i)
161  newBlock[i + 1] = v_[i];
162  }
163  catch (...) {
164  delete[] newBlock;
165  throw;
166  }
167  delete[] v_;
168  v_ = newBlock;
169  space_ = v_+ sz + 1;
170  last_ = v_ + cp;
171  position = v_ + n;
172  }
173  return position;
174  }
175 
176  void resize(std::size_t n) {
177  int const toDestroy = size() - n; // note: conversion to int
178  if (toDestroy > 0) {
179  for (int i = 0; i < toDestroy; ++i)
180  popBack();
181  } else if (toDestroy < 0) {
182  for (int i = toDestroy; i < 0; ++i)
183  push_back(T{});
184  }
185  }
186 
188  // capacity:
189 
190  std::size_t size() const { return space_ - v_; }
191  std::size_t capacity() const { return last_ - v_; }
192  bool empty() const { return v_ == space_; }
193 
195  // access:
196 
197  T const& operator[](std::size_t i) const { return v_[i]; }
198  T& operator[](std::size_t i) { return v_[i]; }
199 
200  T const& at(std::size_t i) const { rangeCheck(i); return v_[i]; }
201  T& at(std::size_t i) { rangeCheck(i); return v_[i]; }
202 
203  T const& front() const { return *v_; }
204  T& front() { return *v_; }
205 
206  T const& back() const { return *(space_ - 1); }
207  T& back() { return *(space_ - 1); }
208 
210  // iterators:
211 
212  T const* begin() const { return v_; }
213  T* begin() { return v_; }
214 
215  T const* end() const { return space_; }
216  T* end() { return space_; }
217 
219  // serialization:
220  template<class Archive>
221  void save(Archive& archive) const {
222  archive(cereal::make_size_tag(size()));
223 
224  for (std::size_t i = 0; i < size(); i++)
225  archive(v_[i]);
226  }
227 
228  template<class Archive>
229  void load(Archive& ar) {
230  cereal::size_type sz;
231  ar(cereal::make_size_tag(sz));
232 
233  resize(sz);
234 
235  for (std::size_t i = 0; i < sz; i++)
236  ar(v_[i]);
237  }
238 
239  void writeToFile(std::string fileName) {
240  std::fstream f;
241  f.open(fileName.c_str(), std::ios::out);
242 
243  f << std::to_string(size()) << "\n";
244  for (std::size_t i = 0; i < size(); i++) {
245  v_[i].writeToFile(&f);
246  }
247  }
248 
249  void readFromFile(std::string fileName) {
250  std::fstream f;
251  f.open(fileName.c_str(), std::ios::in);
252 
253  std::string buffer;
254  int cuantos;
255  std::getline(f, buffer);
256  std::istringstream(buffer) >> cuantos;
257 
258  resize(cuantos);
259 
260  for (std::size_t i = 0; i < size(); i++) {
261  v_[i].readFromFile(&f);
262  }
263  }
264 };
265 
266 } // namespace pel
267 
268 #endif // PEL_Vector_HPP_INCLUDED
Definition: pelVector.hpp:25
Definition: pelVector.hpp:28