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