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