COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
StaticQueue.h
Go to the documentation of this file.
1//
2// Copyright 2012 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: MPL-2.0
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
13
14#pragma once
15
16#include "comms/Assert.h"
19#include "comms/util/SizeToType.h"
21
22#include <algorithm>
23#include <array>
24#include <cstddef>
25#include <cstdint>
26#include <iterator>
27#include <stdexcept>
28#include <string>
29#include <type_traits>
30#include <utility>
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 StaticQueueBase
46{
47public:
48 template <typename TDerived, typename TQueueType>
49 class IteratorBase;
50
51 class ConstIterator;
52 class Iterator;
53
54protected:
55 using ValueType = T;
56 using StorageType = comms::util::AlignedStorage<sizeof(ValueType), std::alignment_of<ValueType>::value>;
57 using StorageTypePtr = StorageType*;
58 using ConstStorageTypePtr = const StorageType*;
59 using SizeType = std::size_t;
60 using Reference = ValueType&;
61 using ConstReference = const ValueType&;
62 using Pointer = ValueType*;
63 using ConstPointer = const ValueType*;
64 using LinearisedIterator = Pointer;
65 using ConstLinearisedIterator = ConstPointer;
66 using ReverseLinearisedIterator = std::reverse_iterator<LinearisedIterator>;
67 using ConstReverseLinearisedIterator = std::reverse_iterator<ConstLinearisedIterator>;
68 using LinearisedIteratorRange = std::pair<LinearisedIterator, LinearisedIterator>;
69 using ConstLinearisedIteratorRange = std::pair<ConstLinearisedIterator, ConstLinearisedIterator>;
70
71 StaticQueueBase(StorageTypePtr data, std::size_t capacity)
72 : m_data(data),
73 m_capacity(capacity),
74 m_startIdx(0),
75 m_count(0)
76 {
77 }
78
79 StaticQueueBase(const StaticQueueBase&) = delete;
80 StaticQueueBase(StaticQueueBase&&) = delete;
81
82 ~StaticQueueBase() noexcept
83 {
84 clear();
85 }
86
87 StaticQueueBase& operator=(const StaticQueueBase& other)
88 {
89 if (this == &other) {
90 return *this;
91 }
92
93 clear();
94 assignElements(other);
95 return *this;
96 }
97
98 StaticQueueBase& operator=(StaticQueueBase&& other)
99 {
100 if (this == &other) {
101 return *this;
102 }
103
104 clear();
105 assignElements(std::move(other));
106 return *this;
107 }
108
109 constexpr std::size_t capacity() const
110 {
111 return m_capacity;
112 }
113
114 std::size_t size() const
115 {
116 return m_count;
117 }
118
119 void clear()
120 {
121 while (!empty()) {
122 popFront();
123 }
124 }
125
126 bool empty() const
127 {
128 return (size() == 0);
129 }
130
131 bool full() const
132 {
133 return (size() == capacity());
134 }
135
136 Reference front()
137 {
138 COMMS_ASSERT(!empty());
139 return (*this)[0];
140 }
141
142 ConstReference front() const
143 {
144 COMMS_ASSERT(!empty());
145 return (*this)[0];
146 }
147
148 Reference back()
149 {
150 auto constThis = static_cast<const StaticQueueBase*>(this);
151 return const_cast<Reference>(constThis->back());
152 }
153
154 ConstReference back() const
155 {
156 COMMS_ASSERT(!empty());
157 if (empty()) {
158 return (*this)[0]; // Back() on empty queue
159 }
160
161 return (*this)[m_count - 1];
162 }
163
164 void popFront()
165 {
166 COMMS_ASSERT(!empty()); // Queue musn't be empty
167 if (empty())
168 {
169 // Do nothing
170 return;
171 }
172
173 Reference element = front();
174 element.~T();
175
176 --m_count;
177 ++m_startIdx;
178 if ((capacity() <= m_startIdx) ||
179 (empty())) {
180 m_startIdx = 0;
181 }
182 }
183
184 void popFront(std::size_t count)
185 {
186 COMMS_ASSERT(count <= size());
187 while ((!empty()) && (count > 0)) {
188 popFront();
189 --count;
190 }
191 }
192
193 void popBack()
194 {
195 COMMS_ASSERT(!empty());
196 if (empty())
197 {
198 // Do nothing
199 return;
200 }
201
202 Reference element = back();
203 element.~T();
204
205 --m_count;
206 }
207
208 void popBack(std::size_t count)
209 {
210 COMMS_ASSERT(count <= size());
211 while ((!empty()) && (count > 0)) {
212 popBack();
213 --count;
214 }
215 }
216
217 Reference operator[](std::size_t index)
218 {
219 auto constThis = static_cast<const StaticQueueBase*>(this);
220 return const_cast<Reference>((*constThis)[index]);
221 }
222
223 ConstReference operator[](std::size_t index) const
224 {
225 COMMS_ASSERT(index < size());
226 return elementAtIndex(index);
227 }
228
229 Reference at(std::size_t index)
230 {
231 auto constThis = static_cast<const StaticQueueBase*>(this);
232 return const_cast<Reference>(constThis->at(index));
233 }
234
235 ConstReference at(std::size_t index) const
236 {
237 if (index >= size()) {
238 throw std::out_of_range(std::string("Index is out of range"));
239 }
240 return (*this)[index];
241 }
242
243 int indexOf(ConstReference element) const
244 {
245 ConstPointer elementPtr = &element;
246 auto cellPtr = reinterpret_cast<ConstStorageTypePtr>(elementPtr);
247 if ((cellPtr < &m_data[0]) ||
248 (&m_data[capacity()] <= cellPtr)) {
249 // invalid, element is not within array boundaries
250 return -1;
251 }
252
253 auto rawIdx = cellPtr - &m_data[0];
254 std::size_t actualIdx = capacity(); // invalid value
255 if (rawIdx < m_startIdx) {
256 actualIdx = (capacity() - m_startIdx) + rawIdx;
257 }
258 else {
259 actualIdx = rawIdx - m_startIdx;
260 }
261
262 if (size() <= actualIdx)
263 {
264 // Element is out of range
265 return -1;
266 }
267
268 return actualIdx;
269 }
270
271 LinearisedIterator invalidIter()
272 {
273 return reinterpret_cast<LinearisedIterator>(&m_data[capacity()]);
274 }
275
276 ConstLinearisedIterator invalidIter() const
277 {
278 return reinterpret_cast<LinearisedIterator>(&m_data[capacity()]);
279 }
280
281 ReverseLinearisedIterator invalidReverseIter()
282 {
283 return ReverseLinearisedIterator(
284 reinterpret_cast<LinearisedIterator>(&m_data[0]));
285 }
286
287 ConstReverseLinearisedIterator invalidReverseIter() const
288 {
289 return ReverseLinearisedIterator(
290 reinterpret_cast<LinearisedIterator>(&m_data[0]));
291 }
292
293 LinearisedIterator lbegin()
294 {
295 if (!linearised()) {
296 return invalidIter();
297 }
298
299 return reinterpret_cast<LinearisedIterator>(&m_data[0] + m_startIdx);
300 }
301
302 ConstLinearisedIterator lbegin() const
303 {
304 return clbegin();
305 }
306
307 ConstLinearisedIterator clbegin() const
308 {
309 if (!linearised()) {
310 return invalidIter();
311 }
312
313 return reinterpret_cast<LinearisedIterator>(&m_data[0] + m_startIdx);
314 }
315
316 ReverseLinearisedIterator rlbegin()
317 {
318 if (!linearised()) {
319 return invalidReverseIter();
320 }
321
322 return ReverseLinearisedIterator(lend());
323 }
324
325 ConstReverseLinearisedIterator rlbegin() const
326 {
327 return crlbegin();
328 }
329
330 ConstReverseLinearisedIterator crlbegin() const
331 {
332 if (!linearised()) {
333 return invalidReverseIter();
334 }
335 return ConstReverseLinearisedIterator(lend());
336 }
337
338 LinearisedIterator lend()
339 {
340 if (!linearised()) {
341 return invalidIter();
342 }
343
344 return lbegin() + size();
345 }
346
347 ConstLinearisedIterator lend() const
348 {
349 return clend();
350 }
351
352 ConstLinearisedIterator clend() const
353 {
354 if (!linearised()) {
355 return invalidIter();
356 }
357
358 return clbegin() + size();
359 }
360
361 ReverseLinearisedIterator rlend()
362 {
363 if (!linearised()) {
364 return invalidReverseIter();
365 }
366
367 return rlbegin() + size();
368 }
369
370 ConstReverseLinearisedIterator rlend() const
371 {
372 return crlend();
373 }
374
375 ConstReverseLinearisedIterator crlend() const
376 {
377 if (!linearised()) {
378 return invalidReverseIter();
379 }
380
381 return rlbegin() + size();
382 }
383
384 void linearise()
385 {
386 if (linearised()) {
387 // Nothing to do
388 return;
389 }
390
391 auto rangeOne = arrayOne();
392 auto rangeOneSize = std::distance(rangeOne.first, rangeOne.second);
393 COMMS_ASSERT(0 < rangeOneSize);
394 auto rangeTwo = arrayTwo();
395 auto rangeTwoSize = std::distance(rangeTwo.first, rangeTwo.second);
396 COMMS_ASSERT(0 < rangeTwoSize);
397 COMMS_ASSERT((rangeOneSize + rangeTwoSize) == size());
398 auto remSpaceSize = capacity() - size();
399
400 if (rangeTwoSize <= remSpaceSize) {
401 lineariseByMoveOneTwo(rangeOne, rangeTwo);
402 return;
403 }
404
405 if (rangeOneSize <= remSpaceSize) {
406 lineariseByMoveTwoOne(rangeOne, rangeTwo);
407 return;
408 }
409
410 if (rangeOneSize < rangeTwoSize) {
411 lineariseByPopOne();
412 }
413
414 lineariseByPopTwo();
415 }
416
417 bool linearised() const
418 {
419 return (empty() || ((m_startIdx + size()) <= capacity()));
420 }
421
422 LinearisedIteratorRange arrayOne()
423 {
424 auto constThis = static_cast<const StaticQueueBase*>(this);
425 auto constRange = constThis->arrayOne();
426 return
427 LinearisedIteratorRange(
428 const_cast<LinearisedIterator>(constRange.first),
429 const_cast<LinearisedIterator>(constRange.second));
430 }
431
432 ConstLinearisedIteratorRange arrayOne() const
433 {
434 auto begCell = &m_data[m_startIdx];
435 auto endCell = std::min(&m_data[m_startIdx + size()], &m_data[capacity()]);
436 return
437 ConstLinearisedIteratorRange(
438 reinterpret_cast<ConstLinearisedIterator>(begCell),
439 reinterpret_cast<ConstLinearisedIterator>(endCell));
440 }
441
442 LinearisedIteratorRange arrayTwo()
443 {
444 auto constThis = static_cast<const StaticQueueBase*>(this);
445 auto constRange = constThis->arrayTwo();
446 return
447 LinearisedIteratorRange(
448 const_cast<LinearisedIterator>(constRange.first),
449 const_cast<LinearisedIterator>(constRange.second));
450 }
451
452 ConstLinearisedIteratorRange arrayTwo() const
453 {
454 if (linearised()) {
455 auto iter = arrayOne().second;
456 return ConstLinearisedIteratorRange(iter, iter);
457 }
458
459 auto begCell = &m_data[0];
460 auto endCell = &m_data[(m_startIdx + size()) - capacity()];
461
462 return
463 ConstLinearisedIteratorRange(
464 reinterpret_cast<ConstLinearisedIterator>(begCell),
465 reinterpret_cast<ConstLinearisedIterator>(endCell));
466 }
467
468 void resize(std::size_t newSize)
469 {
470 COMMS_ASSERT(newSize <= capacity());
471 if (capacity() < newSize) {
472 return;
473 }
474
475 if (size() <= newSize) {
476 while (size() < newSize) {
477 pushBackNotFull(ValueType());
478 }
479
480 return;
481 }
482
483 // New requested size is less than existing now
484 popBack(size() - newSize);
485 }
486
487 LinearisedIterator erase(LinearisedIterator pos)
488 {
489 COMMS_ASSERT(pos != invalidIter());
490 COMMS_ASSERT(!empty());
491 auto rangeOne = arrayOne();
492 auto rangeTwo = arrayTwo();
493
494 auto isInRangeFunc =
495 [](LinearisedIterator pos, const LinearisedIteratorRange range) -> bool
496 {
497 return ((range.first <= pos) && (pos < range.second));
498 };
499
500 COMMS_ASSERT(isInRangeFunc(pos, rangeOne) ||
501 isInRangeFunc(pos, rangeTwo));
502
503 if (isInRangeFunc(pos, rangeOne)) {
504 std::move_backward(rangeOne.first, pos, pos + 1);
505
506 popFront();
507 rangeOne = arrayOne();
508 if (isInRangeFunc(pos, rangeOne)) {
509 return pos + 1;
510 }
511
512 return rangeOne.first;
513 }
514
515 if (isInRangeFunc(pos, rangeTwo)) {
516 std::move(pos + 1, rangeTwo.second, pos);
517 popBack();
518 if (!linearised()) {
519 return pos;
520 }
521 return arrayOne().second;
522 }
523
524 static constexpr bool Invalid_iterator_is_used = false;
525 static_cast<void>(Invalid_iterator_is_used);
526 COMMS_ASSERT(Invalid_iterator_is_used);
527 return invalidIter();
528 }
529
530 Iterator erase(Iterator pos)
531 {
532 COMMS_ASSERT(pos != end());
533 COMMS_ASSERT(!empty());
534 Pointer elem = &(*pos);
535 auto rangeOne = arrayOne();
536 auto rangeTwo = arrayTwo();
537
538 auto isInRangeFunc =
539 [](Pointer elemPtr, const LinearisedIteratorRange range) -> bool
540 {
541 return ((&(*range.first) <= elemPtr) && (elemPtr < &(*range.second)));
542 };
543
544 COMMS_ASSERT(isInRangeFunc(elem, rangeOne) ||
545 isInRangeFunc(elem, rangeTwo));
546
547 if (isInRangeFunc(elem, rangeOne)) {
548 std::move_backward(rangeOne.first, elem, elem + 1);
549
550 popFront();
551 rangeOne = arrayOne();
552 if (isInRangeFunc(elem, rangeOne)) {
553 return pos + 1;
554 }
555
556 return begin();
557 }
558
559 if (isInRangeFunc(elem, rangeTwo)) {
560 std::move(elem + 1, rangeTwo.second, elem);
561 popBack();
562 if (!linearised()) {
563 return pos;
564 }
565 return end();
566 }
567
568 static constexpr bool Invalid_iterator_is_used = false;
569 static_cast<void>(Invalid_iterator_is_used);
570 COMMS_ASSERT(Invalid_iterator_is_used);
571 return end();
572 }
573
574 Iterator begin()
575 {
576 return Iterator(*this, reinterpret_cast<LinearisedIterator>(&m_data[0]));
577 }
578
579 ConstIterator begin() const
580 {
581 return cbegin();
582 }
583
584 ConstIterator cbegin() const
585 {
586 return ConstIterator(*this, reinterpret_cast<ConstLinearisedIterator>(&m_data[0]));
587 }
588
589 Iterator end()
590 {
591 return Iterator(*this, reinterpret_cast<LinearisedIterator>(&m_data[size()]));
592 }
593
594 ConstIterator end() const
595 {
596 return cend();
597 }
598
599 ConstIterator cend() const
600 {
601 return ConstIterator(*this, reinterpret_cast<ConstLinearisedIterator>(&m_data[size()]));
602 }
603
604 template <typename TOther>
605 void assignElements(TOther&& other)
606 {
607 static_assert(std::is_base_of<StaticQueueBase, typename std::decay<TOther>::type>::value,
608 "Assignment works only on the same types");
609
610 using DecayedQueueType = typename std::decay<decltype(other)>::type;
611 using NonRefQueueType = typename std::remove_reference<decltype(other)>::type;
612
613 using QueueValueType =
615 std::is_const<NonRefQueueType>::value
616 >::template Type<
617 const typename DecayedQueueType::ValueType,
618 typename DecayedQueueType::ValueType
619 >;
620
621 using ElemRefType =
623 std::is_rvalue_reference<decltype(other)>::value
624 >::template Type<
625 typename std::add_rvalue_reference<QueueValueType>::type,
626 typename std::add_lvalue_reference<QueueValueType>::type
627 >;
628
629 COMMS_ASSERT(other.size() <= capacity());
630 COMMS_ASSERT(empty());
631
632 auto rangeOne = other.arrayOne();
633 for (auto iter = rangeOne.first; iter != rangeOne.second; ++iter) {
634 pushBackNotFull(std::forward<ElemRefType>(*iter));
635 }
636
637 auto rangeTwo = other.arrayTwo();
638 for (auto iter = rangeTwo.first; iter != rangeTwo.second; ++iter) {
639 pushBackNotFull(std::forward<ElemRefType>(*iter));
640 }
641 }
642
643 template <typename U>
644 void pushBack(U&& value)
645 {
646 COMMS_ASSERT(!full());
647 if (full()) {
648 return;
649 }
650 pushBackNotFull(std::forward<U>(value));
651 }
652
653 template <typename... TArgs>
654 void emplaceBack(TArgs&&... args)
655 {
656 COMMS_ASSERT(!full());
657 if (full()) {
658 return;
659 }
660 emplaceBackNotFull(std::forward<TArgs>(args)...);
661 }
662
663 template <typename U>
664 void pushFront(U&& value)
665 {
666 COMMS_ASSERT(!full());
667 if (full()) {
668 return;
669 }
670
671 pushFrontNotFull(std::forward<U>(value));
672 }
673
674 template <typename U>
675 LinearisedIterator insert(LinearisedIterator pos, U&& value)
676 {
677 COMMS_ASSERT(!full());
678 if (full()) {
679 return invalidIter();
680 }
681
682 return insertNotFull(pos, std::forward<U>(value));
683 }
684
685 bool operator==(const StaticQueueBase& other) const
686 {
687 if (size() != other.size()) {
688 return false;
689 }
690
691 auto rangeOne = arrayOne();
692 auto rangeOneSize = std::distance(rangeOne.first, rangeOne.second);
693 auto rangeTwo = arrayTwo();
694 auto otherRangeOne = other.arrayOne();
695 auto otherRangeOneSize = std::distance(otherRangeOne.first, otherRangeOne.second);
696 auto otherRangeTwo = other.arrayTwo();
697
698 auto firstCompSize = std::min(rangeOneSize, otherRangeOneSize);
699 auto firstCompEnd = rangeOne.first + firstCompSize;
700
701 auto currIter = rangeOne.first;
702 auto otherCurrIter = otherRangeOne.first;
703 if (!std::equal(currIter, firstCompEnd, otherCurrIter)) {
704 return false;
705 }
706
707 currIter = firstCompEnd;
708 otherCurrIter += firstCompSize;
709
710 if (currIter != rangeOne.first) {
711 otherCurrIter = otherRangeTwo.first;
712 if (!std::equal(currIter, rangeOne.second, otherCurrIter)) {
713 return false;
714 }
715 otherCurrIter += rangeOne.second - currIter;
716 currIter = rangeTwo.first;
717 }
718 else {
719 currIter = rangeTwo.first;
720 if (!std::equal(otherCurrIter, otherRangeOne.second, currIter)) {
721 return false;
722 }
723
724 currIter += otherRangeOne.second - otherCurrIter;
725 otherCurrIter = otherRangeOne.first;
726 }
727
728 COMMS_ASSERT(std::distance(currIter, rangeTwo.second) == std::distance(otherCurrIter, otherRangeTwo.second));
729 return std::equal(currIter, rangeTwo.second, otherCurrIter);
730 }
731
732 bool operator!=(const StaticQueueBase& other) const
733 {
734 return !(*this == other);
735 }
736
737private:
738
739 template <typename U>
740 void createValueAtIndex(U&& value, std::size_t index)
741 {
742 COMMS_ASSERT(index < capacity());
743 Reference elementRef = elementAtIndex(index);
744 auto elementPtr = new(&elementRef) ValueType(std::forward<U>(value));
745 static_cast<void>(elementPtr);
746 }
747
748 template <typename U>
749 void pushBackNotFull(U&& value)
750 {
751 COMMS_ASSERT(!full());
752 createValueAtIndex(std::forward<U>(value), size());
753 ++m_count;
754 }
755
756 template <typename... TArgs>
757 void emplaceBackNotFull(TArgs&&... args)
758 {
759 COMMS_ASSERT(!full());
760 Reference elementRef = elementAtIndex(size());
761 auto elementPtr = new(&elementRef) ValueType(std::forward<TArgs>(args)...);
762 static_cast<void>(elementPtr);
763 ++m_count;
764 }
765
766 template <typename U>
767 void pushFrontNotFull(U&& value)
768 {
769 COMMS_ASSERT(!full());
770 createValueAtIndex(std::forward<U>(value), capacity() - 1);
771 if (m_startIdx == 0) {
772 m_startIdx = capacity() - 1;
773 }
774 else {
775 --m_startIdx;
776 }
777
778 ++m_count;
779 }
780
781 template <typename U>
782 LinearisedIterator insertNotFull(LinearisedIterator pos, U&& value)
783 {
784 COMMS_ASSERT(!full());
785 COMMS_ASSERT(pos != invalidIter());
786 auto rangeOne = arrayOne();
787 auto rangeTwo = arrayTwo();
788
789 if (pos == rangeOne.first) {
790 pushFrontNotFull(std::forward<U>(value));
791 return arrayOne().first;
792 }
793
794 if (pos == rangeTwo.second) {
795 pushBackNotFull(std::forward<U>(value));
796 return arrayTwo().second - 1;
797 }
798
799 auto isInRangeFunc = [](LinearisedIterator pos, const LinearisedIteratorRange range) -> bool
800 {
801 return ((range.first <= pos) && (pos < range.second));
802 };
803
804 COMMS_ASSERT(isInRangeFunc(pos, rangeOne) ||
805 isInRangeFunc(pos, rangeTwo));
806
807 if (isInRangeFunc(pos, rangeOne)) {
808 pushFrontNotFull(std::move(front())); // move first element
809
810 std::move(rangeOne.first + 1, pos, rangeOne.first);
811 *pos = std::forward<U>(value);
812 return pos;
813 }
814
815 if (isInRangeFunc(pos, rangeTwo)) {
816 pushBackNotFull(std::move(back())); // move last element
817 std::move_backward(pos, rangeTwo.second - 1, rangeTwo.second);
818 *pos = std::forward<U>(value);
819 return pos;
820 }
821
822 return invalidIter();
823 }
824
825 Reference elementAtIndex(std::size_t index) {
826 auto constThis = static_cast<const StaticQueueBase*>(this);
827 return const_cast<Reference>(constThis->elementAtIndex(index));
828 }
829
830 ConstReference elementAtIndex(std::size_t index) const
831 {
832 std::size_t rawIdx = m_startIdx + index;
833 while (capacity() <= rawIdx) {
834 rawIdx = rawIdx - capacity();
835 }
836
837 auto cellAddr = &m_data[rawIdx];
838 return *(reinterpret_cast<ConstPointer>(cellAddr));
839 }
840
841 template <typename TIter>
842 void lineariseByMove(
843 const std::pair<TIter, TIter> firstRange,
844 const std::pair<TIter, TIter> secondRange)
845 {
846 auto movConstructFirstSize =
847 std::min(
848 std::size_t(std::distance(firstRange.first, firstRange.second)),
849 capacity() - size());
850 auto movConstructFirstEnd = firstRange.first + movConstructFirstSize;
851 COMMS_ASSERT(movConstructFirstEnd <= firstRange.second);
852 COMMS_ASSERT(movConstructFirstSize <= (firstRange.second - firstRange.first));
853
854 auto newPlacePtr = secondRange.second;
855 for (auto iter = firstRange.first; iter != movConstructFirstEnd; ++iter) {
856 auto ptr = new (&(*newPlacePtr)) ValueType(std::move(*iter));
857 static_cast<void>(ptr);
858 ++newPlacePtr;
859 }
860
861 std::move(movConstructFirstEnd, firstRange.second, newPlacePtr);
862 newPlacePtr += (firstRange.second - movConstructFirstEnd);
863
864 auto movConstructTwoSize = 0;
865 if (newPlacePtr < firstRange.first) {
866 movConstructTwoSize =
867 std::min(std::distance(newPlacePtr, firstRange.first),
868 std::distance(secondRange.first, secondRange.second));
869 }
870
871 auto movConstructTwoEnd = secondRange.first + movConstructTwoSize;
872 for (auto iter = secondRange.first; iter != movConstructTwoEnd; ++iter) {
873 auto ptr = new (&(*newPlacePtr)) ValueType(std::move(*iter));
874 static_cast<void>(ptr);
875 ++newPlacePtr;
876 }
877
878 std::move(movConstructTwoEnd, secondRange.second, newPlacePtr);
879 newPlacePtr += (secondRange.second - movConstructTwoEnd);
880
881 for (auto iter = std::max(newPlacePtr, firstRange.first); iter != firstRange.second; ++iter) {
882 iter->~T();
883 }
884
885 for (auto iter = secondRange.first; iter != secondRange.second; ++iter) {
886 iter->~T();
887 }
888 }
889
890 void lineariseByMoveOneTwo(
891 const LinearisedIteratorRange& rangeOne,
892 const LinearisedIteratorRange& rangeTwo)
893 {
894 lineariseByMove(rangeOne, rangeTwo);
895 m_startIdx = std::distance(rangeTwo.first, rangeTwo.second);
896 }
897
898 void lineariseByMoveTwoOne(
899 const LinearisedIteratorRange& rangeOne,
900 const LinearisedIteratorRange& rangeTwo)
901 {
902 using RevIter = std::reverse_iterator<Pointer>;
903 lineariseByMove(
904 std::make_pair(RevIter(rangeTwo.second), RevIter(rangeTwo.first)),
905 std::make_pair(RevIter(rangeOne.second), RevIter(rangeOne.first)));
906
907 m_startIdx = (capacity() - std::distance(rangeOne.first, rangeOne.second)) - size();
908 }
909
910 void lineariseByPopOne()
911 {
912 if (linearised()) {
913 return;
914 }
915
916 ValueType tmp(std::move(front()));
917 popFront();
918 lineariseByPopOne();
919 if (m_startIdx == 0) {
920 using RevIter = std::reverse_iterator<LinearisedIterator>;
921 auto target =
922 RevIter(reinterpret_cast<LinearisedIterator>(&m_data[capacity()]));
923 moveRange(rlbegin(), rlend(), target);
924 m_startIdx = capacity() - size();
925 }
926 pushFront(std::move(tmp));
927 COMMS_ASSERT(linearised());
928 }
929
930 void lineariseByPopTwo()
931 {
932 if (linearised()) {
933 return;
934 }
935
936 ValueType tmp(std::move(back()));
937 popBack();
938 lineariseByPopTwo();
939 if (m_startIdx != 0) {
940 auto target = reinterpret_cast<LinearisedIterator>(&m_data[0]);
941 moveRange(lbegin(), lend(), target);
942 m_startIdx = 0;
943 }
944 pushBack(std::move(tmp));
945 COMMS_ASSERT(linearised());
946 }
947
948 template <typename TIter>
949 void moveRange(TIter rangeBeg, TIter rangeEnd, TIter target)
950 {
951 COMMS_ASSERT(target < rangeBeg);
952 auto moveConstructSize =
953 std::min(
954 std::distance(rangeBeg, rangeEnd),
955 std::distance(target, rangeBeg));
956
957 TIter moveConstructEnd = rangeBeg + moveConstructSize;
958 for (auto iter = rangeBeg; iter != moveConstructEnd; ++iter) {
959 auto ptr = new (&(*target)) ValueType(std::move(*iter));
960 static_cast<void>(ptr);
961 ++target;
962 }
963
964 COMMS_ASSERT(target < moveConstructEnd);
965 std::move(moveConstructEnd, rangeEnd, target);
966 target += std::distance(moveConstructEnd, rangeEnd);
967
968 for (auto iter = std::max(target, rangeBeg); iter != rangeEnd; ++iter) {
969 iter->~T();
970 }
971 }
972
973 StorageTypePtr const m_data;
974 const std::size_t m_capacity;
975 std::size_t m_startIdx;
976 std::size_t m_count;
977};
978
979template <typename T>
980template <typename TDerived, typename TQueueType>
981class StaticQueueBase<T>::IteratorBase
982{
983 friend class StaticQueueBase<T>;
984public:
985
986 IteratorBase(const IteratorBase&) = default;
987
988 ~IteratorBase() noexcept = default;
989
990protected:
991 using Derived = TDerived;
992 using QueueType = TQueueType;
993 using ArrayIterator = decltype(std::declval<QueueType>().lbegin());
994 using IteratorCategory = typename std::iterator_traits<ArrayIterator>::iterator_category;
995 using iterator_category = IteratorCategory;
996 using ValueType = typename std::iterator_traits<ArrayIterator>::value_type;
997 using value_type = ValueType;
998 using DifferenceType = typename std::iterator_traits<ArrayIterator>::difference_type;
999 using difference_type = DifferenceType;
1000 using Pointer = typename std::iterator_traits<ArrayIterator>::pointer;
1001 using pointer = Pointer;
1002 using ConstPointer =
1003 typename std::add_pointer<
1004 typename std::add_const<
1005 typename std::remove_pointer<Pointer>::type
1006 >::type
1007 >::type;
1008 using Reference = typename std::iterator_traits<ArrayIterator>::reference;
1009 using reference = Reference;
1010 using ConstReference = typename std::add_const<Reference>::type;
1011
1012 IteratorBase(QueueType& queue, ArrayIterator iterator)
1013 : m_queue(queue),
1014 m_iterator(iterator)
1015 {
1016 }
1017
1018 Derived& operator=(const IteratorBase& other)
1019 {
1020 COMMS_ASSERT(&m_queue == &other.m_queue);
1021 m_iterator = other.m_iterator; // No need to check for self assignment
1022 return static_cast<Derived&>(*this);
1023 }
1024
1025 Derived& operator++()
1026 {
1027 ++m_iterator;
1028 return static_cast<Derived&>(*this);
1029 }
1030
1031 Derived operator++(int)
1032 {
1033 IteratorBase copy(*this);
1034 ++m_iterator;
1035 return std::move(*(static_cast<Derived*>(&copy)));
1036 }
1037
1038 Derived& operator--()
1039 {
1040 --m_iterator;
1041 return static_cast<Derived&>(*this);
1042 }
1043
1044 Derived operator--(int)
1045 {
1046 IteratorBase copy(*this);
1047 --m_iterator;
1048 return std::move(*(static_cast<Derived*>(&copy)));
1049 }
1050
1051 Derived& operator+=(DifferenceType value)
1052 {
1053 m_iterator += value;
1054 return static_cast<Derived&>(*this);
1055 }
1056
1057 Derived& operator-=(DifferenceType value)
1058 {
1059 m_iterator -= value;
1060 return static_cast<Derived&>(*this);
1061 }
1062
1063 Derived operator+(DifferenceType value) const
1064 {
1065 IteratorBase copy(*this);
1066 copy += value;
1067 return std::move(*(static_cast<Derived*>(&copy)));
1068 }
1069
1070 Derived operator-(DifferenceType value) const
1071 {
1072 IteratorBase copy(*this);
1073 copy -= value;
1074 return std::move(*(static_cast<Derived*>(&copy)));
1075 }
1076
1077 DifferenceType operator-(const IteratorBase& other) const
1078 {
1079 return m_iterator - other.m_iterator;
1080 }
1081
1082 bool operator==(const IteratorBase& other) const
1083 {
1084 return (m_iterator == other.m_iterator);
1085 }
1086
1087 bool operator!=(const IteratorBase& other) const
1088 {
1089 return (m_iterator != other.m_iterator);
1090 }
1091
1092 bool operator<(const IteratorBase& other) const
1093 {
1094 return m_iterator < other.m_iterator;
1095 }
1096
1097 bool operator<=(const IteratorBase& other) const
1098 {
1099 return m_iterator <= other.m_iterator;
1100 }
1101
1102 bool operator>(const IteratorBase& other) const
1103 {
1104 return m_iterator > other.m_iterator;
1105 }
1106
1107 bool operator>=(const IteratorBase& other) const
1108 {
1109 return m_iterator >= other.m_iterator;
1110 }
1111
1112 Reference operator*()
1113 {
1114 auto& constThisRef = static_cast<const IteratorBase&>(*this);
1115 auto& constRef = *constThisRef;
1116 return const_cast<Reference>(constRef);
1117 }
1118
1119 ConstReference operator*() const
1120 {
1121 auto begCell = reinterpret_cast<ArrayIterator>(&m_queue.m_data[0]);
1122 auto idx = m_iterator - begCell;
1123 COMMS_ASSERT(0 <= idx);
1124 return m_queue[static_cast<std::size_t>(idx)];
1125 }
1126
1127 Pointer operator->()
1128 {
1129 return &(*(*this));
1130 }
1131
1132 ConstPointer operator->() const
1133 {
1134 return &(*(*this));
1135 }
1136
1137 QueueType& getQueue() {
1138 return m_queue;
1139 }
1140
1141 typename std::add_const<QueueType&>::type getQueue() const
1142 {
1143 return m_queue;
1144 }
1145
1146 ArrayIterator& getIterator() {
1147 return m_iterator;
1148 }
1149
1150 typename std::add_const<ArrayIterator>::type& getIterator() const
1151 {
1152 return m_iterator;
1153 }
1154
1155private:
1156
1157 QueueType& m_queue;
1158 ArrayIterator m_iterator;
1159};
1160
1161template <typename T>
1162class StaticQueueBase<T>::ConstIterator :
1163 public StaticQueueBase<T>::template
1164 IteratorBase<typename StaticQueueBase<T>::ConstIterator, const StaticQueueBase<T> >
1165{
1166 using Base = typename StaticQueueBase<T>::template
1167 IteratorBase<typename StaticQueueBase<T>::ConstIterator, const StaticQueueBase<T> >;
1168
1169public:
1170 using QueueType = typename Base::QueueType;
1171 using ArrayIterator = typename Base::ArrayIterator;
1172
1173 ConstIterator(const ConstIterator&) = default;
1174 ~ConstIterator() noexcept = default;
1175
1176 ConstIterator(QueueType& queue, ArrayIterator iterator)
1177 : Base(queue, iterator)
1178 {
1179 }
1180
1181};
1182
1183template <typename T>
1184class StaticQueueBase<T>::Iterator :
1185 public StaticQueueBase<T>::template
1186 IteratorBase<typename StaticQueueBase<T>::Iterator, StaticQueueBase<T> >
1187{
1188 using Base = typename StaticQueueBase<T>::template
1189 IteratorBase<typename StaticQueueBase<T>::Iterator, StaticQueueBase<T> >;
1190
1191public:
1192 using QueueType = typename Base::QueueType;
1193 using ArrayIterator = typename Base::ArrayIterator;
1194
1195 Iterator(const Iterator&) = default;
1196 ~Iterator() noexcept = default;
1197
1198 Iterator(QueueType& queue, ArrayIterator iterator)
1199 : Base(queue, iterator)
1200 {
1201 }
1202
1203 operator ConstIterator() const
1204 {
1205 return ConstIterator(Base::getQueue(), Base::getIterator());
1206 }
1207};
1208
1209template <typename TWrapperElemType, typename TQueueElemType>
1210class CastWrapperQueueBase : public StaticQueueBase<TQueueElemType>
1211{
1212 using Base = StaticQueueBase<TQueueElemType>;
1213 using WrapperElemType = TWrapperElemType;
1214
1215 using BaseValueType = typename Base::ValueType;
1216 using BaseStorageTypePtr = typename Base::StorageTypePtr;
1217 using BaseReference = typename Base::Reference;
1218 using BaseConstReference = typename Base::ConstReference;
1219 using BasePointer = typename Base::Pointer;
1220 using BaseConstPointer = typename Base::ConstPointer;
1221 using BaseLinearisedIterator = typename Base::LinearisedIterator;
1222 using BaseConstLinearisedIterator = typename Base::ConstLinearisedIterator;
1223 using BaseReverseLinearisedIterator = typename Base::ReverseLinearisedIterator;
1224 using BaseConstReverseLinearisedIterator = typename Base::ConstReverseLinearisedIterator;
1225 using BaseLinearisedIteratorRange = typename Base::LinearisedIteratorRange;
1226 using BaseConstLinearisedIteratorRange = typename Base::ConstLinearisedIteratorRange;
1227
1228public:
1229
1230 class ConstIterator;
1231 class Iterator;
1232
1233protected:
1234 using ValueType = WrapperElemType;
1235 using StorageType = comms::util::AlignedStorage<sizeof(ValueType), std::alignment_of<ValueType>::value>;
1236 using StorageTypePtr = StorageType*;
1237 using Reference = ValueType&;
1238 using ConstReference = const ValueType&;
1239 using Pointer = ValueType*;
1240 using ConstPointer = const ValueType*;
1241 using LinearisedIterator = Pointer;
1242 using ConstLinearisedIterator = ConstPointer;
1243 using ReverseLinearisedIterator = std::reverse_iterator<LinearisedIterator>;
1244 using ConstReverseLinearisedIterator = std::reverse_iterator<ConstLinearisedIterator>;
1245 using LinearisedIteratorRange = std::pair<LinearisedIterator, LinearisedIterator>;
1246 using ConstLinearisedIteratorRange = std::pair<ConstLinearisedIterator, ConstLinearisedIterator>;
1247
1248 CastWrapperQueueBase(StorageTypePtr data, std::size_t capacity)
1249 : Base(reinterpret_cast<BaseStorageTypePtr>(data), capacity)
1250 {
1251 static_assert(sizeof(ValueType) == sizeof(BaseValueType),
1252 "The times must have identical size.");
1253 }
1254
1255 ~CastWrapperQueueBase() noexcept = default;
1256
1257 CastWrapperQueueBase& operator=(const CastWrapperQueueBase& other) = default;
1258 CastWrapperQueueBase& operator=(CastWrapperQueueBase&& other) = default;
1259
1260 Reference front()
1261 {
1262 return reinterpret_cast<Reference>(Base::front());
1263 }
1264
1265 ConstReference front() const
1266 {
1267 return reinterpret_cast<ConstReference>(Base::front());
1268 }
1269
1270 Reference back()
1271 {
1272 return reinterpret_cast<Reference>(Base::back());
1273 }
1274
1275 ConstReference back() const
1276 {
1277 return reinterpret_cast<Reference>(Base::back());
1278 }
1279
1280 Reference operator[](std::size_t index)
1281 {
1282 return reinterpret_cast<Reference>(Base::operator[](index));
1283 }
1284
1285 ConstReference operator[](std::size_t index) const
1286 {
1287 return reinterpret_cast<ConstReference>(Base::operator[](index));
1288 }
1289
1290 Reference at(std::size_t index)
1291 {
1292 return reinterpret_cast<Reference>(Base::at(index));
1293 }
1294
1295 ConstReference at(std::size_t index) const
1296 {
1297 return reinterpret_cast<ConstReference>(Base::at(index));
1298 }
1299
1300 int indexOf(ConstReference element) const
1301 {
1302 return Base::indexOf(reinterpret_cast<BaseConstReference>(element));
1303 }
1304
1305 LinearisedIterator invalidIter()
1306 {
1307 return reinterpret_cast<LinearisedIterator>(Base::invalidIter());
1308 }
1309
1310 ConstLinearisedIterator invalidIter() const
1311 {
1312 return reinterpret_cast<ConstLinearisedIterator>(Base::invalidIter());
1313 }
1314
1315 ReverseLinearisedIterator invalidReverseIter()
1316 {
1317 return ReverseLinearisedIterator(
1318 reinterpret_cast<LinearisedIterator>(
1319 Base::invalidReverseIter().base()));
1320 }
1321
1322 ConstReverseLinearisedIterator invalidReverseIter() const
1323 {
1324 return ConstReverseLinearisedIterator(
1325 reinterpret_cast<ConstLinearisedIterator>(
1326 Base::invalidReverseIter().base()));
1327 }
1328
1329 LinearisedIterator lbegin()
1330 {
1331 return reinterpret_cast<LinearisedIterator>(Base::lbegin());
1332 }
1333
1334 ConstLinearisedIterator lbegin() const
1335 {
1336 return reinterpret_cast<ConstLinearisedIterator>(Base::lbegin());
1337 }
1338
1339 ConstLinearisedIterator clbegin() const
1340 {
1341 return reinterpret_cast<ConstLinearisedIterator>(Base::clbegin());
1342 }
1343
1344 ReverseLinearisedIterator rlbegin()
1345 {
1346 return ReverseLinearisedIterator(
1347 reinterpret_cast<LinearisedIterator>(
1348 Base::rlbegin().base()));
1349 }
1350
1351 ConstReverseLinearisedIterator rlbegin() const
1352 {
1353 return ConstReverseLinearisedIterator(
1354 reinterpret_cast<ConstLinearisedIterator>(
1355 Base::rlbegin().base()));
1356 }
1357
1358 ConstReverseLinearisedIterator crlbegin() const
1359 {
1360 return ConstReverseLinearisedIterator(
1361 reinterpret_cast<ConstLinearisedIterator>(
1362 Base::crlbegin().base()));
1363 }
1364
1365 LinearisedIterator lend()
1366 {
1367 return reinterpret_cast<LinearisedIterator>(Base::lend());
1368 }
1369
1370 ConstLinearisedIterator lend() const
1371 {
1372 return reinterpret_cast<ConstLinearisedIterator>(Base::lend());
1373 }
1374
1375 ConstLinearisedIterator clend() const
1376 {
1377 return reinterpret_cast<ConstLinearisedIterator>(Base::clend());
1378 }
1379
1380 ReverseLinearisedIterator rlend()
1381 {
1382 return ReverseLinearisedIterator(
1383 reinterpret_cast<LinearisedIterator>(
1384 Base::rlend().base()));
1385 }
1386
1387 ConstReverseLinearisedIterator rlend() const
1388 {
1389 return ConstReverseLinearisedIterator(
1390 reinterpret_cast<ConstLinearisedIterator>(
1391 Base::rlend().base()));
1392 }
1393
1394 ConstReverseLinearisedIterator crlend() const
1395 {
1396 return ConstReverseLinearisedIterator(
1397 reinterpret_cast<ConstLinearisedIterator>(
1398 Base::crlend().base()));
1399 }
1400
1401 LinearisedIteratorRange arrayOne()
1402 {
1403 auto range = Base::arrayOne();
1404 return LinearisedIteratorRange(
1405 reinterpret_cast<LinearisedIterator>(range.first),
1406 reinterpret_cast<LinearisedIterator>(range.second));
1407 }
1408
1409 ConstLinearisedIteratorRange arrayOne() const
1410 {
1411 auto range = Base::arrayOne();
1412 return ConstLinearisedIteratorRange(
1413 reinterpret_cast<ConstLinearisedIterator>(range.first),
1414 reinterpret_cast<ConstLinearisedIterator>(range.second));
1415
1416 }
1417
1418 LinearisedIteratorRange arrayTwo()
1419 {
1420 auto range = Base::arrayTwo();
1421 return LinearisedIteratorRange(
1422 reinterpret_cast<LinearisedIterator>(range.first),
1423 reinterpret_cast<LinearisedIterator>(range.second));
1424
1425 }
1426
1427 ConstLinearisedIteratorRange arrayTwo() const
1428 {
1429 auto range = Base::arrayTwo();
1430 return ConstLinearisedIteratorRange(
1431 reinterpret_cast<ConstLinearisedIterator>(range.first),
1432 reinterpret_cast<ConstLinearisedIterator>(range.second));
1433
1434 }
1435
1436 LinearisedIterator erase(LinearisedIterator pos)
1437 {
1438 return reinterpret_cast<LinearisedIterator>(
1439 Base::erase(
1440 reinterpret_cast<BaseLinearisedIterator>(pos)));
1441 }
1442
1443 Iterator erase(Iterator pos)
1444 {
1445 auto tmp = Base::erase(pos);
1446 return *(reinterpret_cast<Iterator*>(&tmp));
1447 }
1448
1449 Iterator begin()
1450 {
1451 auto tmp = Base::begin();
1452 return *(reinterpret_cast<Iterator*>(&tmp));
1453 }
1454
1455 ConstIterator begin() const
1456 {
1457 auto tmp = Base::begin();
1458 return *(reinterpret_cast<ConstIterator*>(&tmp));
1459 }
1460
1461 ConstIterator cbegin() const
1462 {
1463 auto tmp = Base::cbegin();
1464 return *(reinterpret_cast<ConstIterator*>(&tmp));
1465
1466 }
1467
1468 Iterator end()
1469 {
1470 auto tmp = Base::end();
1471 return *(reinterpret_cast<Iterator*>(&tmp));
1472 }
1473
1474 ConstIterator end() const
1475 {
1476 auto tmp = Base::end();
1477 return *(reinterpret_cast<ConstIterator*>(&tmp));
1478 }
1479
1480 ConstIterator cend() const
1481 {
1482 auto tmp = Base::cend();
1483 return *(reinterpret_cast<ConstIterator*>(&tmp));
1484 }
1485
1486 void pushBack(ConstReference value)
1487 {
1488 Base::pushBack(reinterpret_cast<BaseConstReference>(value));
1489 }
1490
1491 void pushFront(ConstReference value)
1492 {
1493 Base::pushFront(reinterpret_cast<BaseConstReference>(value));
1494 }
1495
1496 LinearisedIterator insert(LinearisedIterator pos, ConstReference value)
1497 {
1498 return reinterpret_cast<LinearisedIterator>(
1499 Base::insert(
1500 reinterpret_cast<BaseLinearisedIterator>(pos),
1501 reinterpret_cast<BaseConstReference>(value)));
1502 }
1503
1504 void assignElements(const CastWrapperQueueBase& other)
1505 {
1506 Base::assignElements(static_cast<const Base&>(other));
1507 }
1508
1509 void assignElements(CastWrapperQueueBase&& other)
1510 {
1511 Base::assignElements(static_cast<Base&&>(std::move(other)));
1512 }
1513};
1514
1515template <typename TWrapperElemType, typename TQueueElemType>
1516class CastWrapperQueueBase<TWrapperElemType, TQueueElemType>::ConstIterator :
1517 public StaticQueueBase<TQueueElemType>::ConstIterator
1518{
1519 using Base = typename StaticQueueBase<TQueueElemType>::ConstIterator;
1520public:
1521 ConstIterator(const ConstIterator&) = default;
1522 ConstIterator& operator=(const ConstIterator&) = default;
1523 ~ConstIterator() noexcept = default;
1524
1525protected:
1526 using ExpectedQueueType = const StaticQueueBase<TWrapperElemType>;
1527 using ActualQueueType = const StaticQueueBase<TQueueElemType>;
1528 using ValueType = TWrapperElemType;
1529 using Reference = const ValueType&;
1530 using ConstReference = const ValueType&;
1531 using Pointer = const ValueType*;
1532 using ConstPointer = const ValueType*;
1533 using DifferenceType = typename Base::DifferenceType;
1534
1535 ConstIterator(ExpectedQueueType& queue, Pointer iterator)
1536 : Base(reinterpret_cast<ActualQueueType&>(queue), iterator)
1537 {
1538 }
1539
1540 ConstIterator& operator++()
1541 {
1542 Base::operator++();
1543 return *this;
1544 }
1545
1546 ConstIterator operator++(int dummy)
1547 {
1548 auto tmp = Base::operator++(dummy);
1549 return *(static_cast<ConstIterator*>(&tmp));
1550 }
1551
1552 ConstIterator& operator--()
1553 {
1554 Base::operator--();
1555 return *this;
1556 }
1557
1558 ConstIterator operator--(int dummy)
1559 {
1560 auto tmp = Base::operator--(dummy);
1561 return *(static_cast<ConstIterator*>(&tmp));
1562 }
1563
1564 ConstIterator& operator+=(DifferenceType value)
1565 {
1566 Base::operator+=(value);
1567 return *this;
1568 }
1569
1570 ConstIterator& operator-=(DifferenceType value)
1571 {
1572 Base::operator-=(value);
1573 return *this;
1574 }
1575
1576 ConstIterator operator+(DifferenceType value) const
1577 {
1578 auto tmp = Base::operator+(value);
1579 return *(static_cast<ConstIterator*>(&tmp));
1580 }
1581
1582 ConstIterator operator-(DifferenceType value) const
1583 {
1584 auto tmp = Base::operator-(value);
1585 return *(static_cast<ConstIterator*>(&tmp));
1586 }
1587
1588 DifferenceType operator-(const ConstIterator& other) const
1589 {
1590 return Base::operator-(other);
1591 }
1592
1593 Reference operator*()
1594 {
1595 auto& ref = Base::operator*();
1596 return reinterpret_cast<Reference>(ref);
1597 }
1598
1599 ConstReference operator*() const
1600 {
1601 auto& ref = Base::operator*();
1602 return reinterpret_cast<ConstReference>(ref);
1603 }
1604
1605 Pointer operator->()
1606 {
1607 auto* ptr = Base::operator->();
1608 return reinterpret_cast<Pointer>(ptr);
1609 }
1610
1611 ConstPointer operator->() const
1612 {
1613 auto* ptr = Base::operator->();
1614 return reinterpret_cast<ConstPointer>(ptr);
1615 }
1616};
1617
1618template <typename TWrapperElemType, typename TQueueElemType>
1619class CastWrapperQueueBase<TWrapperElemType, TQueueElemType>::Iterator :
1620 public StaticQueueBase<TQueueElemType>::Iterator
1621{
1622 using Base = typename StaticQueueBase<TQueueElemType>::Iterator;
1623public:
1624 Iterator(const Iterator&) = default;
1625 Iterator& operator=(const Iterator&) = default;
1626 ~Iterator() noexcept = default;
1627
1628protected:
1629 using ExpectedQueueType = const StaticQueueBase<TWrapperElemType>;
1630 using ActualQueueType = const StaticQueueBase<TQueueElemType>;
1631 using ValueType = TWrapperElemType;
1632 using Reference = ValueType&;
1633 using ConstReference = const ValueType&;
1634 using Pointer = ValueType*;
1635 using ConstPointer = const ValueType*;
1636 using DifferenceType = typename Base::DifferenceType;
1637
1638 Iterator(ExpectedQueueType& queue, Pointer iterator)
1639 : Base(reinterpret_cast<ActualQueueType&>(queue), iterator)
1640 {
1641 }
1642
1643 Iterator& operator++()
1644 {
1645 Base::operator++();
1646 return *this;
1647 }
1648
1649 Iterator operator++(int dummy)
1650 {
1651 auto tmp = Base::operator++(dummy);
1652 return *(static_cast<Iterator*>(&tmp));
1653 }
1654
1655 Iterator& operator--()
1656 {
1657 Base::operator--();
1658 return *this;
1659 }
1660
1661 Iterator operator--(int dummy)
1662 {
1663 auto tmp = Base::operator--(dummy);
1664 return *(static_cast<Iterator*>(&tmp));
1665 }
1666
1667 Iterator& operator+=(DifferenceType value)
1668 {
1669 Base::operator+=(value);
1670 return *this;
1671 }
1672
1673 Iterator& operator-=(DifferenceType value)
1674 {
1675 Base::operator-=(value);
1676 return *this;
1677 }
1678
1679 Iterator operator+(DifferenceType value) const
1680 {
1681 auto tmp = Base::operator+(value);
1682 return *(static_cast<Iterator*>(&tmp));
1683 }
1684
1685 Iterator operator-(DifferenceType value) const
1686 {
1687 auto tmp = Base::operator-(value);
1688 return *(static_cast<Iterator*>(&tmp));
1689 }
1690
1691 DifferenceType operator-(const Iterator& other) const
1692 {
1693 return Base::operator-(other);
1694 }
1695
1696 Reference operator*()
1697 {
1698 auto& ref = Base::operator*();
1699 return reinterpret_cast<Reference>(ref);
1700 }
1701
1702 ConstReference operator*() const
1703 {
1704 auto& ref = Base::operator*();
1705 return reinterpret_cast<ConstReference>(ref);
1706 }
1707
1708 Pointer operator->()
1709 {
1710 auto* ptr = Base::operator->();
1711 return reinterpret_cast<Pointer>(ptr);
1712 }
1713
1714 ConstPointer operator->() const
1715 {
1716 auto* ptr = Base::operator->();
1717 return reinterpret_cast<ConstPointer>(ptr);
1718 }
1719};
1720
1721template <typename T>
1722class StaticQueueBaseOptimised : public StaticQueueBase<T>
1723{
1724 usign Base = StaticQueueBase<T>;
1725protected:
1726
1727 using StorageTypePtr = typename Base::StorageTypePtr;
1728
1729 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1730 : Base(data, capacity)
1731 {
1732 }
1733
1734 ~StaticQueueBaseOptimised() noexcept = default;
1735
1736 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1737 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1738};
1739
1740template <>
1741class StaticQueueBaseOptimised<std::int8_t> : public CastWrapperQueueBase<std::int8_t, std::uint8_t>
1742{
1743 using Base = CastWrapperQueueBase<std::int8_t, std::uint8_t>;
1744protected:
1745
1746 using StorageTypePtr = typename Base::StorageTypePtr;
1747
1748 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1749 : Base(data, capacity)
1750 {
1751 }
1752
1753 ~StaticQueueBaseOptimised() noexcept = default;
1754 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1755 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1756};
1757
1758template <>
1759class StaticQueueBaseOptimised<std::int16_t> : public CastWrapperQueueBase<std::int16_t, std::uint16_t>
1760{
1761 using Base = CastWrapperQueueBase<std::int16_t, std::uint16_t>;
1762protected:
1763
1764 using StorageTypePtr = typename Base::StorageTypePtr;
1765
1766 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1767 : Base(data, capacity)
1768 {
1769 }
1770
1771 ~StaticQueueBaseOptimised() noexcept = default;
1772 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1773 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1774};
1775
1776template <>
1777class StaticQueueBaseOptimised<std::int32_t> : public CastWrapperQueueBase<std::int32_t, std::uint32_t>
1778{
1779 using Base = CastWrapperQueueBase<std::int32_t, std::uint32_t>;
1780protected:
1781
1782 using StorageTypePtr = typename Base::StorageTypePtr;
1783
1784 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1785 : Base(data, capacity)
1786 {
1787 }
1788
1789 ~StaticQueueBaseOptimised() noexcept = default;
1790 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1791 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1792};
1793
1794template <>
1795class StaticQueueBaseOptimised<std::int64_t> : public CastWrapperQueueBase<std::int64_t, std::uint64_t>
1796{
1797 using Base = CastWrapperQueueBase<std::int64_t, std::uint64_t>;
1798protected:
1799
1800 using StorageTypePtr = typename Base::StorageTypePtr;
1801
1802 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1803 : Base(data, capacity)
1804 {
1805 }
1806
1807 ~StaticQueueBaseOptimised() noexcept = default;
1808 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1809 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1810};
1811
1812template <typename T>
1813class StaticQueueBaseOptimised<T*> : public CastWrapperQueueBase<T*, typename comms::util::SizeToType<sizeof(T*)>::Type>
1814{
1815 using Base = CastWrapperQueueBase<T*, typename comms::util::SizeToType<sizeof(T*)>::Type>;
1816protected:
1817
1818 using Base = typename Base::StorageTypePtr;
1819
1820 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1821 : Base(data, capacity)
1822 {
1823 }
1824
1825 ~StaticQueueBaseOptimised() noexcept = default;
1826 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1827 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1828};
1829
1830} // namespace details
1831
1833
1844template <typename T, std::size_t TSize>
1845class StaticQueue : public details::StaticQueueBaseOptimised<T>
1846{
1847 using Base = details::StaticQueueBaseOptimised<T>;
1848
1849 using StorageType = typename Base::StorageType;
1850public:
1852 using ValueType = typename Base::ValueType;
1853
1855 using value_type = ValueType;
1856
1858 using SizeType = typename Base::SizeType;
1859
1861 using size_type = SizeType;
1862
1864 using Reference = typename Base::Reference;
1865
1867 using reference = Reference;
1868
1870 using ConstReference = typename Base::ConstReference;
1871
1873 using const_reference = ConstReference;
1874
1876 using Pointer = typename Base::Pointer;
1877
1879 using pointer = Pointer;
1880
1882 using ConstPointer = typename Base::ConstPointer;
1883
1885 using const_pointer = ConstPointer;
1886
1888 using LinearisedIterator = typename Base::LinearisedIterator;
1889
1891 using ConstLinearisedIterator = typename Base::ConstLinearisedIterator;
1892
1894 using ReverseLinearisedIterator = typename Base::ReverseLinearisedIterator;
1895
1897 using ConstReverseLinearisedIterator = typename Base::ConstReverseLinearisedIterator;
1898
1900 using LinearisedIteratorRange = typename Base::LinearisedIteratorRange;
1901
1903 using ConstLinearisedIteratorRange = typename Base::ConstLinearisedIteratorRange;
1904
1906 class ConstIterator;
1907
1909 using const_iterator = ConstIterator;
1910
1912 class Iterator;
1913
1915 using iterator = Iterator;
1916
1917 // Member functions
1922 StaticQueue()
1923 : Base(&m_array[0], TSize)
1924 {
1925 }
1926
1935 StaticQueue(const StaticQueue& queue)
1936 : Base(&m_array[0], TSize)
1937 {
1938 Base::assignElements(queue);
1939 }
1940
1949 StaticQueue(StaticQueue&& queue)
1950 : Base(&m_array[0], TSize)
1951 {
1952 Base::assignElements(std::move(queue));
1953 }
1954
1963 template <std::size_t TAnySize>
1964 StaticQueue(const StaticQueue<T, TAnySize>& queue)
1965 : Base(&m_array[0], TSize)
1966 {
1967 Base::assignElements(queue);
1968 }
1969
1978 template <std::size_t TAnySize>
1979 StaticQueue(StaticQueue<T, TAnySize>&& queue)
1980 : Base(&m_array[0], TSize)
1981 {
1982 Base::assignElements(std::move(queue));
1983 }
1984
1991 ~StaticQueue() noexcept
1992 {
1993 clear();
1994 }
1995
2006 StaticQueue& operator=(const StaticQueue& queue)
2007 {
2008 return static_cast<StaticQueue&>(Base::operator=(queue));
2009 }
2010
2021 StaticQueue& operator=(StaticQueue&& queue)
2022 {
2023 return static_cast<StaticQueue&>(Base::operator=(std::move(queue)));
2024 }
2025
2037 template <std::size_t TAnySize>
2038 StaticQueue& operator=(const StaticQueue<T, TAnySize>& queue)
2039 {
2040 return static_cast<StaticQueue&>(Base::operator=(queue));
2041 }
2042
2054 template <std::size_t TAnySize>
2055 StaticQueue& operator=(StaticQueue<T, TAnySize>&& queue)
2056 {
2057 return static_cast<StaticQueue&>(Base::operator=(std::move(queue)));
2058 }
2059
2066 static constexpr std::size_t capacity()
2067 {
2068 return TSize;
2069 }
2070
2078 std::size_t size() const
2079 {
2080 return Base::size();
2081 }
2082
2088 bool empty() const
2089 {
2090 return Base::empty();
2091 }
2092
2094 bool isEmpty() const
2095 {
2096 return empty();
2097 }
2098
2104 bool full() const
2105 {
2106 return Base::full();
2107 }
2108
2110 bool isFull() const
2111 {
2112 return full();
2113 }
2114
2120 void clear()
2121 {
2122 Base::clear();
2123 }
2124
2131 void popBack()
2132 {
2133 Base::popBack();
2134 }
2135
2137 inline void pop_back()
2138 {
2139 popBack();
2140 }
2141
2151 void popBack(std::size_t count)
2152 {
2153 Base::popBack(count);
2154 }
2155
2157 void pop_back(std::size_t count)
2158 {
2159 popBack(count);
2160 }
2161
2168 void popFront()
2169 {
2170 Base::popFront();
2171 }
2172
2174 inline void pop_front()
2175 {
2176 popFront();
2177 }
2178
2186 void popFront(std::size_t count)
2187 {
2188 Base::popFront(count);
2189 }
2190
2192 inline void pop_front(std::size_t count)
2193 {
2194 popFront(count);
2195 }
2196
2204 template <typename U>
2205 void pushBack(U&& value)
2206 {
2207 Base::pushBack(std::forward<U>(value));
2208 }
2209
2218 template <typename... TArgs>
2219 void emplaceBack(TArgs&&... args)
2220 {
2221 Base::emplaceBack(std::forward<TArgs>(args)...);
2222 }
2223
2225 template <typename U>
2226 inline void push_back(U&& value)
2227 {
2228 pushBack(std::forward<U>(value));
2229 }
2230
2238 template <typename U>
2239 void pushFront(U&& value)
2240 {
2241 Base::pushFront(std::forward<U>(value));
2242 }
2243
2245 template <typename U>
2246 inline void push_front(U&& value)
2247 {
2248 pushFront(std::forward<U>(value));
2249 }
2250
2266 template <typename U>
2267 LinearisedIterator insert(LinearisedIterator pos, U&& value)
2268 {
2269 return Base::insert(pos, std::forward<U>(value));
2270 }
2271
2278 Reference front()
2279 {
2280 return Base::front();
2281 }
2282
2284 ConstReference front() const
2285 {
2286 return Base::front();
2287 }
2288
2295 Reference back()
2296 {
2297 return Base::back();
2298 }
2299
2301 ConstReference back() const
2302 {
2303 return Base::back();
2304 }
2305
2316 Reference operator[](std::size_t index)
2317 {
2318 return Base::operator[](index);
2319 }
2320
2322 ConstReference operator[](std::size_t index) const
2323 {
2324 return Base::operator[](index);
2325 }
2326
2338 Reference at(std::size_t index)
2339 {
2340 return Base::at(index);
2341 }
2342
2344 ConstReference at(std::size_t index) const
2345 {
2346 return Base::at(index);
2347 }
2348
2358 int indexOf(ConstReference element) const
2359 {
2360 return Base::indexOf(element);
2361 }
2362
2369 LinearisedIterator invalidIter()
2370 {
2371 return Base::invalidIter();
2372 }
2373
2375 ConstLinearisedIterator invalidIter() const
2376 {
2377 return Base::invalidIter();
2378 }
2379
2385 ReverseLinearisedIterator invalidReverseIter()
2386 {
2387 return Base::invalidReverseIter();
2388 }
2389
2391 ConstReverseLinearisedIterator invalidReverseIter() const
2392 {
2393 return Base::invalidReverseIter();
2394 }
2395
2410 LinearisedIterator lbegin()
2411 {
2412 return Base::lbegin();
2413 }
2414
2416 ConstLinearisedIterator lbegin() const
2417 {
2418 return Base::lbegin();
2419 }
2420
2422 ConstLinearisedIterator clbegin() const
2423 {
2424 return Base::clbegin();
2425 }
2426
2441 ReverseLinearisedIterator rlbegin()
2442 {
2443 return Base::rlbegin();
2444 }
2445
2447 ConstReverseLinearisedIterator rlbegin() const
2448 {
2449 return Base::rlbegin();
2450 }
2451
2453 ConstReverseLinearisedIterator crlbegin() const
2454 {
2455 return Base::crlbegin();
2456 }
2457
2470 LinearisedIterator lend()
2471 {
2472 return Base::lend();
2473 }
2474
2476 ConstLinearisedIterator lend() const
2477 {
2478 return Base::lend();
2479 }
2480
2482 ConstLinearisedIterator clend() const
2483 {
2484 return Base::clend();
2485 }
2486
2499 ReverseLinearisedIterator rlend()
2500 {
2501 return Base::rlend();
2502 }
2503
2505 ConstReverseLinearisedIterator rlend() const
2506 {
2507 return Base::rlend();
2508 }
2509
2511 ConstReverseLinearisedIterator crlend() const
2512 {
2513 return Base::crlend();
2514 }
2515
2541 void linearise()
2542 {
2543 Base::linearise();
2544 }
2545
2556 bool linearised() const
2557 {
2558 return Base::linearised();
2559 }
2560
2562 bool isLinearised() const
2563 {
2564 return linearised();
2565 }
2566
2586 LinearisedIteratorRange arrayOne()
2587 {
2588 return Base::arrayOne();
2589 }
2590
2592 ConstLinearisedIteratorRange arrayOne() const
2593 {
2594 return Base::arrayOne();
2595 }
2596
2620 LinearisedIteratorRange arrayTwo()
2621 {
2622 return Base::arrayTwo();
2623 }
2624
2626 ConstLinearisedIteratorRange arrayTwo() const
2627 {
2628 return Base::arrayTwo();
2629 }
2630
2644 void resize(std::size_t newSize)
2645 {
2646 Base::resize(newSize);
2647 }
2648
2660 LinearisedIterator erase(LinearisedIterator pos)
2661 {
2662 return Base::erase(pos);
2663 }
2664
2675 Iterator erase(Iterator pos)
2676 {
2677 auto iter = Base::erase(pos);
2678 return *(static_cast<Iterator*>(&iter));
2679 }
2680
2688 Iterator begin()
2689 {
2690 auto iter = Base::begin();
2691 return *(static_cast<Iterator*>(&iter));
2692 }
2693
2695 ConstIterator begin() const
2696 {
2697 auto iter = Base::begin();
2698 return *(static_cast<ConstIterator*>(&iter));
2699 }
2700
2702 ConstIterator cbegin() const
2703 {
2704 auto iter = Base::cbegin();
2705 return *(static_cast<ConstIterator*>(&iter));
2706 }
2707
2716 Iterator end()
2717 {
2718 auto iter = Base::end();
2719 return *(static_cast<Iterator*>(&iter));
2720 }
2721
2723 ConstIterator end() const
2724 {
2725 auto iter = Base::end();
2726 return *(static_cast<ConstIterator*>(&iter));
2727 }
2728
2730 ConstIterator cend() const
2731 {
2732 auto iter = Base::end();
2733 return *(static_cast<ConstIterator*>(&iter));
2734 }
2735
2737 template <std::size_t TAnySize>
2738 bool operator==(const StaticQueue<T, TAnySize>& other) const
2739 {
2740 return Base::operator==(other);
2741 }
2742
2744 template <std::size_t TAnySize>
2745 bool operator!=(const StaticQueue<T, TAnySize>& other) const
2746 {
2747 return Base::operator!=(other);
2748 }
2749
2750private:
2751 using ArrayType = std::array<StorageType, TSize>;
2752 alignas(alignof(T)) ArrayType m_array;
2753};
2754
2758template <typename T, std::size_t TSize>
2759class StaticQueue<T, TSize>::ConstIterator : public StaticQueue<T, TSize>::Base::ConstIterator
2760{
2761 using Base = typename StaticQueue<T, TSize>::Base::ConstIterator;
2762public:
2763
2765 using IteratorCategory = typename Base::IteratorCategory;
2766
2768 using iterator_category = IteratorCategory;
2769
2771 using ValueType = typename Base::ValueType;
2772
2774 using value_type = ValueType;
2775
2777 using DifferenceType = typename Base::DifferenceType;
2778
2780 using difference_type = DifferenceType;
2781
2783 using Pointer = typename Base::Pointer;
2784
2786 using pointer = Pointer;
2787
2789 using ConstPointer = typename Base::ConstPointer;
2790
2792 using Reference = typename Base::Reference;
2793
2795 using reference = Reference;
2796
2798 using ConstReference = typename Base::ConstReference;
2799
2801 using QueueType = StaticQueue<T, TSize>;
2802
2804 using ConstLinearisedIterator = typename QueueType::ConstLinearisedIterator;
2805
2809 ConstIterator(const QueueType& queue, ConstLinearisedIterator iterator)
2810 : Base(queue, iterator)
2811 {
2812 }
2813
2815 ConstIterator(const ConstIterator&) = default;
2816
2820 ConstIterator& operator=(const ConstIterator& other)
2821 {
2822 return static_cast<ConstIterator&>(Base::operator=(other));
2823 }
2824
2826 ConstIterator& operator++()
2827 {
2828 return static_cast<ConstIterator&>(Base::operator++());
2829 }
2830
2832 ConstIterator operator++(int dummyParam)
2833 {
2834 auto tmp = Base::operator++(dummyParam);
2835 return *(static_cast<ConstIterator*>(&tmp));
2836 }
2837
2839 ConstIterator& operator--()
2840 {
2841 return static_cast<ConstIterator&>(Base::operator--());
2842 }
2843
2845 ConstIterator operator--(int dummyParam)
2846 {
2847 auto tmp = Base::operator--(dummyParam);
2848 return *(static_cast<ConstIterator*>(&tmp));
2849 }
2850
2853 ConstIterator& operator+=(DifferenceType value)
2854 {
2855 return static_cast<ConstIterator&>(Base::operator+=(value));
2856 }
2857
2860 ConstIterator& operator-=(DifferenceType value)
2861 {
2862 return static_cast<ConstIterator&>(Base::operator-=(value));
2863 }
2864
2869 ConstIterator operator+(DifferenceType value) const
2870 {
2871 auto tmp = Base::operator+(value);
2872 return *(static_cast<ConstIterator*>(&tmp));
2873 }
2874
2879 ConstIterator operator-(DifferenceType value) const
2880 {
2881 auto tmp = Base::operator-(value);
2882 return *(static_cast<ConstIterator*>(&tmp));
2883 }
2884
2888 DifferenceType operator-(const ConstIterator& other) const
2889 {
2890 return Base::operator-(other);
2891 }
2892
2895 bool operator==(const ConstIterator& other) const
2896 {
2897 return Base::operator==(other);
2898 }
2899
2902 bool operator!=(const ConstIterator& other) const
2903 {
2904 return Base::operator!=(other);
2905 }
2906
2909 bool operator<(const ConstIterator& other) const
2910 {
2911 return Base::operator<(other);
2912 }
2913
2916 bool operator<=(const ConstIterator& other) const
2917 {
2918 return Base::operator<=(other);
2919 }
2920
2923 bool operator>(const ConstIterator& other) const
2924 {
2925 return Base::operator>(other);
2926 }
2927
2930 bool operator>=(const ConstIterator& other) const
2931 {
2932 return Base::operator>=(other);
2933 }
2934
2936 Reference operator*()
2937 {
2938 return Base::operator*();
2939 }
2940
2942 ConstReference operator*() const
2943 {
2944 return Base::operator*();
2945 }
2946
2948 Pointer operator->()
2949 {
2950 return Base::operator->();
2951 }
2952
2954 ConstPointer operator->() const
2955 {
2956 return Base::operator->();
2957 }
2958};
2959
2963template <typename T, std::size_t TSize>
2964class StaticQueue<T, TSize>::Iterator : public StaticQueue<T, TSize>::Base::Iterator
2965{
2966 using Base = typename StaticQueue<T, TSize>::Base::Iterator;
2967public:
2968
2970 using IteratorCategory = typename Base::IteratorCategory;
2971
2973 using iterator_category = IteratorCategory;
2974
2976 using ValueType = typename Base::ValueType;
2977
2979 using value_type = ValueType;
2980
2982 using DifferenceType = typename Base::DifferenceType;
2983
2985 using difference_type = DifferenceType;
2986
2988 using Pointer = typename Base::Pointer;
2989
2991 using pointer = Pointer;
2992
2994 using ConstPointer = typename Base::ConstPointer;
2995
2997 using Reference = typename Base::Reference;
2998
3000 using reference = Reference;
3001
3003 using ConstReference = typename Base::ConstReference;
3004
3006 using QueueType = StaticQueue<T, TSize>;
3007
3009 using LinearisedIterator = typename QueueType::LinearisedIterator;
3010
3012 using ConstLinearisedIterator = typename QueueType::ConstLinearisedIterator;
3013
3017 Iterator(QueueType& queue, LinearisedIterator iterator)
3018 : Base(queue, iterator)
3019 {
3020 }
3021
3023 Iterator(const Iterator&) = default;
3024
3028 Iterator& operator=(const Iterator& other)
3029 {
3030 return static_cast<Iterator&>(Base::operator=(other));
3031 }
3032
3034 Iterator& operator++()
3035 {
3036 return static_cast<Iterator&>(Base::operator++());
3037 }
3038
3040 Iterator operator++(int dummyParam)
3041 {
3042 auto tmp = Base::operator++(dummyParam);
3043 return *(static_cast<Iterator*>(&tmp));
3044 }
3045
3047 Iterator& operator--()
3048 {
3049 return static_cast<Iterator&>(Base::operator--());
3050 }
3051
3053 Iterator operator--(int dummyParam)
3054 {
3055 auto tmp = Base::operator--(dummyParam);
3056 return *(static_cast<Iterator*>(&tmp));
3057 }
3058
3061 Iterator& operator+=(DifferenceType value)
3062 {
3063 return static_cast<Iterator&>(Base::operator+=(value));
3064 }
3065
3068 Iterator& operator-=(DifferenceType value)
3069 {
3070 return static_cast<Iterator&>(Base::operator-=(value));
3071 }
3072
3077 Iterator operator+(DifferenceType value) const
3078 {
3079 auto tmp = Base::operator+(value);
3080 return *(static_cast<Iterator*>(&tmp));
3081 }
3082
3087 Iterator operator-(DifferenceType value) const
3088 {
3089 auto tmp = Base::operator-(value);
3090 return *(static_cast<Iterator*>(&tmp));
3091 }
3092
3096 DifferenceType operator-(const Iterator& other) const
3097 {
3098 return Base::operator-(other);
3099 }
3100
3103 bool operator==(const Iterator& other) const
3104 {
3105 return Base::operator==(other);
3106 }
3107
3110 bool operator!=(const Iterator& other) const
3111 {
3112 return Base::operator!=(other);
3113 }
3114
3117 bool operator<(const Iterator& other) const
3118 {
3119 return Base::operator<(other);
3120 }
3121
3124 bool operator<=(const Iterator& other) const
3125 {
3126 return Base::operator<=(other);
3127 }
3128
3131 bool operator>(const Iterator& other) const
3132 {
3133 return Base::operator>(other);
3134 }
3135
3138 bool operator>=(const Iterator& other) const
3139 {
3140 return Base::operator>=(other);
3141 }
3142
3144 Reference operator*()
3145 {
3146 return Base::operator*();
3147 }
3148
3150 ConstReference operator*() const
3151 {
3152 return Base::operator*();
3153 }
3154
3156 Pointer operator->()
3157 {
3158 return Base::operator->();
3159 }
3160
3162 ConstPointer operator->() const
3163 {
3164 return Base::operator->();
3165 }
3166
3167 operator ConstIterator() const
3168 {
3169 auto iter = static_cast<ConstLinearisedIterator>(Base::getIterator());
3170 const auto& queue = static_cast<QueueType&>(Base::getQueue());
3171 return ConstIterator(queue, iter);
3172 }
3173};
3174
3176
3177} // namespace util
3178
3179} // namespace comms
3180
3181COMMS_MSVC_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.
Main namespace for all classes / functions of COMMS library.
STL namespace.
Replacement to std::conditional.
Definition type_traits.h:32
Replacement to some types from standard type_traits.