Ocean
StackHeapVector.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_BASE_STACK_HEAP_VECTOR_H
9 #define META_OCEAN_BASE_STACK_HEAP_VECTOR_H
10 
11 #include "ocean/base/Base.h"
13 
14 namespace Ocean
15 {
16 
17 /**
18  * Vector like data structure combining stack and heap memory.
19  * This class implements a vector-like data structure which stores the first `tStackCapacity` elements on the stack, and any additional elements on the heap.<br>
20  * This approach can optimize performance and memory usage when the number of elements is often within the `tStackCapacity` but can occasionally exceed it.
21  * @tparam T Data type of the elements that will be stored
22  * @tparam tStackCapacity Number of elements that can be stored on the stack, with range [1, infinity)
23  * @ingroup base
24  */
25 template <typename T, size_t tStackCapacity>
27 {
28  static_assert(tStackCapacity >= 1, "Invalid stack capacity!");
29 
30  public:
31 
32  /**
33  * Definition of an iterator allowing to iterate through the vector.
34  * The iterator allows to modified the element to which the iterator is pointing.
35  */
36  class Iterator
37  {
38  friend class StackHeapVector;
39 
40  public:
41 
42  /**
43  * (Pre-) increments this iterator.
44  * @return Reference to the incremented iterator
45  */
47 
48  /**
49  * (Post-) increments this iterator.
50  * @return The current (not yet) incremented iterator.
51  */
53 
54  /**
55  * De-references the iterator and provides access to the underlying element in the vector.
56  * @return The vector element to which this iterator points
57  */
58  T& operator*();
59 
60  /**
61  * Compares two iterators and returns whether both iterators point to the same vector element.
62  * @return True, if so
63  */
64  bool operator==(const Iterator& iterator) const;
65 
66  /**
67  * Compares two iterators and returns whether both iterators do not point to the same vector element.
68  * @return True, if so
69  */
70  bool operator!=(const Iterator& iterator) const;
71 
72  protected:
73 
74  /**
75  * Creates a new iterator pointing to a specified elements in the vector.
76  * @param vector The vector owning this iterator
77  * @param index The index of the element to which the iterator points
78  */
79  Iterator(StackHeapVector& vector, const size_t index);
80 
81  protected:
82 
83  /// The vector owning this iterator.
85 
86  /// The index of the element within the vector to which the iterator points.
87  size_t index_ = size_t(-1);
88  };
89 
90  /**
91  * Definition of an iterator allowing to iterate through the vector.
92  * The iterator does ont allow to modified the element to which the iterator is pointing.
93  */
95  {
96  friend class StackHeapVector;
97 
98  public:
99 
100  /**
101  * (Pre-) increments this iterator.
102  * @return Reference to the incremented iterator
103  */
105 
106  /**
107  * (Post-) increments this iterator.
108  * @return The current (not yet) incremented iterator.
109  */
111 
112  /**
113  * De-references the iterator and provides access to the underlying element in the vector.
114  * @return The vector element to which this iterator points
115  */
116  const T& operator*() const;
117 
118  /**
119  * Compares two iterators and returns whether both iterators point to the same vector element.
120  * @return True, if so
121  */
122  bool operator==(const ConstIterator& iterator) const;
123 
124  /**
125  * Compares two iterators and returns whether both iterators do not point to the same vector element.
126  * @return True, if so
127  */
128  bool operator!=(const ConstIterator& iterator) const;
129 
130  protected:
131 
132  /**
133  * Creates a new iterator pointing to a specified elements in the vector.
134  * @param vector The vector owning this iterator
135  * @param index The index of the element to which the iterator points
136  */
137  ConstIterator(const StackHeapVector& vector, const size_t index);
138 
139  protected:
140 
141  /// The vector owning this iterator.
143 
144  /// The index of the element within the vector to which the iterator points.
145  size_t index_ = size_t(-1);
146  };
147 
148  public:
149 
150  /**
151  * Creates a new vector object.
152  */
154 
155  /**
156  * Creates a new vector object.
157  * @param size The number of elements to be created
158  * @param element The value that will be created in the first 'number' elements of this vector
159  */
160  StackHeapVector(const size_t size, const T& element);
161 
162  /**
163  * Pushes a new element to the end of this vector.
164  * @param element The new element to be pushed
165  */
166  void pushBack(T&& element);
167 
168  /**
169  * Pushes a new element to the end of this vector.
170  * @param element The new element to be pushed
171  */
172  void pushBack(const T& element);
173 
174  /**
175  * Emplaces a new element to the end of this vector.
176  * @param args The arguments of the new element
177  * @tparam TArgs The data types of the arguments
178  */
179  template <typename... TArgs>
180  T& emplaceBack(TArgs&&... args);
181 
182  /**
183  * Removed the last elements from the vector.
184  * The vector must not be empty.
185  */
186  void popBack();
187 
188  /**
189  * Resizes the vector.
190  * @param size The new size of the vector
191  */
192  void resize(const size_t size);
193 
194  /**
195  * Replaces the content of the vector with 'size' copies of the provided element.
196  * @param size The new size of the vector, with range [0, infinity)
197  * @param element The element which will be copied into all places of the resized vector
198  */
199  void assign(const size_t size, const T& element);
200 
201  /**
202  * Returns the number of elements of this vector.
203  * @return The vector's number of elements, with range [0, infinity)
204  */
205  inline size_t size() const;
206 
207  /**
208  * Returns the overall capacity of this vector (including the capacity on the stack and on the heap).
209  * @return The vector's capacity, with range [size(), infinity)
210  */
211  inline size_t capacity() const;
212 
213  /**
214  * Returns whether this vector is empty.
215  * @return True, if so
216  */
217  inline bool isEmpty() const;
218 
219  /**
220  * Clears this vector.
221  * All stack elements will be overwritten with default values.
222  */
223  void clear();
224 
225  /**
226  * Sets the capacity of this vector to a specified number of elements.
227  * In case the specified capacity is smaller than the current capacity or is smaller than the number of elements in this vector, nothing happens.
228  * @param capacity The capacity to set, with range [0, infinity)
229  */
230  void setCapacity(const size_t capacity);
231 
232  /**
233  * Returns the first element of this vector.
234  * Ensure that the vector is not empty before calling this function.
235  * @return The vector's first element
236  */
237  const T& front() const;
238 
239  /**
240  * Returns the first element of this vector.
241  * Ensure that the vector is not empty before calling this function.
242  * @return The vector's first element
243  */
244  T& front();
245 
246  /**
247  * Returns the last element of this vector.
248  * Ensure that the vector is not empty before calling this function.
249  * @return The vector's last element
250  */
251  const T& back() const;
252 
253  /**
254  * Returns the last element of this vector.
255  * Ensure that the vector is not empty before calling this function.
256  * @return The vector's last element
257  */
258  T& back();
259 
260  /**
261  * Returns an iterator to the first element in this vector.
262  * @return The vector's iterator to the first element
263  */
264  Iterator begin();
265 
266  /**
267  * Returns an iterator to the element following the last element in this vector.
268  * @return The vector's iterator to the element following the last element
269  */
270  Iterator end();
271 
272  /**
273  * Returns a const iterator to the first element in this vector.
274  * @return The vector's iterator to the first element
275  */
276  ConstIterator begin() const;
277 
278  /**
279  * Returns an iterator to the element following the last element in this vector.
280  * @return The vector's iterator to the element following the last element
281  */
282  ConstIterator end() const;
283 
284  /**
285  * Elements access operator.
286  * @param index The index of the element to access, with range [0, size() - 1]
287  * @return The element with specified index
288  */
289  inline const T& operator[](const size_t index) const;
290 
291  /**
292  * Elements access operator.
293  * @param index The index of the element to access, with range [0, size() - 1]
294  * @return The element with specified index
295  */
296  inline T& operator[](const size_t index);
297 
298  protected:
299 
300  /// The elements located on the stack.
301  T stackElements_[tStackCapacity];
302 
303  /// The remaining elements located on the heap.
304  std::vector<T> heapElements_;
305 
306  /// The number of elements in this vector.
307  size_t size_ = 0;
308 };
309 
310 template <typename T, size_t tStackCapacity>
312  vector_(vector),
313  index_(index)
314 {
315  ocean_assert(index <= vector_.size_);
316 }
317 
318 template <typename T, size_t tStackCapacity>
320 {
321  ++index_;
322 
323  return *this;
324 }
325 
326 template <typename T, size_t tStackCapacity>
328 {
329  Iterator iterator(*this);
330 
331  ++index_;
332 
333  return iterator;
334 }
335 
336 template <typename T, size_t tStackCapacity>
338 {
339  return vector_[index_];
340 }
341 
342 template <typename T, size_t tStackCapacity>
344 {
345  ocean_assert(&vector_ == &iterator.vector_);
346 
347  return &vector_ == &iterator.vector_ && index_ == iterator.index_;
348 }
349 
350 template <typename T, size_t tStackCapacity>
352 {
353  return !(*this == iterator);
354 }
355 
356 template <typename T, size_t tStackCapacity>
358  vector_(vector),
359  index_(index)
360 {
361  ocean_assert(index <= vector_.size_);
362 }
363 
364 template <typename T, size_t tStackCapacity>
366 {
367  ++index_;
368 
369  return *this;
370 }
371 
372 template <typename T, size_t tStackCapacity>
374 {
375  Iterator iterator(*this);
376 
377  ++index_;
378 
379  return iterator;
380 }
381 
382 template <typename T, size_t tStackCapacity>
384 {
385  return vector_[index_];
386 }
387 
388 template <typename T, size_t tStackCapacity>
390 {
391  ocean_assert(&vector_ == &iterator.vector_);
392 
393  return &vector_ == &iterator.vector_ && index_ == iterator.index_;
394 }
395 
396 template <typename T, size_t tStackCapacity>
398 {
399  return !(*this == iterator);
400 }
401 
402 template <typename T, size_t tStackCapacity>
404 {
405  // nothing to do here
406 }
407 
408 template <typename T, size_t tStackCapacity>
410 {
411  setCapacity(size);
412 
413  for (size_t n = 0; n < size; ++n)
414  {
415  pushBack(element);
416  }
417 }
418 
419 template <typename T, size_t tStackCapacity>
421 {
422  if (size_ < tStackCapacity)
423  {
424  stackElements_[size_] = std::move(element);
425  }
426  else
427  {
428  heapElements_.emplace_back(std::move(element));
429  }
430 
431  ++size_;
432 }
433 
434 template <typename T, size_t tStackCapacity>
436 {
437  if (size_ < tStackCapacity)
438  {
439  stackElements_[size_] = element;
440  }
441  else
442  {
443  heapElements_.push_back(element);
444  }
445 
446  ++size_;
447 }
448 
449 template <typename T, size_t tStackCapacity>
450 template <typename... TArgs>
452 {
453  const size_t index = size_;
454 
455  ++size_;
456 
457  if (index < tStackCapacity)
458  {
459  stackElements_[index] = T(std::forward<TArgs>(args)...);
460 
461  return stackElements_[index];
462  }
463  else
464  {
465  return heapElements_.emplace_back(std::forward<TArgs>(args)...);
466  }
467 }
468 
469 template <typename T, size_t tStackCapacity>
471 {
472  ocean_assert(size_ >= 1);
473 
474  --size_;
475 
476  if (size_ >= tStackCapacity)
477  {
478  heapElements_.pop_back();
479  }
480  else
481  {
482  stackElements_[size_] = T();
483  }
484 }
485 
486 template <typename T, size_t tStackCapacity>
488 {
489  if (size == size_)
490  {
491  return;
492  }
493 
494  if (size < size_)
495  {
496  // we have to remove elements
497 
498  for (size_t n = size; n < tStackCapacity; ++n) // in case size >= tStackCapacity, nothing happens
499  {
500  stackElements_[n] = T();
501  }
502 
503  if (size_ > tStackCapacity)
504  {
505  if (size < tStackCapacity)
506  {
507  heapElements_.clear();
508  }
509  else
510  {
511  heapElements_.resize(size - tStackCapacity);
512  }
513  }
514  }
515  else
516  {
517  ocean_assert(size > size_);
518 
519  if (size > tStackCapacity)
520  {
521  heapElements_.resize(size - tStackCapacity);
522  }
523  }
524 
525  size_ = size;
526 }
527 
528 template <typename T, size_t tStackCapacity>
529 void StackHeapVector<T, tStackCapacity>::assign(const size_t size, const T& element)
530 {
531  for (size_t n = 0; n < std::min(size, tStackCapacity); ++n) // we assign as many elements in the stack
532  {
533  stackElements_[n] = element;
534  }
535 
536  for (size_t n = size; n < std::min(tStackCapacity, size_); ++n) // if necessary (if the new size is smaller than the previous size), we overwrite stack elements with default values
537  {
538  stackElements_[n] = T();
539  }
540 
541  if (size < tStackCapacity)
542  {
543  heapElements_.clear();
544  }
545  else
546  {
547  const size_t newHeapSize = size - tStackCapacity;
548 
549  heapElements_.assign(newHeapSize, element);
550  }
551 
552  size_ = size;
553 }
554 
555 template <typename T, size_t tStackCapacity>
557 {
558  ocean_assert(size_ <= tStackCapacity || size_ == tStackCapacity + heapElements_.size());
559 
560  return size_;
561 }
562 
563 template <typename T, size_t tStackCapacity>
565 {
566  return tStackCapacity + heapElements_.capacity();
567 }
568 
569 template <typename T, size_t tStackCapacity>
571 {
572  return size() == 0;
573 }
574 
575 template <typename T, size_t tStackCapacity>
577 {
578  for (size_t nStack = 0; nStack < std::min(size_, tStackCapacity); ++nStack)
579  {
580  stackElements_[nStack] = T();
581  }
582 
583  heapElements_.clear();
584 
585  size_ = 0;
586 }
587 
588 template <typename T, size_t tStackCapacity>
590 {
591  if (capacity > size_)
592  {
593  if (capacity > tStackCapacity)
594  {
595  heapElements_.reserve(capacity - tStackCapacity);
596  }
597  }
598 }
599 
600 template <typename T, size_t tStackCapacity>
602 {
603  ocean_assert(!isEmpty());
604 
605  return stackElements_[0];
606 }
607 
608 template <typename T, size_t tStackCapacity>
610 {
611  ocean_assert(!isEmpty());
612 
613  return stackElements_[0];
614 }
615 
616 template <typename T, size_t tStackCapacity>
618 {
619  ocean_assert(!isEmpty());
620 
621  if (size_ <= tStackCapacity)
622  {
623  return stackElements_[size_ - 1];
624  }
625  else
626  {
627  return heapElements_.back();
628  }
629 }
630 
631 template <typename T, size_t tStackCapacity>
633 {
634  ocean_assert(!isEmpty());
635 
636  if (size_ <= tStackCapacity)
637  {
638  return stackElements_[size_ - 1];
639  }
640  else
641  {
642  return heapElements_.back();
643  }
644 }
645 
646 template <typename T, size_t tStackCapacity>
648 {
649  return Iterator(*this, 0);
650 }
651 
652 template <typename T, size_t tStackCapacity>
654 {
655  return Iterator(*this, size_);
656 }
657 
658 template <typename T, size_t tStackCapacity>
660 {
661  return ConstIterator(*this, 0);
662 }
663 
664 template <typename T, size_t tStackCapacity>
666 {
667  return ConstIterator(*this, size_);
668 }
669 
670 template <typename T, size_t tStackCapacity>
671 inline const T& StackHeapVector<T, tStackCapacity>::operator[](const size_t index) const
672 {
673  ocean_assert(index < size());
674 
675  if (index < tStackCapacity)
676  {
677  return stackElements_[index];
678  }
679 
680  return heapElements_[index - tStackCapacity];
681 }
682 
683 template <typename T, size_t tStackCapacity>
685 {
686  ocean_assert(index < size());
687 
688  if (index < tStackCapacity)
689  {
690  return stackElements_[index];
691  }
692 
693  return heapElements_[index - tStackCapacity];
694 }
695 
696 }
697 
698 #endif // META_OCEAN_BASE_STACK_HEAP_VECTOR_H
Definition of an iterator allowing to iterate through the vector.
Definition: StackHeapVector.h:95
const StackHeapVector & vector_
The vector owning this iterator.
Definition: StackHeapVector.h:142
ConstIterator(const StackHeapVector &vector, const size_t index)
Creates a new iterator pointing to a specified elements in the vector.
Definition: StackHeapVector.h:357
bool operator==(const ConstIterator &iterator) const
Compares two iterators and returns whether both iterators point to the same vector element.
Definition: StackHeapVector.h:389
size_t index_
The index of the element within the vector to which the iterator points.
Definition: StackHeapVector.h:145
bool operator!=(const ConstIterator &iterator) const
Compares two iterators and returns whether both iterators do not point to the same vector element.
Definition: StackHeapVector.h:397
const T & operator*() const
De-references the iterator and provides access to the underlying element in the vector.
Definition: StackHeapVector.h:383
ConstIterator & operator++()
(Pre-) increments this iterator.
Definition: StackHeapVector.h:365
Definition of an iterator allowing to iterate through the vector.
Definition: StackHeapVector.h:37
size_t index_
The index of the element within the vector to which the iterator points.
Definition: StackHeapVector.h:87
bool operator==(const Iterator &iterator) const
Compares two iterators and returns whether both iterators point to the same vector element.
Definition: StackHeapVector.h:343
bool operator!=(const Iterator &iterator) const
Compares two iterators and returns whether both iterators do not point to the same vector element.
Definition: StackHeapVector.h:351
Iterator(StackHeapVector &vector, const size_t index)
Creates a new iterator pointing to a specified elements in the vector.
Definition: StackHeapVector.h:311
StackHeapVector & vector_
The vector owning this iterator.
Definition: StackHeapVector.h:84
T & operator*()
De-references the iterator and provides access to the underlying element in the vector.
Definition: StackHeapVector.h:337
Iterator & operator++()
(Pre-) increments this iterator.
Definition: StackHeapVector.h:319
Vector like data structure combining stack and heap memory.
Definition: StackHeapVector.h:27
size_t size_
The number of elements in this vector.
Definition: StackHeapVector.h:307
StackHeapVector(const size_t size, const T &element)
Creates a new vector object.
Definition: StackHeapVector.h:409
Iterator begin()
Returns an iterator to the first element in this vector.
Definition: StackHeapVector.h:647
void setCapacity(const size_t capacity)
Sets the capacity of this vector to a specified number of elements.
Definition: StackHeapVector.h:589
std::vector< T > heapElements_
The remaining elements located on the heap.
Definition: StackHeapVector.h:304
StackHeapVector()
Creates a new vector object.
Definition: StackHeapVector.h:403
const T & operator[](const size_t index) const
Elements access operator.
Definition: StackHeapVector.h:671
T stackElements_[tStackCapacity]
The elements located on the stack.
Definition: StackHeapVector.h:301
void assign(const size_t size, const T &element)
Replaces the content of the vector with 'size' copies of the provided element.
Definition: StackHeapVector.h:529
const T & back() const
Returns the last element of this vector.
Definition: StackHeapVector.h:617
T & emplaceBack(TArgs &&... args)
Emplaces a new element to the end of this vector.
Definition: StackHeapVector.h:451
Iterator end()
Returns an iterator to the element following the last element in this vector.
Definition: StackHeapVector.h:653
size_t capacity() const
Returns the overall capacity of this vector (including the capacity on the stack and on the heap).
Definition: StackHeapVector.h:564
const T & front() const
Returns the first element of this vector.
Definition: StackHeapVector.h:601
void pushBack(T &&element)
Pushes a new element to the end of this vector.
Definition: StackHeapVector.h:420
void resize(const size_t size)
Resizes the vector.
Definition: StackHeapVector.h:487
ConstIterator begin() const
Returns a const iterator to the first element in this vector.
Definition: StackHeapVector.h:659
T & operator[](const size_t index)
Elements access operator.
Definition: StackHeapVector.h:684
void clear()
Clears this vector.
Definition: StackHeapVector.h:576
T & back()
Returns the last element of this vector.
Definition: StackHeapVector.h:632
T & front()
Returns the first element of this vector.
Definition: StackHeapVector.h:609
ConstIterator end() const
Returns an iterator to the element following the last element in this vector.
Definition: StackHeapVector.h:665
void pushBack(const T &element)
Pushes a new element to the end of this vector.
Definition: StackHeapVector.h:435
bool isEmpty() const
Returns whether this vector is empty.
Definition: StackHeapVector.h:570
void popBack()
Removed the last elements from the vector.
Definition: StackHeapVector.h:470
size_t size() const
Returns the number of elements of this vector.
Definition: StackHeapVector.h:556
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15