COMMS
Template library intended to help with implementation of communication protocols.
StaticVector.h
Go to the documentation of this file.
1 //
2 // Copyright 2015 - 2024 (C). Alex Robenko. All rights reserved.
3 //
4 // This Source Code Form is subject to the terms of the Mozilla Public
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 
10 
11 #pragma once
12 
13 #include <cstddef>
14 #include <array>
15 #include <algorithm>
16 #include <iterator>
17 #include <initializer_list>
18 
19 #include "comms/CompileControl.h"
20 #include "comms/Assert.h"
21 
22 COMMS_GNU_WARNING_PUSH
23 
24 #if COMMS_IS_GCC_12 && defined(NDEBUG)
25 // Release compilation with gcc-12
26 // assumes size / capacity of the StaticVectorBase is 0 and generates
27 // unjustified warnings.
28 COMMS_GNU_WARNING_DISABLE("-Warray-bounds")
29 #endif
30 
31 namespace comms
32 {
33 
34 namespace util
35 {
36 
37 namespace details
38 {
39 
40 template <typename T>
41 class StaticVectorBase
42 {
43 public:
44  using value_type = T;
45  using size_type = std::size_t;
46  using reference = T&;
47  using const_reference = const T&;
48  using pointer = T*;
49  using const_pointer = const T*;
50  using iterator = pointer;
51  using const_iterator = const_pointer;
52  using reverse_iterator = std::reverse_iterator<iterator>;
53  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
54 
55  using CellType =
56  typename std::aligned_storage<
57  sizeof(T),
58  std::alignment_of<T>::value
59  >::type;
60 
61  static_assert(sizeof(CellType) == sizeof(T), "Type T must be padded");
62 
63  StaticVectorBase(CellType* dataPtr, std::size_t cap)
64  : data_(dataPtr),
65  capacity_(cap)
66  {
67  }
68 
69  ~StaticVectorBase() noexcept
70  {
71  clear();
72  }
73 
74  StaticVectorBase(const StaticVectorBase&) = delete;
75  StaticVectorBase& operator=(const StaticVectorBase&) = delete;
76 
77 
78  std::size_t size() const
79  {
80  return size_;
81  }
82 
83  std::size_t capacity() const
84  {
85  return capacity_;
86  }
87 
88  bool empty() const
89  {
90  return (size() == 0);
91  }
92 
93  void pop_back()
94  {
95  COMMS_MSVC_WARNING_SUPPRESS(4189) // MSVC claims lastElem not referenced
96  auto& lastElem = back();
97  lastElem.~T();
98  --size_;
99  }
100 
101  T& back()
102  {
103  COMMS_ASSERT(!empty());
104  return elem(size() - 1);
105  }
106 
107  const T& back() const
108  {
109  COMMS_ASSERT(!empty());
110  return elem(size() - 1);
111  }
112 
113  T& front()
114  {
115  COMMS_ASSERT(!empty());
116  return elem(0);
117  }
118 
119  const T& front() const
120  {
121  COMMS_ASSERT(!empty());
122  return elem(0);
123  }
124 
125  template <typename TIter>
126  void assign(TIter from, TIter to)
127  {
128  clear();
129  for (auto iter = from; iter != to; ++iter) {
130  if (capacity() <= size()) {
131  static constexpr bool Not_all_elements_are_copied = false;
132  static_cast<void>(Not_all_elements_are_copied);
133  COMMS_ASSERT(Not_all_elements_are_copied);
134  return;
135  }
136 
137  new (cellPtr(size())) T(*(reinterpret_cast<const T*>(&*iter)));
138  ++size_;
139  }
140  }
141 
142  void fill(std::size_t count, const T& value)
143  {
144  clear();
145  COMMS_ASSERT(count <= capacity());
146  for (auto idx = 0U; idx < count; ++idx) {
147  new (cellPtr(idx)) T(value);
148  }
149  size_ = count;
150  }
151 
152  void clear() {
153  for (auto idx = 0U; idx < size(); ++idx) {
154  elem(idx).~T();
155  }
156  size_ = 0;
157  }
158 
159 
160  T* begin()
161  {
162  if (size() == 0U) {
163  return nullptr;
164  }
165 
166  return &(elem(0));
167  }
168 
169  const T* begin() const
170  {
171  return cbegin();
172  }
173 
174  const T* cbegin() const
175  {
176  if (size() == 0U) {
177  return nullptr;
178  }
179 
180  return &(elem(0));
181  }
182 
183  T* end()
184  {
185  return begin() + size();
186  }
187 
188  const T* end() const
189  {
190  return cend();
191  }
192 
193  const T* cend() const
194  {
195  return cbegin() + size();
196  }
197 
198  T& at(std::size_t pos)
199  {
200  COMMS_ASSERT(pos < size());
201  return elem(pos);
202  }
203 
204  const T& at(std::size_t pos) const
205  {
206  COMMS_ASSERT(pos < size());
207  return elem(pos);
208  }
209 
210  T& operator[](std::size_t pos)
211  {
212  return elem(pos);
213  }
214 
215  const T& operator[](std::size_t pos) const
216  {
217  return elem(pos);
218  }
219 
220  T* data()
221  {
222  if (size() == 0U) {
223  return nullptr;
224  }
225 
226  return &(elem(0));
227  }
228 
229  const T* data() const
230  {
231  if (size() == 0U) {
232  return nullptr;
233  }
234 
235  return &(elem(0));
236  }
237 
238  template <typename U>
239  T* insert(const T* pos, U&& value)
240  {
241  COMMS_ASSERT(pos <= end());
242  COMMS_ASSERT(size() < capacity());
243  if (end() <= pos) {
244  push_back(std::forward<U>(value));
245  return &(back());
246  }
247 
248  COMMS_ASSERT(!empty());
249  push_back(std::move(back()));
250  auto* insertIter = begin() + std::distance(cbegin(), pos);
251  std::move_backward(insertIter, end() - 2, end() - 1);
252  *insertIter = std::forward<U>(value);
253  return insertIter;
254  }
255 
256  T* insert(const T* pos, std::size_t count, const T& value)
257  {
258  COMMS_ASSERT(pos <= end());
259  COMMS_ASSERT((size() + count) <= capacity());
260  auto dist = std::distance(cbegin(), pos);
261  COMMS_ASSERT((0 <= dist) && static_cast<std::size_t>(dist) < size());
262  auto* posIter = begin() + dist;
263  if (end() <= posIter) {
264  while (0 < count) {
265  push_back(value);
266  --count;
267  }
268  return posIter;
269  }
270 
271  COMMS_ASSERT(!empty());
272  auto tailCount = static_cast<std::size_t>(std::distance(posIter, end()));
273  if (count <= tailCount) {
274  auto pushBegIter = end() - count;
275  auto pushEndIter = end();
276  for (auto iter = pushBegIter; iter != pushEndIter; ++iter) {
277  push_back(std::move(*iter));
278  }
279 
280  auto moveBegIter = posIter;
281  auto moveEndIter = moveBegIter + (tailCount - count);
282  COMMS_ASSERT(moveEndIter < pushEndIter);
283 
284  COMMS_GNU_WARNING_PUSH
285 #if COMMS_IS_GCC_12 && defined(NDEBUG)
286  // Release compilation with gcc-12
287  // gives a warning here, while any debug build works fine.
288  COMMS_GNU_WARNING_DISABLE("-Wstringop-overflow")
289 #endif
290  std::move_backward(moveBegIter, moveEndIter, pushEndIter);
291  COMMS_GNU_WARNING_POP
292 
293  auto* assignBegIter = posIter;
294  auto* assignEndIter = assignBegIter + count;
295  for (auto iter = assignBegIter; iter != assignEndIter; ++iter) {
296  *iter = value;
297  }
298  return posIter;
299  }
300 
301  auto pushValueCount = count - tailCount;
302  for (auto idx = 0U; idx < pushValueCount; ++idx) {
303  push_back(value);
304  }
305 
306  auto* pushBegIter = posIter;
307  auto* pushEndIter = pushBegIter + tailCount;
308  for (auto iter = pushBegIter; iter != pushEndIter; ++iter) {
309  push_back(std::move(*iter));
310  }
311 
312  auto assignBegIter = posIter;
313  auto assignEndIter = assignBegIter + tailCount;
314  for (auto iter = assignBegIter; iter != assignEndIter; ++iter) {
315  *iter = value;
316  }
317  return posIter;
318  }
319 
320  template <typename TIter>
321  T* insert(const T* pos, TIter from, TIter to)
322  {
323  using Tag = typename std::iterator_traits<TIter>::iterator_category;
324  return insert_internal(pos, from, to, Tag());
325  }
326 
327  template <typename... TArgs>
328  T* emplace(const T* iter, TArgs&&... args)
329  {
330  auto* insertIter = begin() + std::distance(cbegin(), iter);
331  if (iter == cend()) {
332  emplace_back(std::forward<TArgs>(args)...);
333  return insertIter;
334  }
335 
336  COMMS_ASSERT(!empty());
337  push_back(std::move(back()));
338  std::move_backward(insertIter, end() - 2, end() - 1);
339  insertIter->~T();
340  new (insertIter) T(std::forward<TArgs>(args)...);
341  return insertIter;
342  }
343 
344  T* erase(const T* from, const T* to)
345  {
346  COMMS_ASSERT(from <= cend());
347  COMMS_ASSERT(to <= cend());
348  COMMS_ASSERT(from <= to);
349 
350  auto tailCount = static_cast<std::size_t>(std::distance(to, cend()));
351  auto eraseCount = static_cast<std::size_t>(std::distance(from, to));
352 
353  auto* moveSrc = begin() + std::distance(cbegin(), to);
354  auto* moveDest = begin() + std::distance(cbegin(), from);
355  std::move(moveSrc, end(), moveDest);
356 
357  auto* eraseFrom = moveDest + tailCount;
358  auto* eraseTo = end();
359  COMMS_ASSERT(eraseFrom <= end());
360  COMMS_ASSERT(eraseCount <= size());
361  COMMS_ASSERT(static_cast<std::size_t>(std::distance(eraseFrom, eraseTo)) == eraseCount);
362  for (auto iter = eraseFrom; iter != eraseTo; ++iter) {
363  iter->~T();
364  }
365  size_ -= eraseCount;
366  return moveDest;
367  }
368 
369  template <typename U>
370  void push_back(U&& value)
371  {
372  COMMS_ASSERT(size() < capacity());
373  new (cellPtr(size())) T(std::forward<U>(value));
374  ++size_;
375  }
376 
377  template <typename... TArgs>
378  void emplace_back(TArgs&&... args)
379  {
380  COMMS_ASSERT(size() < capacity());
381  new (cellPtr(size())) T(std::forward<TArgs>(args)...);
382  ++size_;
383  }
384 
385  void resize(std::size_t count, const T& value)
386  {
387  if (count < size()) {
388  erase(begin() + count, end());
389  COMMS_ASSERT(count == size());
390  return;
391  }
392 
393  while (size() < count) {
394  push_back(value);
395  }
396  }
397 
398  void swap(StaticVectorBase<T>& other)
399  {
400  auto swapSize = std::min(other.size(), size());
401  for (auto idx = 0U; idx < swapSize; ++idx) {
402  std::swap(this->operator[](idx), other[idx]);
403  }
404 
405  auto otherSize = other.size();
406  auto thisSize = size();
407 
408  if (otherSize == thisSize) {
409  return;
410  }
411 
412  if (otherSize < thisSize) {
413  auto limit = std::min(thisSize, other.capacity());
414  for (auto idx = swapSize; idx < limit; ++idx) {
415  new (other.cellPtr(idx)) T(std::move(elem(idx)));
416  }
417 
418  other.size_ = thisSize;
419  erase(begin() + otherSize, end());
420  return;
421  }
422 
423  auto limit = std::min(otherSize, capacity());
424  for (auto idx = swapSize; idx < limit; ++idx) {
425  new (cellPtr(idx)) T(std::move(other.elem(idx)));
426  }
427  size_ = otherSize;
428  other.erase(other.begin() + thisSize, other.end());
429  }
430 
431 private:
432  CellType& cell(std::size_t idx)
433  {
434  COMMS_ASSERT(idx < capacity());
435  return data_[idx];
436  }
437 
438  const CellType& cell(std::size_t idx) const
439  {
440  COMMS_ASSERT(idx < capacity());
441  return data_[idx];
442  }
443 
444  CellType* cellPtr(std::size_t idx)
445  {
446  COMMS_ASSERT(idx < capacity());
447  return &data_[idx];
448  }
449 
450  T& elem(std::size_t idx)
451  {
452  return reinterpret_cast<T&>(cell(idx));
453  }
454 
455  const T& elem(std::size_t idx) const
456  {
457  return reinterpret_cast<const T&>(cell(idx));
458  }
459 
460  template <typename TIter>
461  T* insert_random_access(const T* pos, TIter from, TIter to)
462  {
463  COMMS_ASSERT(pos <= end());
464  auto* posIter = begin() + std::distance(cbegin(), pos);
465  if (end() <= posIter) {
466  for (; from != to; ++from) {
467  push_back(*from);
468  }
469 
470  return posIter;
471  }
472 
473  auto count = static_cast<std::size_t>(std::distance(from, to));
474  COMMS_ASSERT(!empty());
475  auto tailCount = static_cast<std::size_t>(std::distance(posIter, end()));
476  if (count <= tailCount) {
477  auto pushBegIter = end() - count;
478  auto pushEndIter = end();
479  for (auto iter = pushBegIter; iter != pushEndIter; ++iter) {
480  push_back(std::move(*iter));
481  }
482 
483  auto moveBegIter = posIter;
484  auto moveEndIter = moveBegIter + (tailCount - count);
485  COMMS_ASSERT(moveEndIter < pushEndIter);
486  std::move_backward(moveBegIter, moveEndIter, pushEndIter);
487 
488  auto* assignBegIter = posIter;
489  auto* assignEndIter = assignBegIter + count;
490  for (auto iter = assignBegIter; iter != assignEndIter; ++iter) {
491  *iter = *from;
492  ++from;
493  }
494  return posIter;
495  }
496 
497  auto pushValueCount = count - tailCount;
498  auto pushInsertedBegIter = to - pushValueCount;
499  for (auto idx = 0U; idx < pushValueCount; ++idx) {
500  push_back(*pushInsertedBegIter);
501  ++pushInsertedBegIter;
502  }
503 
504  auto* pushBegIter = posIter;
505  auto* pushEndIter = pushBegIter + tailCount;
506  for (auto iter = pushBegIter; iter != pushEndIter; ++iter) {
507  push_back(std::move(*iter));
508  }
509 
510  auto assignBegIter = posIter;
511  auto assignEndIter = assignBegIter + tailCount;
512  for (auto iter = assignBegIter; iter != assignEndIter; ++iter) {
513  *iter = *from;
514  ++from;
515  }
516 
517  return posIter;
518  }
519 
520  template <typename TIter>
521  T* insert_input(const T* pos, TIter from, TIter to)
522  {
523  T* ret = nullptr;
524  for (; from != to; ++from) {
525  if (ret == nullptr) {
526  ret = begin() + std::distance(cbegin(), pos);
527  }
528  insert(pos, *from);
529  ++pos;
530  }
531  return ret;
532  }
533 
534  template <typename TIter>
535  T* insert_internal(const T* pos, TIter from, TIter to, std::random_access_iterator_tag)
536  {
537  return insert_random_access(pos, from, to);
538  }
539 
540  template <typename TIter>
541  T* insert_internal(const T* pos, TIter from, TIter to, std::input_iterator_tag)
542  {
543  return insert_input(pos, from, to);
544  }
545 
546 
547  CellType* data_ = nullptr;
548  std::size_t capacity_ = 0;
549  std::size_t size_ = 0;
550 };
551 
552 template <typename T, std::size_t TSize>
553 struct StaticVectorStorageBase
554 {
555  using ElementType = typename std::aligned_storage<
556  sizeof(T),
557  std::alignment_of<T>::value
558  >::type;
559 
560  using StorageType = std::array<ElementType, TSize>;
561  StorageType data_;
562 };
563 
564 template <typename T, std::size_t TSize>
565 class StaticVectorGeneric :
566  public StaticVectorStorageBase<T, TSize>,
567  public StaticVectorBase<T>
568 {
569  using StorageBase = StaticVectorStorageBase<T, TSize>;
570  using Base = StaticVectorBase<T>;
571 
572 public:
573  using value_type = typename Base::value_type;
574  using size_type = typename Base::size_type;
575  using difference_type = typename StorageBase::StorageType::difference_type;
576  using reference = typename Base::reference;
577  using const_reference = typename Base::const_reference;
578  using pointer = typename Base::pointer;
579  using const_pointer = typename Base::const_pointer;
580  using iterator = typename Base::iterator;
581  using const_iterator = typename Base::const_iterator;
582  using reverse_iterator = typename Base::reverse_iterator;
583  using const_reverse_iterator = typename Base::const_reverse_iterator;
584 
585  StaticVectorGeneric()
586  : Base(StorageBase::data_.data(), StorageBase::data_.size())
587  {
588  }
589 
590  StaticVectorGeneric(size_type count, const T& value)
591  : Base(StorageBase::data_.data(), StorageBase::data_.size())
592  {
593  assign(count, value);
594  }
595 
596  explicit StaticVectorGeneric(size_type count)
597  : Base(StorageBase::data_.data(), StorageBase::data_.size())
598  {
599  COMMS_ASSERT(count < Base::capacity());
600  while (0 < count) {
601  Base::emplace_back();
602  --count;
603  }
604  }
605 
606  template <typename TIter>
607  StaticVectorGeneric(TIter from, TIter to)
608  : Base(StorageBase::data_.data(), StorageBase::data_.size())
609  {
610  assign(from, to);
611  }
612 
613  template <std::size_t TOtherSize>
614  StaticVectorGeneric(const StaticVectorGeneric<T, TOtherSize>& other)
615  : Base(StorageBase::data_.data(), StorageBase::data_.size())
616  {
617  assign(other.begin(), other.end());
618  }
619 
620  StaticVectorGeneric(const StaticVectorGeneric& other)
621  : Base(StorageBase::data_.data(), StorageBase::data_.size())
622  {
623  assign(other.begin(), other.end());
624  }
625 
626  StaticVectorGeneric(std::initializer_list<value_type> init)
627  : Base(StorageBase::data_.data(), StorageBase::data_.size())
628  {
629  assign(init.begin(), init.end());
630  }
631 
632  ~StaticVectorGeneric() noexcept = default;
633 
634  StaticVectorGeneric& operator=(const StaticVectorGeneric& other)
635  {
636  if (&other == this) {
637  return *this;
638  }
639 
640  assign(other.begin(), other.end());
641  return *this;
642  }
643 
644  template <std::size_t TOtherSize>
645  StaticVectorGeneric& operator=(const StaticVectorGeneric<T, TOtherSize>& other)
646  {
647  assign(other.cbegin(), other.cend());
648  return *this;
649  }
650 
651  StaticVectorGeneric& operator=(std::initializer_list<value_type> init)
652  {
653  assign(init);
654  return *this;
655  }
656 
657  void assign(size_type count, const T& value)
658  {
659  COMMS_ASSERT(count <= TSize);
660  Base::fill(count, value);
661  }
662 
663  template <typename TIter>
664  void assign(TIter from, TIter to)
665  {
666  Base::assign(from, to);
667  }
668 
669  void assign(std::initializer_list<value_type> init)
670  {
671  assign(init.begin(), init.end());
672  }
673 
674  void reserve(size_type new_cap)
675  {
676  static_cast<void>(new_cap);
677  COMMS_ASSERT(new_cap <= Base::capacity());
678  }
679 };
680 
681 template <typename TOrig, typename TCast, std::size_t TSize>
682 class StaticVectorCasted : public StaticVectorGeneric<TCast, TSize>
683 {
684  using Base = StaticVectorGeneric<TCast, TSize>;
685  static_assert(sizeof(TOrig) == sizeof(TCast), "The sizes are not equal");
686 
687 public:
688  using value_type = TOrig;
689  using size_type = typename Base::size_type;
690  using difference_type = typename Base::difference_type;
691  using reference = value_type&;
692  using const_reference = const value_type&;
693  using pointer = value_type*;
694  using const_pointer = const value_type*;
695  using iterator = pointer;
696  using const_iterator = const_pointer;
697 
698  StaticVectorCasted() = default;
699 
700  StaticVectorCasted(size_type count, const_reference& value)
701  : Base(count, *(reinterpret_cast<typename Base::const_pointer>(&value)))
702  {
703  }
704 
705  explicit StaticVectorCasted(size_type count)
706  : Base(count)
707  {
708  }
709 
710  template <typename TIter>
711  StaticVectorCasted(TIter from, TIter to)
712  : Base(from, to)
713  {
714  }
715 
716  template <std::size_t TOtherSize>
717  StaticVectorCasted(const StaticVectorCasted<TOrig, TCast, TOtherSize>& other)
718  : Base(other)
719  {
720  }
721 
722  StaticVectorCasted(const StaticVectorCasted& other)
723  : Base(other)
724  {
725  }
726 
727  StaticVectorCasted(std::initializer_list<value_type> init)
728  : Base(init.begin(), init.end())
729  {
730  }
731 
732  ~StaticVectorCasted() noexcept = default;
733 
734  StaticVectorCasted& operator=(const StaticVectorCasted&) = default;
735 
736  template <std::size_t TOtherSize>
737  StaticVectorCasted& operator=(const StaticVectorCasted<TOrig, TCast, TOtherSize>& other)
738  {
739  Base::operator=(other);
740  return *this;
741  }
742 
743  StaticVectorCasted& operator=(std::initializer_list<value_type> init)
744  {
745  Base::operator=(init);
746  return *this;
747  }
748 
749  void assign(size_type count, const_reference& value)
750  {
751  Base::assign(count, value);
752  }
753 
754  template <typename TIter>
755  void assign(TIter from, TIter to)
756  {
757  Base::assign(from, to);
758  }
759 
760  void assign(std::initializer_list<value_type> init)
761  {
762  assign(init.begin(), init.end());
763  }
764 
765  reference at(size_type pos)
766  {
767  return *(reinterpret_cast<pointer>(&(Base::at(pos))));
768  }
769 
770  const_reference at(size_type pos) const
771  {
772  return *(reinterpret_cast<const_pointer>(&(Base::at(pos))));
773  }
774 
775  reference operator[](size_type pos)
776  {
777  return *(reinterpret_cast<pointer>(&(Base::operator[](pos))));
778  }
779 
780  const_reference operator[](size_type pos) const
781  {
782  return *(reinterpret_cast<const_pointer>(&(Base::operator[](pos))));
783  }
784 
785  reference front()
786  {
787  return *(reinterpret_cast<pointer>(&(Base::front())));
788  }
789 
790  const_reference front() const
791  {
792  return *(reinterpret_cast<const_pointer>(&(Base::front())));
793  }
794 
795  reference back()
796  {
797  return *(reinterpret_cast<pointer>(&(Base::back())));
798  }
799 
800  const_reference back() const
801  {
802  return *(reinterpret_cast<const_pointer>(&(Base::back())));
803  }
804 
805  pointer data()
806  {
807  return reinterpret_cast<pointer>(Base::data());
808  }
809 
810  const_pointer data() const
811  {
812  return reinterpret_cast<const_pointer>(Base::data());
813  }
814 
815  iterator begin()
816  {
817  return reinterpret_cast<iterator>(Base::begin());
818  }
819 
820  const_iterator begin() const
821  {
822  return cbegin();
823  }
824 
825  const_iterator cbegin() const
826  {
827  return reinterpret_cast<const_iterator>(Base::cbegin());
828  }
829 
830  iterator end()
831  {
832  return reinterpret_cast<iterator>(Base::end());
833  }
834 
835  const_iterator end() const
836  {
837  return cend();
838  }
839 
840  const_iterator cend() const
841  {
842  return reinterpret_cast<const_iterator>(Base::cend());
843  }
844 
845  iterator insert(const_iterator iter, const_reference value)
846  {
847  return
848  reinterpret_cast<iterator>(
849  Base::insert(
850  reinterpret_cast<typename Base::const_iterator>(iter),
851  *(reinterpret_cast<typename Base::const_pointer>(&value))));
852  }
853 
854  iterator insert(const_iterator iter, TCast&& value)
855  {
856  return
857  reinterpret_cast<iterator>(
858  Base::insert(
859  reinterpret_cast<typename Base::const_iterator>(iter),
860  std::move(*(reinterpret_cast<typename Base::pointer>(&value)))));
861  }
862 
863  iterator insert(const_iterator iter, size_type count, const_reference value)
864  {
865  return
866  reinterpret_cast<iterator>(
867  Base::insert(
868  reinterpret_cast<typename Base::const_iterator>(iter),
869  count,
870  *(reinterpret_cast<typename Base::const_pointer>(&value))));
871  }
872 
873  template <typename TIter>
874  iterator insert(const_iterator iter, TIter from, TIter to)
875  {
876  return
877  reinterpret_cast<iterator>(
878  Base::insert(
879  reinterpret_cast<typename Base::const_iterator>(iter),
880  from,
881  to));
882  }
883 
884  iterator insert(const_iterator iter, std::initializer_list<value_type> init)
885  {
886  return
887  reinterpret_cast<iterator>(
888  Base::insert(
889  reinterpret_cast<typename Base::const_iterator>(iter),
890  init.begin(),
891  init.end()));
892  }
893 
894  template <typename... TArgs>
895  iterator emplace(const_iterator iter, TArgs&&... args)
896  {
897  return
898  reinterpret_cast<iterator>(
899  Base::emplace(
900  reinterpret_cast<typename Base::const_iterator>(iter),
901  std::forward<TArgs>(args)...));
902  }
903 
904  iterator erase(const_iterator iter)
905  {
906  return erase(iter, iter + 1);
907  }
908 
911  iterator erase(const_iterator from, const_iterator to)
912  {
913  return
914  reinterpret_cast<iterator>(
915  Base::erase(
916  reinterpret_cast<typename Base::const_iterator>(from),
917  reinterpret_cast<typename Base::const_iterator>(to)));
918  }
919 
920  void push_back(const_reference value)
921  {
922  Base::push_back(*(reinterpret_cast<typename Base::const_pointer>(&value)));
923  }
924 
925  void push_back(TCast&& value)
926  {
927  Base::push_back(std::move(*(reinterpret_cast<TCast*>(&value))));
928  }
929 };
930 
931 template <bool TSignedIntegral>
932 struct StaticVectorBaseSignedIntegral;
933 
934 template <>
935 struct StaticVectorBaseSignedIntegral<true>
936 {
937  template <typename T, std::size_t TSize>
938  using Type = StaticVectorCasted<T, typename std::make_unsigned<T>::type, TSize>;
939 };
940 
941 template <>
942 struct StaticVectorBaseSignedIntegral<false>
943 {
944  template <typename T, std::size_t TSize>
945  using Type = StaticVectorGeneric<T, TSize>;
946 };
947 
948 template <typename T, std::size_t TSize>
949 using ChooseStaticVectorBase =
950  typename StaticVectorBaseSignedIntegral<std::is_integral<T>::value && std::is_signed<T>::value>::template Type<T, TSize>;
951 
952 } // namespace details
953 
963 template <typename T, std::size_t TSize>
964 class StaticVector : public details::ChooseStaticVectorBase<T, TSize>
965 {
966  using Base = details::ChooseStaticVectorBase<T, TSize>;
967  using ElementType = typename Base::ElementType;
968 
969  static_assert(sizeof(T) == sizeof(ElementType),
970  "Sizes are not equal as expected.");
971 
972  template <typename U, std::size_t TOtherSize>
973  friend class StaticVector;
974 
975 public:
977  using value_type = typename Base::value_type;
978 
980  using size_type = typename Base::size_type;
981 
983  using difference_type = typename Base::StorageType::difference_type;
984 
986  using reference = typename Base::reference;
987 
989  using const_reference = typename Base::const_reference;
990 
992  using pointer = typename Base::pointer;
993 
995  using const_pointer = typename Base::const_pointer;
996 
998  using iterator = typename Base::iterator;
999 
1001  using const_iterator = typename Base::const_iterator;
1002 
1004  using reverse_iterator = typename Base::reverse_iterator;
1005 
1007  using const_reverse_iterator = typename Base::const_reverse_iterator;
1008 
1010  StaticVector() = default;
1011 
1014  StaticVector(size_type count, const T& value)
1015  : Base(count, value)
1016  {
1017  }
1018 
1021  explicit StaticVector(size_type count)
1022  : Base(count)
1023  {
1024  }
1025 
1028  template <typename TIter>
1029  StaticVector(TIter from, TIter to)
1030  : Base(from, to)
1031  {
1032  }
1033 
1036  template <std::size_t TOtherSize>
1038  : Base(other)
1039  {
1040  }
1041 
1045  : Base(other)
1046  {
1047  }
1048 
1051  StaticVector(std::initializer_list<value_type> init)
1052  : Base(init)
1053  {
1054  }
1055 
1057  ~StaticVector() noexcept = default;
1058 
1061  StaticVector& operator=(const StaticVector&) = default;
1062 
1065  template <std::size_t TOtherSize>
1066  StaticVector& operator=(const StaticVector<T, TOtherSize>& other)
1067  {
1068  Base::operator=(other);
1069  return *this;
1070  }
1071 
1074  StaticVector& operator=(std::initializer_list<value_type> init)
1075  {
1076  Base::operator=(init);
1077  return *this;
1078  }
1079 
1082  void assign(size_type count, const T& value)
1083  {
1084  Base::assign(count, value);
1085  }
1086 
1089  template <typename TIter>
1090  void assign(TIter from, TIter to)
1091  {
1092  Base::assign(from, to);
1093  }
1094 
1097  void assign(std::initializer_list<value_type> init)
1098  {
1099  assign(init.begin(), init.end());
1100  }
1101 
1109  {
1110  return Base::at(pos);
1111  }
1119  {
1120  return Base::at(pos);
1121  }
1122 
1126  {
1127  return Base::operator[](pos);
1128  }
1129 
1133  {
1134  return Base::operator[](pos);
1135  }
1136 
1141  {
1142  return Base::front();
1143  }
1144 
1149  {
1150  return Base::front();
1151  }
1152 
1157  {
1158  return Base::back();
1159  }
1160 
1165  {
1166  return Base::back();
1167  }
1168 
1172  {
1173  return Base::data();
1174  }
1175 
1179  {
1180  return Base::data();
1181  }
1182 
1186  {
1187  return Base::begin();
1188  }
1189 
1193  {
1194  return cbegin();
1195  }
1196 
1200  {
1201  return Base::cbegin();
1202  }
1203 
1207  {
1208  return Base::end();
1209  }
1210 
1214  {
1215  return cend();
1216  }
1217 
1221  {
1222  return Base::cend();
1223  }
1224 
1228  {
1229  return reverse_iterator(end());
1230  }
1231 
1235  {
1236  return crbegin();
1237  }
1238 
1242  {
1243  return const_reverse_iterator(cend());
1244  }
1245 
1249  {
1250  return reverse_iterator(begin());
1251  }
1252 
1256  {
1257  return crend();
1258  }
1259 
1263  {
1264  return const_reverse_iterator(cbegin());
1265  }
1266 
1269  bool empty() const
1270  {
1271  return Base::empty();
1272  }
1273 
1276  size_type size() const
1277  {
1278  return Base::size();
1279  }
1280 
1286  {
1287  return capacity();
1288  }
1289 
1293  void reserve(size_type new_cap)
1294  {
1295  return Base::reserve(new_cap);
1296  }
1297 
1303  {
1304  return Base::capacity();
1305  }
1306 
1311  {
1312  }
1313 
1316  void clear()
1317  {
1318  Base::clear();
1319  }
1320 
1323  iterator insert(const_iterator iter, const T& value)
1324  {
1325  return Base::insert(iter, value);
1326  }
1327 
1330  iterator insert(const_iterator iter, T&& value)
1331  {
1332  return Base::insert(iter, std::move(value));
1333  }
1334 
1337  iterator insert(const_iterator iter, size_type count, const T& value)
1338  {
1339  return Base::insert(iter, count, value);
1340  }
1341 
1344  template <typename TIter>
1345  iterator insert(const_iterator iter, TIter from, TIter to)
1346  {
1347  return Base::insert(iter, from, to);
1348  }
1349 
1352  iterator insert(const_iterator iter, std::initializer_list<value_type> init)
1353  {
1354  return Base::insert(iter, init.begin(), init.end());
1355  }
1356 
1359  template <typename... TArgs>
1360  iterator emplace(const_iterator iter, TArgs&&... args)
1361  {
1362  return Base::emplace(iter, std::forward<TArgs>(args)...);
1363  }
1364 
1368  {
1369  return erase(iter, iter + 1);
1370  }
1371 
1375  {
1376  return Base::erase(from, to);
1377  }
1378 
1382  void push_back(const T& value)
1383  {
1384  Base::push_back(value);
1385  }
1386 
1390  void push_back(T&& value)
1391  {
1392  Base::push_back(std::move(value));
1393  }
1394 
1398  template <typename... TArgs>
1399  void emplace_back(TArgs&&... args)
1400  {
1401  Base::emplace_back(std::forward<TArgs>(args)...);
1402  }
1403 
1407  void pop_back()
1408  {
1409  Base::pop_back();
1410  }
1411 
1415  void resize(size_type count)
1416  {
1417  resize(count, T());
1418  }
1419 
1423  void resize(size_type count, const value_type& value)
1424  {
1425  Base::resize(count, value);
1426  }
1427 
1431  template <std::size_t TOtherSize>
1433  {
1434  Base::swap(other);
1435  }
1436 };
1437 
1438 // Template specialization for zero sized vectors
1439 template <typename T>
1440 class StaticVector<T, 0U>
1441 {
1442  using StorageType = std::array<T, 0U>;
1443 
1444  template <typename U, std::size_t TOtherSize>
1445  friend class StaticVector;
1446 
1447 public:
1448  using value_type = typename StorageType::value_type;
1449  using size_type = typename StorageType::size_type;
1450  using difference_type = typename StorageType::difference_type;
1451  using reference = typename StorageType::reference;
1452  using const_reference = typename StorageType::const_reference;
1453  using pointer = typename StorageType::pointer;
1454  using const_pointer = typename StorageType::const_pointer;
1455  using iterator = typename StorageType::iterator;
1456  using const_iterator = typename StorageType::const_iterator;
1457  using reverse_iterator = typename StorageType::reverse_iterator;
1458  using const_reverse_iterator = typename StorageType::const_reverse_iterator;
1459 
1460  StaticVector() = default;
1461 
1462  StaticVector(size_type count, const T& value)
1463  {
1464  static_cast<void>(value);
1465  if (count == 0U) {
1466  return;
1467  }
1468 
1469  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1470  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1471  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1472  }
1473 
1474  explicit StaticVector(size_type count)
1475  {
1476  if (count == 0U) {
1477  return;
1478  }
1479 
1480  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1481  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1482  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1483  }
1484 
1485  template <typename TIter>
1486  StaticVector(TIter from, TIter to)
1487  {
1488  if (from == to) {
1489  return;
1490  }
1491 
1492  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1493  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1494  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1495  }
1496 
1497  template <std::size_t TOtherSize>
1498  StaticVector(const StaticVector<T, TOtherSize>& other)
1499  {
1500  static_cast<void>(other);
1501  if (TOtherSize == 0U) {
1502  return;
1503  }
1504 
1505  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1506  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1507  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1508  }
1509 
1510  StaticVector(const StaticVector& other)
1511  {
1512  static_cast<void>(other);
1513  }
1514 
1515  StaticVector(std::initializer_list<value_type> init)
1516  {
1517  if (std::begin(init) == std::end(init)) {
1518  return;
1519  }
1520 
1521  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1522  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1523  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1524  }
1525 
1526  ~StaticVector() noexcept = default;
1527 
1528  StaticVector& operator=(const StaticVector&) = default;
1529 
1530  template <std::size_t TOtherSize>
1531  StaticVector& operator=(const StaticVector<T, TOtherSize>& other)
1532  {
1533  static_cast<void>(other);
1534  if (TOtherSize == 0U) {
1535  return *this;
1536  }
1537 
1538  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1539  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1540  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1541  return *this;
1542  }
1543 
1544  StaticVector& operator=(std::initializer_list<value_type> init)
1545  {
1546  if (std::begin(init) == std::end(init)) {
1547  return *this;
1548  }
1549 
1550  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1551  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1552  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1553  return *this;
1554  }
1555 
1556  void assign(size_type count, const T& value)
1557  {
1558  static_cast<void>(value);
1559  if (count == 0U) {
1560  return;
1561  }
1562 
1563  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1564  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1565  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1566  }
1567 
1568  template <typename TIter>
1569  void assign(TIter from, TIter to)
1570  {
1571  if (from == to) {
1572  return;
1573  }
1574 
1575  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1576  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1577  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1578  }
1579 
1580  void assign(std::initializer_list<value_type> init)
1581  {
1582  if (std::begin(init) == std::end(init)) {
1583  return;
1584  }
1585 
1586  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1587  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1588  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1589  }
1590 
1591  reference at(size_type pos)
1592  {
1593  static_cast<void>(pos);
1594  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1595  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1596  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1597  return m_data[pos];
1598  }
1599 
1600  const_reference at(size_type pos) const
1601  {
1602  static_cast<void>(pos);
1603  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1604  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1605  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1606  return m_data[pos];
1607  }
1608 
1609  reference operator[](size_type pos)
1610  {
1611  static_cast<void>(pos);
1612  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1613  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1614  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1615  return m_data[pos];
1616  }
1617 
1618  const_reference operator[](size_type pos) const
1619  {
1620  static_cast<void>(pos);
1621  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1622  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1623  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1624  return m_data[pos];
1625  }
1626 
1627  reference front()
1628  {
1629  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1630  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1631  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1632  return m_data.front();
1633  }
1634 
1635  const_reference front() const
1636  {
1637  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1638  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1639  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1640  return m_data.front();
1641  }
1642 
1643  reference back()
1644  {
1645  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1646  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1647  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1648  return m_data.back();
1649  }
1650 
1651  const_reference back() const
1652  {
1653  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1654  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1655  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1656  return m_data.back();
1657  }
1658 
1659  pointer data()
1660  {
1661  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1662  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1663  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1664  return m_data.data();
1665  }
1666 
1667  const_pointer data() const
1668  {
1669  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1670  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1671  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1672  return m_data.data();
1673  }
1674 
1675  iterator begin()
1676  {
1677  return m_data.begin();
1678  }
1679 
1680  const_iterator begin() const
1681  {
1682  return m_data.begin();
1683  }
1684 
1685  const_iterator cbegin() const
1686  {
1687  return m_data.cbegin();
1688  }
1689 
1690  iterator end()
1691  {
1692  return m_data.end();
1693  }
1694 
1695  const_iterator end() const
1696  {
1697  return m_data.end();
1698  }
1699 
1700  const_iterator cend() const
1701  {
1702  return m_data.cend();
1703  }
1704 
1705  reverse_iterator rbegin()
1706  {
1707  return m_data.rbegin();
1708  }
1709 
1710  const_reverse_iterator rbegin() const
1711  {
1712  return m_data.rbegin();
1713  }
1714 
1715  const_reverse_iterator crbegin() const
1716  {
1717  return m_data.crbegin();
1718  }
1719 
1720  reverse_iterator rend()
1721  {
1722  return m_data.rend();
1723  }
1724 
1725  const_reverse_iterator rend() const
1726  {
1727  return m_data.rend();
1728  }
1729 
1730  const_reverse_iterator crend() const
1731  {
1732  return m_data.crend();
1733  }
1734 
1735  bool empty() const
1736  {
1737  return m_data.empty();
1738  }
1739 
1740  size_type size() const
1741  {
1742  return m_data.size();
1743  }
1744 
1745  size_type max_size() const
1746  {
1747  return m_data.max_size();
1748  }
1749 
1750  void reserve(size_type new_cap)
1751  {
1752  static_cast<void>(new_cap);
1753  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1754  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1755  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1756  }
1757 
1758  size_type capacity() const
1759  {
1760  return max_size();
1761  }
1762 
1763  void shrink_to_fit()
1764  {
1765  }
1766 
1767  void clear()
1768  {
1769  }
1770 
1771  iterator insert(const_iterator iter, const T& value)
1772  {
1773  static_cast<void>(iter);
1774  static_cast<void>(value);
1775  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1776  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1777  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1778  return m_data.end();
1779  }
1780 
1781  iterator insert(const_iterator iter, T&& value)
1782  {
1783  static_cast<void>(iter);
1784  static_cast<void>(value);
1785  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1786  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1787  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1788  return m_data.end();
1789  }
1790 
1791  iterator insert(const_iterator iter, size_type count, const T& value)
1792  {
1793  static_cast<void>(iter);
1794  static_cast<void>(count);
1795  static_cast<void>(value);
1796  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1797  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1798  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1799  return m_data.end();
1800  }
1801 
1802  template <typename TIter>
1803  iterator insert(const_iterator iter, TIter from, TIter to)
1804  {
1805  static_cast<void>(iter);
1806  static_cast<void>(from);
1807  static_cast<void>(to);
1808  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1809  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1810  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1811  return m_data.end();
1812  }
1813 
1814  iterator insert(const_iterator iter, std::initializer_list<value_type> init)
1815  {
1816  static_cast<void>(iter);
1817  static_cast<void>(init);
1818  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1819  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1820  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1821  return m_data.end();
1822  }
1823 
1824  template <typename... TArgs>
1825  iterator emplace(const_iterator iter, TArgs&&...)
1826  {
1827  static_cast<void>(iter);
1828  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1829  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1830  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1831  return m_data.end();
1832  }
1833 
1834  iterator erase(const_iterator iter)
1835  {
1836  static_cast<void>(iter);
1837  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1838  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1839  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1840  return m_data.end();
1841  }
1842 
1843  iterator erase(const_iterator from, const_iterator to)
1844  {
1845  if (from != to) {
1846  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1847  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1848  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1849  }
1850  return m_data.end();
1851  }
1852 
1853  void push_back(const T& value)
1854  {
1855  static_cast<void>(value);
1856  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1857  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1858  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1859  }
1860 
1861  void push_back(T&& value)
1862  {
1863  static_cast<void>(value);
1864  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1865  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1866  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1867  }
1868 
1869  template <typename... TArgs>
1870  void emplace_back(TArgs&&...)
1871  {
1872  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1873  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1874  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1875  }
1876 
1877  void pop_back()
1878  {
1879  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1880  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1881  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1882  }
1883 
1884  void resize(size_type count)
1885  {
1886  if (count == 0U) {
1887  return;
1888  }
1889 
1890  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1891  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1892  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1893  }
1894 
1895  void resize(size_type count, const value_type& value)
1896  {
1897  static_cast<void>(value);
1898  if (count == 0U) {
1899  return;
1900  }
1901 
1902  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1903  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1904  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1905  }
1906 
1907  template <std::size_t TOtherSize>
1908  void swap(StaticVector<T, TOtherSize>& other)
1909  {
1910  static_cast<void>(other);
1911  if (TOtherSize != 0U) {
1912  static constexpr bool Must_not_be_called_for_zero_sized_vector = false;
1913  static_cast<void>(Must_not_be_called_for_zero_sized_vector);
1914  COMMS_ASSERT(Must_not_be_called_for_zero_sized_vector);
1915  }
1916  }
1917 
1918 private:
1919  StorageType m_data;
1920 };
1921 
1925 template <typename T, std::size_t TSize1, std::size_t TSize2>
1927 {
1928  return std::lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end());
1929 }
1930 
1934 template <typename T, std::size_t TSize1, std::size_t TSize2>
1936 {
1937  return !(v2 < v1);
1938 }
1939 
1943 template <typename T, std::size_t TSize1, std::size_t TSize2>
1945 {
1946  return v2 < v1;
1947 }
1948 
1952 template <typename T, std::size_t TSize1, std::size_t TSize2>
1954 {
1955  return !(v1 < v2);
1956 }
1957 
1961 template <typename T, std::size_t TSize1, std::size_t TSize2>
1963 {
1964  return (v1.size() == v2.size()) &&
1965  (!(v1 < v2)) &&
1966  (!(v2 < v1));
1967 }
1968 
1972 template <typename T, std::size_t TSize1, std::size_t TSize2>
1974 {
1975  return !(v1 == v2);
1976 }
1977 
1978 namespace details
1979 {
1980 
1981 
1982 template <typename T>
1983 struct IsStaticVector
1984 {
1985  static const bool Value = false;
1986 };
1987 
1988 template <typename T, std::size_t TSize>
1989 struct IsStaticVector<comms::util::StaticVector<T, TSize> >
1990 {
1991  static const bool Value = true;
1992 };
1993 
1994 } // namespace details
1995 
1999 template <typename T>
2000 static constexpr bool isStaticVector()
2001 {
2002  return details::IsStaticVector<T>::Value;
2003 }
2004 
2005 } // namespace util
2006 
2007 } // namespace comms
2008 
2009 namespace std
2010 {
2011 
2015 template <typename T, std::size_t TSize1, std::size_t TSize2>
2017 {
2018  v1.swap(v2);
2019 }
2020 
2021 }
2022 
2023 COMMS_GNU_WARNING_POP
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition: Assert.h:170
Contains various compiler related definitions.
Replacement to std::vector when no dynamic memory allocation is allowed.
Definition: StaticVector.h:965
const_iterator cend() const
Returns an iterator to the end.
Definition: StaticVector.h:1220
void assign(std::initializer_list< value_type > init)
Assigns values to the container.
Definition: StaticVector.h:1097
reference at(size_type pos)
Access specified element with bounds checking.
Definition: StaticVector.h:1108
size_type max_size() const
Returns the maximum possible number of elements.
Definition: StaticVector.h:1285
typename Base::const_reference const_reference
Const reference to single element.
Definition: StaticVector.h:989
void assign(size_type count, const T &value)
Assigns values to the container.
Definition: StaticVector.h:1082
void resize(size_type count)
Changes the number of elements stored.
Definition: StaticVector.h:1415
const_reverse_iterator rbegin() const
Returns a reverse iterator to the beginning.
Definition: StaticVector.h:1234
iterator begin()
Returns an iterator to the beginning.
Definition: StaticVector.h:1185
static constexpr bool isStaticVector()
Compile time check whether the provided type is a variant of comms::util::StaticVector.
Definition: StaticVector.h:2000
void swap(StaticVector< T, TOtherSize > &other)
Swaps the contents.
Definition: StaticVector.h:1432
const_iterator begin() const
Returns an iterator to the beginning.
Definition: StaticVector.h:1192
const_reference at(size_type pos) const
Access specified element with bounds checking.
Definition: StaticVector.h:1118
StaticVector(TIter from, TIter to)
Constructor.
Definition: StaticVector.h:1029
typename Base::reference reference
Reference to single element.
Definition: StaticVector.h:986
StaticVector(const StaticVector< T, TOtherSize > &other)
Copy constructor.
Definition: StaticVector.h:1037
bool operator!=(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition: StaticVector.h:1973
StaticVector(size_type count)
Constructor.
Definition: StaticVector.h:1021
StaticVector(const StaticVector &other)
Copy constructor.
Definition: StaticVector.h:1044
iterator insert(const_iterator iter, std::initializer_list< value_type > init)
Inserts elements.
Definition: StaticVector.h:1352
const_reference operator[](size_type pos) const
Access specified element without bounds checking.
Definition: StaticVector.h:1132
size_type capacity() const
Returns the number of elements that can be held in currently allocated storage.
Definition: StaticVector.h:1302
void assign(TIter from, TIter to)
Assigns values to the container.
Definition: StaticVector.h:1090
reference front()
Access the first element.
Definition: StaticVector.h:1140
const_reference back() const
Access the last element.
Definition: StaticVector.h:1164
void clear()
Clears the contents.
Definition: StaticVector.h:1316
reference back()
Access the last element.
Definition: StaticVector.h:1156
const_reference front() const
Access the first element.
Definition: StaticVector.h:1148
bool operator<(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition: StaticVector.h:1926
bool operator<=(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition: StaticVector.h:1935
iterator insert(const_iterator iter, T &&value)
Inserts elements.
Definition: StaticVector.h:1330
const_iterator end() const
Returns an iterator to the end.
Definition: StaticVector.h:1213
typename Base::size_type size_type
Type used for size information.
Definition: StaticVector.h:980
StaticVector(std::initializer_list< value_type > init)
Constructor.
Definition: StaticVector.h:1051
StaticVector()=default
Default constructor.
StaticVector & operator=(std::initializer_list< value_type > init)
Copy assignement.
Definition: StaticVector.h:1074
StaticVector(size_type count, const T &value)
Constructor.
Definition: StaticVector.h:1014
const_reverse_iterator rend() const
Returns a reverse iterator to the end.
Definition: StaticVector.h:1255
void pop_back()
Removes the last element.
Definition: StaticVector.h:1407
void resize(size_type count, const value_type &value)
Changes the number of elements stored.
Definition: StaticVector.h:1423
void shrink_to_fit()
Reduces memory usage by freeing unused memory.
Definition: StaticVector.h:1310
typename Base::iterator iterator
Type of the iterator.
Definition: StaticVector.h:998
iterator insert(const_iterator iter, TIter from, TIter to)
Inserts elements.
Definition: StaticVector.h:1345
const_reverse_iterator crbegin() const
Returns a reverse iterator to the beginning.
Definition: StaticVector.h:1241
iterator insert(const_iterator iter, const T &value)
Inserts elements.
Definition: StaticVector.h:1323
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: StaticVector.h:1248
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: StaticVector.h:1227
typename Base::StorageType::difference_type difference_type
Type used in pointer arithmetics.
Definition: StaticVector.h:983
iterator end()
Returns an iterator to the end.
Definition: StaticVector.h:1206
bool operator>(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition: StaticVector.h:1944
void push_back(const T &value)
Adds an element to the end.
Definition: StaticVector.h:1382
typename Base::value_type value_type
Type of single element.
Definition: StaticVector.h:977
iterator erase(const_iterator from, const_iterator to)
Erases elements.
Definition: StaticVector.h:1374
void swap(comms::util::StaticVector< T, TSize1 > &v1, comms::util::StaticVector< T, TSize2 > &v2)
Specializes the std::swap algorithm.
Definition: StaticVector.h:2016
void reserve(size_type new_cap)
Reserves storage.
Definition: StaticVector.h:1293
iterator insert(const_iterator iter, size_type count, const T &value)
Inserts elements.
Definition: StaticVector.h:1337
size_type size() const
Returns the number of elements.
Definition: StaticVector.h:1276
typename Base::const_reverse_iterator const_reverse_iterator
Type of the const reverse iterator.
Definition: StaticVector.h:1007
bool operator==(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition: StaticVector.h:1962
void push_back(T &&value)
Adds an element to the end.
Definition: StaticVector.h:1390
typename Base::const_pointer const_pointer
Const pointer to single element.
Definition: StaticVector.h:995
bool operator>=(const StaticVector< T, TSize1 > &v1, const StaticVector< T, TSize2 > &v2)
Lexicographically compares the values in the vector.
Definition: StaticVector.h:1953
iterator emplace(const_iterator iter, TArgs &&... args)
Constructs elements in place.
Definition: StaticVector.h:1360
void emplace_back(TArgs &&... args)
Constructs an element in place at the end.
Definition: StaticVector.h:1399
typename Base::const_iterator const_iterator
Type of the const iterator.
Definition: StaticVector.h:1001
~StaticVector() noexcept=default
Destructor.
iterator erase(const_iterator iter)
Erases elements.
Definition: StaticVector.h:1367
bool empty() const
Checks whether the container is empty.
Definition: StaticVector.h:1269
const_pointer data() const
Direct access to the underlying array.
Definition: StaticVector.h:1178
pointer data()
Direct access to the underlying array.
Definition: StaticVector.h:1171
typename Base::reverse_iterator reverse_iterator
Type of the reverse iterator.
Definition: StaticVector.h:1004
typename Base::pointer pointer
Pointer to single element.
Definition: StaticVector.h:992
const_reverse_iterator crend() const
Returns a reverse iterator to the end.
Definition: StaticVector.h:1262
reference operator[](size_type pos)
Access specified element without bounds checking.
Definition: StaticVector.h:1125
const_iterator cbegin() const
Returns an iterator to the beginning.
Definition: StaticVector.h:1199
void assign(T &obj, TIter from, TIter to)
Assigns a new value to provided object.
Definition: assign.h:39
Main namespace for all classes / functions of COMMS library.