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