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