Ocean
Loading...
Searching...
No Matches
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
14namespace 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 */
25template <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 */
37 {
38 friend class StackHeapVector;
39
40 public:
41
42 /**
43 * (Pre-) increments this iterator.
44 * @return Reference to the incremented iterator
45 */
46 Iterator& operator++();
47
48 /**
49 * (Post-) increments this iterator.
50 * @return The current (not yet) incremented iterator.
51 */
52 Iterator operator++(int);
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 */
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 */
104 ConstIterator& operator++();
105
106 /**
107 * (Post-) increments this iterator.
108 * @return The current (not yet) incremented iterator.
109 */
110 ConstIterator operator++(int);
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 * Creates a new vector object and moves the elements to this vector.
164 * @param elements The elements to be moved
165 */
166 StackHeapVector(std::vector<T>&& elements);
167
168 /**
169 * Creates a new vector object and copies the elements to this vector.
170 * @param elements The elements to be copied
171 */
172 StackHeapVector(const std::vector<T>& elements);
173
174 /**
175 * Creates a new vector object and copies the elements to this vector.
176 * @param elements The elements to be copied
177 */
178 StackHeapVector(const std::initializer_list<T> elements);
179
180 /**
181 * Pushes a new element to the end of this vector.
182 * @param element The new element to be pushed
183 */
184 void pushBack(T&& element);
185
186 /**
187 * Pushes a new element to the end of this vector.
188 * @param element The new element to be pushed
189 */
190 void pushBack(const T& element);
191
192 /**
193 * Emplaces a new element to the end of this vector.
194 * @param args The arguments of the new element
195 * @tparam TArgs The data types of the arguments
196 */
197 template <typename... TArgs>
198 T& emplaceBack(TArgs&&... args);
199
200 /**
201 * Removed the last elements from the vector.
202 * The vector must not be empty.
203 */
204 void popBack();
205
206 /**
207 * Resizes the vector.
208 * @param size The new size of the vector
209 */
210 void resize(const size_t size);
211
212 /**
213 * Replaces the content of the vector with 'size' copies of the provided element.
214 * @param size The new size of the vector, with range [0, infinity)
215 * @param element The element which will be copied into all places of the resized vector
216 */
217 void assign(const size_t size, const T& element);
218
219 /**
220 * Returns the number of elements of this vector.
221 * @return The vector's number of elements, with range [0, infinity)
222 */
223 inline size_t size() const;
224
225 /**
226 * Returns the overall capacity of this vector (including the capacity on the stack and on the heap).
227 * @return The vector's capacity, with range [size(), infinity)
228 */
229 inline size_t capacity() const;
230
231 /**
232 * Returns whether this vector is empty.
233 * @return True, if so
234 */
235 inline bool isEmpty() const;
236
237 /**
238 * Clears this vector.
239 * All stack elements will be overwritten with default values.
240 */
241 void clear();
242
243 /**
244 * Reserves a specified capacity for this vector.
245 * In case the specified capacity is smaller than the current capacity or is smaller than the number of elements in this vector, nothing happens.
246 * @param capacity The capacity to reserve, with range [0, infinity)
247 */
248 void reserve(const size_t capacity);
249
250 /**
251 * Returns the first element of this vector.
252 * Ensure that the vector is not empty before calling this function.
253 * @return The vector's first element
254 */
255 const T& front() const;
256
257 /**
258 * Returns the first element of this vector.
259 * Ensure that the vector is not empty before calling this function.
260 * @return The vector's first element
261 */
262 T& front();
263
264 /**
265 * Returns the last element of this vector.
266 * Ensure that the vector is not empty before calling this function.
267 * @return The vector's last element
268 */
269 const T& back() const;
270
271 /**
272 * Returns the last element of this vector.
273 * Ensure that the vector is not empty before calling this function.
274 * @return The vector's last element
275 */
276 T& back();
277
278 /**
279 * Returns an iterator to the first element in this vector.
280 * @return The vector's iterator to the first element
281 */
282 Iterator begin();
283
284 /**
285 * Returns an iterator to the element following the last element in this vector.
286 * @return The vector's iterator to the element following the last element
287 */
288 Iterator end();
289
290 /**
291 * Returns a const iterator to the first element in this vector.
292 * @return The vector's iterator to the first element
293 */
294 ConstIterator begin() const;
295
296 /**
297 * Returns an iterator to the element following the last element in this vector.
298 * @return The vector's iterator to the element following the last element
299 */
300 ConstIterator end() const;
301
302 /**
303 * Elements access operator.
304 * @param index The index of the element to access, with range [0, size() - 1]
305 * @return The element with specified index
306 */
307 inline const T& operator[](const size_t index) const;
308
309 /**
310 * Elements access operator.
311 * @param index The index of the element to access, with range [0, size() - 1]
312 * @return The element with specified index
313 */
314 inline T& operator[](const size_t index);
315
316 protected:
317
318 /// The elements located on the stack.
319 T stackElements_[tStackCapacity];
320
321 /// The remaining elements located on the heap.
322 std::vector<T> heapElements_;
323
324 /// The number of elements in this vector.
325 size_t size_ = 0;
326};
327
328template <typename T, size_t tStackCapacity>
330 vector_(vector),
331 index_(index)
332{
333 ocean_assert(index <= vector_.size_);
334}
335
336template <typename T, size_t tStackCapacity>
343
344template <typename T, size_t tStackCapacity>
346{
347 Iterator iterator(*this);
348
349 ++index_;
350
351 return iterator;
352}
353
354template <typename T, size_t tStackCapacity>
356{
357 return vector_[index_];
358}
359
360template <typename T, size_t tStackCapacity>
362{
363 ocean_assert(&vector_ == &iterator.vector_);
364
365 return &vector_ == &iterator.vector_ && index_ == iterator.index_;
366}
367
368template <typename T, size_t tStackCapacity>
370{
371 return !(*this == iterator);
372}
373
374template <typename T, size_t tStackCapacity>
376 vector_(vector),
377 index_(index)
378{
379 ocean_assert(index <= vector_.size_);
380}
381
382template <typename T, size_t tStackCapacity>
389
390template <typename T, size_t tStackCapacity>
392{
393 Iterator iterator(*this);
394
395 ++index_;
396
397 return iterator;
398}
399
400template <typename T, size_t tStackCapacity>
402{
403 return vector_[index_];
404}
405
406template <typename T, size_t tStackCapacity>
408{
409 ocean_assert(&vector_ == &iterator.vector_);
410
411 return &vector_ == &iterator.vector_ && index_ == iterator.index_;
412}
413
414template <typename T, size_t tStackCapacity>
416{
417 return !(*this == iterator);
418}
419
420template <typename T, size_t tStackCapacity>
422{
423 // nothing to do here
424}
425
426template <typename T, size_t tStackCapacity>
428{
429 reserve(size);
430
431 for (size_t n = 0; n < size; ++n)
432 {
433 pushBack(element);
434 }
435}
436
437template <typename T, size_t tStackCapacity>
439{
440 reserve(elements.size());
441
442 for (T& element : elements)
443 {
444 pushBack(std::move(element));
445 }
446}
447
448template <typename T, size_t tStackCapacity>
450{
451 reserve(elements.size());
452
453 for (const T& element : elements)
454 {
455 pushBack(element);
456 }
457}
458
459template <typename T, size_t tStackCapacity>
460StackHeapVector<T, tStackCapacity>::StackHeapVector(const std::initializer_list<T> elements)
461{
462 reserve(elements.size());
463
464 for (const T& element : elements)
465 {
466 pushBack(element);
467 }
468}
469
470template <typename T, size_t tStackCapacity>
472{
473 if (size_ < tStackCapacity)
474 {
475 stackElements_[size_] = std::move(element);
476 }
477 else
478 {
479 heapElements_.emplace_back(std::move(element));
480 }
481
482 ++size_;
483}
484
485template <typename T, size_t tStackCapacity>
487{
488 if (size_ < tStackCapacity)
489 {
490 stackElements_[size_] = element;
491 }
492 else
493 {
494 heapElements_.push_back(element);
495 }
496
497 ++size_;
498}
499
500template <typename T, size_t tStackCapacity>
501template <typename... TArgs>
503{
504 const size_t index = size_;
505
506 ++size_;
507
508 if (index < tStackCapacity)
509 {
510 stackElements_[index] = T(std::forward<TArgs>(args)...);
511
512 return stackElements_[index];
513 }
514 else
515 {
516 return heapElements_.emplace_back(std::forward<TArgs>(args)...);
517 }
518}
519
520template <typename T, size_t tStackCapacity>
522{
523 ocean_assert(size_ >= 1);
524
525 --size_;
526
527 if (size_ >= tStackCapacity)
528 {
529 heapElements_.pop_back();
530 }
531 else
532 {
533 stackElements_[size_] = T();
534 }
535}
536
537template <typename T, size_t tStackCapacity>
539{
540 if (size == size_)
541 {
542 return;
543 }
544
545 if (size < size_)
546 {
547 // we have to remove elements
548
549 for (size_t n = size; n < tStackCapacity; ++n) // in case size >= tStackCapacity, nothing happens
550 {
551 stackElements_[n] = T();
552 }
553
554 if (size_ > tStackCapacity)
555 {
556 if (size < tStackCapacity)
557 {
558 heapElements_.clear();
559 }
560 else
561 {
562 heapElements_.resize(size - tStackCapacity);
563 }
564 }
565 }
566 else
567 {
568 ocean_assert(size > size_);
569
570 if (size > tStackCapacity)
571 {
572 heapElements_.resize(size - tStackCapacity);
573 }
574 }
575
576 size_ = size;
577}
578
579template <typename T, size_t tStackCapacity>
580void StackHeapVector<T, tStackCapacity>::assign(const size_t size, const T& element)
581{
582 for (size_t n = 0; n < std::min(size, tStackCapacity); ++n) // we assign as many elements in the stack
583 {
584 stackElements_[n] = element;
585 }
586
587 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
588 {
589 stackElements_[n] = T();
590 }
591
592 if (size < tStackCapacity)
593 {
594 heapElements_.clear();
595 }
596 else
597 {
598 const size_t newHeapSize = size - tStackCapacity;
599
600 heapElements_.assign(newHeapSize, element);
601 }
602
603 size_ = size;
604}
605
606template <typename T, size_t tStackCapacity>
608{
609 ocean_assert(size_ <= tStackCapacity || size_ == tStackCapacity + heapElements_.size());
610
611 return size_;
612}
613
614template <typename T, size_t tStackCapacity>
616{
617 return tStackCapacity + heapElements_.capacity();
618}
619
620template <typename T, size_t tStackCapacity>
622{
623 return size() == 0;
624}
625
626template <typename T, size_t tStackCapacity>
628{
629 for (size_t nStack = 0; nStack < std::min(size_, tStackCapacity); ++nStack)
630 {
631 stackElements_[nStack] = T();
632 }
633
634 heapElements_.clear();
635
636 size_ = 0;
637}
638
639template <typename T, size_t tStackCapacity>
641{
642 if (capacity > size_)
643 {
644 if (capacity > tStackCapacity)
645 {
646 heapElements_.reserve(capacity - tStackCapacity);
647 }
648 }
649}
650
651template <typename T, size_t tStackCapacity>
653{
654 ocean_assert(!isEmpty());
655
656 return stackElements_[0];
657}
658
659template <typename T, size_t tStackCapacity>
661{
662 ocean_assert(!isEmpty());
663
664 return stackElements_[0];
665}
666
667template <typename T, size_t tStackCapacity>
669{
670 ocean_assert(!isEmpty());
671
672 if (size_ <= tStackCapacity)
673 {
674 return stackElements_[size_ - 1];
675 }
676 else
677 {
678 return heapElements_.back();
679 }
680}
681
682template <typename T, size_t tStackCapacity>
684{
685 ocean_assert(!isEmpty());
686
687 if (size_ <= tStackCapacity)
688 {
689 return stackElements_[size_ - 1];
690 }
691 else
692 {
693 return heapElements_.back();
694 }
695}
696
697template <typename T, size_t tStackCapacity>
702
703template <typename T, size_t tStackCapacity>
708
709template <typename T, size_t tStackCapacity>
714
715template <typename T, size_t tStackCapacity>
720
721template <typename T, size_t tStackCapacity>
722inline const T& StackHeapVector<T, tStackCapacity>::operator[](const size_t index) const
723{
724 ocean_assert(index < size());
725
726 if (index < tStackCapacity)
727 {
728 return stackElements_[index];
729 }
730
731 return heapElements_[index - tStackCapacity];
732}
733
734template <typename T, size_t tStackCapacity>
736{
737 ocean_assert(index < size());
738
739 if (index < tStackCapacity)
740 {
741 return stackElements_[index];
742 }
743
744 return heapElements_[index - tStackCapacity];
745}
746
747}
748
749#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:375
bool operator==(const ConstIterator &iterator) const
Compares two iterators and returns whether both iterators point to the same vector element.
Definition StackHeapVector.h:407
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:415
const T & operator*() const
De-references the iterator and provides access to the underlying element in the vector.
Definition StackHeapVector.h:401
ConstIterator & operator++()
(Pre-) increments this iterator.
Definition StackHeapVector.h:383
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:361
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:369
Iterator(StackHeapVector &vector, const size_t index)
Creates a new iterator pointing to a specified elements in the vector.
Definition StackHeapVector.h:329
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:355
Iterator & operator++()
(Pre-) increments this iterator.
Definition StackHeapVector.h:337
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:325
StackHeapVector(const size_t size, const T &element)
Creates a new vector object.
Definition StackHeapVector.h:427
StackHeapVector(const std::vector< T > &elements)
Creates a new vector object and copies the elements to this vector.
Definition StackHeapVector.h:449
Iterator begin()
Returns an iterator to the first element in this vector.
Definition StackHeapVector.h:698
std::vector< T > heapElements_
The remaining elements located on the heap.
Definition StackHeapVector.h:322
StackHeapVector()
Creates a new vector object.
Definition StackHeapVector.h:421
StackHeapVector(const std::initializer_list< T > elements)
Creates a new vector object and copies the elements to this vector.
Definition StackHeapVector.h:460
const T & operator[](const size_t index) const
Elements access operator.
Definition StackHeapVector.h:722
T stackElements_[tStackCapacity]
The elements located on the stack.
Definition StackHeapVector.h:319
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:580
const T & back() const
Returns the last element of this vector.
Definition StackHeapVector.h:668
T & emplaceBack(TArgs &&... args)
Emplaces a new element to the end of this vector.
Definition StackHeapVector.h:502
Iterator end()
Returns an iterator to the element following the last element in this vector.
Definition StackHeapVector.h:704
size_t capacity() const
Returns the overall capacity of this vector (including the capacity on the stack and on the heap).
Definition StackHeapVector.h:615
void reserve(const size_t capacity)
Reserves a specified capacity for this vector.
Definition StackHeapVector.h:640
const T & front() const
Returns the first element of this vector.
Definition StackHeapVector.h:652
void pushBack(T &&element)
Pushes a new element to the end of this vector.
Definition StackHeapVector.h:471
void resize(const size_t size)
Resizes the vector.
Definition StackHeapVector.h:538
ConstIterator begin() const
Returns a const iterator to the first element in this vector.
Definition StackHeapVector.h:710
T & operator[](const size_t index)
Elements access operator.
Definition StackHeapVector.h:735
void clear()
Clears this vector.
Definition StackHeapVector.h:627
T & back()
Returns the last element of this vector.
Definition StackHeapVector.h:683
T & front()
Returns the first element of this vector.
Definition StackHeapVector.h:660
StackHeapVector(std::vector< T > &&elements)
Creates a new vector object and moves the elements to this vector.
Definition StackHeapVector.h:438
ConstIterator end() const
Returns an iterator to the element following the last element in this vector.
Definition StackHeapVector.h:716
void pushBack(const T &element)
Pushes a new element to the end of this vector.
Definition StackHeapVector.h:486
bool isEmpty() const
Returns whether this vector is empty.
Definition StackHeapVector.h:621
void popBack()
Removed the last elements from the vector.
Definition StackHeapVector.h:521
size_t size() const
Returns the number of elements of this vector.
Definition StackHeapVector.h:607
The namespace covering the entire Ocean framework.
Definition Accessor.h:15