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 - 2024 (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 <cstddef>
14#include <array>
15#include <algorithm>
16#include <iterator>
17#include <initializer_list>
18
20#include "comms/Assert.h"
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 : data_(dataPtr),
64 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 size_;
80 }
81
82 std::size_t capacity() const
83 {
84 return 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 --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 ++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 size_ = count;
149 }
150
151 void clear() {
152 for (auto idx = 0U; idx < size(); ++idx) {
153 elem(idx).~T();
154 }
155 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 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 ++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 ++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.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 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 data_[idx];
435 }
436
437 const CellType& cell(std::size_t idx) const
438 {
439 COMMS_ASSERT(idx < capacity());
440 return data_[idx];
441 }
442
443 CellType* cellPtr(std::size_t idx)
444 {
445 COMMS_ASSERT(idx < capacity());
446 return &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* data_ = nullptr;
547 std::size_t capacity_ = 0;
548 std::size_t 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 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::data_.data(), StorageBase::data_.size())
582 {
583 }
584
585 StaticVectorGeneric(size_type count, const T& value)
586 : Base(StorageBase::data_.data(), StorageBase::data_.size())
587 {
588 assign(count, value);
589 }
590
591 explicit StaticVectorGeneric(size_type count)
592 : Base(StorageBase::data_.data(), StorageBase::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::data_.data(), StorageBase::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::data_.data(), StorageBase::data_.size())
611 {
612 assign(other.begin(), other.end());
613 }
614
615 StaticVectorGeneric(const StaticVectorGeneric& other)
616 : Base(StorageBase::data_.data(), StorageBase::data_.size())
617 {
618 assign(other.begin(), other.end());
619 }
620
621 StaticVectorGeneric(std::initializer_list<value_type> init)
622 : Base(StorageBase::data_.data(), StorageBase::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 }
1114 {
1115 return Base::at(pos);
1116 }
1117
1121 {
1122 return Base::operator[](pos);
1123 }
1124
1128 {
1129 return Base::operator[](pos);
1130 }
1131
1136 {
1137 return Base::front();
1138 }
1139
1144 {
1145 return Base::front();
1146 }
1147
1152 {
1153 return Base::back();
1154 }
1155
1160 {
1161 return Base::back();
1162 }
1163
1167 {
1168 return Base::data();
1169 }
1170
1174 {
1175 return Base::data();
1176 }
1177
1181 {
1182 return Base::begin();
1183 }
1184
1188 {
1189 return cbegin();
1190 }
1191
1195 {
1196 return Base::cbegin();
1197 }
1198
1202 {
1203 return Base::end();
1204 }
1205
1209 {
1210 return cend();
1211 }
1212
1216 {
1217 return Base::cend();
1218 }
1219
1223 {
1224 return reverse_iterator(end());
1225 }
1226
1230 {
1231 return crbegin();
1232 }
1233
1237 {
1238 return const_reverse_iterator(cend());
1239 }
1240
1244 {
1245 return reverse_iterator(begin());
1246 }
1247
1251 {
1252 return crend();
1253 }
1254
1258 {
1259 return const_reverse_iterator(cbegin());
1260 }
1261
1264 bool empty() const
1265 {
1266 return Base::empty();
1267 }
1268
1272 {
1273 return Base::size();
1274 }
1275
1281 {
1282 return capacity();
1283 }
1284
1288 void reserve(size_type new_cap)
1289 {
1290 return Base::reserve(new_cap);
1291 }
1292
1298 {
1299 return Base::capacity();
1300 }
1301
1306 {
1307 }
1308
1311 void clear()
1312 {
1313 Base::clear();
1314 }
1315
1318 iterator insert(const_iterator iter, const T& value)
1319 {
1320 return Base::insert(iter, value);
1321 }
1322
1326 {
1327 return Base::insert(iter, std::move(value));
1328 }
1329
1332 iterator insert(const_iterator iter, size_type count, const T& value)
1333 {
1334 return Base::insert(iter, count, value);
1335 }
1336
1339 template <typename TIter>
1340 iterator insert(const_iterator iter, TIter from, TIter to)
1341 {
1342 return Base::insert(iter, from, to);
1343 }
1344
1347 iterator insert(const_iterator iter, std::initializer_list<value_type> init)
1348 {
1349 return Base::insert(iter, init.begin(), init.end());
1350 }
1351
1354 template <typename... TArgs>
1355 iterator emplace(const_iterator iter, TArgs&&... args)
1356 {
1357 return Base::emplace(iter, std::forward<TArgs>(args)...);
1358 }
1359
1363 {
1364 return erase(iter, iter + 1);
1365 }
1366
1370 {
1371 return Base::erase(from, to);
1372 }
1373
1377 void push_back(const T& value)
1378 {
1379 Base::push_back(value);
1380 }
1381
1385 void push_back(T&& value)
1386 {
1387 Base::push_back(std::move(value));
1388 }
1389
1393 template <typename... TArgs>
1394 void emplace_back(TArgs&&... args)
1395 {
1396 Base::emplace_back(std::forward<TArgs>(args)...);
1397 }
1398
1403 {
1404 Base::pop_back();
1405 }
1406
1410 void resize(size_type count)
1411 {
1412 resize(count, T());
1413 }
1414
1418 void resize(size_type count, const value_type& value)
1419 {
1420 Base::resize(count, value);
1421 }
1422
1426 template <std::size_t TOtherSize>
1428 {
1429 Base::swap(other);
1430 }
1431};
1432
1433// Template specialization for zero sized vectors
1434template <typename T>
1435class StaticVector<T, 0U>
1436{
1437 using StorageType = std::array<T, 0U>;
1438
1439 template <typename U, std::size_t TOtherSize>
1440 friend class StaticVector;
1441
1442public:
1443 using value_type = typename StorageType::value_type;
1444 using size_type = typename StorageType::size_type;
1445 using difference_type = typename StorageType::difference_type;
1446 using reference = typename StorageType::reference;
1447 using const_reference = typename StorageType::const_reference;
1448 using pointer = typename StorageType::pointer;
1449 using const_pointer = typename StorageType::const_pointer;
1450 using iterator = typename StorageType::iterator;
1451 using const_iterator = typename StorageType::const_iterator;
1452 using reverse_iterator = typename StorageType::reverse_iterator;
1453 using const_reverse_iterator = typename StorageType::const_reverse_iterator;
1454
1455 StaticVector() = default;
1456
1457 StaticVector(size_type count, const T& value)
1458 {
1459 static_cast<void>(value);
1460 if (count == 0U) {
1461 return;
1462 }
1463
1464 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1465 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1466 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1467 }
1468
1469 explicit StaticVector(size_type count)
1470 {
1471 if (count == 0U) {
1472 return;
1473 }
1474
1475 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1476 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1477 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1478 }
1479
1480 template <typename TIter>
1481 StaticVector(TIter from, TIter to)
1482 {
1483 if (from == to) {
1484 return;
1485 }
1486
1487 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1488 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1489 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1490 }
1491
1492 template <std::size_t TOtherSize>
1493 StaticVector(const StaticVector<T, TOtherSize>& other)
1494 {
1495 static_cast<void>(other);
1496 if (TOtherSize == 0U) {
1497 return;
1498 }
1499
1500 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1501 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1502 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1503 }
1504
1505 StaticVector(const StaticVector& other)
1506 {
1507 static_cast<void>(other);
1508 }
1509
1510 StaticVector(std::initializer_list<value_type> init)
1511 {
1512 if (std::begin(init) == std::end(init)) {
1513 return;
1514 }
1515
1516 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1517 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1518 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1519 }
1520
1521 ~StaticVector() noexcept = default;
1522
1523 StaticVector& operator=(const StaticVector&) = default;
1524
1525 template <std::size_t TOtherSize>
1526 StaticVector& operator=(const StaticVector<T, TOtherSize>& other)
1527 {
1528 static_cast<void>(other);
1529 if (TOtherSize == 0U) {
1530 return *this;
1531 }
1532
1533 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1534 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1535 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1536 return *this;
1537 }
1538
1539 StaticVector& operator=(std::initializer_list<value_type> init)
1540 {
1541 if (std::begin(init) == std::end(init)) {
1542 return *this;
1543 }
1544
1545 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1546 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1547 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1548 return *this;
1549 }
1550
1551 void assign(size_type count, const T& value)
1552 {
1553 static_cast<void>(value);
1554 if (count == 0U) {
1555 return;
1556 }
1557
1558 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1559 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1560 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1561 }
1562
1563 template <typename TIter>
1564 void assign(TIter from, TIter to)
1565 {
1566 if (from == to) {
1567 return;
1568 }
1569
1570 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1571 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1572 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1573 }
1574
1575 void assign(std::initializer_list<value_type> init)
1576 {
1577 if (std::begin(init) == std::end(init)) {
1578 return;
1579 }
1580
1581 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1582 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1583 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1584 }
1585
1586 reference at(size_type pos)
1587 {
1588 static_cast<void>(pos);
1589 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1590 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1591 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1592 return m_data[pos];
1593 }
1594
1595 const_reference at(size_type pos) const
1596 {
1597 static_cast<void>(pos);
1598 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1599 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1600 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1601 return m_data[pos];
1602 }
1603
1604 reference operator[](size_type pos)
1605 {
1606 static_cast<void>(pos);
1607 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1608 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1609 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1610 return m_data[pos];
1611 }
1612
1613 const_reference operator[](size_type pos) const
1614 {
1615 static_cast<void>(pos);
1616 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1617 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1618 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1619 return m_data[pos];
1620 }
1621
1622 reference front()
1623 {
1624 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1625 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1626 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1627 return m_data.front();
1628 }
1629
1630 const_reference front() const
1631 {
1632 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1633 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1634 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1635 return m_data.front();
1636 }
1637
1638 reference back()
1639 {
1640 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1641 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1642 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1643 return m_data.back();
1644 }
1645
1646 const_reference back() const
1647 {
1648 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1649 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1650 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1651 return m_data.back();
1652 }
1653
1654 pointer data()
1655 {
1656 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1657 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1658 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1659 return m_data.data();
1660 }
1661
1662 const_pointer data() const
1663 {
1664 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1665 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1666 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1667 return m_data.data();
1668 }
1669
1670 iterator begin()
1671 {
1672 return m_data.begin();
1673 }
1674
1675 const_iterator begin() const
1676 {
1677 return m_data.begin();
1678 }
1679
1680 const_iterator cbegin() const
1681 {
1682 return m_data.cbegin();
1683 }
1684
1685 iterator end()
1686 {
1687 return m_data.end();
1688 }
1689
1690 const_iterator end() const
1691 {
1692 return m_data.end();
1693 }
1694
1695 const_iterator cend() const
1696 {
1697 return m_data.cend();
1698 }
1699
1700 reverse_iterator rbegin()
1701 {
1702 return m_data.rbegin();
1703 }
1704
1705 const_reverse_iterator rbegin() const
1706 {
1707 return m_data.rbegin();
1708 }
1709
1710 const_reverse_iterator crbegin() const
1711 {
1712 return m_data.crbegin();
1713 }
1714
1715 reverse_iterator rend()
1716 {
1717 return m_data.rend();
1718 }
1719
1720 const_reverse_iterator rend() const
1721 {
1722 return m_data.rend();
1723 }
1724
1725 const_reverse_iterator crend() const
1726 {
1727 return m_data.crend();
1728 }
1729
1730 bool empty() const
1731 {
1732 return m_data.empty();
1733 }
1734
1735 size_type size() const
1736 {
1737 return m_data.size();
1738 }
1739
1740 size_type max_size() const
1741 {
1742 return m_data.max_size();
1743 }
1744
1745 void reserve(size_type new_cap)
1746 {
1747 static_cast<void>(new_cap);
1748 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1749 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1750 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1751 }
1752
1753 size_type capacity() const
1754 {
1755 return max_size();
1756 }
1757
1758 void shrink_to_fit()
1759 {
1760 }
1761
1762 void clear()
1763 {
1764 }
1765
1766 iterator insert(const_iterator iter, const T& value)
1767 {
1768 static_cast<void>(iter);
1769 static_cast<void>(value);
1770 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1771 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1772 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1773 return m_data.end();
1774 }
1775
1776 iterator insert(const_iterator iter, T&& value)
1777 {
1778 static_cast<void>(iter);
1779 static_cast<void>(value);
1780 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1781 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1782 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1783 return m_data.end();
1784 }
1785
1786 iterator insert(const_iterator iter, size_type count, const T& value)
1787 {
1788 static_cast<void>(iter);
1789 static_cast<void>(count);
1790 static_cast<void>(value);
1791 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1792 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1793 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1794 return m_data.end();
1795 }
1796
1797 template <typename TIter>
1798 iterator insert(const_iterator iter, TIter from, TIter to)
1799 {
1800 static_cast<void>(iter);
1801 static_cast<void>(from);
1802 static_cast<void>(to);
1803 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1804 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1805 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1806 return m_data.end();
1807 }
1808
1809 iterator insert(const_iterator iter, std::initializer_list<value_type> init)
1810 {
1811 static_cast<void>(iter);
1812 static_cast<void>(init);
1813 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1814 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1815 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1816 return m_data.end();
1817 }
1818
1819 template <typename... TArgs>
1820 iterator emplace(const_iterator iter, TArgs&&...)
1821 {
1822 static_cast<void>(iter);
1823 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1824 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1825 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1826 return m_data.end();
1827 }
1828
1829 iterator erase(const_iterator iter)
1830 {
1831 static_cast<void>(iter);
1832 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1833 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1834 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1835 return m_data.end();
1836 }
1837
1838 iterator erase(const_iterator from, const_iterator to)
1839 {
1840 if (from != to) {
1841 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1842 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1843 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1844 }
1845 return m_data.end();
1846 }
1847
1848 void push_back(const T& value)
1849 {
1850 static_cast<void>(value);
1851 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1852 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1853 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1854 }
1855
1856 void push_back(T&& value)
1857 {
1858 static_cast<void>(value);
1859 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1860 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1861 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1862 }
1863
1864 template <typename... TArgs>
1865 void emplace_back(TArgs&&...)
1866 {
1867 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1868 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1869 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1870 }
1871
1872 void pop_back()
1873 {
1874 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1875 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1876 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1877 }
1878
1879 void resize(size_type count)
1880 {
1881 if (count == 0U) {
1882 return;
1883 }
1884
1885 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1886 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1887 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1888 }
1889
1890 void resize(size_type count, const value_type& value)
1891 {
1892 static_cast<void>(value);
1893 if (count == 0U) {
1894 return;
1895 }
1896
1897 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1898 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1899 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1900 }
1901
1902 template <std::size_t TOtherSize>
1903 void swap(StaticVector<T, TOtherSize>& other)
1904 {
1905 static_cast<void>(other);
1906 if (TOtherSize != 0U) {
1907 static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1908 static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1909 COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1910 }
1911 }
1912
1913private:
1914 StorageType m_data;
1915};
1916
1920template <typename T, std::size_t TSize1, std::size_t TSize2>
1922{
1923 return std::lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end());
1924}
1925
1929template <typename T, std::size_t TSize1, std::size_t TSize2>
1931{
1932 return !(v2 < v1);
1933}
1934
1938template <typename T, std::size_t TSize1, std::size_t TSize2>
1940{
1941 return v2 < v1;
1942}
1943
1947template <typename T, std::size_t TSize1, std::size_t TSize2>
1949{
1950 return !(v1 < v2);
1951}
1952
1956template <typename T, std::size_t TSize1, std::size_t TSize2>
1958{
1959 return (v1.size() == v2.size()) &&
1960 (!(v1 < v2)) &&
1961 (!(v2 < v1));
1962}
1963
1967template <typename T, std::size_t TSize1, std::size_t TSize2>
1969{
1970 return !(v1 == v2);
1971}
1972
1973namespace details
1974{
1975
1976
1977template <typename T>
1978struct IsStaticVector
1979{
1980 static const bool Value = false;
1981};
1982
1983template <typename T, std::size_t TSize>
1984struct IsStaticVector<comms::util::StaticVector<T, TSize> >
1985{
1986 static const bool Value = true;
1987};
1988
1989} // namespace details
1990
1994template <typename T>
1995static constexpr bool isStaticVector()
1996{
1997 return details::IsStaticVector<T>::Value;
1998}
1999
2000} // namespace util
2001
2002} // namespace comms
2003
2004namespace std
2005{
2006
2010template <typename T, std::size_t TSize1, std::size_t TSize2>
2015
2016}
2017
2018COMMS_MSVC_WARNING_POP
2019COMMS_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:1215
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:1280
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:1410
const_reverse_iterator rbegin() const
Returns a reverse iterator to the beginning.
Definition StaticVector.h:1229
iterator begin()
Returns an iterator to the beginning.
Definition StaticVector.h:1180
static constexpr bool isStaticVector()
Compile time check whether the provided type is a variant of comms::util::StaticVector.
Definition StaticVector.h:1995
void swap(StaticVector< T, TOtherSize > &other)
Swaps the contents.
Definition StaticVector.h:1427
const_iterator begin() const
Returns an iterator to the beginning.
Definition StaticVector.h:1187
const_reference at(size_type pos) const
Access specified element with bounds checking.
Definition StaticVector.h:1113
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:1968
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:1347
const_reference operator[](size_type pos) const
Access specified element without bounds checking.
Definition StaticVector.h:1127
size_type capacity() const
Returns the number of elements that can be held in currently allocated storage.
Definition StaticVector.h:1297
void assign(TIter from, TIter to)
Assigns values to the container.
Definition StaticVector.h:1085
reference front()
Access the first element.
Definition StaticVector.h:1135
const_reference back() const
Access the last element.
Definition StaticVector.h:1159
void clear()
Clears the contents.
Definition StaticVector.h:1311
reference back()
Access the last element.
Definition StaticVector.h:1151
const_reference front() const
Access the first element.
Definition StaticVector.h:1143
bool operator<(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition StaticVector.h:1921
bool operator<=(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition StaticVector.h:1930
iterator insert(const_iterator iter, T &&value)
Inserts elements.
Definition StaticVector.h:1325
const_iterator end() const
Returns an iterator to the end.
Definition StaticVector.h:1208
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:1250
void pop_back()
Removes the last element.
Definition StaticVector.h:1402
void resize(size_type count, const value_type &value)
Changes the number of elements stored.
Definition StaticVector.h:1418
void shrink_to_fit()
Reduces memory usage by freeing unused memory.
Definition StaticVector.h:1305
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:1340
const_reverse_iterator crbegin() const
Returns a reverse iterator to the beginning.
Definition StaticVector.h:1236
iterator insert(const_iterator iter, const T &value)
Inserts elements.
Definition StaticVector.h:1318
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition StaticVector.h:1243
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition StaticVector.h:1222
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:1201
bool operator>(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition StaticVector.h:1939
void push_back(const T &value)
Adds an element to the end.
Definition StaticVector.h:1377
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:1369
void swap(comms::util::StaticVector< T, TSize1 > &v1, comms::util::StaticVector< T, TSize2 > &v2)
Specializes the std::swap algorithm.
Definition StaticVector.h:2011
void reserve(size_type new_cap)
Reserves storage.
Definition StaticVector.h:1288
iterator insert(const_iterator iter, size_type count, const T &value)
Inserts elements.
Definition StaticVector.h:1332
size_type size() const
Returns the number of elements.
Definition StaticVector.h:1271
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:1957
void push_back(T &&value)
Adds an element to the end.
Definition StaticVector.h:1385
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:1948
iterator emplace(const_iterator iter, TArgs &&... args)
Constructs elements in place.
Definition StaticVector.h:1355
void emplace_back(TArgs &&... args)
Constructs an element in place at the end.
Definition StaticVector.h:1394
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:1362
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:1264
const_pointer data() const
Direct access to the underlying array.
Definition StaticVector.h:1173
pointer data()
Direct access to the underlying array.
Definition StaticVector.h:1166
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:1257
reference operator[](size_type pos)
Access specified element without bounds checking.
Definition StaticVector.h:1120
const_iterator cbegin() const
Returns an iterator to the beginning.
Definition StaticVector.h:1194
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.