Vector Deque
 All Classes Functions Variables Typedefs
VectorDeque.hpp
1 #include <cstddef>
2 #include <sstream>
3 #include <stdexcept>
4 #include <cstring>
5 #include <string>
6 
21 template <class DataType>
22 class VectorDeque {
23  private:
24  // Allow testing class to access private methods and fields.
25  friend class VectorDequeTest;
26 
27  // Base class for the mutable and immutable iterator implementations.
28  template <class VectorDequeType, class MemberType, bool IS_REVERSE>
29  class IteratorBase {
30  typedef IteratorBase<VectorDeque, DataType, IS_REVERSE> Iterator;
31  typedef IteratorBase<const VectorDeque, const DataType, IS_REVERSE> ConstIterator;
32  friend VectorDeque;
33 
34  private:
35  // Position in the VectorDeque this iterator is pointing to.
36  size_t _position;
37 
38  // Pointer to VectorDeque this iterator is iterating on.
39  VectorDequeType* const _vectorDequePtr;
40 
41  static MemberType& dereferenceAt(VectorDequeType* const vectorDequePtr, const ptrdiff_t position) throw() {
42  if (IS_REVERSE) {
43  return (*vectorDequePtr)[vectorDequePtr->size() - position - 1];
44  }
45  return (*vectorDequePtr)[position];
46  }
47 
48  public:
49  // Constructs an Iterator from a VectorDeque pointer and a position.
50  IteratorBase(VectorDequeType* const vectorDequePtr, const size_t position) throw():
51  _vectorDequePtr(vectorDequePtr), _position(position) {}
52 
53  // Constructs an Iterator from a VectorDeque pointer.
54  IteratorBase(VectorDequeType* const vectorDequePtr) throw(): _vectorDequePtr(vectorDequePtr), _position(0) {}
55 
60  IteratorBase() throw(): _position(0), _vectorDequePtr(NULL) {}
61 
67  IteratorBase(const Iterator& that) throw(): _position(that._position),
68  _vectorDequePtr(that._vectorDequePtr) {}
69 
75  IteratorBase(const ConstIterator& that) throw(): _position(that._position),
76  _vectorDequePtr(that._vectorDequePtr) {}
77 
84  IteratorBase& operator =(const Iterator& that) throw() {
85  _position = that._position;
86  _vectorDequePtr = that._vectorDequePointer;
87  return *this;
88  }
89 
96  IteratorBase& operator =(const ConstIterator& that) throw() {
97  _position = that._position;
98  _vectorDequePtr = that._vectorDequePointer;
99  return *this;
100  }
101 
119  bool operator ==(const ConstIterator& that) const throw() {
120  return _position == that._position && _vectorDequePtr == that._vectorDequePtr;
121  }
122 
130  bool operator !=(const ConstIterator& that) const throw() {
131  return !(*this == that);
132  }
133 
141  bool operator <(const ConstIterator& that) const throw() {
142  return _position < that._position;
143  }
144 
152  bool operator >(const ConstIterator& that) const throw() {
153  return _position > that._position;
154  }
155 
164  bool operator <=(const ConstIterator& that) const throw() {
165  return *this == that || *this < that;
166  }
167 
176  bool operator >=(const ConstIterator& that) const throw() {
177  return *this == that || *this > that;
178  }
179 
185  IteratorBase& operator ++() throw() {
186  ++_position;
187  return *this;
188  }
189 
195  IteratorBase operator ++(int) throw() {
196  const IteratorBase copy(*this);
197  ++_position;
198  return copy;
199  }
200 
206  IteratorBase& operator --() throw() {
207  --_position;
208  return *this;
209  }
210 
216  IteratorBase operator --(int) throw() {
217  const IteratorBase copy(*this);
218  --_position;
219  return copy;
220  }
221 
228  IteratorBase& operator +=(const ptrdiff_t amount) throw() {
229  _position += amount;
230  return *this;
231  }
232 
239  IteratorBase& operator -=(const ptrdiff_t amount) throw() {
240  _position -= amount;
241  return *this;
242  }
243 
251  IteratorBase operator +(const ptrdiff_t amount) const throw() {
252  return IteratorBase(*this) += amount;
253  }
254 
262  friend IteratorBase operator +(const ptrdiff_t amount, const IteratorBase& it) throw() {
263  return it + amount;
264  }
265 
273  IteratorBase operator -(const ptrdiff_t amount) const throw() {
274  return IteratorBase(*this) -= amount;
275  }
276 
286  ptrdiff_t operator -(const ConstIterator& that) const throw() {
287  return static_cast<ptrdiff_t>(_position) - that._position;
288  }
289 
297  MemberType& operator *() const {
298  return dereferenceAt(_vectorDequePtr, static_cast<ptrdiff_t>(_position));
299  }
300 
307  MemberType* operator ->() const throw() {
308  return &(**this);
309  }
310 
318  MemberType& operator [](const ptrdiff_t offset) const {
319  return dereferenceAt(_vectorDequePtr, static_cast<ptrdiff_t>(_position) + offset);
320  }
321  };
322 
323  // Length of current backing array.
324  size_t _capacity;
325 
326  // The stored data.
327  DataType* _data;
328 
329  // Index in the backing array of the first element.
330  size_t _position;
331 
332  // Total number of elements currently contained.
333  size_t _size;
334 
335  // Add `length` elements from `elements` to the back.
336  // Assumes length of internal array has already been verified.
337  void _addAll(const DataType* const elements, const size_t start, const size_t length) throw() {
338  // Number of elements before wrapping around to beginning.
339  const size_t numBeforeWrap = std::min(_capacity - start, length);
340  const size_t numAfterWrap = length - numBeforeWrap;
341  std::memcpy(_data + start, elements, sizeof(DataType) * numBeforeWrap);
342  std::memcpy(_data, elements + numBeforeWrap, sizeof(DataType) * numAfterWrap);
343  }
344 
345  // Check to see if `index` is valid.
346  // If not, throw `length_error`.
347  void _checkIndex(const size_t index) const {
348  if (index >= _size) {
349  throw std::length_error(std::to_string(index));
350  }
351  }
352 
353  // Check to see if `it` iterates over `*this`.
354  // If not, throw `invalid_argument`.
355  template <class IteratorType>
356  void _checkIterator(const IteratorType& it) const {
357  if (this != it._vectorDequePtr) {
358  throw std::invalid_argument("Iterator is not iterating over this VectorDeque");
359  }
360  }
361 
362  // Check to see if `[from, until)` is a valid range.
363  // If not, throw `length_error`.
364  void _checkRange(const size_t from, const size_t until) const {
365  _checkSize(until);
366  if (from > until) {
367  throw std::invalid_argument("Bad range: start = " + std::to_string(from) + ", end = " +
368  std::to_string(until));
369  }
370  }
371 
372  // Check to see if this has at least `required` elements.
373  // If not, throw `length_error`.
374  void _checkSize(const size_t required = 1) const {
375  if (required > 0) {
376  _checkIndex(required - 1);
377  }
378  }
379 
380  // Check to see if the current backing array has length at least `required`.
381  // If not, resize.
382  void _ensureCapacity(const size_t required) throw() {
383  if (_capacity < required) {
384  const size_t newCapacity = required * 2 + 1;
385  DataType* const newData = new DataType[newCapacity];
386  copyToArray(newData);
387  _position = 0;
388  delete[] _data;
389  _data = newData;
390  _capacity = newCapacity;
391  }
392  }
393 
394  // Check to see if `amount` more elements can fit in `*this`.
395  // If not, resize.
396  void _ensureCanFit(const size_t amount = 1) throw() {
397  _ensureCapacity(_size + amount);
398  }
399 
400  // Initialize the backing array and all fields.
401  void _init(const size_t capacity) throw() {
402  _capacity = capacity;
403  _data = new DataType[capacity];
404  _position = 0;
405  _size = 0;
406  }
407 
408  // Optimization: Insert `element` and resize at the same time when _size == _capacity pre-insertion.
409  void _insertAndResize(const DataType& element, const size_t before) {
410  const size_t newCapacity = 2 * _capacity + 1;
411  DataType* const newData = new DataType[newCapacity];
412  sliceToArray(newData, 0, before);
413  newData[before] = element;
414  if (before < _size) {
415  // `before == _size` would result in an exception.
416  sliceToArray(newData + before + 1, before, _size);
417  }
418  delete[] _data;
419  _data = newData;
420  _capacity = newCapacity;
421  ++_size;
422  _position = 0;
423  }
424 
425  // Compute the internal index for the offset `offset`.
426  size_t _internalIndex(const size_t offset) const throw() {
427  if (_position + offset < _capacity) {
428  return _position + offset;
429  }
430  // Target index is past the length of _data: wrap around to the beginning.
431  // Note that if `_position + offset == _capacity`, the resulting index is 0.
432  return _position + offset - _capacity;
433  }
434 
435  // Determine the internal index offsetted by `offset` from `from` going backwards.
436  size_t _internalNegativeIndexFrom(const size_t from, const size_t offset) const throw() {
437  const size_t internal = _internalIndex(from);
438  if (internal >= offset) {
439  return internal - offset;
440  }
441  // Target index is before 0: wrap around to the end.
442  // Note that if `from == offset - 1`, the resulting index is `_capacity - 1`.
443  return _capacity - (offset - internal);
444  }
445 
446  // Compute the number of elements remaining before we need to wrap to the beginning starting from `start`
447  // when `length` elements need to be added.
448  size_t _numBeforeWrap(const size_t start, const size_t length) const throw() {
449  return std::min(_capacity - start, length);
450  }
451 
452  // Shift the elements down from `from` until `until`.
453  void _shiftDown(const size_t from, const size_t until) throw() {
454  // Since elements are overwritten before they are copied, it is safe to use `memcpy`.
455  const size_t length = until - from;
456  // Start the `memcpy` 1 before the `from`.
457  const size_t start = _internalNegativeIndexFrom(from, 1);
458  const size_t numBeforeWrap = _numBeforeWrap(start, length);
459  const size_t numAfterWrap = length - numBeforeWrap;
460  std::memcpy(_data + start, _data + start + 1, sizeof(DataType) * numBeforeWrap);
461  if (numAfterWrap != 0) {
462  // First internal elements should be "shifted down" to the last position.
463  _data[_capacity - 1] = _data[0];
464  // Note numAfterWrap >= 1, so this is safe.
465  std::memcpy(_data, _data + 1, sizeof(DataType) * (numAfterWrap - 1));
466  }
467  if (from == 0) {
468  // Update the position if we are shifting down the first element.
469  if (_position == 0) {
470  _position = _capacity - 1;
471  } else {
472  --_position;
473  }
474  }
475  }
476 
477  // Shift the elements up from `from` until `until`.
478  void _shiftUp(const size_t from, const size_t until) {
479  // Need to start from the end and go backwards, since otherwise elements will be overwritten before they are
480  // copied. Thus, we may not use `memcpy`.
481  for (size_t i = 0; i < until - from; ++i) {
482  _data[_internalNegativeIndexFrom(until, i)] = _data[_internalNegativeIndexFrom(until, i + 1)];
483  }
484  if (from == 0) {
485  // If we're shifting up the first element, we need to update `_position`.
486  if (_position == _capacity - 1) {
487  _position = 0;
488  } else {
489  ++_position;
490  }
491  }
492  }
493 
494  // Compute the internal index for where the next element should be written.
495  size_t _writePosition() const throw() {
496  // We write _size elements after the current position.
497  return _internalIndex(_size);
498  }
499 
500  public:
504  typedef IteratorBase<VectorDeque, DataType, false> Iterator;
505 
509  typedef IteratorBase<const VectorDeque, const DataType, false> ConstIterator;
510 
514  typedef IteratorBase<VectorDeque, DataType, true> ReverseIterator;
515 
519  typedef IteratorBase<const VectorDeque, const DataType, true> ConstReverseIterator;
520 
524  const static size_t DEFAULT_INITIAL_CAPACITY;
525 
530  VectorDeque() throw() {
532  }
533 
539  explicit VectorDeque(const size_t capacity) throw() {
540  _init(capacity);
541  }
542 
549  VectorDeque(const VectorDeque& that) throw() {
550  // Initialize backing array to be large enough to contain the contents of that.
551  _init(that._size);
552  that.copyToArray(_data);
553  // Note that._position is still 0, and we are at capacity.
554  _size = that._size;
555  }
556 
563  VectorDeque(VectorDeque&& that) throw() {
564  // Move contents of that with memcpy.
565  std::memcpy(this, &that, sizeof(VectorDeque));
566  // Allow safe destruction of that.
567  that._data = NULL;
568  }
569 
577  VectorDeque& operator =(const VectorDeque& that) throw() {
578  if (this == &that) {
579  return *this;
580  }
581  if (_capacity < that._size) {
582  delete[] _data;
583  _data = new DataType[that._size];
584  _capacity = that._size;
585  }
586  that.copyToArray(_data);
587  _position = 0;
588  _size = that._size;
589  return *this;
590  }
591 
599  VectorDeque& operator =(VectorDeque&& that) throw() {
600  delete[] _data;
601  // Move with memcpy.
602  std::memcpy(this, &that, sizeof(VectorDeque));
603  // Allow safe destruction of that.
604  that._data = NULL;
605  }
606 
613  bool operator ==(const VectorDeque& that) const throw() {
614  if (this == &that) {
615  return true;
616  }
617  if (_size != that.size()) {
618  return false;
619  }
620  for (size_t i = 0; i < _size; ++i) {
621  if ((*this)[i] != that[i]) {
622  return false;
623  }
624  }
625  return true;
626  }
627 
634  bool operator !=(const VectorDeque& that) const throw() {
635  return !(*this == that);
636  }
637 
646  DataType& operator [](const size_t index) const {
647  _checkIndex(index);
648  return _data[_internalIndex(index)];
649  }
650 
656  operator std::string() const throw() {
657  if (isEmpty()) {
658  return "{}";
659  }
660  std::stringstream stream;
661  stream << '{';
662  stream << (*this)[0];
663  for (size_t i = 1; i < _size; ++i) {
664  stream << ", " << (*this)[i];
665  }
666  stream << '}';
667  return stream.str();
668  }
669 
675  void add(const DataType& element) throw() {
676  _ensureCanFit();
677  _data[_writePosition()] = element;
678  ++_size;
679  }
680 
687  void addAll(const DataType* const elements, const size_t length) throw() {
688  _ensureCanFit(length);
689  _addAll(elements, _writePosition(), length);
690  _size += length;
691  }
692 
700  template <class IteratorType>
701  void addAll(IteratorType begin, IteratorType end) throw() {
702  for (IteratorType it = begin; it != end; ++it) {
703  add(*it);
704  }
705  }
706 
715  void addAllFirst(const DataType* const elements, const size_t length) throw() {
716  // Can't take advantage of memcpy: use iterator version.
717  addAllFirst(elements, elements + length);
718  }
719 
729  template <class IteratorType>
730  void addAllFirst(IteratorType begin, IteratorType end) throw() {
731  for (IteratorType it = begin; it != end; ++it) {
732  addFirst(*it);
733  }
734  }
735 
741  void addFirst(const DataType& element) throw() {
742  _ensureCanFit();
743  if (_position == 0) {
744  _position = _capacity - 1;
745  } else {
746  --_position;
747  }
748  // The position is now at the element which was added to the front.
749  _data[_position] = element;
750  ++_size;
751  }
752 
758  Iterator begin() throw() {
759  return Iterator(this);
760  }
761 
767  ConstIterator cbegin() const throw() {
768  return ConstIterator(this);
769  }
770 
776  ConstIterator cend() const throw() {
777  return ConstIterator(this, _size);
778  }
779 
784  void clear() throw() {
785  _size = 0;
786  }
787 
794  bool contains(const DataType& element) const throw() {
795  return find(element) != -1;
796  }
797 
803  void copyToArray(DataType* const target) const throw() {
804  sliceToArray(target, 0, _size);
805  }
806 
812  ConstReverseIterator crbegin() const throw() {
813  return ConstReverseIterator(this);
814  }
815 
821  ConstReverseIterator crend() const throw() {
822  return ConstReverseIterator(this, _size);
823  }
824 
830  Iterator end() throw() {
831  return Iterator(this, _size);
832  }
833 
840  ssize_t find(const DataType& element) const throw() {
841  for (size_t i = 0; i < _size; ++i) {
842  if (element == (*this)[i]) {
843  return i;
844  }
845  }
846  return -1;
847  }
848 
857  DataType& fromBack(const size_t index) const {
858  return (*this)[_size - index - 1];
859  }
860 
869  void insert(const DataType& element, const size_t before) {
870  if (before == 0) {
871  // Handle the logic for 0 specially since it changes the position.
872  addFirst(element);
873  return;
874  }
875  if (before != _size) {
876  // `before == _size` is okay because it translates to inserting `element` at the end.
877  _checkIndex(before);
878  } else {
879  add(element);
880  return;
881  }
882  if (_size == _capacity) {
883  // Handle insertion and resizing simultaneously for efficiency.
884  _insertAndResize(element, before);
885  return;
886  }
887 
888  if (before <= _size / 2) {
889  // More efficient to shift front elements backwards.
890  _shiftDown(0, before);
891 
892  } else {
893  // More efficient to shift back elements forwards.
894  _shiftUp(before, _size);
895  }
896  ++_size;
897  const size_t insertionIndex = _internalIndex(before);
898  _data[insertionIndex] = element;
899  }
900 
910  void insert(const DataType& element, const ConstIterator& it) {
911  _checkIterator(it);
912  insert(element, it._position);
913  }
914 
924  void insert(const DataType& element, const ConstReverseIterator& it) {
925  _checkIterator(it);
926  insert(element, _size - it._position);
927  }
928 
934  bool isEmpty() const throw() {
935  return _size == 0;
936  }
937 
945  DataType peek() const {
946  _checkSize();
947  return (*this)[0];
948  }
949 
957  DataType peekLast() const {
958  _checkSize();
959  return (*this)[_size - 1];
960  }
961 
969  DataType pop() {
970  _checkSize();
971  const DataType popped = peek();
972  skip();
973  return popped;
974  }
975 
981  void popAll(DataType* const target) throw() {
982  copyToArray(target);
983  clear();
984  }
985 
991  void popAllLast(DataType* const target) throw() {
992  reverseCopyToArray(target);
993  clear();
994  }
995 
1003  DataType popLast() {
1004  _checkSize();
1005  const DataType popped = peekLast();
1006  skipLast();
1007  return popped;
1008  }
1009 
1017  void popSome(DataType* const target, const size_t amount) {
1018  sliceToArray(target, 0, amount);
1019  skip(amount);
1020  }
1021 
1031  void popSomeLast(DataType* const target, const size_t amount) {
1032  reverseSliceToArray(target, 0, amount);
1033  skipLast(amount);
1034  }
1035 
1042  return ReverseIterator(this);
1043  }
1044 
1053  DataType removeAt(const size_t index) {
1054  _checkIndex(index);
1055  const DataType result = (*this)[index];
1056  if (index == _size - 1) {
1057  --_size;
1058  }
1059  else if (index / 2 <= _size) {
1060  // More efficient to shift front elements forward.
1061  _shiftUp(0, index);
1062  --_size;
1063 
1064  } else {
1065  // More efficient to shift back elements backward.
1066  _shiftDown(index + 1, _size);
1067  --_size;
1068  }
1069  return result;
1070  }
1071 
1081  DataType removeAt(const ConstIterator& it) {
1082  _checkIterator(it);
1083  return removeAt(it._position);
1084  }
1085 
1095  DataType removeAt(const ConstReverseIterator& it) {
1096  _checkIterator(it);
1097  removeAt(_size - it._position);
1098  }
1099 
1105  Iterator rend() throw() {
1106  return ReverseIterator(this, _size);
1107  }
1108 
1114  void reverseCopyToArray(DataType* const target) const throw() {
1115  reverseSliceToArray(target, 0, _size);
1116  }
1117 
1128  void reverseSliceToArray(DataType* const target, const size_t from, const size_t until) const {
1129  _checkRange(from, until);
1130  const size_t length = until - from;
1131  for (size_t i = 0; i < length; ++i) {
1132  target[i] = fromBack(i + from);
1133  }
1134  }
1135 
1141  size_t size() const throw() {
1142  return _size;
1143  }
1144 
1152  void skip(const size_t amount = 1) {
1153  _checkSize(amount);
1154  _position = _internalIndex(amount);
1155  _size -= amount;
1156  }
1157 
1165  void skipLast(const size_t amount = 1) {
1166  _checkSize(amount);
1167  // _position is already fine, since we are not removing from the front.
1168  _size -= amount;
1169  }
1170 
1180  void sliceToArray(DataType* const target, const size_t from, const size_t until) const {
1181  _checkRange(from, until);
1182  const size_t length = until - from;
1183  const size_t start = _internalIndex(from);
1184  const size_t numBeforeWrap = _numBeforeWrap(start, length);
1185  const size_t numAfterWrap = length - numBeforeWrap;
1186  memcpy(target, _data + start, sizeof(DataType) * numBeforeWrap);
1187  memcpy(target + numBeforeWrap, _data, sizeof(DataType) * numAfterWrap);
1188  }
1189 };
1190 
1191 template <class DataType>
1193 
1194 // Leftover friend function.
1195 
1196 template <class DataType, class VectorDequeType, class MemberType, bool IS_REVERSE>
1197 typename VectorDeque<DataType>::template IteratorBase<VectorDequeType, MemberType, IS_REVERSE> operator +
1198  (const ptrdiff_t amount, const typename VectorDeque<DataType>::template
1199  IteratorBase<VectorDequeType, MemberType, IS_REVERSE>& it) throw();
ssize_t find(const DataType &element) const
Check to see where element is located in *this.
Definition: VectorDeque.hpp:840
DataType pop()
Remove and return the first element.
Definition: VectorDeque.hpp:969
DataType removeAt(const ConstReverseIterator &it)
Remove the element pointed to by it.
Definition: VectorDeque.hpp:1095
ReverseIterator rbegin()
Get a reverse iterator pointing to the last element of *this.
Definition: VectorDeque.hpp:1041
bool operator==(const VectorDeque &that) const
Checks to see if *this is equal to another VectorDeque.
Definition: VectorDeque.hpp:613
void reverseCopyToArray(DataType *const target) const
Copy the contents of *this to the given array in reverse order.
Definition: VectorDeque.hpp:1114
DataType & operator[](const size_t index) const
Access the element at index.
Definition: VectorDeque.hpp:646
void insert(const DataType &element, const ConstReverseIterator &it)
Insert element after (with respect to *this) the element pointed to by the reverse iterator it...
Definition: VectorDeque.hpp:924
Iterator end()
Get an iterator past the last element of *this.
Definition: VectorDeque.hpp:830
size_t size() const
Returns the number of elements in *this.
Definition: VectorDeque.hpp:1141
void insert(const DataType &element, const size_t before)
Insert element before before.
Definition: VectorDeque.hpp:869
Iterator rend()
Get an iterator past the last element of *this.
Definition: VectorDeque.hpp:1105
bool operator!=(const VectorDeque &that) const
Checks to see if *this is not equal to another VectorDeque.
Definition: VectorDeque.hpp:634
VectorDeque satisfies the resource constraints typically expected of both Vectors and Deques...
Definition: VectorDeque.hpp:22
DataType popLast()
Remove and return the last element.
Definition: VectorDeque.hpp:1003
IteratorBase< VectorDeque, DataType, true > ReverseIterator
Mutable reverse iterator for VectorDeques.
Definition: VectorDeque.hpp:514
VectorDeque(VectorDeque &&that)
Temporary copy constructor.
Definition: VectorDeque.hpp:563
ConstIterator cend() const
Get an iterator past the last element of *this.
Definition: VectorDeque.hpp:776
void popAllLast(DataType *const target)
Put every element into target from the back and then remove them from *this.
Definition: VectorDeque.hpp:991
VectorDeque(const VectorDeque &that)
Non-temporary copy constructor.
Definition: VectorDeque.hpp:549
DataType peekLast() const
Get the last element of *this.
Definition: VectorDeque.hpp:957
IteratorBase< const VectorDeque, const DataType, true > ConstReverseIterator
Immutable reverse iterator for VectorDeques.
Definition: VectorDeque.hpp:519
void addFirst(const DataType &element)
Add element to the front of *this.
Definition: VectorDeque.hpp:741
DataType peek() const
Get the first element of *this.
Definition: VectorDeque.hpp:945
DataType & fromBack(const size_t index) const
Access the element at index starting from the last element.
Definition: VectorDeque.hpp:857
void popSomeLast(DataType *const target, const size_t amount)
Remove amount elements from the back and put them into target.
Definition: VectorDeque.hpp:1031
IteratorBase< const VectorDeque, const DataType, false > ConstIterator
Immutable iterator for VectorDeques.
Definition: VectorDeque.hpp:509
void addAllFirst(IteratorType begin, IteratorType end)
Add a collection of elements to the front of *this.
Definition: VectorDeque.hpp:730
VectorDeque & operator=(const VectorDeque &that)
Non-temporary assignment.
Definition: VectorDeque.hpp:577
VectorDeque()
Constructs a VectorDeque with a default initial capacity.
Definition: VectorDeque.hpp:530
void sliceToArray(DataType *const target, const size_t from, const size_t until) const
Copy a slice of elements of *this to target.
Definition: VectorDeque.hpp:1180
void addAll(IteratorType begin, IteratorType end)
Add a collection of elements to the back of *this.
Definition: VectorDeque.hpp:701
void popSome(DataType *const target, const size_t amount)
Remove amount elements and put them into target.
Definition: VectorDeque.hpp:1017
DataType removeAt(const size_t index)
Remove the element at index.
Definition: VectorDeque.hpp:1053
ConstIterator cbegin() const
Get a constant iterator pointing to the first element of *this.
Definition: VectorDeque.hpp:767
DataType removeAt(const ConstIterator &it)
Remove the element pointed to by it.
Definition: VectorDeque.hpp:1081
Iterator begin()
Get an iterator pointing to the first element of *this.
Definition: VectorDeque.hpp:758
ConstReverseIterator crend() const
Get an iterator past the last element of *this.
Definition: VectorDeque.hpp:821
IteratorBase< VectorDeque, DataType, false > Iterator
Mutable iterator for VectorDeques.
Definition: VectorDeque.hpp:504
void popAll(DataType *const target)
Put every element into target and then remove them from *this.
Definition: VectorDeque.hpp:981
void add(const DataType &element)
Add element to the back of *this.
Definition: VectorDeque.hpp:675
bool isEmpty() const
Checks whether *this is empty.
Definition: VectorDeque.hpp:934
bool contains(const DataType &element) const
Check to see if element is contained in *this.
Definition: VectorDeque.hpp:794
ConstReverseIterator crbegin() const
Get a constant reverse iterator pointing to the last element of *this.
Definition: VectorDeque.hpp:812
void skip(const size_t amount=1)
Removes amount elements from the front of *this.
Definition: VectorDeque.hpp:1152
void reverseSliceToArray(DataType *const target, const size_t from, const size_t until) const
Copy a slice of contents of *this to target in reverse order.
Definition: VectorDeque.hpp:1128
void copyToArray(DataType *const target) const
Copy the contents of *this to target.
Definition: VectorDeque.hpp:803
static const size_t DEFAULT_INITIAL_CAPACITY
The capacity to initialize a VectorDeque to by default.
Definition: VectorDeque.hpp:524
void clear()
Remove all elements from *this.
Definition: VectorDeque.hpp:784
void addAll(const DataType *const elements, const size_t length)
Add an array of elements to the back of *this.
Definition: VectorDeque.hpp:687
void insert(const DataType &element, const ConstIterator &it)
Insert element before the element pointed to by it.
Definition: VectorDeque.hpp:910
void addAllFirst(const DataType *const elements, const size_t length)
Add an array of elements to the front of *this.
Definition: VectorDeque.hpp:715
void skipLast(const size_t amount=1)
Removes amount elements from the back of *this.
Definition: VectorDeque.hpp:1165
VectorDeque(const size_t capacity)
Constructs a VectorDeque with the given initial capacity.
Definition: VectorDeque.hpp:539