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 - 2024 (C). Alex Robenko. All rights reserved.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
11
12#pragma once
13
14#include <cstdint>
15#include <cstddef>
16#include <array>
17#include <string>
18#include <stdexcept>
19#include <utility>
20#include <type_traits>
21#include <iterator>
22#include <algorithm>
23
25#include "comms/Assert.h"
26#include "comms/util/SizeToType.h"
29
30COMMS_MSVC_WARNING_PUSH
31COMMS_MSVC_WARNING_DISABLE(4324) // Disable warning about alignment padding
32
33
34namespace comms
35{
36
37namespace util
38{
39
40namespace details
41{
42
43template <typename T>
44class StaticQueueBase
45{
46public:
47 template <typename TDerived, typename TQueueType>
48 class IteratorBase;
49
50 class ConstIterator;
51 class Iterator;
52
53protected:
54 using ValueType = T;
55 using StorageType = comms::util::AlignedStorage<sizeof(ValueType), std::alignment_of<ValueType>::value>;
56 using StorageTypePtr = StorageType*;
57 using ConstStorageTypePtr = const StorageType*;
58 using SizeType = std::size_t;
59 using Reference = ValueType&;
60 using ConstReference = const ValueType&;
61 using Pointer = ValueType*;
62 using ConstPointer = const ValueType*;
63 using LinearisedIterator = Pointer;
64 using ConstLinearisedIterator = ConstPointer;
65 using ReverseLinearisedIterator = std::reverse_iterator<LinearisedIterator>;
66 using ConstReverseLinearisedIterator = std::reverse_iterator<ConstLinearisedIterator>;
67 using LinearisedIteratorRange = std::pair<LinearisedIterator, LinearisedIterator>;
68 using ConstLinearisedIteratorRange = std::pair<ConstLinearisedIterator, ConstLinearisedIterator>;
69
70 StaticQueueBase(StorageTypePtr data, std::size_t capacity)
71 : data_(data),
72 capacity_(capacity),
73 startIdx_(0),
74 count_(0)
75 {
76 }
77
78 StaticQueueBase(const StaticQueueBase&) = delete;
79 StaticQueueBase(StaticQueueBase&&) = delete;
80
81 ~StaticQueueBase() noexcept
82 {
83 clear();
84 }
85
86 StaticQueueBase& operator=(const StaticQueueBase& other)
87 {
88 if (this == &other) {
89 return *this;
90 }
91
92 clear();
93 assignElements(other);
94 return *this;
95 }
96
97 StaticQueueBase& operator=(StaticQueueBase&& other)
98 {
99 if (this == &other) {
100 return *this;
101 }
102
103 clear();
104 assignElements(std::move(other));
105 return *this;
106 }
107
108 constexpr std::size_t capacity() const
109 {
110 return capacity_;
111 }
112
113 std::size_t size() const
114 {
115 return count_;
116 }
117
118 void clear()
119 {
120 while (!empty()) {
121 popFront();
122 }
123 }
124
125 bool empty() const
126 {
127 return (size() == 0);
128 }
129
130 bool full() const
131 {
132 return (size() == capacity());
133 }
134
135 Reference front()
136 {
137 COMMS_ASSERT(!empty());
138 return (*this)[0];
139 }
140
141 ConstReference front() const
142 {
143 COMMS_ASSERT(!empty());
144 return (*this)[0];
145 }
146
147 Reference back()
148 {
149 auto constThis = static_cast<const StaticQueueBase*>(this);
150 return const_cast<Reference>(constThis->back());
151 }
152
153 ConstReference back() const
154 {
155 COMMS_ASSERT(!empty());
156 if (empty()) {
157 return (*this)[0]; // Back() on empty queue
158 }
159
160 return (*this)[count_ - 1];
161 }
162
163
164 void popFront()
165 {
166 COMMS_ASSERT(!empty()); // Queue musn't be empty
167 if (empty())
168 {
169 // Do nothing
170 return;
171 }
172
173 Reference element = front();
174 element.~T();
175
176 --count_;
177 ++startIdx_;
178 if ((capacity() <= startIdx_) ||
179 (empty())) {
180 startIdx_ = 0;
181 }
182 }
183
184 void popFront(std::size_t count)
185 {
186 COMMS_ASSERT(count <= size());
187 while ((!empty()) && (count > 0)) {
188 popFront();
189 --count;
190 }
191 }
192
193 void popBack()
194 {
195 COMMS_ASSERT(!empty());
196 if (empty())
197 {
198 // Do nothing
199 return;
200 }
201
202 Reference element = back();
203 element.~T();
204
205 --count_;
206 }
207
208 void popBack(std::size_t count)
209 {
210 COMMS_ASSERT(count <= size());
211 while ((!empty()) && (count > 0)) {
212 popBack();
213 --count;
214 }
215 }
216
217 Reference operator[](std::size_t index)
218 {
219 auto constThis = static_cast<const StaticQueueBase*>(this);
220 return const_cast<Reference>((*constThis)[index]);
221 }
222
223 ConstReference operator[](std::size_t index) const
224 {
225 COMMS_ASSERT(index < size());
226 return elementAtIndex(index);
227 }
228
229 Reference at(std::size_t index)
230 {
231 auto constThis = static_cast<const StaticQueueBase*>(this);
232 return const_cast<Reference>(constThis->at(index));
233 }
234
235 ConstReference at(std::size_t index) const
236 {
237 if (index >= size()) {
238 throw std::out_of_range(std::string("Index is out of range"));
239 }
240 return (*this)[index];
241 }
242
243 int indexOf(ConstReference element) const
244 {
245 ConstPointer elementPtr = &element;
246 auto cellPtr = reinterpret_cast<ConstStorageTypePtr>(elementPtr);
247 if ((cellPtr < &data_[0]) ||
248 (&data_[capacity()] <= cellPtr)) {
249 // invalid, element is not within array boundaries
250 return -1;
251 }
252
253 auto rawIdx = cellPtr - &data_[0];
254 std::size_t actualIdx = capacity(); // invalid value
255 if (rawIdx < startIdx_) {
256 actualIdx = (capacity() - startIdx_) + rawIdx;
257 }
258 else {
259 actualIdx = rawIdx - startIdx_;
260 }
261
262 if (size() <= actualIdx)
263 {
264 // Element is out of range
265 return -1;
266 }
267
268 return actualIdx;
269 }
270
271 LinearisedIterator invalidIter()
272 {
273 return reinterpret_cast<LinearisedIterator>(&data_[capacity()]);
274 }
275
276 ConstLinearisedIterator invalidIter() const
277 {
278 return reinterpret_cast<LinearisedIterator>(&data_[capacity()]);
279 }
280
281 ReverseLinearisedIterator invalidReverseIter()
282 {
283 return ReverseLinearisedIterator(
284 reinterpret_cast<LinearisedIterator>(&data_[0]));
285 }
286
287 ConstReverseLinearisedIterator invalidReverseIter() const
288 {
289 return ReverseLinearisedIterator(
290 reinterpret_cast<LinearisedIterator>(&data_[0]));
291 }
292
293 LinearisedIterator lbegin()
294 {
295 if (!linearised()) {
296 return invalidIter();
297 }
298
299 return reinterpret_cast<LinearisedIterator>(&data_[0] + startIdx_);
300 }
301
302 ConstLinearisedIterator lbegin() const
303 {
304 return clbegin();
305 }
306
307 ConstLinearisedIterator clbegin() const
308 {
309 if (!linearised()) {
310 return invalidIter();
311 }
312
313 return reinterpret_cast<LinearisedIterator>(&data_[0] + startIdx_);
314 }
315
316 ReverseLinearisedIterator rlbegin()
317 {
318 if (!linearised()) {
319 return invalidReverseIter();
320 }
321
322 return ReverseLinearisedIterator(lend());
323 }
324
325 ConstReverseLinearisedIterator rlbegin() const
326 {
327 return crlbegin();
328 }
329
330 ConstReverseLinearisedIterator crlbegin() const
331 {
332 if (!linearised()) {
333 return invalidReverseIter();
334 }
335 return ConstReverseLinearisedIterator(lend());
336 }
337
338 LinearisedIterator lend()
339 {
340 if (!linearised()) {
341 return invalidIter();
342 }
343
344 return lbegin() + size();
345 }
346
347 ConstLinearisedIterator lend() const
348 {
349 return clend();
350 }
351
352 ConstLinearisedIterator clend() const
353 {
354 if (!linearised()) {
355 return invalidIter();
356 }
357
358 return clbegin() + size();
359 }
360
361 ReverseLinearisedIterator rlend()
362 {
363 if (!linearised()) {
364 return invalidReverseIter();
365 }
366
367 return rlbegin() + size();
368 }
369
370 ConstReverseLinearisedIterator rlend() const
371 {
372 return crlend();
373 }
374
375 ConstReverseLinearisedIterator crlend() const
376 {
377 if (!linearised()) {
378 return invalidReverseIter();
379 }
380
381 return rlbegin() + size();
382 }
383
384 void linearise()
385 {
386 if (linearised()) {
387 // Nothing to do
388 return;
389 }
390
391 auto rangeOne = arrayOne();
392 auto rangeOneSize = std::distance(rangeOne.first, rangeOne.second);
393 COMMS_ASSERT(0 < rangeOneSize);
394 auto rangeTwo = arrayTwo();
395 auto rangeTwoSize = std::distance(rangeTwo.first, rangeTwo.second);
396 COMMS_ASSERT(0 < rangeTwoSize);
397 COMMS_ASSERT((rangeOneSize + rangeTwoSize) == size());
398 auto remSpaceSize = capacity() - size();
399
400 if (rangeTwoSize <= remSpaceSize) {
401 lineariseByMoveOneTwo(rangeOne, rangeTwo);
402 return;
403 }
404
405 if (rangeOneSize <= remSpaceSize) {
406 lineariseByMoveTwoOne(rangeOne, rangeTwo);
407 return;
408 }
409
410 if (rangeOneSize < rangeTwoSize) {
411 lineariseByPopOne();
412 }
413
414 lineariseByPopTwo();
415 }
416
417 bool linearised() const
418 {
419 return (empty() || ((startIdx_ + size()) <= capacity()));
420 }
421
422 LinearisedIteratorRange arrayOne()
423 {
424 auto constThis = static_cast<const StaticQueueBase*>(this);
425 auto constRange = constThis->arrayOne();
426 return
427 LinearisedIteratorRange(
428 const_cast<LinearisedIterator>(constRange.first),
429 const_cast<LinearisedIterator>(constRange.second));
430 }
431
432 ConstLinearisedIteratorRange arrayOne() const
433 {
434 auto begCell = &data_[startIdx_];
435 auto endCell = std::min(&data_[startIdx_ + size()], &data_[capacity()]);
436 return
437 ConstLinearisedIteratorRange(
438 reinterpret_cast<ConstLinearisedIterator>(begCell),
439 reinterpret_cast<ConstLinearisedIterator>(endCell));
440 }
441
442 LinearisedIteratorRange arrayTwo()
443 {
444 auto constThis = static_cast<const StaticQueueBase*>(this);
445 auto constRange = constThis->arrayTwo();
446 return
447 LinearisedIteratorRange(
448 const_cast<LinearisedIterator>(constRange.first),
449 const_cast<LinearisedIterator>(constRange.second));
450 }
451
452 ConstLinearisedIteratorRange arrayTwo() const
453 {
454 if (linearised()) {
455 auto iter = arrayOne().second;
456 return ConstLinearisedIteratorRange(iter, iter);
457 }
458
459 auto begCell = &data_[0];
460 auto endCell = &data_[(startIdx_ + size()) - capacity()];
461
462 return
463 ConstLinearisedIteratorRange(
464 reinterpret_cast<ConstLinearisedIterator>(begCell),
465 reinterpret_cast<ConstLinearisedIterator>(endCell));
466 }
467
468 void resize(std::size_t newSize)
469 {
470 COMMS_ASSERT(newSize <= capacity());
471 if (capacity() < newSize) {
472 return;
473 }
474
475 if (size() <= newSize) {
476 while (size() < newSize) {
477 pushBackNotFull(ValueType());
478 }
479
480 return;
481 }
482
483 // New requested size is less than existing now
484 popBack(size() - newSize);
485 }
486
487 LinearisedIterator erase(LinearisedIterator pos)
488 {
489 COMMS_ASSERT(pos != invalidIter());
490 COMMS_ASSERT(!empty());
491 auto rangeOne = arrayOne();
492 auto rangeTwo = arrayTwo();
493
494 auto isInRangeFunc =
495 [](LinearisedIterator pos, const LinearisedIteratorRange range) -> bool
496 {
497 return ((range.first <= pos) && (pos < range.second));
498 };
499
500 COMMS_ASSERT(isInRangeFunc(pos, rangeOne) ||
501 isInRangeFunc(pos, rangeTwo));
502
503 if (isInRangeFunc(pos, rangeOne)) {
504 std::move_backward(rangeOne.first, pos, pos + 1);
505
506 popFront();
507 rangeOne = arrayOne();
508 if (isInRangeFunc(pos, rangeOne)) {
509 return pos + 1;
510 }
511
512 return rangeOne.first;
513 }
514
515 if (isInRangeFunc(pos, rangeTwo)) {
516 std::move(pos + 1, rangeTwo.second, pos);
517 popBack();
518 if (!linearised()) {
519 return pos;
520 }
521 return arrayOne().second;
522 }
523
524 static constexpr bool Invalid_iterator_is_used = false;
525 static_cast<void>(Invalid_iterator_is_used);
526 COMMS_ASSERT(Invalid_iterator_is_used);
527 return invalidIter();
528 }
529
530 Iterator erase(Iterator pos)
531 {
532 COMMS_ASSERT(pos != end());
533 COMMS_ASSERT(!empty());
534 Pointer elem = &(*pos);
535 auto rangeOne = arrayOne();
536 auto rangeTwo = arrayTwo();
537
538 auto isInRangeFunc =
539 [](Pointer elemPtr, const LinearisedIteratorRange range) -> bool
540 {
541 return ((&(*range.first) <= elemPtr) && (elemPtr < &(*range.second)));
542 };
543
544 COMMS_ASSERT(isInRangeFunc(elem, rangeOne) ||
545 isInRangeFunc(elem, rangeTwo));
546
547 if (isInRangeFunc(elem, rangeOne)) {
548 std::move_backward(rangeOne.first, elem, elem + 1);
549
550 popFront();
551 rangeOne = arrayOne();
552 if (isInRangeFunc(elem, rangeOne)) {
553 return pos + 1;
554 }
555
556 return begin();
557 }
558
559 if (isInRangeFunc(elem, rangeTwo)) {
560 std::move(elem + 1, rangeTwo.second, elem);
561 popBack();
562 if (!linearised()) {
563 return pos;
564 }
565 return end();
566 }
567
568 static constexpr bool Invalid_iterator_is_used = false;
569 static_cast<void>(Invalid_iterator_is_used);
570 COMMS_ASSERT(Invalid_iterator_is_used);
571 return end();
572 }
573
574 Iterator begin()
575 {
576 return Iterator(*this, reinterpret_cast<LinearisedIterator>(&data_[0]));
577 }
578
579 ConstIterator begin() const
580 {
581 return cbegin();
582 }
583
584 ConstIterator cbegin() const
585 {
586 return ConstIterator(*this, reinterpret_cast<ConstLinearisedIterator>(&data_[0]));
587 }
588
589 Iterator end()
590 {
591 return Iterator(*this, reinterpret_cast<LinearisedIterator>(&data_[size()]));
592 }
593
594 ConstIterator end() const
595 {
596 return cend();
597 }
598
599 ConstIterator cend() const
600 {
601 return ConstIterator(*this, reinterpret_cast<ConstLinearisedIterator>(&data_[size()]));
602 }
603
604 template <typename TOther>
605 void assignElements(TOther&& other)
606 {
607 static_assert(std::is_base_of<StaticQueueBase, typename std::decay<TOther>::type>::value,
608 "Assignment works only on the same types");
609
610
611 using DecayedQueueType = typename std::decay<decltype(other)>::type;
612 using NonRefQueueType = typename std::remove_reference<decltype(other)>::type;
613
614 using QueueValueType =
616 std::is_const<NonRefQueueType>::value
617 >::template Type<
618 const typename DecayedQueueType::ValueType,
619 typename DecayedQueueType::ValueType
620 >;
621
622 using ElemRefType =
624 std::is_rvalue_reference<decltype(other)>::value
625 >::template Type<
626 typename std::add_rvalue_reference<QueueValueType>::type,
627 typename std::add_lvalue_reference<QueueValueType>::type
628 >;
629
630 COMMS_ASSERT(other.size() <= capacity());
631 COMMS_ASSERT(empty());
632
633 auto rangeOne = other.arrayOne();
634 for (auto iter = rangeOne.first; iter != rangeOne.second; ++iter) {
635 pushBackNotFull(std::forward<ElemRefType>(*iter));
636 }
637
638 auto rangeTwo = other.arrayTwo();
639 for (auto iter = rangeTwo.first; iter != rangeTwo.second; ++iter) {
640 pushBackNotFull(std::forward<ElemRefType>(*iter));
641 }
642 }
643
644 template <typename U>
645 void pushBack(U&& value)
646 {
647 COMMS_ASSERT(!full());
648 if (full()) {
649 return;
650 }
651 pushBackNotFull(std::forward<U>(value));
652 }
653
654 template <typename... TArgs>
655 void emplaceBack(TArgs&&... args)
656 {
657 COMMS_ASSERT(!full());
658 if (full()) {
659 return;
660 }
661 emplaceBackNotFull(std::forward<TArgs>(args)...);
662 }
663
664 template <typename U>
665 void pushFront(U&& value)
666 {
667 COMMS_ASSERT(!full());
668 if (full()) {
669 return;
670 }
671
672 pushFrontNotFull(std::forward<U>(value));
673 }
674
675 template <typename U>
676 LinearisedIterator insert(LinearisedIterator pos, U&& value)
677 {
678 COMMS_ASSERT(!full());
679 if (full()) {
680 return invalidIter();
681 }
682
683 return insertNotFull(pos, std::forward<U>(value));
684 }
685
686 bool operator==(const StaticQueueBase& other) const
687 {
688 if (size() != other.size()) {
689 return false;
690 }
691
692 auto rangeOne = arrayOne();
693 auto rangeOneSize = std::distance(rangeOne.first, rangeOne.second);
694 auto rangeTwo = arrayTwo();
695 auto otherRangeOne = other.arrayOne();
696 auto otherRangeOneSize = std::distance(otherRangeOne.first, otherRangeOne.second);
697 auto otherRangeTwo = other.arrayTwo();
698
699 auto firstCompSize = std::min(rangeOneSize, otherRangeOneSize);
700 auto firstCompEnd = rangeOne.first + firstCompSize;
701
702 auto currIter = rangeOne.first;
703 auto otherCurrIter = otherRangeOne.first;
704 if (!std::equal(currIter, firstCompEnd, otherCurrIter)) {
705 return false;
706 }
707
708 currIter = firstCompEnd;
709 otherCurrIter += firstCompSize;
710
711 if (currIter != rangeOne.first) {
712 otherCurrIter = otherRangeTwo.first;
713 if (!std::equal(currIter, rangeOne.second, otherCurrIter)) {
714 return false;
715 }
716 otherCurrIter += rangeOne.second - currIter;
717 currIter = rangeTwo.first;
718 }
719 else {
720 currIter = rangeTwo.first;
721 if (!std::equal(otherCurrIter, otherRangeOne.second, currIter)) {
722 return false;
723 }
724
725 currIter += otherRangeOne.second - otherCurrIter;
726 otherCurrIter = otherRangeOne.first;
727 }
728
729 COMMS_ASSERT(std::distance(currIter, rangeTwo.second) == std::distance(otherCurrIter, otherRangeTwo.second));
730 return std::equal(currIter, rangeTwo.second, otherCurrIter);
731 }
732
733 bool operator!=(const StaticQueueBase& other) const
734 {
735 return !(*this == other);
736 }
737
738private:
739
740 template <typename U>
741 void createValueAtIndex(U&& value, std::size_t index)
742 {
743 COMMS_ASSERT(index < capacity());
744 Reference elementRef = elementAtIndex(index);
745 auto elementPtr = new(&elementRef) ValueType(std::forward<U>(value));
746 static_cast<void>(elementPtr);
747 }
748
749 template <typename U>
750 void pushBackNotFull(U&& value)
751 {
752 COMMS_ASSERT(!full());
753 createValueAtIndex(std::forward<U>(value), size());
754 ++count_;
755 }
756
757 template <typename... TArgs>
758 void emplaceBackNotFull(TArgs&&... args)
759 {
760 COMMS_ASSERT(!full());
761 Reference elementRef = elementAtIndex(size());
762 auto elementPtr = new(&elementRef) ValueType(std::forward<TArgs>(args)...);
763 static_cast<void>(elementPtr);
764 ++count_;
765 }
766
767 template <typename U>
768 void pushFrontNotFull(U&& value)
769 {
770 COMMS_ASSERT(!full());
771 createValueAtIndex(std::forward<U>(value), capacity() - 1);
772 if (startIdx_ == 0) {
773 startIdx_ = capacity() - 1;
774 }
775 else {
776 --startIdx_;
777 }
778
779 ++count_;
780 }
781
782 template <typename U>
783 LinearisedIterator insertNotFull(LinearisedIterator pos, U&& value)
784 {
785 COMMS_ASSERT(!full());
786 COMMS_ASSERT(pos != invalidIter());
787 auto rangeOne = arrayOne();
788 auto rangeTwo = arrayTwo();
789
790 if (pos == rangeOne.first) {
791 pushFrontNotFull(std::forward<U>(value));
792 return arrayOne().first;
793 }
794
795 if (pos == rangeTwo.second) {
796 pushBackNotFull(std::forward<U>(value));
797 return arrayTwo().second - 1;
798 }
799
800 auto isInRangeFunc = [](LinearisedIterator pos, const LinearisedIteratorRange range) -> bool
801 {
802 return ((range.first <= pos) && (pos < range.second));
803 };
804
805 COMMS_ASSERT(isInRangeFunc(pos, rangeOne) ||
806 isInRangeFunc(pos, rangeTwo));
807
808 if (isInRangeFunc(pos, rangeOne)) {
809 pushFrontNotFull(std::move(front())); // move first element
810
811 std::move(rangeOne.first + 1, pos, rangeOne.first);
812 *pos = std::forward<U>(value);
813 return pos;
814 }
815
816 if (isInRangeFunc(pos, rangeTwo)) {
817 pushBackNotFull(std::move(back())); // move last element
818 std::move_backward(pos, rangeTwo.second - 1, rangeTwo.second);
819 *pos = std::forward<U>(value);
820 return pos;
821 }
822
823 return invalidIter();
824 }
825
826 Reference elementAtIndex(std::size_t index) {
827 auto constThis = static_cast<const StaticQueueBase*>(this);
828 return const_cast<Reference>(constThis->elementAtIndex(index));
829 }
830
831 ConstReference elementAtIndex(std::size_t index) const
832 {
833 std::size_t rawIdx = startIdx_ + index;
834 while (capacity() <= rawIdx) {
835 rawIdx = rawIdx - capacity();
836 }
837
838 auto cellAddr = &data_[rawIdx];
839 return *(reinterpret_cast<ConstPointer>(cellAddr));
840 }
841
842 template <typename TIter>
843 void lineariseByMove(
844 const std::pair<TIter, TIter> firstRange,
845 const std::pair<TIter, TIter> secondRange)
846 {
847 auto movConstructFirstSize =
848 std::min(
849 std::size_t(std::distance(firstRange.first, firstRange.second)),
850 capacity() - size());
851 auto movConstructFirstEnd = firstRange.first + movConstructFirstSize;
852 COMMS_ASSERT(movConstructFirstEnd <= firstRange.second);
853 COMMS_ASSERT(movConstructFirstSize <= (firstRange.second - firstRange.first));
854
855 auto newPlacePtr = secondRange.second;
856 for (auto iter = firstRange.first; iter != movConstructFirstEnd; ++iter) {
857 auto ptr = new (&(*newPlacePtr)) ValueType(std::move(*iter));
858 static_cast<void>(ptr);
859 ++newPlacePtr;
860 }
861
862 std::move(movConstructFirstEnd, firstRange.second, newPlacePtr);
863 newPlacePtr += (firstRange.second - movConstructFirstEnd);
864
865 auto movConstructTwoSize = 0;
866 if (newPlacePtr < firstRange.first) {
867 movConstructTwoSize =
868 std::min(std::distance(newPlacePtr, firstRange.first),
869 std::distance(secondRange.first, secondRange.second));
870 }
871
872 auto movConstructTwoEnd = secondRange.first + movConstructTwoSize;
873 for (auto iter = secondRange.first; iter != movConstructTwoEnd; ++iter) {
874 auto ptr = new (&(*newPlacePtr)) ValueType(std::move(*iter));
875 static_cast<void>(ptr);
876 ++newPlacePtr;
877 }
878
879 std::move(movConstructTwoEnd, secondRange.second, newPlacePtr);
880 newPlacePtr += (secondRange.second - movConstructTwoEnd);
881
882 for (auto iter = std::max(newPlacePtr, firstRange.first); iter != firstRange.second; ++iter) {
883 iter->~T();
884 }
885
886 for (auto iter = secondRange.first; iter != secondRange.second; ++iter) {
887 iter->~T();
888 }
889 }
890
891 void lineariseByMoveOneTwo(
892 const LinearisedIteratorRange& rangeOne,
893 const LinearisedIteratorRange& rangeTwo)
894 {
895 lineariseByMove(rangeOne, rangeTwo);
896 startIdx_ = std::distance(rangeTwo.first, rangeTwo.second);
897 }
898
899 void lineariseByMoveTwoOne(
900 const LinearisedIteratorRange& rangeOne,
901 const LinearisedIteratorRange& rangeTwo)
902 {
903 using RevIter = std::reverse_iterator<Pointer>;
904 lineariseByMove(
905 std::make_pair(RevIter(rangeTwo.second), RevIter(rangeTwo.first)),
906 std::make_pair(RevIter(rangeOne.second), RevIter(rangeOne.first)));
907
908 startIdx_ = (capacity() - std::distance(rangeOne.first, rangeOne.second)) - size();
909 }
910
911 void lineariseByPopOne()
912 {
913 if (linearised()) {
914 return;
915 }
916
917 ValueType tmp(std::move(front()));
918 popFront();
919 lineariseByPopOne();
920 if (startIdx_ == 0) {
921 using RevIter = std::reverse_iterator<LinearisedIterator>;
922 auto target =
923 RevIter(reinterpret_cast<LinearisedIterator>(&data_[capacity()]));
924 moveRange(rlbegin(), rlend(), target);
925 startIdx_ = capacity() - size();
926 }
927 pushFront(std::move(tmp));
928 COMMS_ASSERT(linearised());
929 }
930
931 void lineariseByPopTwo()
932 {
933 if (linearised()) {
934 return;
935 }
936
937 ValueType tmp(std::move(back()));
938 popBack();
939 lineariseByPopTwo();
940 if (startIdx_ != 0) {
941 auto target = reinterpret_cast<LinearisedIterator>(&data_[0]);
942 moveRange(lbegin(), lend(), target);
943 startIdx_ = 0;
944 }
945 pushBack(std::move(tmp));
946 COMMS_ASSERT(linearised());
947 }
948
949 template <typename TIter>
950 void moveRange(TIter rangeBeg, TIter rangeEnd, TIter target)
951 {
952 COMMS_ASSERT(target < rangeBeg);
953 auto moveConstructSize =
954 std::min(
955 std::distance(rangeBeg, rangeEnd),
956 std::distance(target, rangeBeg));
957
958 TIter moveConstructEnd = rangeBeg + moveConstructSize;
959 for (auto iter = rangeBeg; iter != moveConstructEnd; ++iter) {
960 auto ptr = new (&(*target)) ValueType(std::move(*iter));
961 static_cast<void>(ptr);
962 ++target;
963 }
964
965 COMMS_ASSERT(target < moveConstructEnd);
966 std::move(moveConstructEnd, rangeEnd, target);
967 target += std::distance(moveConstructEnd, rangeEnd);
968
969 for (auto iter = std::max(target, rangeBeg); iter != rangeEnd; ++iter) {
970 iter->~T();
971 }
972 }
973
974 StorageTypePtr const data_;
975 const std::size_t capacity_;
976 std::size_t startIdx_;
977 std::size_t count_;
978};
979
980template <typename T>
981template <typename TDerived, typename TQueueType>
982class StaticQueueBase<T>::IteratorBase
983{
984 friend class StaticQueueBase<T>;
985public:
986
987 IteratorBase(const IteratorBase&) = default;
988
989 ~IteratorBase() noexcept = default;
990
991protected:
992 using Derived = TDerived;
993 using QueueType = TQueueType;
994 using ArrayIterator = decltype(std::declval<QueueType>().lbegin());
995 using IteratorCategory = typename std::iterator_traits<ArrayIterator>::iterator_category;
996 using iterator_category = IteratorCategory;
997 using ValueType = typename std::iterator_traits<ArrayIterator>::value_type;
998 using value_type = ValueType;
999 using DifferenceType = typename std::iterator_traits<ArrayIterator>::difference_type;
1000 using difference_type = DifferenceType;
1001 using Pointer = typename std::iterator_traits<ArrayIterator>::pointer;
1002 using pointer = Pointer;
1003 using ConstPointer =
1004 typename std::add_pointer<
1005 typename std::add_const<
1006 typename std::remove_pointer<Pointer>::type
1007 >::type
1008 >::type;
1009 using Reference = typename std::iterator_traits<ArrayIterator>::reference;
1010 using reference = Reference;
1011 using ConstReference = typename std::add_const<Reference>::type;
1012
1013 IteratorBase(QueueType& queue, ArrayIterator iterator)
1014 : queue_(queue),
1015 iterator_(iterator)
1016 {
1017 }
1018
1019 Derived& operator=(const IteratorBase& other)
1020 {
1021 COMMS_ASSERT(&queue_ == &other.queue_);
1022 iterator_ = other.iterator_; // No need to check for self assignment
1023 return static_cast<Derived&>(*this);
1024 }
1025
1026 Derived& operator++()
1027 {
1028 ++iterator_;
1029 return static_cast<Derived&>(*this);
1030 }
1031
1032 Derived operator++(int)
1033 {
1034 IteratorBase copy(*this);
1035 ++iterator_;
1036 return std::move(*(static_cast<Derived*>(&copy)));
1037 }
1038
1039 Derived& operator--()
1040 {
1041 --iterator_;
1042 return static_cast<Derived&>(*this);
1043 }
1044
1045 Derived operator--(int)
1046 {
1047 IteratorBase copy(*this);
1048 --iterator_;
1049 return std::move(*(static_cast<Derived*>(&copy)));
1050 }
1051
1052 Derived& operator+=(DifferenceType value)
1053 {
1054 iterator_ += value;
1055 return static_cast<Derived&>(*this);
1056 }
1057
1058 Derived& operator-=(DifferenceType value)
1059 {
1060 iterator_ -= value;
1061 return static_cast<Derived&>(*this);
1062 }
1063
1064 Derived operator+(DifferenceType value) const
1065 {
1066 IteratorBase copy(*this);
1067 copy += value;
1068 return std::move(*(static_cast<Derived*>(&copy)));
1069 }
1070
1071 Derived operator-(DifferenceType value) const
1072 {
1073 IteratorBase copy(*this);
1074 copy -= value;
1075 return std::move(*(static_cast<Derived*>(&copy)));
1076 }
1077
1078 DifferenceType operator-(const IteratorBase& other) const
1079 {
1080 return iterator_ - other.iterator_;
1081 }
1082
1083 bool operator==(const IteratorBase& other) const
1084 {
1085 return (iterator_ == other.iterator_);
1086 }
1087
1088 bool operator!=(const IteratorBase& other) const
1089 {
1090 return (iterator_ != other.iterator_);
1091 }
1092
1093 bool operator<(const IteratorBase& other) const
1094 {
1095 return iterator_ < other.iterator_;
1096 }
1097
1098 bool operator<=(const IteratorBase& other) const
1099 {
1100 return iterator_ <= other.iterator_;
1101 }
1102
1103 bool operator>(const IteratorBase& other) const
1104 {
1105 return iterator_ > other.iterator_;
1106 }
1107
1108 bool operator>=(const IteratorBase& other) const
1109 {
1110 return iterator_ >= other.iterator_;
1111 }
1112
1113 Reference operator*()
1114 {
1115 auto& constThisRef = static_cast<const IteratorBase&>(*this);
1116 auto& constRef = *constThisRef;
1117 return const_cast<Reference>(constRef);
1118 }
1119
1120 ConstReference operator*() const
1121 {
1122 auto begCell = reinterpret_cast<ArrayIterator>(&queue_.data_[0]);
1123 auto idx = iterator_ - begCell;
1124 COMMS_ASSERT(0 <= idx);
1125 return queue_[static_cast<std::size_t>(idx)];
1126 }
1127
1128 Pointer operator->()
1129 {
1130 return &(*(*this));
1131 }
1132
1133 ConstPointer operator->() const
1134 {
1135 return &(*(*this));
1136 }
1137
1138 QueueType& getQueue() {
1139 return queue_;
1140 }
1141
1142 typename std::add_const<QueueType&>::type getQueue() const
1143 {
1144 return queue_;
1145 }
1146
1147 ArrayIterator& getIterator() {
1148 return iterator_;
1149 }
1150
1151 typename std::add_const<ArrayIterator>::type& getIterator() const
1152 {
1153 return iterator_;
1154 }
1155
1156private:
1157
1158 QueueType& queue_;
1159 ArrayIterator iterator_;
1160};
1161
1162template <typename T>
1163class StaticQueueBase<T>::ConstIterator :
1164 public StaticQueueBase<T>::template
1165 IteratorBase<typename StaticQueueBase<T>::ConstIterator, const StaticQueueBase<T> >
1166{
1167 using Base = typename StaticQueueBase<T>::template
1168 IteratorBase<typename StaticQueueBase<T>::ConstIterator, const StaticQueueBase<T> >;
1169
1170public:
1171 using QueueType = typename Base::QueueType;
1172 using ArrayIterator = typename Base::ArrayIterator;
1173
1174 ConstIterator(const ConstIterator&) = default;
1175 ~ConstIterator() noexcept = default;
1176
1177 ConstIterator(QueueType& queue, ArrayIterator iterator)
1178 : Base(queue, iterator)
1179 {
1180 }
1181
1182};
1183
1184template <typename T>
1185class StaticQueueBase<T>::Iterator :
1186 public StaticQueueBase<T>::template
1187 IteratorBase<typename StaticQueueBase<T>::Iterator, StaticQueueBase<T> >
1188{
1189 using Base = typename StaticQueueBase<T>::template
1190 IteratorBase<typename StaticQueueBase<T>::Iterator, StaticQueueBase<T> >;
1191
1192public:
1193 using QueueType = typename Base::QueueType;
1194 using ArrayIterator = typename Base::ArrayIterator;
1195
1196 Iterator(const Iterator&) = default;
1197 ~Iterator() noexcept = default;
1198
1199 Iterator(QueueType& queue, ArrayIterator iterator)
1200 : Base(queue, iterator)
1201 {
1202 }
1203
1204 operator ConstIterator() const
1205 {
1206 return ConstIterator(Base::getQueue(), Base::getIterator());
1207 }
1208};
1209
1210
1211template <typename TWrapperElemType, typename TQueueElemType>
1212class CastWrapperQueueBase : public StaticQueueBase<TQueueElemType>
1213{
1214 using Base = StaticQueueBase<TQueueElemType>;
1215 using WrapperElemType = TWrapperElemType;
1216
1217 using BaseValueType = typename Base::ValueType;
1218 using BaseStorageTypePtr = typename Base::StorageTypePtr;
1219 using BaseReference = typename Base::Reference;
1220 using BaseConstReference = typename Base::ConstReference;
1221 using BasePointer = typename Base::Pointer;
1222 using BaseConstPointer = typename Base::ConstPointer;
1223 using BaseLinearisedIterator = typename Base::LinearisedIterator;
1224 using BaseConstLinearisedIterator = typename Base::ConstLinearisedIterator;
1225 using BaseReverseLinearisedIterator = typename Base::ReverseLinearisedIterator;
1226 using BaseConstReverseLinearisedIterator = typename Base::ConstReverseLinearisedIterator;
1227 using BaseLinearisedIteratorRange = typename Base::LinearisedIteratorRange;
1228 using BaseConstLinearisedIteratorRange = typename Base::ConstLinearisedIteratorRange;
1229
1230public:
1231
1232 class ConstIterator;
1233 class Iterator;
1234
1235protected:
1236 using ValueType = WrapperElemType;
1237 using StorageType = comms::util::AlignedStorage<sizeof(ValueType), std::alignment_of<ValueType>::value>;
1238 using StorageTypePtr = StorageType*;
1239 using Reference = ValueType&;
1240 using ConstReference = const ValueType&;
1241 using Pointer = ValueType*;
1242 using ConstPointer = const ValueType*;
1243 using LinearisedIterator = Pointer;
1244 using ConstLinearisedIterator = ConstPointer;
1245 using ReverseLinearisedIterator = std::reverse_iterator<LinearisedIterator>;
1246 using ConstReverseLinearisedIterator = std::reverse_iterator<ConstLinearisedIterator>;
1247 using LinearisedIteratorRange = std::pair<LinearisedIterator, LinearisedIterator>;
1248 using ConstLinearisedIteratorRange = std::pair<ConstLinearisedIterator, ConstLinearisedIterator>;
1249
1250 CastWrapperQueueBase(StorageTypePtr data, std::size_t capacity)
1251 : Base(reinterpret_cast<BaseStorageTypePtr>(data), capacity)
1252 {
1253 static_assert(sizeof(ValueType) == sizeof(BaseValueType),
1254 "The times must have identical size.");
1255 }
1256
1257 ~CastWrapperQueueBase() noexcept = default;
1258
1259 CastWrapperQueueBase& operator=(const CastWrapperQueueBase& other) = default;
1260 CastWrapperQueueBase& operator=(CastWrapperQueueBase&& other) = default;
1261
1262 Reference front()
1263 {
1264 return reinterpret_cast<Reference>(Base::front());
1265 }
1266
1267 ConstReference front() const
1268 {
1269 return reinterpret_cast<ConstReference>(Base::front());
1270 }
1271
1272 Reference back()
1273 {
1274 return reinterpret_cast<Reference>(Base::back());
1275 }
1276
1277 ConstReference back() const
1278 {
1279 return reinterpret_cast<Reference>(Base::back());
1280 }
1281
1282 Reference operator[](std::size_t index)
1283 {
1284 return reinterpret_cast<Reference>(Base::operator[](index));
1285 }
1286
1287 ConstReference operator[](std::size_t index) const
1288 {
1289 return reinterpret_cast<ConstReference>(Base::operator[](index));
1290 }
1291
1292 Reference at(std::size_t index)
1293 {
1294 return reinterpret_cast<Reference>(Base::at(index));
1295 }
1296
1297 ConstReference at(std::size_t index) const
1298 {
1299 return reinterpret_cast<ConstReference>(Base::at(index));
1300 }
1301
1302 int indexOf(ConstReference element) const
1303 {
1304 return Base::indexOf(reinterpret_cast<BaseConstReference>(element));
1305 }
1306
1307 LinearisedIterator invalidIter()
1308 {
1309 return reinterpret_cast<LinearisedIterator>(Base::invalidIter());
1310 }
1311
1312 ConstLinearisedIterator invalidIter() const
1313 {
1314 return reinterpret_cast<ConstLinearisedIterator>(Base::invalidIter());
1315 }
1316
1317 ReverseLinearisedIterator invalidReverseIter()
1318 {
1319 return ReverseLinearisedIterator(
1320 reinterpret_cast<LinearisedIterator>(
1321 Base::invalidReverseIter().base()));
1322 }
1323
1324 ConstReverseLinearisedIterator invalidReverseIter() const
1325 {
1326 return ConstReverseLinearisedIterator(
1327 reinterpret_cast<ConstLinearisedIterator>(
1328 Base::invalidReverseIter().base()));
1329 }
1330
1331 LinearisedIterator lbegin()
1332 {
1333 return reinterpret_cast<LinearisedIterator>(Base::lbegin());
1334 }
1335
1336 ConstLinearisedIterator lbegin() const
1337 {
1338 return reinterpret_cast<ConstLinearisedIterator>(Base::lbegin());
1339 }
1340
1341 ConstLinearisedIterator clbegin() const
1342 {
1343 return reinterpret_cast<ConstLinearisedIterator>(Base::clbegin());
1344 }
1345
1346 ReverseLinearisedIterator rlbegin()
1347 {
1348 return ReverseLinearisedIterator(
1349 reinterpret_cast<LinearisedIterator>(
1350 Base::rlbegin().base()));
1351 }
1352
1353 ConstReverseLinearisedIterator rlbegin() const
1354 {
1355 return ConstReverseLinearisedIterator(
1356 reinterpret_cast<ConstLinearisedIterator>(
1357 Base::rlbegin().base()));
1358 }
1359
1360 ConstReverseLinearisedIterator crlbegin() const
1361 {
1362 return ConstReverseLinearisedIterator(
1363 reinterpret_cast<ConstLinearisedIterator>(
1364 Base::crlbegin().base()));
1365 }
1366
1367 LinearisedIterator lend()
1368 {
1369 return reinterpret_cast<LinearisedIterator>(Base::lend());
1370 }
1371
1372 ConstLinearisedIterator lend() const
1373 {
1374 return reinterpret_cast<ConstLinearisedIterator>(Base::lend());
1375 }
1376
1377 ConstLinearisedIterator clend() const
1378 {
1379 return reinterpret_cast<ConstLinearisedIterator>(Base::clend());
1380 }
1381
1382 ReverseLinearisedIterator rlend()
1383 {
1384 return ReverseLinearisedIterator(
1385 reinterpret_cast<LinearisedIterator>(
1386 Base::rlend().base()));
1387 }
1388
1389 ConstReverseLinearisedIterator rlend() const
1390 {
1391 return ConstReverseLinearisedIterator(
1392 reinterpret_cast<ConstLinearisedIterator>(
1393 Base::rlend().base()));
1394 }
1395
1396 ConstReverseLinearisedIterator crlend() const
1397 {
1398 return ConstReverseLinearisedIterator(
1399 reinterpret_cast<ConstLinearisedIterator>(
1400 Base::crlend().base()));
1401 }
1402
1403 LinearisedIteratorRange arrayOne()
1404 {
1405 auto range = Base::arrayOne();
1406 return LinearisedIteratorRange(
1407 reinterpret_cast<LinearisedIterator>(range.first),
1408 reinterpret_cast<LinearisedIterator>(range.second));
1409 }
1410
1411 ConstLinearisedIteratorRange arrayOne() const
1412 {
1413 auto range = Base::arrayOne();
1414 return ConstLinearisedIteratorRange(
1415 reinterpret_cast<ConstLinearisedIterator>(range.first),
1416 reinterpret_cast<ConstLinearisedIterator>(range.second));
1417
1418 }
1419
1420 LinearisedIteratorRange arrayTwo()
1421 {
1422 auto range = Base::arrayTwo();
1423 return LinearisedIteratorRange(
1424 reinterpret_cast<LinearisedIterator>(range.first),
1425 reinterpret_cast<LinearisedIterator>(range.second));
1426
1427 }
1428
1429 ConstLinearisedIteratorRange arrayTwo() const
1430 {
1431 auto range = Base::arrayTwo();
1432 return ConstLinearisedIteratorRange(
1433 reinterpret_cast<ConstLinearisedIterator>(range.first),
1434 reinterpret_cast<ConstLinearisedIterator>(range.second));
1435
1436 }
1437
1438 LinearisedIterator erase(LinearisedIterator pos)
1439 {
1440 return reinterpret_cast<LinearisedIterator>(
1441 Base::erase(
1442 reinterpret_cast<BaseLinearisedIterator>(pos)));
1443 }
1444
1445 Iterator erase(Iterator pos)
1446 {
1447 auto tmp = Base::erase(pos);
1448 return *(reinterpret_cast<Iterator*>(&tmp));
1449 }
1450
1451 Iterator begin()
1452 {
1453 auto tmp = Base::begin();
1454 return *(reinterpret_cast<Iterator*>(&tmp));
1455 }
1456
1457 ConstIterator begin() const
1458 {
1459 auto tmp = Base::begin();
1460 return *(reinterpret_cast<ConstIterator*>(&tmp));
1461 }
1462
1463 ConstIterator cbegin() const
1464 {
1465 auto tmp = Base::cbegin();
1466 return *(reinterpret_cast<ConstIterator*>(&tmp));
1467
1468 }
1469
1470 Iterator end()
1471 {
1472 auto tmp = Base::end();
1473 return *(reinterpret_cast<Iterator*>(&tmp));
1474 }
1475
1476 ConstIterator end() const
1477 {
1478 auto tmp = Base::end();
1479 return *(reinterpret_cast<ConstIterator*>(&tmp));
1480 }
1481
1482 ConstIterator cend() const
1483 {
1484 auto tmp = Base::cend();
1485 return *(reinterpret_cast<ConstIterator*>(&tmp));
1486 }
1487
1488 void pushBack(ConstReference value)
1489 {
1490 Base::pushBack(reinterpret_cast<BaseConstReference>(value));
1491 }
1492
1493 void pushFront(ConstReference value)
1494 {
1495 Base::pushFront(reinterpret_cast<BaseConstReference>(value));
1496 }
1497
1498 LinearisedIterator insert(LinearisedIterator pos, ConstReference value)
1499 {
1500 return reinterpret_cast<LinearisedIterator>(
1501 Base::insert(
1502 reinterpret_cast<BaseLinearisedIterator>(pos),
1503 reinterpret_cast<BaseConstReference>(value)));
1504 }
1505
1506 void assignElements(const CastWrapperQueueBase& other)
1507 {
1508 Base::assignElements(static_cast<const Base&>(other));
1509 }
1510
1511 void assignElements(CastWrapperQueueBase&& other)
1512 {
1513 Base::assignElements(static_cast<Base&&>(std::move(other)));
1514 }
1515};
1516
1517template <typename TWrapperElemType, typename TQueueElemType>
1518class CastWrapperQueueBase<TWrapperElemType, TQueueElemType>::ConstIterator :
1519 public StaticQueueBase<TQueueElemType>::ConstIterator
1520{
1521 using Base = typename StaticQueueBase<TQueueElemType>::ConstIterator;
1522public:
1523 ConstIterator(const ConstIterator&) = default;
1524 ConstIterator& operator=(const ConstIterator&) = default;
1525 ~ConstIterator() noexcept = default;
1526
1527protected:
1528 using ExpectedQueueType = const StaticQueueBase<TWrapperElemType>;
1529 using ActualQueueType = const StaticQueueBase<TQueueElemType>;
1530 using ValueType = TWrapperElemType;
1531 using Reference = const ValueType&;
1532 using ConstReference = const ValueType&;
1533 using Pointer = const ValueType*;
1534 using ConstPointer = const ValueType*;
1535 using DifferenceType = typename Base::DifferenceType;
1536
1537 ConstIterator(ExpectedQueueType& queue, Pointer iterator)
1538 : Base(reinterpret_cast<ActualQueueType&>(queue), iterator)
1539 {
1540 }
1541
1542 ConstIterator& operator++()
1543 {
1544 Base::operator++();
1545 return *this;
1546 }
1547
1548 ConstIterator operator++(int dummy)
1549 {
1550 auto tmp = Base::operator++(dummy);
1551 return *(static_cast<ConstIterator*>(&tmp));
1552 }
1553
1554 ConstIterator& operator--()
1555 {
1556 Base::operator--();
1557 return *this;
1558 }
1559
1560 ConstIterator operator--(int dummy)
1561 {
1562 auto tmp = Base::operator--(dummy);
1563 return *(static_cast<ConstIterator*>(&tmp));
1564 }
1565
1566 ConstIterator& operator+=(DifferenceType value)
1567 {
1568 Base::operator+=(value);
1569 return *this;
1570 }
1571
1572 ConstIterator& operator-=(DifferenceType value)
1573 {
1574 Base::operator-=(value);
1575 return *this;
1576 }
1577
1578 ConstIterator operator+(DifferenceType value) const
1579 {
1580 auto tmp = Base::operator+(value);
1581 return *(static_cast<ConstIterator*>(&tmp));
1582 }
1583
1584 ConstIterator operator-(DifferenceType value) const
1585 {
1586 auto tmp = Base::operator-(value);
1587 return *(static_cast<ConstIterator*>(&tmp));
1588 }
1589
1590 DifferenceType operator-(const ConstIterator& other) const
1591 {
1592 return Base::operator-(other);
1593 }
1594
1595 Reference operator*()
1596 {
1597 auto& ref = Base::operator*();
1598 return reinterpret_cast<Reference>(ref);
1599 }
1600
1601 ConstReference operator*() const
1602 {
1603 auto& ref = Base::operator*();
1604 return reinterpret_cast<ConstReference>(ref);
1605 }
1606
1607 Pointer operator->()
1608 {
1609 auto* ptr = Base::operator->();
1610 return reinterpret_cast<Pointer>(ptr);
1611 }
1612
1613 ConstPointer operator->() const
1614 {
1615 auto* ptr = Base::operator->();
1616 return reinterpret_cast<ConstPointer>(ptr);
1617 }
1618};
1619
1620template <typename TWrapperElemType, typename TQueueElemType>
1621class CastWrapperQueueBase<TWrapperElemType, TQueueElemType>::Iterator :
1622 public StaticQueueBase<TQueueElemType>::Iterator
1623{
1624 using Base = typename StaticQueueBase<TQueueElemType>::Iterator;
1625public:
1626 Iterator(const Iterator&) = default;
1627 Iterator& operator=(const Iterator&) = default;
1628 ~Iterator() noexcept = default;
1629
1630protected:
1631 using ExpectedQueueType = const StaticQueueBase<TWrapperElemType>;
1632 using ActualQueueType = const StaticQueueBase<TQueueElemType>;
1633 using ValueType = TWrapperElemType;
1634 using Reference = ValueType&;
1635 using ConstReference = const ValueType&;
1636 using Pointer = ValueType*;
1637 using ConstPointer = const ValueType*;
1638 using DifferenceType = typename Base::DifferenceType;
1639
1640 Iterator(ExpectedQueueType& queue, Pointer iterator)
1641 : Base(reinterpret_cast<ActualQueueType&>(queue), iterator)
1642 {
1643 }
1644
1645 Iterator& operator++()
1646 {
1647 Base::operator++();
1648 return *this;
1649 }
1650
1651 Iterator operator++(int dummy)
1652 {
1653 auto tmp = Base::operator++(dummy);
1654 return *(static_cast<Iterator*>(&tmp));
1655 }
1656
1657 Iterator& operator--()
1658 {
1659 Base::operator--();
1660 return *this;
1661 }
1662
1663 Iterator operator--(int dummy)
1664 {
1665 auto tmp = Base::operator--(dummy);
1666 return *(static_cast<Iterator*>(&tmp));
1667 }
1668
1669 Iterator& operator+=(DifferenceType value)
1670 {
1671 Base::operator+=(value);
1672 return *this;
1673 }
1674
1675 Iterator& operator-=(DifferenceType value)
1676 {
1677 Base::operator-=(value);
1678 return *this;
1679 }
1680
1681 Iterator operator+(DifferenceType value) const
1682 {
1683 auto tmp = Base::operator+(value);
1684 return *(static_cast<Iterator*>(&tmp));
1685 }
1686
1687 Iterator operator-(DifferenceType value) const
1688 {
1689 auto tmp = Base::operator-(value);
1690 return *(static_cast<Iterator*>(&tmp));
1691 }
1692
1693 DifferenceType operator-(const Iterator& other) const
1694 {
1695 return Base::operator-(other);
1696 }
1697
1698 Reference operator*()
1699 {
1700 auto& ref = Base::operator*();
1701 return reinterpret_cast<Reference>(ref);
1702 }
1703
1704 ConstReference operator*() const
1705 {
1706 auto& ref = Base::operator*();
1707 return reinterpret_cast<ConstReference>(ref);
1708 }
1709
1710 Pointer operator->()
1711 {
1712 auto* ptr = Base::operator->();
1713 return reinterpret_cast<Pointer>(ptr);
1714 }
1715
1716 ConstPointer operator->() const
1717 {
1718 auto* ptr = Base::operator->();
1719 return reinterpret_cast<ConstPointer>(ptr);
1720 }
1721};
1722
1723template <typename T>
1724class StaticQueueBaseOptimised : public StaticQueueBase<T>
1725{
1726 usign Base = StaticQueueBase<T>;
1727protected:
1728
1729 using StorageTypePtr = typename Base::StorageTypePtr;
1730
1731 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1732 : Base(data, capacity)
1733 {
1734 }
1735
1736 ~StaticQueueBaseOptimised() noexcept = default;
1737
1738 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1739 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1740};
1741
1742template <>
1743class StaticQueueBaseOptimised<std::int8_t> : public CastWrapperQueueBase<std::int8_t, std::uint8_t>
1744{
1745 using Base = CastWrapperQueueBase<std::int8_t, std::uint8_t>;
1746protected:
1747
1748 using StorageTypePtr = typename Base::StorageTypePtr;
1749
1750 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1751 : Base(data, capacity)
1752 {
1753 }
1754
1755 ~StaticQueueBaseOptimised() noexcept = default;
1756 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1757 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1758};
1759
1760template <>
1761class StaticQueueBaseOptimised<std::int16_t> : public CastWrapperQueueBase<std::int16_t, std::uint16_t>
1762{
1763 using Base = CastWrapperQueueBase<std::int16_t, std::uint16_t>;
1764protected:
1765
1766 using StorageTypePtr = typename Base::StorageTypePtr;
1767
1768 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1769 : Base(data, capacity)
1770 {
1771 }
1772
1773 ~StaticQueueBaseOptimised() noexcept = default;
1774 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1775 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1776};
1777
1778template <>
1779class StaticQueueBaseOptimised<std::int32_t> : public CastWrapperQueueBase<std::int32_t, std::uint32_t>
1780{
1781 using Base = CastWrapperQueueBase<std::int32_t, std::uint32_t>;
1782protected:
1783
1784 using StorageTypePtr = typename Base::StorageTypePtr;
1785
1786 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1787 : Base(data, capacity)
1788 {
1789 }
1790
1791 ~StaticQueueBaseOptimised() noexcept = default;
1792 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1793 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1794};
1795
1796template <>
1797class StaticQueueBaseOptimised<std::int64_t> : public CastWrapperQueueBase<std::int64_t, std::uint64_t>
1798{
1799 using Base = CastWrapperQueueBase<std::int64_t, std::uint64_t>;
1800protected:
1801
1802 using StorageTypePtr = typename Base::StorageTypePtr;
1803
1804 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1805 : Base(data, capacity)
1806 {
1807 }
1808
1809 ~StaticQueueBaseOptimised() noexcept = default;
1810 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1811 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1812};
1813
1814template <typename T>
1815class StaticQueueBaseOptimised<T*> : public CastWrapperQueueBase<T*, typename comms::util::SizeToType<sizeof(T*)>::Type>
1816{
1817 using Base = CastWrapperQueueBase<T*, typename comms::util::SizeToType<sizeof(T*)>::Type>;
1818protected:
1819
1820 using Base = typename Base::StorageTypePtr;
1821
1822 StaticQueueBaseOptimised(StorageTypePtr data, std::size_t capacity)
1823 : Base(data, capacity)
1824 {
1825 }
1826
1827 ~StaticQueueBaseOptimised() noexcept = default;
1828 StaticQueueBaseOptimised& operator=(const StaticQueueBaseOptimised& other) = default;
1829 StaticQueueBaseOptimised& operator=(StaticQueueBaseOptimised&& other) = default;
1830};
1831
1832
1833} // namespace details
1834
1836
1847template <typename T, std::size_t TSize>
1848class StaticQueue : public details::StaticQueueBaseOptimised<T>
1849{
1850 using Base = details::StaticQueueBaseOptimised<T>;
1851
1852 using StorageType = typename Base::StorageType;
1853public:
1855 using ValueType = typename Base::ValueType;
1856
1858 using value_type = ValueType;
1859
1861 using SizeType = typename Base::SizeType;
1862
1864 using size_type = SizeType;
1865
1867 using Reference = typename Base::Reference;
1868
1870 using reference = Reference;
1871
1873 using ConstReference = typename Base::ConstReference;
1874
1876 using const_reference = ConstReference;
1877
1879 using Pointer = typename Base::Pointer;
1880
1882 using pointer = Pointer;
1883
1885 using ConstPointer = typename Base::ConstPointer;
1886
1888 using const_pointer = ConstPointer;
1889
1891 using LinearisedIterator = typename Base::LinearisedIterator;
1892
1894 using ConstLinearisedIterator = typename Base::ConstLinearisedIterator;
1895
1897 using ReverseLinearisedIterator = typename Base::ReverseLinearisedIterator;
1898
1900 using ConstReverseLinearisedIterator = typename Base::ConstReverseLinearisedIterator;
1901
1903 using LinearisedIteratorRange = typename Base::LinearisedIteratorRange;
1904
1906 using ConstLinearisedIteratorRange = typename Base::ConstLinearisedIteratorRange;
1907
1909 class ConstIterator;
1910
1912 using const_iterator = ConstIterator;
1913
1915 class Iterator;
1916
1918 using iterator = Iterator;
1919
1920 // Member functions
1925 StaticQueue()
1926 : Base(&array_[0], TSize)
1927 {
1928 }
1929
1938 StaticQueue(const StaticQueue& queue)
1939 : Base(&array_[0], TSize)
1940 {
1941 Base::assignElements(queue);
1942 }
1943
1952 StaticQueue(StaticQueue&& queue)
1953 : Base(&array_[0], TSize)
1954 {
1955 Base::assignElements(std::move(queue));
1956 }
1957
1958
1967 template <std::size_t TAnySize>
1968 StaticQueue(const StaticQueue<T, TAnySize>& queue)
1969 : Base(&array_[0], TSize)
1970 {
1971 Base::assignElements(queue);
1972 }
1973
1982 template <std::size_t TAnySize>
1983 StaticQueue(StaticQueue<T, TAnySize>&& queue)
1984 : Base(&array_[0], TSize)
1985 {
1986 Base::assignElements(std::move(queue));
1987 }
1988
1995 ~StaticQueue() noexcept
1996 {
1997 clear();
1998 }
1999
2010 StaticQueue& operator=(const StaticQueue& queue)
2011 {
2012 return static_cast<StaticQueue&>(Base::operator=(queue));
2013 }
2014
2025 StaticQueue& operator=(StaticQueue&& queue)
2026 {
2027 return static_cast<StaticQueue&>(Base::operator=(std::move(queue)));
2028 }
2029
2030
2042 template <std::size_t TAnySize>
2043 StaticQueue& operator=(const StaticQueue<T, TAnySize>& queue)
2044 {
2045 return static_cast<StaticQueue&>(Base::operator=(queue));
2046 }
2047
2059 template <std::size_t TAnySize>
2060 StaticQueue& operator=(StaticQueue<T, TAnySize>&& queue)
2061 {
2062 return static_cast<StaticQueue&>(Base::operator=(std::move(queue)));
2063 }
2064
2071 static constexpr std::size_t capacity()
2072 {
2073 return TSize;
2074 }
2075
2083 std::size_t size() const
2084 {
2085 return Base::size();
2086 }
2087
2093 bool empty() const
2094 {
2095 return Base::empty();
2096 }
2097
2099 bool isEmpty() const
2100 {
2101 return empty();
2102 }
2103
2109 bool full() const
2110 {
2111 return Base::full();
2112 }
2113
2115 bool isFull() const
2116 {
2117 return full();
2118 }
2119
2125 void clear()
2126 {
2127 Base::clear();
2128 }
2129
2136 void popBack()
2137 {
2138 Base::popBack();
2139 }
2140
2142 inline void pop_back()
2143 {
2144 popBack();
2145 }
2146
2156 void popBack(std::size_t count)
2157 {
2158 Base::popBack(count);
2159 }
2160
2162 void pop_back(std::size_t count)
2163 {
2164 popBack(count);
2165 }
2166
2173 void popFront()
2174 {
2175 Base::popFront();
2176 }
2177
2179 inline void pop_front()
2180 {
2181 popFront();
2182 }
2183
2191 void popFront(std::size_t count)
2192 {
2193 Base::popFront(count);
2194 }
2195
2197 inline void pop_front(std::size_t count)
2198 {
2199 popFront(count);
2200 }
2201
2209 template <typename U>
2210 void pushBack(U&& value)
2211 {
2212 Base::pushBack(std::forward<U>(value));
2213 }
2214
2223 template <typename... TArgs>
2224 void emplaceBack(TArgs&&... args)
2225 {
2226 Base::emplaceBack(std::forward<TArgs>(args)...);
2227 }
2228
2230 template <typename U>
2231 inline void push_back(U&& value)
2232 {
2233 pushBack(std::forward<U>(value));
2234 }
2235
2243 template <typename U>
2244 void pushFront(U&& value)
2245 {
2246 Base::pushFront(std::forward<U>(value));
2247 }
2248
2250 template <typename U>
2251 inline void push_front(U&& value)
2252 {
2253 pushFront(std::forward<U>(value));
2254 }
2255
2271 template <typename U>
2272 LinearisedIterator insert(LinearisedIterator pos, U&& value)
2273 {
2274 return Base::insert(pos, std::forward<U>(value));
2275 }
2276
2277
2284 Reference front()
2285 {
2286 return Base::front();
2287 }
2288
2290 ConstReference front() const
2291 {
2292 return Base::front();
2293 }
2294
2301 Reference back()
2302 {
2303 return Base::back();
2304 }
2305
2307 ConstReference back() const
2308 {
2309 return Base::back();
2310 }
2311
2322 Reference operator[](std::size_t index)
2323 {
2324 return Base::operator[](index);
2325 }
2326
2328 ConstReference operator[](std::size_t index) const
2329 {
2330 return Base::operator[](index);
2331 }
2332
2344 Reference at(std::size_t index)
2345 {
2346 return Base::at(index);
2347 }
2348
2350 ConstReference at(std::size_t index) const
2351 {
2352 return Base::at(index);
2353 }
2354
2364 int indexOf(ConstReference element) const
2365 {
2366 return Base::indexOf(element);
2367 }
2368
2375 LinearisedIterator invalidIter()
2376 {
2377 return Base::invalidIter();
2378 }
2379
2381 ConstLinearisedIterator invalidIter() const
2382 {
2383 return Base::invalidIter();
2384 }
2385
2391 ReverseLinearisedIterator invalidReverseIter()
2392 {
2393 return Base::invalidReverseIter();
2394 }
2395
2397 ConstReverseLinearisedIterator invalidReverseIter() const
2398 {
2399 return Base::invalidReverseIter();
2400 }
2401
2416 LinearisedIterator lbegin()
2417 {
2418 return Base::lbegin();
2419 }
2420
2422 ConstLinearisedIterator lbegin() const
2423 {
2424 return Base::lbegin();
2425 }
2426
2428 ConstLinearisedIterator clbegin() const
2429 {
2430 return Base::clbegin();
2431 }
2432
2447 ReverseLinearisedIterator rlbegin()
2448 {
2449 return Base::rlbegin();
2450 }
2451
2453 ConstReverseLinearisedIterator rlbegin() const
2454 {
2455 return Base::rlbegin();
2456 }
2457
2459 ConstReverseLinearisedIterator crlbegin() const
2460 {
2461 return Base::crlbegin();
2462 }
2463
2476 LinearisedIterator lend()
2477 {
2478 return Base::lend();
2479 }
2480
2482 ConstLinearisedIterator lend() const
2483 {
2484 return Base::lend();
2485 }
2486
2488 ConstLinearisedIterator clend() const
2489 {
2490 return Base::clend();
2491 }
2492
2505 ReverseLinearisedIterator rlend()
2506 {
2507 return Base::rlend();
2508 }
2509
2511 ConstReverseLinearisedIterator rlend() const
2512 {
2513 return Base::rlend();
2514 }
2515
2517 ConstReverseLinearisedIterator crlend() const
2518 {
2519 return Base::crlend();
2520 }
2521
2547 void linearise()
2548 {
2549 Base::linearise();
2550 }
2551
2562 bool linearised() const
2563 {
2564 return Base::linearised();
2565 }
2566
2568 bool isLinearised() const
2569 {
2570 return linearised();
2571 }
2572
2592 LinearisedIteratorRange arrayOne()
2593 {
2594 return Base::arrayOne();
2595 }
2596
2598 ConstLinearisedIteratorRange arrayOne() const
2599 {
2600 return Base::arrayOne();
2601 }
2602
2626 LinearisedIteratorRange arrayTwo()
2627 {
2628 return Base::arrayTwo();
2629 }
2630
2632 ConstLinearisedIteratorRange arrayTwo() const
2633 {
2634 return Base::arrayTwo();
2635 }
2636
2650 void resize(std::size_t newSize)
2651 {
2652 Base::resize(newSize);
2653 }
2654
2666 LinearisedIterator erase(LinearisedIterator pos)
2667 {
2668 return Base::erase(pos);
2669 }
2670
2681 Iterator erase(Iterator pos)
2682 {
2683 auto iter = Base::erase(pos);
2684 return *(static_cast<Iterator*>(&iter));
2685 }
2686
2687
2695 Iterator begin()
2696 {
2697 auto iter = Base::begin();
2698 return *(static_cast<Iterator*>(&iter));
2699 }
2700
2702 ConstIterator begin() const
2703 {
2704 auto iter = Base::begin();
2705 return *(static_cast<ConstIterator*>(&iter));
2706 }
2707
2709 ConstIterator cbegin() const
2710 {
2711 auto iter = Base::cbegin();
2712 return *(static_cast<ConstIterator*>(&iter));
2713 }
2714
2723 Iterator end()
2724 {
2725 auto iter = Base::end();
2726 return *(static_cast<Iterator*>(&iter));
2727 }
2728
2730 ConstIterator end() const
2731 {
2732 auto iter = Base::end();
2733 return *(static_cast<ConstIterator*>(&iter));
2734 }
2735
2737 ConstIterator cend() const
2738 {
2739 auto iter = Base::end();
2740 return *(static_cast<ConstIterator*>(&iter));
2741 }
2742
2744 template <std::size_t TAnySize>
2745 bool operator==(const StaticQueue<T, TAnySize>& other) const
2746 {
2747 return Base::operator==(other);
2748 }
2749
2751 template <std::size_t TAnySize>
2752 bool operator!=(const StaticQueue<T, TAnySize>& other) const
2753 {
2754 return Base::operator!=(other);
2755 }
2756
2757
2758private:
2759 using ArrayType = std::array<StorageType, TSize>;
2760 alignas(alignof(T)) ArrayType array_;
2761};
2762
2766template <typename T, std::size_t TSize>
2767class StaticQueue<T, TSize>::ConstIterator : public StaticQueue<T, TSize>::Base::ConstIterator
2768{
2769 using Base = typename StaticQueue<T, TSize>::Base::ConstIterator;
2770public:
2771
2773 using IteratorCategory = typename Base::IteratorCategory;
2774
2776 using iterator_category = IteratorCategory;
2777
2779 using ValueType = typename Base::ValueType;
2780
2782 using value_type = ValueType;
2783
2785 using DifferenceType = typename Base::DifferenceType;
2786
2788 using difference_type = DifferenceType;
2789
2791 using Pointer = typename Base::Pointer;
2792
2794 using pointer = Pointer;
2795
2797 using ConstPointer = typename Base::ConstPointer;
2798
2800 using Reference = typename Base::Reference;
2801
2803 using reference = Reference;
2804
2806 using ConstReference = typename Base::ConstReference;
2807
2809 using QueueType = StaticQueue<T, TSize>;
2810
2812 using ConstLinearisedIterator = typename QueueType::ConstLinearisedIterator;
2813
2817 ConstIterator(const QueueType& queue, ConstLinearisedIterator iterator)
2818 : Base(queue, iterator)
2819 {
2820 }
2821
2823 ConstIterator(const ConstIterator&) = default;
2824
2828 ConstIterator& operator=(const ConstIterator& other)
2829 {
2830 return static_cast<ConstIterator&>(Base::operator=(other));
2831 }
2832
2834 ConstIterator& operator++()
2835 {
2836 return static_cast<ConstIterator&>(Base::operator++());
2837 }
2838
2840 ConstIterator operator++(int dummyParam)
2841 {
2842 auto tmp = Base::operator++(dummyParam);
2843 return *(static_cast<ConstIterator*>(&tmp));
2844 }
2845
2847 ConstIterator& operator--()
2848 {
2849 return static_cast<ConstIterator&>(Base::operator--());
2850 }
2851
2853 ConstIterator operator--(int dummyParam)
2854 {
2855 auto tmp = Base::operator--(dummyParam);
2856 return *(static_cast<ConstIterator*>(&tmp));
2857 }
2858
2861 ConstIterator& operator+=(DifferenceType value)
2862 {
2863 return static_cast<ConstIterator&>(Base::operator+=(value));
2864 }
2865
2868 ConstIterator& operator-=(DifferenceType value)
2869 {
2870 return static_cast<ConstIterator&>(Base::operator-=(value));
2871 }
2872
2877 ConstIterator operator+(DifferenceType value) const
2878 {
2879 auto tmp = Base::operator+(value);
2880 return *(static_cast<ConstIterator*>(&tmp));
2881 }
2882
2887 ConstIterator operator-(DifferenceType value) const
2888 {
2889 auto tmp = Base::operator-(value);
2890 return *(static_cast<ConstIterator*>(&tmp));
2891 }
2892
2896 DifferenceType operator-(const ConstIterator& other) const
2897 {
2898 return Base::operator-(other);
2899 }
2900
2903 bool operator==(const ConstIterator& other) const
2904 {
2905 return Base::operator==(other);
2906 }
2907
2910 bool operator!=(const ConstIterator& other) const
2911 {
2912 return Base::operator!=(other);
2913 }
2914
2917 bool operator<(const ConstIterator& other) const
2918 {
2919 return Base::operator<(other);
2920 }
2921
2924 bool operator<=(const ConstIterator& other) const
2925 {
2926 return Base::operator<=(other);
2927 }
2928
2931 bool operator>(const ConstIterator& other) const
2932 {
2933 return Base::operator>(other);
2934 }
2935
2938 bool operator>=(const ConstIterator& other) const
2939 {
2940 return Base::operator>=(other);
2941 }
2942
2944 Reference operator*()
2945 {
2946 return Base::operator*();
2947 }
2948
2950 ConstReference operator*() const
2951 {
2952 return Base::operator*();
2953 }
2954
2956 Pointer operator->()
2957 {
2958 return Base::operator->();
2959 }
2960
2962 ConstPointer operator->() const
2963 {
2964 return Base::operator->();
2965 }
2966};
2967
2971template <typename T, std::size_t TSize>
2972class StaticQueue<T, TSize>::Iterator : public StaticQueue<T, TSize>::Base::Iterator
2973{
2974 using Base = typename StaticQueue<T, TSize>::Base::Iterator;
2975public:
2976
2978 using IteratorCategory = typename Base::IteratorCategory;
2979
2981 using iterator_category = IteratorCategory;
2982
2984 using ValueType = typename Base::ValueType;
2985
2987 using value_type = ValueType;
2988
2990 using DifferenceType = typename Base::DifferenceType;
2991
2993 using difference_type = DifferenceType;
2994
2996 using Pointer = typename Base::Pointer;
2997
2999 using pointer = Pointer;
3000
3002 using ConstPointer = typename Base::ConstPointer;
3003
3005 using Reference = typename Base::Reference;
3006
3008 using reference = Reference;
3009
3011 using ConstReference = typename Base::ConstReference;
3012
3014 using QueueType = StaticQueue<T, TSize>;
3015
3017 using LinearisedIterator = typename QueueType::LinearisedIterator;
3018
3020 using ConstLinearisedIterator = typename QueueType::ConstLinearisedIterator;
3021
3025 Iterator(QueueType& queue, LinearisedIterator iterator)
3026 : Base(queue, iterator)
3027 {
3028 }
3029
3031 Iterator(const Iterator&) = default;
3032
3036 Iterator& operator=(const Iterator& other)
3037 {
3038 return static_cast<Iterator&>(Base::operator=(other));
3039 }
3040
3042 Iterator& operator++()
3043 {
3044 return static_cast<Iterator&>(Base::operator++());
3045 }
3046
3048 Iterator operator++(int dummyParam)
3049 {
3050 auto tmp = Base::operator++(dummyParam);
3051 return *(static_cast<Iterator*>(&tmp));
3052 }
3053
3055 Iterator& operator--()
3056 {
3057 return static_cast<Iterator&>(Base::operator--());
3058 }
3059
3061 Iterator operator--(int dummyParam)
3062 {
3063 auto tmp = Base::operator--(dummyParam);
3064 return *(static_cast<Iterator*>(&tmp));
3065 }
3066
3069 Iterator& operator+=(DifferenceType value)
3070 {
3071 return static_cast<Iterator&>(Base::operator+=(value));
3072 }
3073
3076 Iterator& operator-=(DifferenceType value)
3077 {
3078 return static_cast<Iterator&>(Base::operator-=(value));
3079 }
3080
3085 Iterator operator+(DifferenceType value) const
3086 {
3087 auto tmp = Base::operator+(value);
3088 return *(static_cast<Iterator*>(&tmp));
3089 }
3090
3095 Iterator operator-(DifferenceType value) const
3096 {
3097 auto tmp = Base::operator-(value);
3098 return *(static_cast<Iterator*>(&tmp));
3099 }
3100
3104 DifferenceType operator-(const Iterator& other) const
3105 {
3106 return Base::operator-(other);
3107 }
3108
3111 bool operator==(const Iterator& other) const
3112 {
3113 return Base::operator==(other);
3114 }
3115
3118 bool operator!=(const Iterator& other) const
3119 {
3120 return Base::operator!=(other);
3121 }
3122
3125 bool operator<(const Iterator& other) const
3126 {
3127 return Base::operator<(other);
3128 }
3129
3132 bool operator<=(const Iterator& other) const
3133 {
3134 return Base::operator<=(other);
3135 }
3136
3139 bool operator>(const Iterator& other) const
3140 {
3141 return Base::operator>(other);
3142 }
3143
3146 bool operator>=(const Iterator& other) const
3147 {
3148 return Base::operator>=(other);
3149 }
3150
3152 Reference operator*()
3153 {
3154 return Base::operator*();
3155 }
3156
3158 ConstReference operator*() const
3159 {
3160 return Base::operator*();
3161 }
3162
3164 Pointer operator->()
3165 {
3166 return Base::operator->();
3167 }
3168
3170 ConstPointer operator->() const
3171 {
3172 return Base::operator->();
3173 }
3174
3175 operator ConstIterator() const
3176 {
3177 auto iter = static_cast<ConstLinearisedIterator>(Base::getIterator());
3178 const auto& queue = static_cast<QueueType&>(Base::getQueue());
3179 return ConstIterator(queue, iter);
3180 }
3181};
3182
3184
3185} // namespace util
3186
3187} // namespace comms
3188
3189COMMS_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:28
Replacement to some types from standard type_traits.