orbtree
vector_realloc.h
1 /* -*- C++ -*-
2  * vector_realloc.h
3  *
4  * Copyright 2018,2020 Daniel Kondor <kondor.dani@gmail.com>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of the nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  *
33  */
34 
72 #ifndef VECTOR_REALLOC_H
73 #define VECTOR_REALLOC_H
74 
75 #include <limits>
76 #include <new>
77 #include <stdexcept>
78 #include <type_traits>
79 #include <stdlib.h>
80 #include <string.h>
81 
82 
83 /* constexpr if support only for c++17 or newer */
84 #if __cplusplus >= 201703L
85 #define CONSTEXPR constexpr
86 #else
87 #define CONSTEXPR
88 #endif
89 
90 
91 namespace realloc_vector {
92 
94  template<class It>
96  constexpr static bool value =
97  std::is_same< typename std::iterator_traits<It>::iterator_category, typename std::forward_iterator_tag >::value ||
98  std::is_same< typename std::iterator_traits<It>::iterator_category, typename std::bidirectional_iterator_tag >::value ||
99  std::is_same< typename std::iterator_traits<It>::iterator_category, typename std::random_access_iterator_tag >::value
100 #if __cplusplus >= 202000L
101  || std::is_same< typename std::iterator_traits<It>::iterator_category, typename std::contiguous_iterator_tag >::value
102 #endif
103  ;
104  };
106  template<class It>
108  constexpr static bool value = at_least_forward_iterator<It>::value ||
109  std::is_same< typename std::iterator_traits<It>::iterator_category, typename std::input_iterator_tag >::value;
110  };
111 
112 
113 
114 template <class T>
115 class vector {
116  protected:
117  /* This requirement is too strict; what we actually want is trivially moveable,
118  * i.e. a type that can be moved with memmove(), but the copy constructor could
119  * be nontrivial.
120  * For such types, this assertation will need to be deleted, but this might also
121  * result in undefined behavior depending on the compiler */
122  static_assert(std::is_trivially_copyable<T>::value,"Element type must be trivially copyable for realloc_vector::vector!\n");
123 
124  T* start;
125  size_t p_size;
126  size_t p_capacity;
127  size_t max_grow;
128  static constexpr size_t p_max_capacity = std::numeric_limits<size_t>::max() / sizeof(T);
130 
132  bool change_size(size_t new_size) {
133  T* tmp = (T*)realloc(start,new_size*sizeof(T));
134  if(!tmp) return false;
135  start = tmp;
136  p_capacity = new_size;
137  return true;
138  }
142  bool grow_vector(size_t minimum_size = 0) {
143  if(minimum_size > p_max_capacity) return false;
144  size_t grow_capacity = p_capacity;
145  if(!grow_capacity) grow_capacity = 1;
146  if(grow_capacity > max_grow) grow_capacity = max_grow;
147  if(grow_capacity > p_max_capacity) grow_capacity = p_max_capacity;
148  if(p_max_capacity - grow_capacity < p_capacity) grow_capacity = p_max_capacity - p_capacity;
149  if(!grow_capacity) return false;
150  size_t new_size = p_capacity + grow_capacity;
151  if(new_size < minimum_size) new_size = minimum_size;
152  return change_size(new_size);
153  }
154 
155 
156  public:
157  /* types */
158  typedef T value_type;
159  typedef size_t size_type;
160  typedef ssize_t difference_type;
161  typedef T& reference;
162  typedef const T& const_reference;
163  typedef T* pointer;
164  typedef const T* const_pointer;
165 
166  /* Constructors */
167 
169  vector() noexcept : start(nullptr),p_size(0),p_capacity(0),max_grow(131072) { }
171  explicit vector(size_t count, const T& value = T(), size_t max_grow_ = 131072);
173  template<class It, typename std::enable_if<at_least_input_iterator<It>::value, int>::type = 0>
174  vector(It first, It last, size_t max_grow_ = 131072);
176  vector(const vector& v);
177  vector(vector&& v);
178  /* 5. assignment */
179  vector& operator = (const vector& v);
180  vector& operator = (vector&& v);
181  /* 6. swap */
182  void swap(vector& v);
183 
184  /* Destructor */
185  ~vector() {
186  /* call destructors of existing elements -- these are not allowed to throw an exception! */
187  if(p_size) resize(0);
188  if(start) free(start);
189  }
190 
191 
192  /* Basic access to members */
193 
195  size_t size() const { return p_size; }
197  size_t capacity() const { return p_capacity; }
199  size_t max_size() const { return p_max_capacity; }
201  size_t max_capacity() const { return p_max_capacity; }
203  bool empty() const { return p_size == 0; }
205  size_t get_max_grow() const { return max_grow; }
207  void set_max_grow(size_t max_grow_) {
208  if(max_grow_ == 0) max_grow = 131072;
209  else max_grow = max_grow_;
210  }
211 
212 
213  /* data access functions
214  * similarly to std::vector, only at() checks bounds, all other versions
215  * result in undefined behavior if an out of bounds is attempted */
217  T* data() { return start; }
219  const T* data() const { return start; }
220 
222  T& operator[](size_t i) { return start[i]; }
224  const T& operator[](size_t i) const { return start[i]; }
226  T& at(size_t i) { if(i < p_size) return start[i]; throw std::out_of_range("vector::at(): index out of range!\n"); }
228  const T& at(size_t i) const { if(i < p_size) return start[i]; throw std::out_of_range("vector::at(): index out of range!\n"); }
230  T& front() { return start[0]; }
232  const T& front() const { return start[0]; }
234  T& back() { return start[p_size - 1]; }
236  const T& back() const { return start[p_size - 1]; }
237 
238  /* reserve memory */
240  bool reserve_nothrow(size_t n);
242  void reserve(size_t n) { if(!reserve_nothrow(n)) throw std::bad_alloc(); }
244  void shrink_to_fit(size_t new_capacity = 0);
245 
246  /* insert /create elements at the end of the vector
247  * versions that throw an exception if out of memory */
249  void push_back(const T& x);
251  void push_back(T&& x);
253  template<class... Args> T& emplace_back(Args&&... args);
254  /* versions that return false if out of memory -- note: any exceptions
255  * from T's (copy / move) constructor are propagated, i.e. still can
256  * throw an exception if those throw */
258  bool push_back_nothrow(const T& x);
260  bool push_back_nothrow(T&& x);
262  template<class... Args> bool emplace_back_nothrow(Args&&... args);
263 
264  /* remove elements -- T's destructor should not throw exception! */
266  void clear() { while(p_size) start[--p_size].~T(); }
268  void pop_back() { if(p_size) start[--p_size].~T(); }
269 
272  bool resize_nothrow(size_t count);
275  bool resize_nothrow(size_t count, const T& x);
278  void resize(size_t count) { if(!resize_nothrow(count)) throw std::bad_alloc(); }
281  void resize(size_t count, const T& x) { if(!resize_nothrow(count,x)) throw std::bad_alloc(); }
282 
284  typedef T* iterator;
286  typedef const T* const_iterator;
287 
288  protected:
289  bool insert_helper(size_t pos, size_t new_pos);
290 
291  public:
292  iterator begin() { return iterator(start); }
293  const_iterator begin() const { return const_iterator(start); }
294  const_iterator cbegin() const { return const_iterator(start); }
295  iterator end() { return iterator(start + p_size); }
296  const_iterator end() const { return const_iterator(start + p_size); }
297  const_iterator cend() const { return const_iterator(start + p_size); }
298 
299  iterator erase(const_iterator pos);
300  iterator erase(const_iterator first, const_iterator last);
301 
302  /* inserts that do not throw exception when out of memory,
303  * instead they return whether the insert was successful
304  * the res iterator is updated to point to the inserted element
305  * if the insert is successful, otherwise it is not changed */
306 
311  bool insert_nothrow(const_iterator pos, iterator& res, const T& x);
316  bool insert_nothrow(const_iterator pos, iterator& res, T&& x);
321  bool insert_nothrow(const_iterator pos, iterator& res, size_t count, const T& x);
326  template<class InputIt, typename std::enable_if<at_least_input_iterator<InputIt>::value, int>::type = 0>
327  bool insert_nothrow(const_iterator pos, iterator& res, InputIt first, InputIt last);
328 
330  iterator insert(const_iterator pos, const T& x) {
331  iterator res;
332  if(insert_nothrow(pos,res,x)) return res;
333  else throw std::bad_alloc();
334  }
336  iterator insert(const_iterator pos, T&& x) {
337  iterator res;
338  if(insert_nothrow(pos,res,std::forward<T>(x))) return res;
339  else throw std::bad_alloc();
340  }
342  iterator insert(const_iterator pos, size_t count, const T& x) {
343  iterator res;
344  if(insert_nothrow(pos,res,count,x)) return res;
345  else throw std::bad_alloc();
346  }
348  template<class InputIt, typename std::enable_if<at_least_input_iterator<InputIt>::value, int>::type = 0>
349  iterator insert(const_iterator pos, InputIt first, InputIt last) {
350  iterator res;
351  if(insert_nothrow(pos,res,first,last)) return res;
352  else throw std::bad_alloc();
353  }
354 };
355 
356 
357 
358 
359 /* Constructors */
360 template<class T>
361 vector<T>::vector(size_t count, const T& value, size_t max_grow_) :
362  start(nullptr),p_size(0),p_capacity(0),max_grow(max_grow_) {
363  reserve(count);
364  if CONSTEXPR(std::is_nothrow_constructible<T>::value) {
365  p_size = count;
366  for(size_t i = 0; i<count; i++) new(start + i) T(value);
367  }
368  else for(;p_size < count; ++p_size) new(start + p_size) T(value);
369 }
370 
371 template<class T> template<class It, typename std::enable_if< at_least_input_iterator<It>::value, int>::type >
372 vector<T>::vector(It first, It last, size_t max_grow_) :
373  start(nullptr),p_size(0),p_capacity(0),max_grow(max_grow_) {
374  for(; first != last; ++first) push_back(*first);
375 }
376 
377 template<class T>
378 vector<T>::vector(const vector<T>& v) : start(nullptr), p_size(0), p_capacity(0), max_grow(v.max_grow) {
379  reserve(v.size());
380  memcpy(start, v.start, sizeof(T)*(v.size()));
381  p_size = v.size();
382 }
383 
384 template<class T>
385 void vector<T>::swap(vector<T>& v) {
386  using std::swap;
387  swap(start, v.start);
388  swap(p_size, v.p_size);
389  swap(p_capacity, v.p_capacity);
390  swap(max_grow, v.max_grow);
391 }
392 
393 template<class T>
394 vector<T>::vector(vector<T>&& v) : start(nullptr), p_size(0), p_capacity(0), max_grow(v.max_grow) {
395  swap(v);
396 }
397 
398 template<class T>
400  resize(0);
401  reserve(v.size());
402  memcpy(start, v.start, sizeof(T)*(v.size()));
403  p_size = v.size();
404  return *this;
405 }
406 
407 template<class T>
409  resize(0);
410  if(start) free(start);
411  start = nullptr;
412  swap(v);
413 }
414 
415 template<class T>
417  if(n > p_max_capacity) return false;
418  if(n <= p_capacity) return true;
419  return change_size(n);
420 }
421 
422 template<class T>
423 void vector<T>::shrink_to_fit(size_t new_capacity) {
424  if(new_capacity < p_size) new_capacity = p_size;
425  if(new_capacity > p_capacity) return;
426  if(!change_size(new_capacity)) throw std::bad_alloc(); /* this should not happen, shrinking memory should always succeed */
427 }
428 
429 
430 
431 /* insert /create elements at the end of the vector */
432 template<class T>
433 void vector<T>::push_back(const T& x) {
434  if(!push_back_nothrow(x)) throw std::bad_alloc();
435 }
436 template<class T>
437 void vector<T>::push_back(T&& x) {
438  if(!push_back_nothrow(std::forward<T>(x))) throw std::bad_alloc();
439 }
440 template<class T> template<class... Args>
441 T& vector<T>::emplace_back(Args&&... args) {
442  if(!emplace_back_nothrow(std::forward<Args>(args)...)) throw std::bad_alloc();
443  return back();
444 }
445 template<class T>
447  if(p_size == p_capacity) if(!grow_vector()) return false;
448  new(start + p_size) T(x); /* copy constructor -- might still throw an exception */
449  p_size++;
450  return true;
451 }
452 template<class T>
454  if(p_size == p_capacity) if(!grow_vector()) return false;
455  new(start + p_size) T(std::forward<T>(x)); /* move constructor -- might throw an exception */
456  p_size++;
457  return true;
458 }
459 template<class T> template<class... Args>
460 bool vector<T>::emplace_back_nothrow(Args&&... args) {
461  if(p_size == p_capacity) if(!grow_vector()) return false;
462  new(start + p_size) T(std::forward<Args>(args)...); /* constructor -- might throw an exception */
463  p_size++;
464  return true;
465 }
466 
467 
468 
469 template<class T>
470 bool vector<T>::resize_nothrow(size_t count) {
471  if(count == p_size) return true;
472  if(!count) { clear(); return true; }
473  if(count < p_size) {
474  do { pop_back(); } while(p_size > count);
475  return true;
476  }
477  /* here count > p_size */
478  if(count > p_capacity) if(!grow_vector(count)) return false;
479  if CONSTEXPR(std::is_nothrow_constructible<T>::value) {
480  for(size_t i = p_size; i<count; i++) new(start + i) T();
481  p_size = count;
482  }
483  else for(; p_size < count; p_size++) new(start + p_size) T();
484  return true;
485 }
486 template<class T>
487 bool vector<T>::resize_nothrow(size_t count, const T& x) {
488  if(count == p_size) return true;
489  if(!count) { clear(); return true; }
490  if(count < p_size) {
491  do { pop_back(); } while(p_size > count);
492  return true;
493  }
494  /* here count > p_size */
495  if(count > p_capacity) if(!grow_vector(count)) return false;
496  if CONSTEXPR(std::is_nothrow_copy_constructible<T>::value) {
497  for(size_t i = p_size; i<count; i++) new(start + i) T(x);
498  p_size = count;
499  }
500  else for(; p_size < count; p_size++) new(start + p_size) T(x);
501  return true;
502 }
503 
504 
505 template<class T>
507  size_t p2 = pos - start;
508  if(p2 >= p_size) throw std::out_of_range("vector::erase(): iterator out of bounds!\n");
509 
510  size_t remaining = (p_size - p2) - 1;
511  start[p2].~T();
512  if(remaining) memmove(start + p2, start + p2 + 1, remaining*sizeof(T));
513  p_size--;
514  return iterator(start + p2);
515 }
516 template<class T>
518  ssize_t dist = last - first;
519  if(!dist) return iterator(first);
520 
521  size_t p2 = first.data - start;
522  size_t p3 = last.data - start;
523  if(p2 >= p_size || p3 > p_size) throw std::out_of_range("vector::erase(): iterator out of bounds!\n");
524  for(size_t i = p2; i < p3; i++) start[i].~T();
525 
526  size_t remaining = (p_size - p3) - 1;
527  if(remaining) memmove(start + p2, start + p3, remaining*sizeof(T));
528  p_size -= (p3 - p2);
529  return iterator(start + p2);
530 }
531 
532 
533 
534 /* move elements to new position from given position */
535 template<class T>
536 bool vector<T>::insert_helper(size_t pos, size_t new_pos) {
537  if(new_pos > pos) {
538  size_t diff = new_pos - pos;
539  if(p_size > p_max_capacity - diff || !reserve_nothrow(p_size + diff)) return false;
540  }
541  size_t remaining = p_size - pos;
542  memmove(start + new_pos, start + pos, remaining*sizeof(T));
543  return true;
544 }
545 
546 
547 
548 template<class T>
550  if(pos == cend()) return push_back_nothrow(x);
551  size_t p2 = pos - start;
552  if(!insert_helper(p2,p2+1)) return false;
553  if CONSTEXPR(std::is_nothrow_copy_constructible<T>::value) new(start + p2) T(x);
554  else {
555  /* provide fallback if copy throws -- note: this is not possible for trivially
556  * copyable types, but this vector class will work if type is trivially moveable
557  * only that is a weaker criterion, but is not provided by the type_traits library */
558  try { new(start + p2) T(x); }
559  catch(...) {
560  insert_helper(p2+1,p2);
561  throw;
562  }
563  }
564  p_size++;
565  res = vector<T>::iterator(start + p2);
566  return true;
567 }
568 
569 template<class T>
571  if(pos == cend()) return push_back_nothrow(std::forward<T>(x));
572  size_t p2 = pos - start;
573  if(!insert_helper(p2,p2+1)) return false;
574  /* note: move constructor of T should never throw an exception */
575  new(start + p2) T(std::forward<T>(x));
576  p_size++;
577  res = vector<T>::iterator(start + p2);
578  return true;
579 }
580 
581 
582 template<class T>
583 bool vector<T>::insert_nothrow(vector<T>::const_iterator pos, vector<T>::iterator& res, size_t count, const T& x) {
584  size_t p2 = pos - start;
585  if(pos == cend()) {
586  if(!resize_nothrow(p_size + count, x)) return false;
587  res = vector<T>::iterator(start + p2);
588  return true;
589  }
590 
591  if(!insert_helper(p2,p2+count)) return false;
592  if CONSTEXPR(std::is_nothrow_copy_constructible<T>::value) for(size_t i = 0; i < count; i++) new(start + p2 + i) T(x);
593  else {
594  /* provide fallback if copy throws -- note: this is not possible for trivially
595  * copyable types, but this vector class will work if type is trivially moveable
596  * only that is a weaker criterion, but is not provided by the type_traits library */
597  size_t i = 0;
598  try {
599  for(; i < count; i++) new(start + p2 + i) T(x);
600  }
601  catch(...) {
602  /* ensure that in the case of an exception, this class
603  * is left in a well-defined state */
604  while(i) {
605  i--;
606  start[p2 + i].~T();
607  }
608  insert_helper(p2+count,p2);
609  throw;
610  }
611  }
612  p_size += count;
613  res = vector<T>::iterator(start + p2);
614  return true;
615 }
616 
617 
618 template<class T> template<class InputIt,
619  typename std::enable_if<at_least_input_iterator<InputIt>::value, int>::type >
620 bool vector<T>::insert_nothrow(vector<T>::const_iterator pos, vector<T>::iterator& res, InputIt first, InputIt last) {
621  size_t p2 = pos - start;
622  if(first != last) {
624  ssize_t dist = std::distance(first,last);
625  if(dist < 0) return false;
626 
627  if(pos == cend()) {
628  if(!reserve_nothrow(p_size + dist)) return false;
629  for(; first != last; ++first) push_back(*first);
630  res = vector<T>::iterator(start + p2);
631  return true;
632  }
633 
634  if(!insert_helper(p2,p2+dist)) return false;
635  if CONSTEXPR(std::is_nothrow_copy_constructible<T>::value) {
636  size_t p3 = p2;
637  for(; first != last; ++first, p3++) new(start + p3) T(*first);
638  }
639  else {
640  /* provide fallback if copy throws -- note: this is not possible for trivially
641  * copyable types, but this vector class will work if type is trivially moveable
642  * only that is a weaker criterion, but is not provided by the type_traits library */
643  size_t p3 = p2;
644  try {
645  for(; first != last; ++first, p3++) new(start + p3) T(*first);
646  }
647  catch(...) {
648  while(p3 > p2) {
649  p3--;
650  start[p3].~T();
651  }
652  insert_helper(p2+dist,p2);
653  throw;
654  }
655  }
656  p_size += dist;
657  }
658  else {
659  for(size_t p3 = p2;first != last; ++first, p3++)
660  if(!insert_nothrow(vector<T>::iterator(start + p3),res,*first)) return false;
661  }
662  }
663  res = vector<T>::iterator(start + p2);
664  return true;
665 }
666 
667 
668 
669 } // namespace realloc_vector
670 
671 #undef CONSTEXPR
672 
673 #endif
674 
size_t max_grow
grow memory by maximum this many elements at a time
Definition: vector_realloc.h:127
helper to distinguish iterators
Definition: vector_realloc.h:95
bool empty() const
Returns true if the vector is empty.
Definition: vector_realloc.h:203
const T & at(size_t i) const
Access the ith element with bounds checking, throws an exception if i >= size()
Definition: vector_realloc.h:228
const_iterator cend() const
Iterator to the end.
Definition: vector_realloc.h:297
size_t p_size
number of elements in vector
Definition: vector_realloc.h:125
T * data()
Access the underlying array.
Definition: vector_realloc.h:217
iterator insert(const_iterator pos, T &&x)
Inserts x at pos. Can throw an exception if out of memory.
Definition: vector_realloc.h:336
T & back()
Access the last element. It is undefined behavior if this function is called on an empty vector...
Definition: vector_realloc.h:234
T * iterator
Iterators are simple pointers to the data.
Definition: vector_realloc.h:284
void pop_back()
Removes the last element; does not free up memory, use shrink_to_fit() for that.
Definition: vector_realloc.h:268
const T * data() const
Access the underlying array.
Definition: vector_realloc.h:219
size_t get_max_grow() const
Get the maximum growth size. Memory is grown by this amount maximally.
Definition: vector_realloc.h:205
T * start
pointer to elements
Definition: vector_realloc.h:122
size_t p_capacity
current capacity of vector
Definition: vector_realloc.h:126
void resize(size_t count, const T &x)
Resize vector. If new size is larger than current size, new elements are inserted as copies of x...
Definition: vector_realloc.h:281
const T * const_iterator
Iterators are simple pointers to the data.
Definition: vector_realloc.h:286
iterator insert(const_iterator pos, const T &x)
Inserts a copy of x at pos. Can throw an exception if out of memory.
Definition: vector_realloc.h:330
iterator begin()
Iterator to the beginning.
Definition: vector_realloc.h:292
void reserve(size_t n)
Reserve memory for at least n elements. Throws an exception if memory allocation is not successful...
Definition: vector_realloc.h:242
bool grow_vector(size_t minimum_size=0)
Attempt to grow vector either to the given minimum size or by doubling the current size unless growth...
Definition: vector_realloc.h:142
T & front()
Access the first element. It is undefined behavior if this function is called on an empty vector...
Definition: vector_realloc.h:230
bool change_size(size_t new_size)
Reallocate memory to the given new size.
Definition: vector_realloc.h:132
helper to distinguish iterators
Definition: vector_realloc.h:107
const T & front() const
Access the first element. It is undefined behavior if this function is called on an empty vector...
Definition: vector_realloc.h:232
iterator insert(const_iterator pos, size_t count, const T &x)
Inserts count copies of x at pos. Can throw an exception if out of memory.
Definition: vector_realloc.h:342
vector() noexcept
default constructor, creates empty vector, maximum growth is 128k elements
Definition: vector_realloc.h:169
const_iterator cbegin() const
Iterator to the beginning.
Definition: vector_realloc.h:294
size_t size() const
Current size, i.e. the number of elements stored in this vector.
Definition: vector_realloc.h:195
T & operator[](size_t i)
Access the ith element. It is undefined behavior to if i >= size()
Definition: vector_realloc.h:222
const T & back() const
Access the last element. It is undefined behavior if this function is called on an empty vector...
Definition: vector_realloc.h:236
const T & operator[](size_t i) const
Access the ith element. It is undefined behavior to if i >= size()
Definition: vector_realloc.h:224
iterator end()
Iterator to the end.
Definition: vector_realloc.h:295
size_t max_size() const
Maximum size to avoid overflow when calculating memory size.
Definition: vector_realloc.h:199
void set_max_grow(size_t max_grow_)
Set the maximum growth size. Memory is grown by this amount maximally.
Definition: vector_realloc.h:207
const_iterator end() const
Iterator to the end.
Definition: vector_realloc.h:296
Definition: vector_realloc.h:91
const_iterator begin() const
Iterator to the beginning.
Definition: vector_realloc.h:293
C++ vector-like container for trivially moveable types, using realloc() for growing memory...
Definition: vector_realloc.h:115
size_t capacity() const
Current capacity, i.e. the number of elements that can be stored without allocating more memory...
Definition: vector_realloc.h:197
void clear()
Removes all elements; does not free up memory, use shrink_to_fit() for that.
Definition: vector_realloc.h:266
iterator insert(const_iterator pos, InputIt first, InputIt last)
Inserts the elements in the range [first,last) at pos. Can throw an exception if out of memory...
Definition: vector_realloc.h:349
void resize(size_t count)
Resize vector. If new size is larger than current size, new elements are default constructed. Can throw an exception on memory allocation error.
Definition: vector_realloc.h:278
size_t max_capacity() const
Maximum capacity to avoid overflow when calculating memory size.
Definition: vector_realloc.h:201
T & at(size_t i)
Access the ith element with bounds checking, throws an exception if i >= size()
Definition: vector_realloc.h:226