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
163 void popFront()
164 {
165 COMMS_ASSERT(!empty()); // Queue musn't be empty
166 if (empty())
167 {
168 // Do nothing
169 return;
170 }
171
172 Reference element = front();
173 element.~T();
174
175 --m_count;
176 ++m_startIdx;
177 if ((capacity() <= m_startIdx) ||
178 (empty())) {
179 m_startIdx = 0;
180 }
181 }
182
183 void popFront(std::size_t count)
184 {
185 COMMS_ASSERT(count <= size());
186 while ((!empty()) && (count > 0)) {
187 popFront();
188 --count;
189 }
190 }
191
192 void popBack()
193 {
194 COMMS_ASSERT(!empty());
195 if (empty())
196 {
197 // Do nothing
198 return;
199 }
200
201 Reference element = back();
202 element.~T();
203
204 --m_count;
205 }
206
207 void popBack(std::size_t count)
208 {
209 COMMS_ASSERT(count <= size());
210 while ((!empty()) && (count > 0)) {
211 popBack();
212 --count;
213 }
214 }
215
216 Reference operator[](std::size_t index)
217 {
218 auto constThis = static_cast<const StaticQueueBase*>(this);
219 return const_cast<Reference>((*constThis)[index]);
220 }
221
222 ConstReference operator[](std::size_t index) const
223 {
224 COMMS_ASSERT(index < size());
225 return elementAtIndex(index);
226 }
227
228 Reference at(std::size_t index)
229 {
230 auto constThis = static_cast<const StaticQueueBase*>(this);
231 return const_cast<Reference>(constThis->at(index));
232 }
233
234 ConstReference at(std::size_t index) const
235 {
236 if (index >= size()) {
237 throw std::out_of_range(std::string("Index is out of range"));
238 }
239 return (*this)[index];
240 }
241
242 int indexOf(ConstReference element) const
243 {
244 ConstPointer elementPtr = &element;
245 auto cellPtr = reinterpret_cast<ConstStorageTypePtr>(elementPtr);
246 if ((cellPtr < &m_data[0]) ||
247 (&m_data[capacity()] <= cellPtr)) {
248 // invalid, element is not within array boundaries
249 return -1;
250 }
251
252 auto rawIdx = cellPtr - &m_data[0];
253 std::size_t actualIdx = capacity(); // invalid value
254 if (rawIdx < m_startIdx) {
255 actualIdx = (capacity() - m_startIdx) + rawIdx;
256 }
257 else {
258 actualIdx = rawIdx - m_startIdx;
259 }
260
261 if (size() <= actualIdx)
262 {
263 // Element is out of range
264 return -1;
265 }
266
267 return actualIdx;
268 }
269
270 LinearisedIterator invalidIter()
271 {
272 return reinterpret_cast<LinearisedIterator>(&m_data[capacity()]);
273 }
274
275 ConstLinearisedIterator invalidIter() const
276 {
277 return reinterpret_cast<LinearisedIterator>(&m_data[capacity()]);
278 }
279
280 ReverseLinearisedIterator invalidReverseIter()
281 {
282 return ReverseLinearisedIterator(
283 reinterpret_cast<LinearisedIterator>(&m_data[0]));
284 }
285
286 ConstReverseLinearisedIterator invalidReverseIter() const
287 {
288 return ReverseLinearisedIterator(
289 reinterpret_cast<LinearisedIterator>(&m_data[0]));
290 }
291
292 LinearisedIterator lbegin()
293 {
294 if (!linearised()) {
295 return invalidIter();
296 }
297
298 return reinterpret_cast<LinearisedIterator>(&m_data[0] + m_startIdx);
299 }
300
301 ConstLinearisedIterator lbegin() const
302 {
303 return clbegin();
304 }
305
306 ConstLinearisedIterator clbegin() const
307 {
308 if (!linearised()) {
309 return invalidIter();
310 }
311
312 return reinterpret_cast<LinearisedIterator>(&m_data[0] + m_startIdx);
313 }
314
315 ReverseLinearisedIterator rlbegin()
316 {
317 if (!linearised()) {
318 return invalidReverseIter();
319 }
320
321 return ReverseLinearisedIterator(lend());
322 }
323
324 ConstReverseLinearisedIterator rlbegin() const
325 {
326 return crlbegin();
327 }
328
329 ConstReverseLinearisedIterator crlbegin() const
330 {
331 if (!linearised()) {
332 return invalidReverseIter();
333 }
334 return ConstReverseLinearisedIterator(lend());
335 }
336
337 LinearisedIterator lend()
338 {
339 if (!linearised()) {
340 return invalidIter();
341 }
342
343 return lbegin() + size();
344 }
345
346 ConstLinearisedIterator lend() const
347 {
348 return clend();
349 }
350
351 ConstLinearisedIterator clend() const
352 {
353 if (!linearised()) {
354 return invalidIter();
355 }
356
357 return clbegin() + size();
358 }
359
360 ReverseLinearisedIterator rlend()
361 {
362 if (!linearised()) {
363 return invalidReverseIter();
364 }
365
366 return rlbegin() + size();
367 }
368
369 ConstReverseLinearisedIterator rlend() const
370 {
371 return crlend();
372 }
373
374 ConstReverseLinearisedIterator crlend() const
375 {
376 if (!linearised()) {
377 return invalidReverseIter();
378 }
379
380 return rlbegin() + size();
381 }
382
383 void linearise()
384 {
385 if (linearised()) {
386 // Nothing to do
387 return;
388 }
389
390 auto rangeOne = arrayOne();
391 auto rangeOneSize = std::distance(rangeOne.first, rangeOne.second);
392 COMMS_ASSERT(0 < rangeOneSize);
393 auto rangeTwo = arrayTwo();
394 auto rangeTwoSize = std::distance(rangeTwo.first, rangeTwo.second);
395 COMMS_ASSERT(0 < rangeTwoSize);
396 COMMS_ASSERT((rangeOneSize + rangeTwoSize) == size());
397 auto remSpaceSize = capacity() - size();
398
399 if (rangeTwoSize <= remSpaceSize) {
400 lineariseByMoveOneTwo(rangeOne, rangeTwo);
401 return;
402 }
403
404 if (rangeOneSize <= remSpaceSize) {
405 lineariseByMoveTwoOne(rangeOne, rangeTwo);
406 return;
407 }
408
409 if (rangeOneSize < rangeTwoSize) {
410 lineariseByPopOne();
411 }
412
413 lineariseByPopTwo();
414 }
415
416 bool linearised() const
417 {
418 return (empty() || ((m_startIdx + size()) <= capacity()));
419 }
420
421 LinearisedIteratorRange arrayOne()
422 {
423 auto constThis = static_cast<const StaticQueueBase*>(this);
424 auto constRange = constThis->arrayOne();
425 return
426 LinearisedIteratorRange(
427 const_cast<LinearisedIterator>(constRange.first),
428 const_cast<LinearisedIterator>(constRange.second));
429 }
430
431 ConstLinearisedIteratorRange arrayOne() const
432 {
433 auto begCell = &m_data[m_startIdx];
434 auto endCell = std::min(&m_data[m_startIdx + size()], &m_data[capacity()]);
435 return
436 ConstLinearisedIteratorRange(
437 reinterpret_cast<ConstLinearisedIterator>(begCell),
438 reinterpret_cast<ConstLinearisedIterator>(endCell));
439 }
440
441 LinearisedIteratorRange arrayTwo()
442 {
443 auto constThis = static_cast<const StaticQueueBase*>(this);
444 auto constRange = constThis->arrayTwo();
445 return
446 LinearisedIteratorRange(
447 const_cast<LinearisedIterator>(constRange.first),
448 const_cast<LinearisedIterator>(constRange.second));
449 }
450
451 ConstLinearisedIteratorRange arrayTwo() const
452 {
453 if (linearised()) {
454 auto iter = arrayOne().second;
455 return ConstLinearisedIteratorRange(iter, iter);
456 }
457
458 auto begCell = &m_data[0];
459 auto endCell = &m_data[(m_startIdx + size()) - capacity()];
460
461 return
462 ConstLinearisedIteratorRange(
463 reinterpret_cast<ConstLinearisedIterator>(begCell),
464 reinterpret_cast<ConstLinearisedIterator>(endCell));
465 }
466
467 void resize(std::size_t newSize)
468 {
469 COMMS_ASSERT(newSize <= capacity());
470 if (capacity() < newSize) {
471 return;
472 }
473
474 if (size() <= newSize) {
475 while (size() < newSize) {
476 pushBackNotFull(ValueType());
477 }
478
479 return;
480 }
481
482 // New requested size is less than existing now
483 popBack(size() - newSize);
484 }
485
486 LinearisedIterator erase(LinearisedIterator pos)
487 {
488 COMMS_ASSERT(pos != invalidIter());
489 COMMS_ASSERT(!empty());
490 auto rangeOne = arrayOne();
491 auto rangeTwo = arrayTwo();
492
493 auto isInRangeFunc =
494 [](LinearisedIterator pos, const LinearisedIteratorRange range) -> bool
495 {
496 return ((range.first <= pos) && (pos < range.second));
497 };
498
499 COMMS_ASSERT(isInRangeFunc(pos, rangeOne) ||
500 isInRangeFunc(pos, rangeTwo));
501
502 if (isInRangeFunc(pos, rangeOne)) {
503 std::move_backward(rangeOne.first, pos, pos + 1);
504
505 popFront();
506 rangeOne = arrayOne();
507 if (isInRangeFunc(pos, rangeOne)) {
508 return pos + 1;
509 }
510
511 return rangeOne.first;
512 }
513
514 if (isInRangeFunc(pos, rangeTwo)) {
515 std::move(pos + 1, rangeTwo.second, pos);
516 popBack();
517 if (!linearised()) {
518 return pos;
519 }
520 return arrayOne().second;
521 }
522
523 static constexpr bool Invalid_iterator_is_used = false;
524 static_cast<void>(Invalid_iterator_is_used);
525 COMMS_ASSERT(Invalid_iterator_is_used);
526 return invalidIter();
527 }
528
529 Iterator erase(Iterator pos)
530 {
531 COMMS_ASSERT(pos != end());
532 COMMS_ASSERT(!empty());
533 Pointer elem = &(*pos);
534 auto rangeOne = arrayOne();
535 auto rangeTwo = arrayTwo();
536
537 auto isInRangeFunc =
538 [](Pointer elemPtr, const LinearisedIteratorRange range) -> bool
539 {
540 return ((&(*range.first) <= elemPtr) && (elemPtr < &(*range.second)));
541 };
542
543 COMMS_ASSERT(isInRangeFunc(elem, rangeOne) ||
544 isInRangeFunc(elem, rangeTwo));
545
546 if (isInRangeFunc(elem, rangeOne)) {
547 std::move_backward(rangeOne.first, elem, elem + 1);
548
549 popFront();
550 rangeOne = arrayOne();
551 if (isInRangeFunc(elem, rangeOne)) {
552 return pos + 1;
553 }
554
555 return begin();
556 }
557
558 if (isInRangeFunc(elem, rangeTwo)) {
559 std::move(elem + 1, rangeTwo.second, elem);
560 popBack();
561 if (!linearised()) {
562 return pos;
563 }
564 return end();
565 }
566
567 static constexpr bool Invalid_iterator_is_used = false;
568 static_cast<void>(Invalid_iterator_is_used);
569 COMMS_ASSERT(Invalid_iterator_is_used);
570 return end();
571 }
572
573 Iterator begin()
574 {
575 return Iterator(*this, reinterpret_cast<LinearisedIterator>(&m_data[0]));
576 }
577
578 ConstIterator begin() const
579 {
580 return cbegin();
581 }
582
583 ConstIterator cbegin() const
584 {
585 return ConstIterator(*this, reinterpret_cast<ConstLinearisedIterator>(&m_data[0]));
586 }
587
588 Iterator end()
589 {
590 return Iterator(*this, reinterpret_cast<LinearisedIterator>(&m_data[size()]));
591 }
592
593 ConstIterator end() const
594 {
595 return cend();
596 }
597
598 ConstIterator cend() const
599 {
600 return ConstIterator(*this, reinterpret_cast<ConstLinearisedIterator>(&m_data[size()]));
601 }
602
603 template <typename TOther>
604 void assignElements(TOther&& other)
605 {
606 static_assert(std::is_base_of<StaticQueueBase, typename std::decay<TOther>::type>::value,
607 "Assignment works only on the same types");
608
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
1209
1210template <typename TWrapperElemType, typename TQueueElemType>
1211class CastWrapperQueueBase : public StaticQueueBase<TQueueElemType>
1212{
1213 using Base = StaticQueueBase<TQueueElemType>;
1214 using WrapperElemType = TWrapperElemType;
1215
1216 using BaseValueType = typename Base::ValueType;
1217 using BaseStorageTypePtr = typename Base::StorageTypePtr;
1218 using BaseReference = typename Base::Reference;
1219 using BaseConstReference = typename Base::ConstReference;
1220 using BasePointer = typename Base::Pointer;
1221 using BaseConstPointer = typename Base::ConstPointer;
1222 using BaseLinearisedIterator = typename Base::LinearisedIterator;
1223 using BaseConstLinearisedIterator = typename Base::ConstLinearisedIterator;
1224 using BaseReverseLinearisedIterator = typename Base::ReverseLinearisedIterator;
1225 using BaseConstReverseLinearisedIterator = typename Base::ConstReverseLinearisedIterator;
1226 using BaseLinearisedIteratorRange = typename Base::LinearisedIteratorRange;
1227 using BaseConstLinearisedIteratorRange = typename Base::ConstLinearisedIteratorRange;
1228
1229public:
1230
1231 class ConstIterator;
1232 class Iterator;
1233
1234protected:
1235 using ValueType = WrapperElemType;
1236 using StorageType = comms::util::AlignedStorage<sizeof(ValueType), std::alignment_of<ValueType>::value>;
1237 using StorageTypePtr = StorageType*;
1238 using Reference = ValueType&;
1239 using ConstReference = const ValueType&;
1240 using Pointer = ValueType*;
1241 using ConstPointer = const ValueType*;
1242 using LinearisedIterator = Pointer;
1243 using ConstLinearisedIterator = ConstPointer;
1244 using ReverseLinearisedIterator = std::reverse_iterator<LinearisedIterator>;
1245 using ConstReverseLinearisedIterator = std::reverse_iterator<ConstLinearisedIterator>;
1246 using LinearisedIteratorRange = std::pair<LinearisedIterator, LinearisedIterator>;
1247 using ConstLinearisedIteratorRange = std::pair<ConstLinearisedIterator, ConstLinearisedIterator>;
1248
1249 CastWrapperQueueBase(StorageTypePtr data, std::size_t capacity)
1250 : Base(reinterpret_cast<BaseStorageTypePtr>(data), capacity)
1251 {
1252 static_assert(sizeof(ValueType) == sizeof(BaseValueType),
1253 "The times must have identical size.");
1254 }
1255
1256 ~CastWrapperQueueBase() noexcept = default;
1257
1258 CastWrapperQueueBase& operator=(const CastWrapperQueueBase& other) = default;
1259 CastWrapperQueueBase& operator=(CastWrapperQueueBase&& other) = default;
1260
1261 Reference front()
1262 {
1263 return reinterpret_cast<Reference>(Base::front());
1264 }
1265
1266 ConstReference front() const
1267 {
1268 return reinterpret_cast<ConstReference>(Base::front());
1269 }
1270
1271 Reference back()
1272 {
1273 return reinterpret_cast<Reference>(Base::back());
1274 }
1275
1276 ConstReference back() const
1277 {
1278 return reinterpret_cast<Reference>(Base::back());
1279 }
1280
1281 Reference operator[](std::size_t index)
1282 {
1283 return reinterpret_cast<Reference>(Base::operator[](index));
1284 }
1285
1286 ConstReference operator[](std::size_t index) const
1287 {
1288 return reinterpret_cast<ConstReference>(Base::operator[](index));
1289 }
1290
1291 Reference at(std::size_t index)
1292 {
1293 return reinterpret_cast<Reference>(Base::at(index));
1294 }
1295
1296 ConstReference at(std::size_t index) const
1297 {
1298 return reinterpret_cast<ConstReference>(Base::at(index));
1299 }
1300
1301 int indexOf(ConstReference element) const
1302 {
1303 return Base::indexOf(reinterpret_cast<BaseConstReference>(element));
1304 }
1305
1306 LinearisedIterator invalidIter()
1307 {
1308 return reinterpret_cast<LinearisedIterator>(Base::invalidIter());
1309 }
1310
1311 ConstLinearisedIterator invalidIter() const
1312 {
1313 return reinterpret_cast<ConstLinearisedIterator>(Base::invalidIter());
1314 }
1315
1316 ReverseLinearisedIterator invalidReverseIter()
1317 {
1318 return ReverseLinearisedIterator(
1319 reinterpret_cast<LinearisedIterator>(
1320 Base::invalidReverseIter().base()));
1321 }
1322
1323 ConstReverseLinearisedIterator invalidReverseIter() const
1324 {
1325 return ConstReverseLinearisedIterator(
1326 reinterpret_cast<ConstLinearisedIterator>(
1327 Base::invalidReverseIter().base()));
1328 }
1329
1330 LinearisedIterator lbegin()
1331 {
1332 return reinterpret_cast<LinearisedIterator>(Base::lbegin());
1333 }
1334
1335 ConstLinearisedIterator lbegin() const
1336 {
1337 return reinterpret_cast<ConstLinearisedIterator>(Base::lbegin());
1338 }
1339
1340 ConstLinearisedIterator clbegin() const
1341 {
1342 return reinterpret_cast<ConstLinearisedIterator>(Base::clbegin());
1343 }
1344
1345 ReverseLinearisedIterator rlbegin()
1346 {
1347 return ReverseLinearisedIterator(
1348 reinterpret_cast<LinearisedIterator>(
1349 Base::rlbegin().base()));
1350 }
1351
1352 ConstReverseLinearisedIterator rlbegin() const
1353 {
1354 return ConstReverseLinearisedIterator(
1355 reinterpret_cast<ConstLinearisedIterator>(
1356 Base::rlbegin().base()));
1357 }
1358
1359 ConstReverseLinearisedIterator crlbegin() const
1360 {
1361 return ConstReverseLinearisedIterator(
1362 reinterpret_cast<ConstLinearisedIterator>(
1363 Base::crlbegin().base()));
1364 }
1365
1366 LinearisedIterator lend()
1367 {
1368 return reinterpret_cast<LinearisedIterator>(Base::lend());
1369 }
1370
1371 ConstLinearisedIterator lend() const
1372 {
1373 return reinterpret_cast<ConstLinearisedIterator>(Base::lend());
1374 }
1375
1376 ConstLinearisedIterator clend() const
1377 {
1378 return reinterpret_cast<ConstLinearisedIterator>(Base::clend());
1379 }
1380
1381 ReverseLinearisedIterator rlend()
1382 {
1383 return ReverseLinearisedIterator(
1384 reinterpret_cast<LinearisedIterator>(
1385 Base::rlend().base()));
1386 }
1387
1388 ConstReverseLinearisedIterator rlend() const
1389 {
1390 return ConstReverseLinearisedIterator(
1391 reinterpret_cast<ConstLinearisedIterator>(
1392 Base::rlend().base()));
1393 }
1394
1395 ConstReverseLinearisedIterator crlend() const
1396 {
1397 return ConstReverseLinearisedIterator(
1398 reinterpret_cast<ConstLinearisedIterator>(
1399 Base::crlend().base()));
1400 }
1401
1402 LinearisedIteratorRange arrayOne()
1403 {
1404 auto range = Base::arrayOne();
1405 return LinearisedIteratorRange(
1406 reinterpret_cast<LinearisedIterator>(range.first),
1407 reinterpret_cast<LinearisedIterator>(range.second));
1408 }
1409
1410 ConstLinearisedIteratorRange arrayOne() const
1411 {
1412 auto range = Base::arrayOne();
1413 return ConstLinearisedIteratorRange(
1414 reinterpret_cast<ConstLinearisedIterator>(range.first),
1415 reinterpret_cast<ConstLinearisedIterator>(range.second));
1416
1417 }
1418
1419 LinearisedIteratorRange arrayTwo()
1420 {
1421 auto range = Base::arrayTwo();
1422 return LinearisedIteratorRange(
1423 reinterpret_cast<LinearisedIterator>(range.first),
1424 reinterpret_cast<LinearisedIterator>(range.second));
1425
1426 }
1427
1428 ConstLinearisedIteratorRange arrayTwo() const
1429 {
1430 auto range = Base::arrayTwo();
1431 return ConstLinearisedIteratorRange(
1432 reinterpret_cast<ConstLinearisedIterator>(range.first),
1433 reinterpret_cast<ConstLinearisedIterator>(range.second));
1434
1435 }
1436
1437 LinearisedIterator erase(LinearisedIterator pos)
1438 {
1439 return reinterpret_cast<LinearisedIterator>(
1440 Base::erase(
1441 reinterpret_cast<BaseLinearisedIterator>(pos)));
1442 }
1443
1444 Iterator erase(Iterator pos)
1445 {
1446 auto tmp = Base::erase(pos);
1447 return *(reinterpret_cast<Iterator*>(&tmp));
1448 }
1449
1450 Iterator begin()
1451 {
1452 auto tmp = Base::begin();
1453 return *(reinterpret_cast<Iterator*>(&tmp));
1454 }
1455
1456 ConstIterator begin() const
1457 {
1458 auto tmp = Base::begin();
1459 return *(reinterpret_cast<ConstIterator*>(&tmp));
1460 }
1461
1462 ConstIterator cbegin() const
1463 {
1464 auto tmp = Base::cbegin();
1465 return *(reinterpret_cast<ConstIterator*>(&tmp));
1466
1467 }
1468
1469 Iterator end()
1470 {
1471 auto tmp = Base::end();
1472 return *(reinterpret_cast<Iterator*>(&tmp));
1473 }
1474
1475 ConstIterator end() const
1476 {
1477 auto tmp = Base::end();
1478 return *(reinterpret_cast<ConstIterator*>(&tmp));
1479 }
1480
1481 ConstIterator cend() const
1482 {
1483 auto tmp = Base::cend();
1484 return *(reinterpret_cast<ConstIterator*>(&tmp));
1485 }
1486
1487 void pushBack(ConstReference value)
1488 {
1489 Base::pushBack(reinterpret_cast<BaseConstReference>(value));
1490 }
1491
1492 void pushFront(ConstReference value)
1493 {
1494 Base::pushFront(reinterpret_cast<BaseConstReference>(value));
1495 }
1496
1497 LinearisedIterator insert(LinearisedIterator pos, ConstReference value)
1498 {
1499 return reinterpret_cast<LinearisedIterator>(
1500 Base::insert(
1501 reinterpret_cast<BaseLinearisedIterator>(pos),
1502 reinterpret_cast<BaseConstReference>(value)));
1503 }
1504
1505 void assignElements(const CastWrapperQueueBase& other)
1506 {
1507 Base::assignElements(static_cast<const Base&>(other));
1508 }
1509
1510 void assignElements(CastWrapperQueueBase&& other)
1511 {
1512 Base::assignElements(static_cast<Base&&>(std::move(other)));
1513 }
1514};
1515
1516template <typename TWrapperElemType, typename TQueueElemType>
1517class CastWrapperQueueBase<TWrapperElemType, TQueueElemType>::ConstIterator :
1518 public StaticQueueBase<TQueueElemType>::ConstIterator
1519{
1520 using Base = typename StaticQueueBase<TQueueElemType>::ConstIterator;
1521public:
1522 ConstIterator(const ConstIterator&) = default;
1523 ConstIterator& operator=(const ConstIterator&) = default;
1524 ~ConstIterator() noexcept = default;
1525
1526protected:
1527 using ExpectedQueueType = const StaticQueueBase<TWrapperElemType>;
1528 using ActualQueueType = const StaticQueueBase<TQueueElemType>;
1529 using ValueType = TWrapperElemType;
1530 using Reference = const ValueType&;
1531 using ConstReference = const ValueType&;
1532 using Pointer = const ValueType*;
1533 using ConstPointer = const ValueType*;
1534 using DifferenceType = typename Base::DifferenceType;
1535
1536 ConstIterator(ExpectedQueueType& queue, Pointer iterator)
1537 : Base(reinterpret_cast<ActualQueueType&>(queue), iterator)
1538 {
1539 }
1540
1541 ConstIterator& operator++()
1542 {
1543 Base::operator++();
1544 return *this;
1545 }
1546
1547 ConstIterator operator++(int dummy)
1548 {
1549 auto tmp = Base::operator++(dummy);
1550 return *(static_cast<ConstIterator*>(&tmp));
1551 }
1552
1553 ConstIterator& operator--()
1554 {
1555 Base::operator--();
1556 return *this;
1557 }
1558
1559 ConstIterator operator--(int dummy)
1560 {
1561 auto tmp = Base::operator--(dummy);
1562 return *(static_cast<ConstIterator*>(&tmp));
1563 }
1564
1565 ConstIterator& operator+=(DifferenceType value)
1566 {
1567 Base::operator+=(value);
1568 return *this;
1569 }
1570
1571 ConstIterator& operator-=(DifferenceType value)
1572 {
1573 Base::operator-=(value);
1574 return *this;
1575 }
1576
1577 ConstIterator operator+(DifferenceType value) const
1578 {
1579 auto tmp = Base::operator+(value);
1580 return *(static_cast<ConstIterator*>(&tmp));
1581 }
1582
1583 ConstIterator operator-(DifferenceType value) const
1584 {
1585 auto tmp = Base::operator-(value);
1586 return *(static_cast<ConstIterator*>(&tmp));
1587 }
1588
1589 DifferenceType operator-(const ConstIterator& other) const
1590 {
1591 return Base::operator-(other);
1592 }
1593
1594 Reference operator*()
1595 {
1596 auto& ref = Base::operator*();
1597 return reinterpret_cast<Reference>(ref);
1598 }
1599
1600 ConstReference operator*() const
1601 {
1602 auto& ref = Base::operator*();
1603 return reinterpret_cast<ConstReference>(ref);
1604 }
1605
1606 Pointer operator->()
1607 {
1608 auto* ptr = Base::operator->();
1609 return reinterpret_cast<Pointer>(ptr);
1610 }
1611
1612 ConstPointer operator->() const
1613 {
1614 auto* ptr = Base::operator->();
1615 return reinterpret_cast<ConstPointer>(ptr);
1616 }
1617};
1618
1619template <typename TWrapperElemType, typename TQueueElemType>
1620class CastWrapperQueueBase<TWrapperElemType, TQueueElemType>::Iterator :
1621 public StaticQueueBase<TQueueElemType>::Iterator
1622{
1623 using Base = typename StaticQueueBase<TQueueElemType>::Iterator;
1624public:
1625 Iterator(const Iterator&) = default;
1626 Iterator& operator=(const Iterator&) = default;
1627 ~Iterator() noexcept = default;
1628
1629protected:
1630 using ExpectedQueueType = const StaticQueueBase<TWrapperElemType>;
1631 using ActualQueueType = const StaticQueueBase<TQueueElemType>;
1632 using ValueType = TWrapperElemType;
1633 using Reference = ValueType&;
1634 using ConstReference = const ValueType&;
1635 using Pointer = ValueType*;
1636 using ConstPointer = const ValueType*;
1637 using DifferenceType = typename Base::DifferenceType;
1638
1639 Iterator(ExpectedQueueType& queue, Pointer iterator)
1640 : Base(reinterpret_cast<ActualQueueType&>(queue), iterator)
1641 {
1642 }
1643
1644 Iterator& operator++()
1645 {
1646 Base::operator++();
1647 return *this;
1648 }
1649
1650 Iterator operator++(int dummy)
1651 {
1652 auto tmp = Base::operator++(dummy);
1653 return *(static_cast<Iterator*>(&tmp));
1654 }
1655
1656 Iterator& operator--()
1657 {
1658 Base::operator--();
1659 return *this;
1660 }
1661
1662 Iterator operator--(int dummy)
1663 {
1664 auto tmp = Base::operator--(dummy);
1665 return *(static_cast<Iterator*>(&tmp));
1666 }
1667
1668 Iterator& operator+=(DifferenceType value)
1669 {
1670 Base::operator+=(value);
1671 return *this;
1672 }
1673
1674 Iterator& operator-=(DifferenceType value)
1675 {
1676 Base::operator-=(value);
1677 return *this;
1678 }
1679
1680 Iterator operator+(DifferenceType value) const
1681 {
1682 auto tmp = Base::operator+(value);
1683 return *(static_cast<Iterator*>(&tmp));
1684 }
1685
1686 Iterator operator-(DifferenceType value) const
1687 {
1688 auto tmp = Base::operator-(value);
1689 return *(static_cast<Iterator*>(&tmp));
1690 }
1691
1692 DifferenceType operator-(const Iterator& other) const
1693 {
1694 return Base::operator-(other);
1695 }
1696
1697 Reference operator*()
1698 {
1699 auto& ref = Base::operator*();
1700 return reinterpret_cast<Reference>(ref);
1701 }
1702
1703 ConstReference operator*() const
1704 {
1705 auto& ref = Base::operator*();
1706 return reinterpret_cast<ConstReference>(ref);
1707 }
1708
1709 Pointer operator->()
1710 {
1711 auto* ptr = Base::operator->();
1712 return reinterpret_cast<Pointer>(ptr);
1713 }
1714
1715 ConstPointer operator->() const
1716 {
1717 auto* ptr = Base::operator->();
1718 return reinterpret_cast<ConstPointer>(ptr);
1719 }
1720};
1721
1722template <typename T>
1723class StaticQueueBaseOptimised : public StaticQueueBase<T>
1724{
1725 usign Base = StaticQueueBase<T>;
1726protected:
1727
1728 using StorageTypePtr = typename Base::StorageTypePtr;
1729
1730 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1731 : Base(data, capacity)
1732 {
1733 }
1734
1735 ~StaticQueueBaseOptimised() noexcept = default;
1736
1737 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1738 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1739};
1740
1741template <>
1742class StaticQueueBaseOptimised<std::int8_t> : public CastWrapperQueueBase<std::int8_t, std::uint8_t>
1743{
1744 using Base = CastWrapperQueueBase<std::int8_t, std::uint8_t>;
1745protected:
1746
1747 using StorageTypePtr = typename Base::StorageTypePtr;
1748
1749 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1750 : Base(data, capacity)
1751 {
1752 }
1753
1754 ~StaticQueueBaseOptimised() noexcept = default;
1755 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1756 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1757};
1758
1759template <>
1760class StaticQueueBaseOptimised<std::int16_t> : public CastWrapperQueueBase<std::int16_t, std::uint16_t>
1761{
1762 using Base = CastWrapperQueueBase<std::int16_t, std::uint16_t>;
1763protected:
1764
1765 using StorageTypePtr = typename Base::StorageTypePtr;
1766
1767 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1768 : Base(data, capacity)
1769 {
1770 }
1771
1772 ~StaticQueueBaseOptimised() noexcept = default;
1773 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1774 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1775};
1776
1777template <>
1778class StaticQueueBaseOptimised<std::int32_t> : public CastWrapperQueueBase<std::int32_t, std::uint32_t>
1779{
1780 using Base = CastWrapperQueueBase<std::int32_t, std::uint32_t>;
1781protected:
1782
1783 using StorageTypePtr = typename Base::StorageTypePtr;
1784
1785 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1786 : Base(data, capacity)
1787 {
1788 }
1789
1790 ~StaticQueueBaseOptimised() noexcept = default;
1791 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1792 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1793};
1794
1795template <>
1796class StaticQueueBaseOptimised<std::int64_t> : public CastWrapperQueueBase<std::int64_t, std::uint64_t>
1797{
1798 using Base = CastWrapperQueueBase<std::int64_t, std::uint64_t>;
1799protected:
1800
1801 using StorageTypePtr = typename Base::StorageTypePtr;
1802
1803 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1804 : Base(data, capacity)
1805 {
1806 }
1807
1808 ~StaticQueueBaseOptimised() noexcept = default;
1809 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1810 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1811};
1812
1813template <typename T>
1814class StaticQueueBaseOptimised<T*> : public CastWrapperQueueBase<T*, typename comms::util::SizeToType<sizeof(T*)>::Type>
1815{
1816 using Base = CastWrapperQueueBase<T*, typename comms::util::SizeToType<sizeof(T*)>::Type>;
1817protected:
1818
1819 using Base = typename Base::StorageTypePtr;
1820
1821 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1822 : Base(data, capacity)
1823 {
1824 }
1825
1826 ~StaticQueueBaseOptimised() noexcept = default;
1827 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1828 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1829};
1830
1831
1832} // namespace details
1833
1835
1846template <typename T, std::size_t TSize>
1847class StaticQueue : public details::StaticQueueBaseOptimised<T>
1848{
1849 using Base = details::StaticQueueBaseOptimised<T>;
1850
1851 using StorageType = typename Base::StorageType;
1852public:
1854 using ValueType = typename Base::ValueType;
1855
1857 using value_type = ValueType;
1858
1860 using SizeType = typename Base::SizeType;
1861
1863 using size_type = SizeType;
1864
1866 using Reference = typename Base::Reference;
1867
1869 using reference = Reference;
1870
1872 using ConstReference = typename Base::ConstReference;
1873
1875 using const_reference = ConstReference;
1876
1878 using Pointer = typename Base::Pointer;
1879
1881 using pointer = Pointer;
1882
1884 using ConstPointer = typename Base::ConstPointer;
1885
1887 using const_pointer = ConstPointer;
1888
1890 using LinearisedIterator = typename Base::LinearisedIterator;
1891
1893 using ConstLinearisedIterator = typename Base::ConstLinearisedIterator;
1894
1896 using ReverseLinearisedIterator = typename Base::ReverseLinearisedIterator;
1897
1899 using ConstReverseLinearisedIterator = typename Base::ConstReverseLinearisedIterator;
1900
1902 using LinearisedIteratorRange = typename Base::LinearisedIteratorRange;
1903
1905 using ConstLinearisedIteratorRange = typename Base::ConstLinearisedIteratorRange;
1906
1908 class ConstIterator;
1909
1911 using const_iterator = ConstIterator;
1912
1914 class Iterator;
1915
1917 using iterator = Iterator;
1918
1919 // Member functions
1924 StaticQueue()
1925 : Base(&m_array[0], TSize)
1926 {
1927 }
1928
1937 StaticQueue(const StaticQueue& queue)
1938 : Base(&m_array[0], TSize)
1939 {
1940 Base::assignElements(queue);
1941 }
1942
1951 StaticQueue(StaticQueue&& queue)
1952 : Base(&m_array[0], TSize)
1953 {
1954 Base::assignElements(std::move(queue));
1955 }
1956
1957
1966 template <std::size_t TAnySize>
1967 StaticQueue(const StaticQueue<T, TAnySize>& queue)
1968 : Base(&m_array[0], TSize)
1969 {
1970 Base::assignElements(queue);
1971 }
1972
1981 template <std::size_t TAnySize>
1982 StaticQueue(StaticQueue<T, TAnySize>&& queue)
1983 : Base(&m_array[0], TSize)
1984 {
1985 Base::assignElements(std::move(queue));
1986 }
1987
1994 ~StaticQueue() noexcept
1995 {
1996 clear();
1997 }
1998
2009 StaticQueue& operator=(const StaticQueue& queue)
2010 {
2011 return static_cast<StaticQueue&>(Base::operator=(queue));
2012 }
2013
2024 StaticQueue& operator=(StaticQueue&& queue)
2025 {
2026 return static_cast<StaticQueue&>(Base::operator=(std::move(queue)));
2027 }
2028
2029
2041 template <std::size_t TAnySize>
2042 StaticQueue& operator=(const StaticQueue<T, TAnySize>& queue)
2043 {
2044 return static_cast<StaticQueue&>(Base::operator=(queue));
2045 }
2046
2058 template <std::size_t TAnySize>
2059 StaticQueue& operator=(StaticQueue<T, TAnySize>&& queue)
2060 {
2061 return static_cast<StaticQueue&>(Base::operator=(std::move(queue)));
2062 }
2063
2070 static constexpr std::size_t capacity()
2071 {
2072 return TSize;
2073 }
2074
2082 std::size_t size() const
2083 {
2084 return Base::size();
2085 }
2086
2092 bool empty() const
2093 {
2094 return Base::empty();
2095 }
2096
2098 bool isEmpty() const
2099 {
2100 return empty();
2101 }
2102
2108 bool full() const
2109 {
2110 return Base::full();
2111 }
2112
2114 bool isFull() const
2115 {
2116 return full();
2117 }
2118
2124 void clear()
2125 {
2126 Base::clear();
2127 }
2128
2135 void popBack()
2136 {
2137 Base::popBack();
2138 }
2139
2141 inline void pop_back()
2142 {
2143 popBack();
2144 }
2145
2155 void popBack(std::size_t count)
2156 {
2157 Base::popBack(count);
2158 }
2159
2161 void pop_back(std::size_t count)
2162 {
2163 popBack(count);
2164 }
2165
2172 void popFront()
2173 {
2174 Base::popFront();
2175 }
2176
2178 inline void pop_front()
2179 {
2180 popFront();
2181 }
2182
2190 void popFront(std::size_t count)
2191 {
2192 Base::popFront(count);
2193 }
2194
2196 inline void pop_front(std::size_t count)
2197 {
2198 popFront(count);
2199 }
2200
2208 template <typename U>
2209 void pushBack(U&& value)
2210 {
2211 Base::pushBack(std::forward<U>(value));
2212 }
2213
2222 template <typename... TArgs>
2223 void emplaceBack(TArgs&&... args)
2224 {
2225 Base::emplaceBack(std::forward<TArgs>(args)...);
2226 }
2227
2229 template <typename U>
2230 inline void push_back(U&& value)
2231 {
2232 pushBack(std::forward<U>(value));
2233 }
2234
2242 template <typename U>
2243 void pushFront(U&& value)
2244 {
2245 Base::pushFront(std::forward<U>(value));
2246 }
2247
2249 template <typename U>
2250 inline void push_front(U&& value)
2251 {
2252 pushFront(std::forward<U>(value));
2253 }
2254
2270 template <typename U>
2271 LinearisedIterator insert(LinearisedIterator pos, U&& value)
2272 {
2273 return Base::insert(pos, std::forward<U>(value));
2274 }
2275
2276
2283 Reference front()
2284 {
2285 return Base::front();
2286 }
2287
2289 ConstReference front() const
2290 {
2291 return Base::front();
2292 }
2293
2300 Reference back()
2301 {
2302 return Base::back();
2303 }
2304
2306 ConstReference back() const
2307 {
2308 return Base::back();
2309 }
2310
2321 Reference operator[](std::size_t index)
2322 {
2323 return Base::operator[](index);
2324 }
2325
2327 ConstReference operator[](std::size_t index) const
2328 {
2329 return Base::operator[](index);
2330 }
2331
2343 Reference at(std::size_t index)
2344 {
2345 return Base::at(index);
2346 }
2347
2349 ConstReference at(std::size_t index) const
2350 {
2351 return Base::at(index);
2352 }
2353
2363 int indexOf(ConstReference element) const
2364 {
2365 return Base::indexOf(element);
2366 }
2367
2374 LinearisedIterator invalidIter()
2375 {
2376 return Base::invalidIter();
2377 }
2378
2380 ConstLinearisedIterator invalidIter() const
2381 {
2382 return Base::invalidIter();
2383 }
2384
2390 ReverseLinearisedIterator invalidReverseIter()
2391 {
2392 return Base::invalidReverseIter();
2393 }
2394
2396 ConstReverseLinearisedIterator invalidReverseIter() const
2397 {
2398 return Base::invalidReverseIter();
2399 }
2400
2415 LinearisedIterator lbegin()
2416 {
2417 return Base::lbegin();
2418 }
2419
2421 ConstLinearisedIterator lbegin() const
2422 {
2423 return Base::lbegin();
2424 }
2425
2427 ConstLinearisedIterator clbegin() const
2428 {
2429 return Base::clbegin();
2430 }
2431
2446 ReverseLinearisedIterator rlbegin()
2447 {
2448 return Base::rlbegin();
2449 }
2450
2452 ConstReverseLinearisedIterator rlbegin() const
2453 {
2454 return Base::rlbegin();
2455 }
2456
2458 ConstReverseLinearisedIterator crlbegin() const
2459 {
2460 return Base::crlbegin();
2461 }
2462
2475 LinearisedIterator lend()
2476 {
2477 return Base::lend();
2478 }
2479
2481 ConstLinearisedIterator lend() const
2482 {
2483 return Base::lend();
2484 }
2485
2487 ConstLinearisedIterator clend() const
2488 {
2489 return Base::clend();
2490 }
2491
2504 ReverseLinearisedIterator rlend()
2505 {
2506 return Base::rlend();
2507 }
2508
2510 ConstReverseLinearisedIterator rlend() const
2511 {
2512 return Base::rlend();
2513 }
2514
2516 ConstReverseLinearisedIterator crlend() const
2517 {
2518 return Base::crlend();
2519 }
2520
2546 void linearise()
2547 {
2548 Base::linearise();
2549 }
2550
2561 bool linearised() const
2562 {
2563 return Base::linearised();
2564 }
2565
2567 bool isLinearised() const
2568 {
2569 return linearised();
2570 }
2571
2591 LinearisedIteratorRange arrayOne()
2592 {
2593 return Base::arrayOne();
2594 }
2595
2597 ConstLinearisedIteratorRange arrayOne() const
2598 {
2599 return Base::arrayOne();
2600 }
2601
2625 LinearisedIteratorRange arrayTwo()
2626 {
2627 return Base::arrayTwo();
2628 }
2629
2631 ConstLinearisedIteratorRange arrayTwo() const
2632 {
2633 return Base::arrayTwo();
2634 }
2635
2649 void resize(std::size_t newSize)
2650 {
2651 Base::resize(newSize);
2652 }
2653
2665 LinearisedIterator erase(LinearisedIterator pos)
2666 {
2667 return Base::erase(pos);
2668 }
2669
2680 Iterator erase(Iterator pos)
2681 {
2682 auto iter = Base::erase(pos);
2683 return *(static_cast<Iterator*>(&iter));
2684 }
2685
2686
2694 Iterator begin()
2695 {
2696 auto iter = Base::begin();
2697 return *(static_cast<Iterator*>(&iter));
2698 }
2699
2701 ConstIterator begin() const
2702 {
2703 auto iter = Base::begin();
2704 return *(static_cast<ConstIterator*>(&iter));
2705 }
2706
2708 ConstIterator cbegin() const
2709 {
2710 auto iter = Base::cbegin();
2711 return *(static_cast<ConstIterator*>(&iter));
2712 }
2713
2722 Iterator end()
2723 {
2724 auto iter = Base::end();
2725 return *(static_cast<Iterator*>(&iter));
2726 }
2727
2729 ConstIterator end() const
2730 {
2731 auto iter = Base::end();
2732 return *(static_cast<ConstIterator*>(&iter));
2733 }
2734
2736 ConstIterator cend() const
2737 {
2738 auto iter = Base::end();
2739 return *(static_cast<ConstIterator*>(&iter));
2740 }
2741
2743 template <std::size_t TAnySize>
2744 bool operator==(const StaticQueue<T, TAnySize>& other) const
2745 {
2746 return Base::operator==(other);
2747 }
2748
2750 template <std::size_t TAnySize>
2751 bool operator!=(const StaticQueue<T, TAnySize>& other) const
2752 {
2753 return Base::operator!=(other);
2754 }
2755
2756
2757private:
2758 using ArrayType = std::array<StorageType, TSize>;
2759 alignas(alignof(T)) ArrayType m_array;
2760};
2761
2765template <typename T, std::size_t TSize>
2766class StaticQueue<T, TSize>::ConstIterator : public StaticQueue<T, TSize>::Base::ConstIterator
2767{
2768 using Base = typename StaticQueue<T, TSize>::Base::ConstIterator;
2769public:
2770
2772 using IteratorCategory = typename Base::IteratorCategory;
2773
2775 using iterator_category = IteratorCategory;
2776
2778 using ValueType = typename Base::ValueType;
2779
2781 using value_type = ValueType;
2782
2784 using DifferenceType = typename Base::DifferenceType;
2785
2787 using difference_type = DifferenceType;
2788
2790 using Pointer = typename Base::Pointer;
2791
2793 using pointer = Pointer;
2794
2796 using ConstPointer = typename Base::ConstPointer;
2797
2799 using Reference = typename Base::Reference;
2800
2802 using reference = Reference;
2803
2805 using ConstReference = typename Base::ConstReference;
2806
2808 using QueueType = StaticQueue<T, TSize>;
2809
2811 using ConstLinearisedIterator = typename QueueType::ConstLinearisedIterator;
2812
2816 ConstIterator(const QueueType& queue, ConstLinearisedIterator iterator)
2817 : Base(queue, iterator)
2818 {
2819 }
2820
2822 ConstIterator(const ConstIterator&) = default;
2823
2827 ConstIterator& operator=(const ConstIterator& other)
2828 {
2829 return static_cast<ConstIterator&>(Base::operator=(other));
2830 }
2831
2833 ConstIterator& operator++()
2834 {
2835 return static_cast<ConstIterator&>(Base::operator++());
2836 }
2837
2839 ConstIterator operator++(int dummyParam)
2840 {
2841 auto tmp = Base::operator++(dummyParam);
2842 return *(static_cast<ConstIterator*>(&tmp));
2843 }
2844
2846 ConstIterator& operator--()
2847 {
2848 return static_cast<ConstIterator&>(Base::operator--());
2849 }
2850
2852 ConstIterator operator--(int dummyParam)
2853 {
2854 auto tmp = Base::operator--(dummyParam);
2855 return *(static_cast<ConstIterator*>(&tmp));
2856 }
2857
2860 ConstIterator& operator+=(DifferenceType value)
2861 {
2862 return static_cast<ConstIterator&>(Base::operator+=(value));
2863 }
2864
2867 ConstIterator& operator-=(DifferenceType value)
2868 {
2869 return static_cast<ConstIterator&>(Base::operator-=(value));
2870 }
2871
2876 ConstIterator operator+(DifferenceType value) const
2877 {
2878 auto tmp = Base::operator+(value);
2879 return *(static_cast<ConstIterator*>(&tmp));
2880 }
2881
2886 ConstIterator operator-(DifferenceType value) const
2887 {
2888 auto tmp = Base::operator-(value);
2889 return *(static_cast<ConstIterator*>(&tmp));
2890 }
2891
2895 DifferenceType 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
2937 bool operator>=(const ConstIterator& other) const
2938 {
2939 return Base::operator>=(other);
2940 }
2941
2943 Reference operator*()
2944 {
2945 return Base::operator*();
2946 }
2947
2949 ConstReference operator*() const
2950 {
2951 return Base::operator*();
2952 }
2953
2955 Pointer operator->()
2956 {
2957 return Base::operator->();
2958 }
2959
2961 ConstPointer operator->() const
2962 {
2963 return Base::operator->();
2964 }
2965};
2966
2970template <typename T, std::size_t TSize>
2971class StaticQueue<T, TSize>::Iterator : public StaticQueue<T, TSize>::Base::Iterator
2972{
2973 using Base = typename StaticQueue<T, TSize>::Base::Iterator;
2974public:
2975
2977 using IteratorCategory = typename Base::IteratorCategory;
2978
2980 using iterator_category = IteratorCategory;
2981
2983 using ValueType = typename Base::ValueType;
2984
2986 using value_type = ValueType;
2987
2989 using DifferenceType = typename Base::DifferenceType;
2990
2992 using difference_type = DifferenceType;
2993
2995 using Pointer = typename Base::Pointer;
2996
2998 using pointer = Pointer;
2999
3001 using ConstPointer = typename Base::ConstPointer;
3002
3004 using Reference = typename Base::Reference;
3005
3007 using reference = Reference;
3008
3010 using ConstReference = typename Base::ConstReference;
3011
3013 using QueueType = StaticQueue<T, TSize>;
3014
3016 using LinearisedIterator = typename QueueType::LinearisedIterator;
3017
3019 using ConstLinearisedIterator = typename QueueType::ConstLinearisedIterator;
3020
3024 Iterator(QueueType& queue, LinearisedIterator iterator)
3025 : Base(queue, iterator)
3026 {
3027 }
3028
3030 Iterator(const Iterator&) = default;
3031
3035 Iterator& operator=(const Iterator& other)
3036 {
3037 return static_cast<Iterator&>(Base::operator=(other));
3038 }
3039
3041 Iterator& operator++()
3042 {
3043 return static_cast<Iterator&>(Base::operator++());
3044 }
3045
3047 Iterator operator++(int dummyParam)
3048 {
3049 auto tmp = Base::operator++(dummyParam);
3050 return *(static_cast<Iterator*>(&tmp));
3051 }
3052
3054 Iterator& operator--()
3055 {
3056 return static_cast<Iterator&>(Base::operator--());
3057 }
3058
3060 Iterator operator--(int dummyParam)
3061 {
3062 auto tmp = Base::operator--(dummyParam);
3063 return *(static_cast<Iterator*>(&tmp));
3064 }
3065
3068 Iterator& operator+=(DifferenceType value)
3069 {
3070 return static_cast<Iterator&>(Base::operator+=(value));
3071 }
3072
3075 Iterator& operator-=(DifferenceType value)
3076 {
3077 return static_cast<Iterator&>(Base::operator-=(value));
3078 }
3079
3084 Iterator operator+(DifferenceType value) const
3085 {
3086 auto tmp = Base::operator+(value);
3087 return *(static_cast<Iterator*>(&tmp));
3088 }
3089
3094 Iterator operator-(DifferenceType value) const
3095 {
3096 auto tmp = Base::operator-(value);
3097 return *(static_cast<Iterator*>(&tmp));
3098 }
3099
3103 DifferenceType 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
3145 bool operator>=(const Iterator& other) const
3146 {
3147 return Base::operator>=(other);
3148 }
3149
3151 Reference operator*()
3152 {
3153 return Base::operator*();
3154 }
3155
3157 ConstReference operator*() const
3158 {
3159 return Base::operator*();
3160 }
3161
3163 Pointer operator->()
3164 {
3165 return Base::operator->();
3166 }
3167
3169 ConstPointer operator->() const
3170 {
3171 return Base::operator->();
3172 }
3173
3174 operator ConstIterator() const
3175 {
3176 auto iter = static_cast<ConstLinearisedIterator>(Base::getIterator());
3177 const auto& queue = static_cast<QueueType&>(Base::getQueue());
3178 return ConstIterator(queue, iter);
3179 }
3180};
3181
3183
3184} // namespace util
3185
3186} // namespace comms
3187
3188COMMS_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:29
Replacement to some types from standard type_traits.