COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
StaticVector.h
Go to the documentation of this file.
1//
2// Copyright 2015 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: MPL-2.0
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
12
13#pragma once
14
15#include "comms/Assert.h"
18
19#include <algorithm>
20#include <array>
21#include <cstddef>
22#include <initializer_list>
23#include <iterator>
24#include <type_traits>
25#include <utility>
26
27COMMS_GNU_WARNING_PUSH
28
29#if COMMS_IS_GCC_12 && defined(NDEBUG)
30// Release compilation with gcc-12
31// assumes size / capacity of the StaticVectorBase is 0 and generates
32// unjustified warnings.
33COMMS_GNU_WARNING_DISABLE("-Warray-bounds")
34#endif
35
36COMMS_MSVC_WARNING_PUSH
37COMMS_MSVC_WARNING_DISABLE(4324) // Disable warning about alignment padding
38
39namespace comms
40{
41
42namespace util
43{
44
45namespace details
46{
47
48template <typename T>
49class StaticVectorBase
50{
51public:
52 using value_type = T;
53 using size_type = std::size_t;
54 using reference = T&;
55 using const_reference = const T&;
56 using pointer = T*;
57 using const_pointer = const T*;
58 using iterator = pointer;
59 using const_iterator = const_pointer;
60 using reverse_iterator = std::reverse_iterator<iterator>;
61 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
62 using CellType = comms::util::AlignedStorage<sizeof(T), std::alignment_of<T>::value>;
63
64 static_assert(sizeof(CellType) == sizeof(T), "Type T must be padded");
65
66 StaticVectorBase(CellType* dataPtr, std::size_t cap)
67 : m_data(dataPtr),
68 m_capacity(cap)
69 {
70 }
71
72 ~StaticVectorBase() noexcept
73 {
74 clear();
75 }
76
77 StaticVectorBase(const StaticVectorBase&) = delete;
78 StaticVectorBase& operator=(const StaticVectorBase&) = delete;
79
80 std::size_t size() const
81 {
82 return m_size;
83 }
84
85 std::size_t capacity() const
86 {
87 return m_capacity;
88 }
89
90 bool empty() const
91 {
92 return (size() == 0);
93 }
94
95 void pop_back()
96 {
97 COMMS_MSVC_WARNING_SUPPRESS(4189) // MSVC claims lastElem not referenced
98 auto& lastElem = back();
99 lastElem.~T();
100 --m_size;
101 }
102
103 T& back()
104 {
105 COMMS_ASSERT(!empty());
106 return elem(size() - 1);
107 }
108
109 const T& back() const
110 {
111 COMMS_ASSERT(!empty());
112 return elem(size() - 1);
113 }
114
115 T& front()
116 {
117 COMMS_ASSERT(!empty());
118 return elem(0);
119 }
120
121 const T& front() const
122 {
123 COMMS_ASSERT(!empty());
124 return elem(0);
125 }
126
127 template <typename TIter>
128 void assign(TIter from, TIter to)
129 {
130 clear();
131 for (auto iter = from; iter != to; ++iter) {
132 if (capacity() <= size()) {
133 static constexpr bool Not_all_elements_are_copied = false;
134 static_cast<void>(Not_all_elements_are_copied);
135 COMMS_ASSERT(Not_all_elements_are_copied);
136 return;
137 }
138
139 new (cellPtr(size())) T(*(reinterpret_cast<const T*>(&*iter)));
140 ++m_size;
141 }
142 }
143
144 void fill(std::size_t count, const T& value)
145 {
146 clear();
147 COMMS_ASSERT(count <= capacity());
148 for (auto idx = 0U; idx < count; ++idx) {
149 new (cellPtr(idx)) T(value);
150 }
151 m_size = count;
152 }
153
154 void clear() {
155 for (auto idx = 0U; idx < size(); ++idx) {
156 elem(idx).~T();
157 }
158 m_size = 0;
159 }
160
161 T* begin()
162 {
163 if (size() == 0U) {
164 return nullptr;
165 }
166
167 return &(elem(0));
168 }
169
170 const T* begin() const
171 {
172 return cbegin();
173 }
174
175 const T* cbegin() const
176 {
177 if (size() == 0U) {
178 return nullptr;
179 }
180
181 return &(elem(0));
182 }
183
184 T* end()
185 {
186 return begin() + size();
187 }
188
189 const T* end() const
190 {
191 return cend();
192 }
193
194 const T* cend() const
195 {
196 return cbegin() + size();
197 }
198
199 T& at(std::size_t pos)
200 {
201 COMMS_ASSERT(pos < size());
202 return elem(pos);
203 }
204
205 const T& at(std::size_t pos) const
206 {
207 COMMS_ASSERT(pos < size());
208 return elem(pos);
209 }
210
211 T& operator[](std::size_t pos)
212 {
213 return elem(pos);
214 }
215
216 const T& operator[](std::size_t pos) const
217 {
218 return elem(pos);
219 }
220
221 T* data()
222 {
223 if (size() == 0U) {
224 return nullptr;
225 }
226
227 return &(elem(0));
228 }
229
230 const T* data() const
231 {
232 if (size() == 0U) {
233 return nullptr;
234 }
235
236 return &(elem(0));
237 }
238
239 template <typename U>
240 T* insert(const T* pos, U&& value)
241 {
242 COMMS_ASSERT(pos <= end());
243 COMMS_ASSERT(size() < capacity());
244 if (end() <= pos) {
245 push_back(std::forward<U>(value));
246 return &(back());
247 }
248
249 COMMS_ASSERT(!empty());
250 push_back(std::move(back()));
251 auto* insertIter = begin() + std::distance(cbegin(), pos);
252 std::move_backward(insertIter, end() - 2, end() - 1);
253 *insertIter = std::forward<U>(value);
254 return insertIter;
255 }
256
257 T* insert(const T* pos, std::size_t count, const T& value)
258 {
259 COMMS_ASSERT(pos <= end());
260 COMMS_ASSERT((size() + count) <= capacity());
261 auto dist = std::distance(cbegin(), pos);
262 COMMS_ASSERT((0 <= dist) && static_cast<std::size_t>(dist) < size());
263 auto* posIter = begin() + dist;
264 if (end() <= posIter) {
265 while (0 < count) {
266 push_back(value);
267 --count;
268 }
269 return posIter;
270 }
271
272 COMMS_ASSERT(!empty());
273 auto tailCount = static_cast<std::size_t>(std::distance(posIter, end()));
274 if (count <= tailCount) {
275 auto pushBegIter = end() - count;
276 auto pushEndIter = end();
277 for (auto iter = pushBegIter; iter != pushEndIter; ++iter) {
278 push_back(std::move(*iter));
279 }
280
281 auto moveBegIter = posIter;
282 auto moveEndIter = moveBegIter + (tailCount - count);
283 COMMS_ASSERT(moveEndIter < pushEndIter);
284
285 COMMS_GNU_WARNING_PUSH
286#if COMMS_IS_GCC_12 && defined(NDEBUG)
287 // Release compilation with gcc-12
288 // gives a warning here, while any debug build works fine.
289 COMMS_GNU_WARNING_DISABLE("-Wstringop-overflow")
290#endif
291 std::move_backward(moveBegIter, moveEndIter, pushEndIter);
292 COMMS_GNU_WARNING_POP
293
294 auto* assignBegIter = posIter;
295 auto* assignEndIter = assignBegIter + count;
296 for (auto iter = assignBegIter; iter != assignEndIter; ++iter) {
297 *iter = value;
298 }
299 return posIter;
300 }
301
302 auto pushValueCount = count - tailCount;
303 for (auto idx = 0U; idx < pushValueCount; ++idx) {
304 push_back(value);
305 }
306
307 auto* pushBegIter = posIter;
308 auto* pushEndIter = pushBegIter + tailCount;
309 for (auto iter = pushBegIter; iter != pushEndIter; ++iter) {
310 push_back(std::move(*iter));
311 }
312
313 auto assignBegIter = posIter;
314 auto assignEndIter = assignBegIter + tailCount;
315 for (auto iter = assignBegIter; iter != assignEndIter; ++iter) {
316 *iter = value;
317 }
318 return posIter;
319 }
320
321 template <typename TIter>
322 T* insert(const T* pos, TIter from, TIter to)
323 {
324 using Tag = typename std::iterator_traits<TIter>::iterator_category;
325 return insert_internal(pos, from, to, Tag());
326 }
327
328 template <typename... TArgs>
329 T* emplace(const T* iter, TArgs&&... args)
330 {
331 auto* insertIter = begin() + std::distance(cbegin(), iter);
332 if (iter == cend()) {
333 emplace_back(std::forward<TArgs>(args)...);
334 return insertIter;
335 }
336
337 COMMS_ASSERT(!empty());
338 push_back(std::move(back()));
339 std::move_backward(insertIter, end() - 2, end() - 1);
340 insertIter->~T();
341 new (insertIter) T(std::forward<TArgs>(args)...);
342 return insertIter;
343 }
344
345 T* erase(const T* from, const T* to)
346 {
347 COMMS_ASSERT(from <= cend());
348 COMMS_ASSERT(to <= cend());
349 COMMS_ASSERT(from <= to);
350
351 auto tailCount = static_cast<std::size_t>(std::distance(to, cend()));
352 auto eraseCount = static_cast<std::size_t>(std::distance(from, to));
353
354 auto* moveSrc = begin() + std::distance(cbegin(), to);
355 auto* moveDest = begin() + std::distance(cbegin(), from);
356 std::move(moveSrc, end(), moveDest);
357
358 auto* eraseFrom = moveDest + tailCount;
359 auto* eraseTo = end();
360 COMMS_ASSERT(eraseFrom <= end());
361 COMMS_ASSERT(eraseCount <= size());
362 COMMS_ASSERT(static_cast<std::size_t>(std::distance(eraseFrom, eraseTo)) == eraseCount);
363 for (auto iter = eraseFrom; iter != eraseTo; ++iter) {
364 iter->~T();
365 }
366 m_size -= eraseCount;
367 return moveDest;
368 }
369
370 template <typename U>
371 void push_back(U&& value)
372 {
373 COMMS_ASSERT(size() < capacity());
374 new (cellPtr(size())) T(std::forward<U>(value));
375 ++m_size;
376 }
377
378 template <typename... TArgs>
379 void emplace_back(TArgs&&... args)
380 {
381 COMMS_ASSERT(size() < capacity());
382 new (cellPtr(size())) T(std::forward<TArgs>(args)...);
383 ++m_size;
384 }
385
386 void resize(std::size_t count, const T& value)
387 {
388 if (count < size()) {
389 erase(begin() + count, end());
390 COMMS_ASSERT(count == size());
391 return;
392 }
393
394 while (size() < count) {
395 push_back(value);
396 }
397 }
398
399 void swap(StaticVectorBase<T>& other)
400 {
401 auto swapSize = std::min(other.size(), size());
402 for (auto idx = 0U; idx < swapSize; ++idx) {
403 std::swap(this->operator[](idx), other[idx]);
404 }
405
406 auto otherSize = other.size();
407 auto thisSize = size();
408
409 if (otherSize == thisSize) {
410 return;
411 }
412
413 if (otherSize < thisSize) {
414 auto limit = std::min(thisSize, other.capacity());
415 for (auto idx = swapSize; idx < limit; ++idx) {
416 new (other.cellPtr(idx)) T(std::move(elem(idx)));
417 }
418
419 other.m_size = thisSize;
420 erase(begin() + otherSize, end());
421 return;
422 }
423
424 auto limit = std::min(otherSize, capacity());
425 for (auto idx = swapSize; idx < limit; ++idx) {
426 new (cellPtr(idx)) T(std::move(other.elem(idx)));
427 }
428 m_size = otherSize;
429 other.erase(other.begin() + thisSize, other.end());
430 }
431
432private:
433 CellType& cell(std::size_t idx)
434 {
435 COMMS_ASSERT(idx < capacity());
436 return m_data[idx];
437 }
438
439 const CellType& cell(std::size_t idx) const
440 {
441 COMMS_ASSERT(idx < capacity());
442 return m_data[idx];
443 }
444
445 CellType* cellPtr(std::size_t idx)
446 {
447 COMMS_ASSERT(idx < capacity());
448 return &m_data[idx];
449 }
450
451 T& elem(std::size_t idx)
452 {
453 return reinterpret_cast<T&>(cell(idx));
454 }
455
456 const T& elem(std::size_t idx) const
457 {
458 return reinterpret_cast<const T&>(cell(idx));
459 }
460
461 template <typename TIter>
462 T* insert_random_access(const T* pos, TIter from, TIter to)
463 {
464 COMMS_ASSERT(pos <= end());
465 auto* posIter = begin() + std::distance(cbegin(), pos);
466 if (end() <= posIter) {
467 for (; from != to; ++from) {
468 push_back(*from);
469 }
470
471 return posIter;
472 }
473
474 auto count = static_cast<std::size_t>(std::distance(from, to));
475 COMMS_ASSERT(!empty());
476 auto tailCount = static_cast<std::size_t>(std::distance(posIter, end()));
477 if (count <= tailCount) {
478 auto pushBegIter = end() - count;
479 auto pushEndIter = end();
480 for (auto iter = pushBegIter; iter != pushEndIter; ++iter) {
481 push_back(std::move(*iter));
482 }
483
484 auto moveBegIter = posIter;
485 auto moveEndIter = moveBegIter + (tailCount - count);
486 COMMS_ASSERT(moveEndIter < pushEndIter);
487 std::move_backward(moveBegIter, moveEndIter, pushEndIter);
488
489 auto* assignBegIter = posIter;
490 auto* assignEndIter = assignBegIter + count;
491 for (auto iter = assignBegIter; iter != assignEndIter; ++iter) {
492 *iter = *from;
493 ++from;
494 }
495 return posIter;
496 }
497
498 auto pushValueCount = count - tailCount;
499 auto pushInsertedBegIter = to - pushValueCount;
500 for (auto idx = 0U; idx < pushValueCount; ++idx) {
501 push_back(*pushInsertedBegIter);
502 ++pushInsertedBegIter;
503 }
504
505 auto* pushBegIter = posIter;
506 auto* pushEndIter = pushBegIter + tailCount;
507 for (auto iter = pushBegIter; iter != pushEndIter; ++iter) {
508 push_back(std::move(*iter));
509 }
510
511 auto assignBegIter = posIter;
512 auto assignEndIter = assignBegIter + tailCount;
513 for (auto iter = assignBegIter; iter != assignEndIter; ++iter) {
514 *iter = *from;
515 ++from;
516 }
517
518 return posIter;
519 }
520
521 template <typename TIter>
522 T* insert_input(const T* pos, TIter from, TIter to)
523 {
524 T* ret = nullptr;
525 for (; from != to; ++from) {
526 if (ret == nullptr) {
527 ret = begin() + std::distance(cbegin(), pos);
528 }
529 insert(pos, *from);
530 ++pos;
531 }
532 return ret;
533 }
534
535 template <typename TIter>
536 T* insert_internal(const T* pos, TIter from, TIter to, std::random_access_iterator_tag)
537 {
538 return insert_random_access(pos, from, to);
539 }
540
541 template <typename TIter>
542 T* insert_internal(const T* pos, TIter from, TIter to, std::input_iterator_tag)
543 {
544 return insert_input(pos, from, to);
545 }
546
547 CellType* m_data = nullptr;
548 std::size_t m_capacity = 0;
549 std::size_t m_size = 0;
550};
551
552template <typename T, std::size_t TSize>
553struct StaticVectorStorageBase
554{
555 using ElementType = comms::util::AlignedStorage<sizeof(T), std::alignment_of<T>::value>;
556 using StorageType = std::array<ElementType, TSize>;
557 alignas(alignof(T)) StorageType m_data;
558};
559
560template <typename T, std::size_t TSize>
561class StaticVectorGeneric :
562 public StaticVectorStorageBase<T, TSize>,
563 public StaticVectorBase<T>
564{
565 using StorageBase = StaticVectorStorageBase<T, TSize>;
566 using Base = StaticVectorBase<T>;
567
568public:
569 using value_type = typename Base::value_type;
570 using size_type = typename Base::size_type;
571 using difference_type = typename StorageBase::StorageType::difference_type;
572 using reference = typename Base::reference;
573 using const_reference = typename Base::const_reference;
574 using pointer = typename Base::pointer;
575 using const_pointer = typename Base::const_pointer;
576 using iterator = typename Base::iterator;
577 using const_iterator = typename Base::const_iterator;
578 using reverse_iterator = typename Base::reverse_iterator;
579 using const_reverse_iterator = typename Base::const_reverse_iterator;
580
581 StaticVectorGeneric()
582 : Base(StorageBase::m_data.data(), StorageBase::m_data.size())
583 {
584 }
585
586 StaticVectorGeneric(size_type count, const T& value)
587 : Base(StorageBase::m_data.data(), StorageBase::m_data.size())
588 {
589 assign(count, value);
590 }
591
592 explicit StaticVectorGeneric(size_type count)
593 : Base(StorageBase::m_data.data(), StorageBase::m_data.size())
594 {
595 COMMS_ASSERT(count < Base::capacity());
596 while (0 < count) {
597 Base::emplace_back();
598 --count;
599 }
600 }
601
602 template <typename TIter>
603 StaticVectorGeneric(TIter from, TIter to)
604 : Base(StorageBase::m_data.data(), StorageBase::m_data.size())
605 {
606 assign(from, to);
607 }
608
609 template <std::size_t TOtherSize>
610 StaticVectorGeneric(const StaticVectorGeneric<T, TOtherSize>& other)
611 : Base(StorageBase::m_data.data(), StorageBase::m_data.size())
612 {
613 assign(other.begin(), other.end());
614 }
615
616 StaticVectorGeneric(const StaticVectorGeneric& other)
617 : Base(StorageBase::m_data.data(), StorageBase::m_data.size())
618 {
619 assign(other.begin(), other.end());
620 }
621
622 StaticVectorGeneric(std::initializer_list<value_type> init)
623 : Base(StorageBase::m_data.data(), StorageBase::m_data.size())
624 {
625 assign(init.begin(), init.end());
626 }
627
628 ~StaticVectorGeneric() noexcept = default;
629
630 StaticVectorGeneric& operator=(const StaticVectorGeneric& other)
631 {
632 if (&other == this) {
633 return *this;
634 }
635
636 assign(other.begin(), other.end());
637 return *this;
638 }
639
640 template <std::size_t TOtherSize>
641 StaticVectorGeneric& operator=(const StaticVectorGeneric<T, TOtherSize>& other)
642 {
643 assign(other.cbegin(), other.cend());
644 return *this;
645 }
646
647 StaticVectorGeneric& operator=(std::initializer_list<value_type> init)
648 {
649 assign(init);
650 return *this;
651 }
652
653 void assign(size_type count, const T& value)
654 {
655 COMMS_ASSERT(count <= TSize);
656 Base::fill(count, value);
657 }
658
659 template <typename TIter>
660 void assign(TIter from, TIter to)
661 {
662 Base::assign(from, to);
663 }
664
665 void assign(std::initializer_list<value_type> init)
666 {
667 assign(init.begin(), init.end());
668 }
669
670 void reserve(size_type new_cap)
671 {
672 static_cast<void>(new_cap);
673 COMMS_ASSERT(new_cap <= Base::capacity());
674 }
675};
676
677template <typename TOrig, typename TCast, std::size_t TSize>
678class StaticVectorCasted : public StaticVectorGeneric<TCast, TSize>
679{
680 using Base = StaticVectorGeneric<TCast, TSize>;
681 static_assert(sizeof(TOrig) == sizeof(TCast), "The sizes are not equal");
682
683public:
684 using value_type = TOrig;
685 using size_type = typename Base::size_type;
686 using difference_type = typename Base::difference_type;
687 using reference = value_type&;
688 using const_reference = const value_type&;
689 using pointer = value_type*;
690 using const_pointer = const value_type*;
691 using iterator = pointer;
692 using const_iterator = const_pointer;
693
694 StaticVectorCasted() = default;
695
696 StaticVectorCasted(size_type count, const_reference& value)
697 : Base(count, *(reinterpret_cast<typename Base::const_pointer>(&value)))
698 {
699 }
700
701 explicit StaticVectorCasted(size_type count)
702 : Base(count)
703 {
704 }
705
706 template <typename TIter>
707 StaticVectorCasted(TIter from, TIter to)
708 : Base(from, to)
709 {
710 }
711
712 template <std::size_t TOtherSize>
713 StaticVectorCasted(const StaticVectorCasted<TOrig, TCast, TOtherSize>& other)
714 : Base(other)
715 {
716 }
717
718 StaticVectorCasted(const StaticVectorCasted& other)
719 : Base(other)
720 {
721 }
722
723 StaticVectorCasted(std::initializer_list<value_type> init)
724 : Base(init.begin(), init.end())
725 {
726 }
727
728 ~StaticVectorCasted() noexcept = default;
729
730 StaticVectorCasted& operator=(const StaticVectorCasted&) = default;
731
732 template <std::size_t TOtherSize>
733 StaticVectorCasted& operator=(const StaticVectorCasted<TOrig, TCast, TOtherSize>& other)
734 {
735 Base::operator=(other);
736 return *this;
737 }
738
739 StaticVectorCasted& operator=(std::initializer_list<value_type> init)
740 {
741 Base::operator=(init);
742 return *this;
743 }
744
745 void assign(size_type count, const_reference& value)
746 {
747 Base::assign(count, value);
748 }
749
750 template <typename TIter>
751 void assign(TIter from, TIter to)
752 {
753 Base::assign(from, to);
754 }
755
756 void assign(std::initializer_list<value_type> init)
757 {
758 assign(init.begin(), init.end());
759 }
760
761 reference at(size_type pos)
762 {
763 return *(reinterpret_cast<pointer>(&(Base::at(pos))));
764 }
765
766 const_reference at(size_type pos) const
767 {
768 return *(reinterpret_cast<const_pointer>(&(Base::at(pos))));
769 }
770
771 reference operator[](size_type pos)
772 {
773 return *(reinterpret_cast<pointer>(&(Base::operator[](pos))));
774 }
775
776 const_reference operator[](size_type pos) const
777 {
778 return *(reinterpret_cast<const_pointer>(&(Base::operator[](pos))));
779 }
780
781 reference front()
782 {
783 return *(reinterpret_cast<pointer>(&(Base::front())));
784 }
785
786 const_reference front() const
787 {
788 return *(reinterpret_cast<const_pointer>(&(Base::front())));
789 }
790
791 reference back()
792 {
793 return *(reinterpret_cast<pointer>(&(Base::back())));
794 }
795
796 const_reference back() const
797 {
798 return *(reinterpret_cast<const_pointer>(&(Base::back())));
799 }
800
801 pointer data()
802 {
803 return reinterpret_cast<pointer>(Base::data());
804 }
805
806 const_pointer data() const
807 {
808 return reinterpret_cast<const_pointer>(Base::data());
809 }
810
811 iterator begin()
812 {
813 return reinterpret_cast<iterator>(Base::begin());
814 }
815
816 const_iterator begin() const
817 {
818 return cbegin();
819 }
820
821 const_iterator cbegin() const
822 {
823 return reinterpret_cast<const_iterator>(Base::cbegin());
824 }
825
826 iterator end()
827 {
828 return reinterpret_cast<iterator>(Base::end());
829 }
830
831 const_iterator end() const
832 {
833 return cend();
834 }
835
836 const_iterator cend() const
837 {
838 return reinterpret_cast<const_iterator>(Base::cend());
839 }
840
841 iterator insert(const_iterator iter, const_reference value)
842 {
843 return
844 reinterpret_cast<iterator>(
845 Base::insert(
846 reinterpret_cast<typename Base::const_iterator>(iter),
847 *(reinterpret_cast<typename Base::const_pointer>(&value))));
848 }
849
850 iterator insert(const_iterator iter, TCast&& value)
851 {
852 return
853 reinterpret_cast<iterator>(
854 Base::insert(
855 reinterpret_cast<typename Base::const_iterator>(iter),
856 std::move(*(reinterpret_cast<typename Base::pointer>(&value)))));
857 }
858
859 iterator insert(const_iterator iter, size_type count, const_reference value)
860 {
861 return
862 reinterpret_cast<iterator>(
863 Base::insert(
864 reinterpret_cast<typename Base::const_iterator>(iter),
865 count,
866 *(reinterpret_cast<typename Base::const_pointer>(&value))));
867 }
868
869 template <typename TIter>
870 iterator insert(const_iterator iter, TIter from, TIter to)
871 {
872 return
873 reinterpret_cast<iterator>(
874 Base::insert(
875 reinterpret_cast<typename Base::const_iterator>(iter),
876 from,
877 to));
878 }
879
880 iterator insert(const_iterator iter, std::initializer_list<value_type> init)
881 {
882 return
883 reinterpret_cast<iterator>(
884 Base::insert(
885 reinterpret_cast<typename Base::const_iterator>(iter),
886 init.begin(),
887 init.end()));
888 }
889
890 template <typename... TArgs>
891 iterator emplace(const_iterator iter, TArgs&&... args)
892 {
893 return
894 reinterpret_cast<iterator>(
895 Base::emplace(
896 reinterpret_cast<typename Base::const_iterator>(iter),
897 std::forward<TArgs>(args)...));
898 }
899
900 iterator erase(const_iterator iter)
901 {
902 return erase(iter, iter + 1);
903 }
904
907 iterator erase(const_iterator from, const_iterator to)
908 {
909 return
910 reinterpret_cast<iterator>(
911 Base::erase(
912 reinterpret_cast<typename Base::const_iterator>(from),
913 reinterpret_cast<typename Base::const_iterator>(to)));
914 }
915
916 void push_back(const_reference value)
917 {
918 Base::push_back(*(reinterpret_cast<typename Base::const_pointer>(&value)));
919 }
920
921 void push_back(TCast&& value)
922 {
923 Base::push_back(std::move(*(reinterpret_cast<TCast*>(&value))));
924 }
925};
926
927template <bool TSignedIntegral>
928struct StaticVectorBaseSignedIntegral;
929
930template <>
931struct StaticVectorBaseSignedIntegral<true>
932{
933 template <typename T, std::size_t TSize>
934 using Type = StaticVectorCasted<T, typename std::make_unsigned<T>::type, TSize>;
935};
936
937template <>
938struct StaticVectorBaseSignedIntegral<false>
939{
940 template <typename T, std::size_t TSize>
941 using Type = StaticVectorGeneric<T, TSize>;
942};
943
944template <typename T, std::size_t TSize>
945using ChooseStaticVectorBase =
946 typename StaticVectorBaseSignedIntegral<std::is_integral<T>::value && std::is_signed<T>::value>::template Type<T, TSize>;
947
948} // namespace details
949
959template <typename T, std::size_t TSize>
960class StaticVector : public details::ChooseStaticVectorBase<T, TSize>
961{
962 using Base = details::ChooseStaticVectorBase<T, TSize>;
963 using ElementType = typename Base::ElementType;
964
965 static_assert(sizeof(T) == sizeof(ElementType),
966 "Sizes are not equal as expected.");
967
968 template <typename U, std::size_t TOtherSize>
969 friend class StaticVector;
970
971public:
973 using value_type = typename Base::value_type;
974
976 using size_type = typename Base::size_type;
977
979 using difference_type = typename Base::StorageType::difference_type;
980
982 using reference = typename Base::reference;
983
985 using const_reference = typename Base::const_reference;
986
988 using pointer = typename Base::pointer;
989
991 using const_pointer = typename Base::const_pointer;
992
994 using iterator = typename Base::iterator;
995
997 using const_iterator = typename Base::const_iterator;
998
1000 using reverse_iterator = typename Base::reverse_iterator;
1001
1003 using const_reverse_iterator = typename Base::const_reverse_iterator;
1004
1006 StaticVector() = default;
1007
1010 StaticVector(size_type count, const T& value)
1011 : Base(count, value)
1012 {
1013 }
1014
1017 explicit StaticVector(size_type count)
1018 : Base(count)
1019 {
1020 }
1021
1024 template <typename TIter>
1025 StaticVector(TIter from, TIter to)
1026 : Base(from, to)
1027 {
1028 }
1029
1032 template <std::size_t TOtherSize>
1034 : Base(other)
1035 {
1036 }
1037
1041 : Base(other)
1042 {
1043 }
1044
1047 StaticVector(std::initializer_list<value_type> init)
1048 : Base(init)
1049 {
1050 }
1051
1053 ~StaticVector() noexcept = default;
1054
1057 StaticVector& operator=(const StaticVector&) = default;
1058
1061 template <std::size_t TOtherSize>
1062 StaticVector& operator=(const StaticVector<T, TOtherSize>& other)
1063 {
1064 Base::operator=(other);
1065 return *this;
1066 }
1067
1070 StaticVector& operator=(std::initializer_list<value_type> init)
1071 {
1072 Base::operator=(init);
1073 return *this;
1074 }
1075
1078 void assign(size_type count, const T& value)
1079 {
1080 Base::assign(count, value);
1081 }
1082
1085 template <typename TIter>
1086 void assign(TIter from, TIter to)
1087 {
1088 Base::assign(from, to);
1089 }
1090
1093 void assign(std::initializer_list<value_type> init)
1094 {
1095 assign(init.begin(), init.end());
1096 }
1097
1105 {
1106 return Base::at(pos);
1107 }
1108
1116 {
1117 return Base::at(pos);
1118 }
1119
1123 {
1124 return Base::operator[](pos);
1125 }
1126
1130 {
1131 return Base::operator[](pos);
1132 }
1133
1138 {
1139 return Base::front();
1140 }
1141
1146 {
1147 return Base::front();
1148 }
1149
1154 {
1155 return Base::back();
1156 }
1157
1162 {
1163 return Base::back();
1164 }
1165
1169 {
1170 return Base::data();
1171 }
1172
1176 {
1177 return Base::data();
1178 }
1179
1183 {
1184 return Base::begin();
1185 }
1186
1190 {
1191 return cbegin();
1192 }
1193
1197 {
1198 return Base::cbegin();
1199 }
1200
1204 {
1205 return Base::end();
1206 }
1207
1211 {
1212 return cend();
1213 }
1214
1218 {
1219 return Base::cend();
1220 }
1221
1225 {
1226 return reverse_iterator(end());
1227 }
1228
1232 {
1233 return crbegin();
1234 }
1235
1239 {
1240 return const_reverse_iterator(cend());
1241 }
1242
1246 {
1247 return reverse_iterator(begin());
1248 }
1249
1253 {
1254 return crend();
1255 }
1256
1260 {
1261 return const_reverse_iterator(cbegin());
1262 }
1263
1266 bool empty() const
1267 {
1268 return Base::empty();
1269 }
1270
1274 {
1275 return Base::size();
1276 }
1277
1283 {
1284 return capacity();
1285 }
1286
1290 void reserve(size_type new_cap)
1291 {
1292 return Base::reserve(new_cap);
1293 }
1294
1300 {
1301 return Base::capacity();
1302 }
1303
1308 {
1309 }
1310
1313 void clear()
1314 {
1315 Base::clear();
1316 }
1317
1320 iterator insert(const_iterator iter, const T& value)
1321 {
1322 return Base::insert(iter, value);
1323 }
1324
1328 {
1329 return Base::insert(iter, std::move(value));
1330 }
1331
1334 iterator insert(const_iterator iter, size_type count, const T& value)
1335 {
1336 return Base::insert(iter, count, value);
1337 }
1338
1341 template <typename TIter>
1342 iterator insert(const_iterator iter, TIter from, TIter to)
1343 {
1344 return Base::insert(iter, from, to);
1345 }
1346
1349 iterator insert(const_iterator iter, std::initializer_list<value_type> init)
1350 {
1351 return Base::insert(iter, init.begin(), init.end());
1352 }
1353
1356 template <typename... TArgs>
1357 iterator emplace(const_iterator iter, TArgs&&... args)
1358 {
1359 return Base::emplace(iter, std::forward<TArgs>(args)...);
1360 }
1361
1365 {
1366 return erase(iter, iter + 1);
1367 }
1368
1372 {
1373 return Base::erase(from, to);
1374 }
1375
1379 void push_back(const T& value)
1380 {
1381 Base::push_back(value);
1382 }
1383
1387 void push_back(T&& value)
1388 {
1389 Base::push_back(std::move(value));
1390 }
1391
1395 template <typename... TArgs>
1396 void emplace_back(TArgs&&... args)
1397 {
1398 Base::emplace_back(std::forward<TArgs>(args)...);
1399 }
1400
1405 {
1406 Base::pop_back();
1407 }
1408
1412 void resize(size_type count)
1413 {
1414 resize(count, T());
1415 }
1416
1420 void resize(size_type count, const value_type& value)
1421 {
1422 Base::resize(count, value);
1423 }
1424
1428 template <std::size_t TOtherSize>
1430 {
1431 Base::swap(other);
1432 }
1433};
1434
1435// Template specialization for zero sized vectors
1436template <typename T>
1437class StaticVector<T, 0U>
1438{
1439 using StorageType = std::array<T, 0U>;
1440
1441 template <typename U, std::size_t TOtherSize>
1442 friend class StaticVector;
1443
1444public:
1445 using value_type = typename StorageType::value_type;
1446 using size_type = typename StorageType::size_type;
1447 using difference_type = typename StorageType::difference_type;
1448 using reference = typename StorageType::reference;
1449 using const_reference = typename StorageType::const_reference;
1450 using pointer = typename StorageType::pointer;
1451 using const_pointer = typename StorageType::const_pointer;
1452 using iterator = typename StorageType::iterator;
1453 using const_iterator = typename StorageType::const_iterator;
1454 using reverse_iterator = typename StorageType::reverse_iterator;
1455 using const_reverse_iterator = typename StorageType::const_reverse_iterator;
1456
1457 StaticVector() = default;
1458
1459 StaticVector(size_type count, const T& value)
1460 {
1461 static_cast<void>(value);
1462 if (count == 0U) {
1463 return;
1464 }
1465
1466 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1467 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1468 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1469 }
1470
1471 explicit StaticVector(size_type count)
1472 {
1473 if (count == 0U) {
1474 return;
1475 }
1476
1477 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1478 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1479 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1480 }
1481
1482 template <typename TIter>
1483 StaticVector(TIter from, TIter to)
1484 {
1485 if (from == to) {
1486 return;
1487 }
1488
1489 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1490 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1491 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1492 }
1493
1494 template <std::size_t TOtherSize>
1495 StaticVector(const StaticVector<T, TOtherSize>& other)
1496 {
1497 static_cast<void>(other);
1498 if (TOtherSize == 0U) {
1499 return;
1500 }
1501
1502 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1503 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1504 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1505 }
1506
1507 StaticVector(const StaticVector& other)
1508 {
1509 static_cast<void>(other);
1510 }
1511
1512 StaticVector(std::initializer_list<value_type> init)
1513 {
1514 if (std::begin(init) == std::end(init)) {
1515 return;
1516 }
1517
1518 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1519 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1520 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1521 }
1522
1523 ~StaticVector() noexcept = default;
1524
1525 StaticVector& operator=(const StaticVector&) = default;
1526
1527 template <std::size_t TOtherSize>
1528 StaticVector& operator=(const StaticVector<T, TOtherSize>& other)
1529 {
1530 static_cast<void>(other);
1531 if (TOtherSize == 0U) {
1532 return *this;
1533 }
1534
1535 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1536 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1537 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1538 return *this;
1539 }
1540
1541 StaticVector& operator=(std::initializer_list<value_type> init)
1542 {
1543 if (std::begin(init) == std::end(init)) {
1544 return *this;
1545 }
1546
1547 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1548 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1549 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1550 return *this;
1551 }
1552
1553 void assign(size_type count, const T& value)
1554 {
1555 static_cast<void>(value);
1556 if (count == 0U) {
1557 return;
1558 }
1559
1560 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1561 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1562 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1563 }
1564
1565 template <typename TIter>
1566 void assign(TIter from, TIter to)
1567 {
1568 if (from == to) {
1569 return;
1570 }
1571
1572 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1573 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1574 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1575 }
1576
1577 void assign(std::initializer_list<value_type> init)
1578 {
1579 if (std::begin(init) == std::end(init)) {
1580 return;
1581 }
1582
1583 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1584 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1585 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1586 }
1587
1588 reference at(size_type pos)
1589 {
1590 static_cast<void>(pos);
1591 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1592 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1593 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1594 return m_data[pos];
1595 }
1596
1597 const_reference at(size_type pos) const
1598 {
1599 static_cast<void>(pos);
1600 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1601 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1602 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1603 return m_data[pos];
1604 }
1605
1606 reference operator[](size_type pos)
1607 {
1608 static_cast<void>(pos);
1609 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1610 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1611 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1612 return m_data[pos];
1613 }
1614
1615 const_reference operator[](size_type pos) const
1616 {
1617 static_cast<void>(pos);
1618 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1619 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1620 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1621 return m_data[pos];
1622 }
1623
1624 reference front()
1625 {
1626 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1627 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1628 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1629 return m_data.front();
1630 }
1631
1632 const_reference front() const
1633 {
1634 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1635 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1636 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1637 return m_data.front();
1638 }
1639
1640 reference back()
1641 {
1642 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1643 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1644 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1645 return m_data.back();
1646 }
1647
1648 const_reference back() const
1649 {
1650 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1651 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1652 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1653 return m_data.back();
1654 }
1655
1656 pointer data()
1657 {
1658 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1659 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1660 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1661 return m_data.data();
1662 }
1663
1664 const_pointer data() const
1665 {
1666 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1667 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1668 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1669 return m_data.data();
1670 }
1671
1672 iterator begin()
1673 {
1674 return m_data.begin();
1675 }
1676
1677 const_iterator begin() const
1678 {
1679 return m_data.begin();
1680 }
1681
1682 const_iterator cbegin() const
1683 {
1684 return m_data.cbegin();
1685 }
1686
1687 iterator end()
1688 {
1689 return m_data.end();
1690 }
1691
1692 const_iterator end() const
1693 {
1694 return m_data.end();
1695 }
1696
1697 const_iterator cend() const
1698 {
1699 return m_data.cend();
1700 }
1701
1702 reverse_iterator rbegin()
1703 {
1704 return m_data.rbegin();
1705 }
1706
1707 const_reverse_iterator rbegin() const
1708 {
1709 return m_data.rbegin();
1710 }
1711
1712 const_reverse_iterator crbegin() const
1713 {
1714 return m_data.crbegin();
1715 }
1716
1717 reverse_iterator rend()
1718 {
1719 return m_data.rend();
1720 }
1721
1722 const_reverse_iterator rend() const
1723 {
1724 return m_data.rend();
1725 }
1726
1727 const_reverse_iterator crend() const
1728 {
1729 return m_data.crend();
1730 }
1731
1732 bool empty() const
1733 {
1734 return m_data.empty();
1735 }
1736
1737 size_type size() const
1738 {
1739 return m_data.size();
1740 }
1741
1742 size_type max_size() const
1743 {
1744 return m_data.max_size();
1745 }
1746
1747 void reserve(size_type new_cap)
1748 {
1749 static_cast<void>(new_cap);
1750 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1751 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1752 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1753 }
1754
1755 size_type capacity() const
1756 {
1757 return max_size();
1758 }
1759
1760 void shrink_to_fit()
1761 {
1762 }
1763
1764 void clear()
1765 {
1766 }
1767
1768 iterator insert(const_iterator iter, const T& value)
1769 {
1770 static_cast<void>(iter);
1771 static_cast<void>(value);
1772 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1773 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1774 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1775 return m_data.end();
1776 }
1777
1778 iterator insert(const_iterator iter, T&& value)
1779 {
1780 static_cast<void>(iter);
1781 static_cast<void>(value);
1782 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1783 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1784 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1785 return m_data.end();
1786 }
1787
1788 iterator insert(const_iterator iter, size_type count, const T& value)
1789 {
1790 static_cast<void>(iter);
1791 static_cast<void>(count);
1792 static_cast<void>(value);
1793 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1794 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1795 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1796 return m_data.end();
1797 }
1798
1799 template <typename TIter>
1800 iterator insert(const_iterator iter, TIter from, TIter to)
1801 {
1802 static_cast<void>(iter);
1803 static_cast<void>(from);
1804 static_cast<void>(to);
1805 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1806 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1807 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1808 return m_data.end();
1809 }
1810
1811 iterator insert(const_iterator iter, std::initializer_list<value_type> init)
1812 {
1813 static_cast<void>(iter);
1814 static_cast<void>(init);
1815 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1816 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1817 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1818 return m_data.end();
1819 }
1820
1821 template <typename... TArgs>
1822 iterator emplace(const_iterator iter, TArgs&&...)
1823 {
1824 static_cast<void>(iter);
1825 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1826 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1827 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1828 return m_data.end();
1829 }
1830
1831 iterator erase(const_iterator iter)
1832 {
1833 static_cast<void>(iter);
1834 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1835 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1836 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1837 return m_data.end();
1838 }
1839
1840 iterator erase(const_iterator from, const_iterator to)
1841 {
1842 if (from != to) {
1843 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1844 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1845 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1846 }
1847 return m_data.end();
1848 }
1849
1850 void push_back(const T& value)
1851 {
1852 static_cast<void>(value);
1853 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1854 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1855 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1856 }
1857
1858 void push_back(T&& value)
1859 {
1860 static_cast<void>(value);
1861 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1862 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1863 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1864 }
1865
1866 template <typename... TArgs>
1867 void emplace_back(TArgs&&...)
1868 {
1869 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1870 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1871 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1872 }
1873
1874 void pop_back()
1875 {
1876 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1877 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1878 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1879 }
1880
1881 void resize(size_type count)
1882 {
1883 if (count == 0U) {
1884 return;
1885 }
1886
1887 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1888 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1889 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1890 }
1891
1892 void resize(size_type count, const value_type& value)
1893 {
1894 static_cast<void>(value);
1895 if (count == 0U) {
1896 return;
1897 }
1898
1899 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1900 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1901 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1902 }
1903
1904 template <std::size_t TOtherSize>
1905 void swap(StaticVector<T, TOtherSize>& other)
1906 {
1907 static_cast<void>(other);
1908 if (TOtherSize != 0U) {
1909 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1910 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1911 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1912 }
1913 }
1914
1915private:
1916 StorageType m_data;
1917};
1918
1922template <typename T, std::size_t TSize1, std::size_t TSize2>
1924{
1925 return std::lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end());
1926}
1927
1931template <typename T, std::size_t TSize1, std::size_t TSize2>
1933{
1934 return !(v2 < v1);
1935}
1936
1940template <typename T, std::size_t TSize1, std::size_t TSize2>
1942{
1943 return v2 < v1;
1944}
1945
1949template <typename T, std::size_t TSize1, std::size_t TSize2>
1951{
1952 return !(v1 < v2);
1953}
1954
1958template <typename T, std::size_t TSize1, std::size_t TSize2>
1960{
1961 return (v1.size() == v2.size()) &&
1962 (!(v1 < v2)) &&
1963 (!(v2 < v1));
1964}
1965
1969template <typename T, std::size_t TSize1, std::size_t TSize2>
1971{
1972 return !(v1 == v2);
1973}
1974
1975namespace details
1976{
1977
1978template <typename T>
1979struct IsStaticVector
1980{
1981 static const bool Value = false;
1982};
1983
1984template <typename T, std::size_t TSize>
1985struct IsStaticVector<comms::util::StaticVector<T, TSize> >
1986{
1987 static const bool Value = true;
1988};
1989
1990} // namespace details
1991
1995template <typename T>
1996static constexpr bool isStaticVector()
1997{
1998 return details::IsStaticVector<T>::Value;
1999}
2000
2001} // namespace util
2002
2003} // namespace comms
2004
2005namespace std
2006{
2007
2011template <typename T, std::size_t TSize1, std::size_t TSize2>
2016
2017}
2018
2019COMMS_MSVC_WARNING_POP
2020COMMS_GNU_WARNING_POP
Replacement of std::aligned_storage due to deprecation since C++23.
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
Contains various compiler related definitions.
Replacement to std::vector when no dynamic memory allocation is allowed.
Definition StaticVector.h:961
const_iterator cend() const
Returns an iterator to the end.
Definition StaticVector.h:1217
void assign(std::initializer_list< value_type > init)
Assigns values to the container.
Definition StaticVector.h:1093
reference at(size_type pos)
Access specified element with bounds checking.
Definition StaticVector.h:1104
size_type max_size() const
Returns the maximum possible number of elements.
Definition StaticVector.h:1282
typename Base::const_reference const_reference
Const reference to single element.
Definition StaticVector.h:985
void assign(size_type count, const T &value)
Assigns values to the container.
Definition StaticVector.h:1078
void resize(size_type count)
Changes the number of elements stored.
Definition StaticVector.h:1412
const_reverse_iterator rbegin() const
Returns a reverse iterator to the beginning.
Definition StaticVector.h:1231
iterator begin()
Returns an iterator to the beginning.
Definition StaticVector.h:1182
static constexpr bool isStaticVector()
Compile time check whether the provided type is a variant of comms::util::StaticVector.
Definition StaticVector.h:1996
void swap(StaticVector< T, TOtherSize > &other)
Swaps the contents.
Definition StaticVector.h:1429
const_iterator begin() const
Returns an iterator to the beginning.
Definition StaticVector.h:1189
const_reference at(size_type pos) const
Access specified element with bounds checking.
Definition StaticVector.h:1115
StaticVector(TIter from, TIter to)
Constructor.
Definition StaticVector.h:1025
typename Base::reference reference
Reference to single element.
Definition StaticVector.h:982
StaticVector(const StaticVector< T, TOtherSize > &other)
Copy constructor.
Definition StaticVector.h:1033
bool operator!=(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition StaticVector.h:1970
StaticVector(size_type count)
Constructor.
Definition StaticVector.h:1017
StaticVector(const StaticVector &other)
Copy constructor.
Definition StaticVector.h:1040
iterator insert(const_iterator iter, std::initializer_list< value_type > init)
Inserts elements.
Definition StaticVector.h:1349
const_reference operator[](size_type pos) const
Access specified element without bounds checking.
Definition StaticVector.h:1129
size_type capacity() const
Returns the number of elements that can be held in currently allocated storage.
Definition StaticVector.h:1299
void assign(TIter from, TIter to)
Assigns values to the container.
Definition StaticVector.h:1086
reference front()
Access the first element.
Definition StaticVector.h:1137
const_reference back() const
Access the last element.
Definition StaticVector.h:1161
void clear()
Clears the contents.
Definition StaticVector.h:1313
reference back()
Access the last element.
Definition StaticVector.h:1153
const_reference front() const
Access the first element.
Definition StaticVector.h:1145
bool operator<(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition StaticVector.h:1923
bool operator<=(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition StaticVector.h:1932
iterator insert(const_iterator iter, T &&value)
Inserts elements.
Definition StaticVector.h:1327
const_iterator end() const
Returns an iterator to the end.
Definition StaticVector.h:1210
typename Base::size_type size_type
Type used for size information.
Definition StaticVector.h:976
StaticVector(std::initializer_list< value_type > init)
Constructor.
Definition StaticVector.h:1047
StaticVector()=default
Default constructor.
StaticVector(size_type count, const T &value)
Constructor.
Definition StaticVector.h:1010
const_reverse_iterator rend() const
Returns a reverse iterator to the end.
Definition StaticVector.h:1252
void pop_back()
Removes the last element.
Definition StaticVector.h:1404
void resize(size_type count, const value_type &value)
Changes the number of elements stored.
Definition StaticVector.h:1420
void shrink_to_fit()
Reduces memory usage by freeing unused memory.
Definition StaticVector.h:1307
typename Base::iterator iterator
Type of the iterator.
Definition StaticVector.h:994
iterator insert(const_iterator iter, TIter from, TIter to)
Inserts elements.
Definition StaticVector.h:1342
const_reverse_iterator crbegin() const
Returns a reverse iterator to the beginning.
Definition StaticVector.h:1238
iterator insert(const_iterator iter, const T &value)
Inserts elements.
Definition StaticVector.h:1320
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition StaticVector.h:1245
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition StaticVector.h:1224
typename Base::StorageType::difference_type difference_type
Type used in pointer arithmetics.
Definition StaticVector.h:979
iterator end()
Returns an iterator to the end.
Definition StaticVector.h:1203
bool operator>(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition StaticVector.h:1941
void push_back(const T &value)
Adds an element to the end.
Definition StaticVector.h:1379
typename Base::value_type value_type
Type of single element.
Definition StaticVector.h:973
iterator erase(const_iterator from, const_iterator to)
Erases elements.
Definition StaticVector.h:1371
void swap(comms::util::StaticVector< T, TSize1 > &v1, comms::util::StaticVector< T, TSize2 > &v2)
Specializes the std::swap algorithm.
Definition StaticVector.h:2012
void reserve(size_type new_cap)
Reserves storage.
Definition StaticVector.h:1290
iterator insert(const_iterator iter, size_type count, const T &value)
Inserts elements.
Definition StaticVector.h:1334
size_type size() const
Returns the number of elements.
Definition StaticVector.h:1273
typename Base::const_reverse_iterator const_reverse_iterator
Type of the const reverse iterator.
Definition StaticVector.h:1003
bool operator==(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition StaticVector.h:1959
void push_back(T &&value)
Adds an element to the end.
Definition StaticVector.h:1387
typename Base::const_pointer const_pointer
Const pointer to single element.
Definition StaticVector.h:991
bool operator>=(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition StaticVector.h:1950
iterator emplace(const_iterator iter, TArgs &&... args)
Constructs elements in place.
Definition StaticVector.h:1357
void emplace_back(TArgs &&... args)
Constructs an element in place at the end.
Definition StaticVector.h:1396
typename Base::const_iterator const_iterator
Type of the const iterator.
Definition StaticVector.h:997
~StaticVector() noexcept=default
Destructor.
iterator erase(const_iterator iter)
Erases elements.
Definition StaticVector.h:1364
StaticVector & operator=(std::initializer_list< value_type > init)
Copy assignement.
Definition StaticVector.h:1070
bool empty() const
Checks whether the container is empty.
Definition StaticVector.h:1266
const_pointer data() const
Direct access to the underlying array.
Definition StaticVector.h:1175
pointer data()
Direct access to the underlying array.
Definition StaticVector.h:1168
typename Base::reverse_iterator reverse_iterator
Type of the reverse iterator.
Definition StaticVector.h:1000
typename Base::pointer pointer
Pointer to single element.
Definition StaticVector.h:988
const_reverse_iterator crend() const
Returns a reverse iterator to the end.
Definition StaticVector.h:1259
reference operator[](size_type pos)
Access specified element without bounds checking.
Definition StaticVector.h:1122
const_iterator cbegin() const
Returns an iterator to the beginning.
Definition StaticVector.h:1196
void assign(T &obj, TIter from, TIter to)
Assigns a new value to provided object.
Definition assign.h:41
Main namespace for all classes / functions of COMMS library.
STL namespace.