casacore
Loading...
Searching...
No Matches
uvector.h
Go to the documentation of this file.
1#ifndef AO_UVECTOR_H
2#define AO_UVECTOR_H
3
4#include <algorithm>
5#include <cstring>
6#include <iterator>
7#include <memory>
8#include <utility>
9#include <stdexcept>
10
18namespace ao {
19
72template<typename Tp, typename Alloc = std::allocator<Tp> >
73class uvector : private Alloc
74{
75 static_assert(std::is_standard_layout<Tp>(), "A uvector can only hold classes with standard layout");
76
77 public:
79 typedef Tp value_type;
81 typedef Alloc allocator_type;
83 typedef Tp& reference;
85 typedef const Tp& const_reference;
87 typedef Tp* pointer;
89 typedef const Tp* const_pointer;
91 typedef Tp* iterator;
93 typedef const Tp* const_iterator;
95 typedef std::reverse_iterator<iterator> reverse_iterator;
97 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
99 typedef std::ptrdiff_t difference_type;
101 typedef std::size_t size_t;
103 typedef std::size_t size_type;
104
105 private:
106#if __cplusplus > 201402L
107 typedef typename std::allocator_traits<allocator_type>::is_always_equal
109#else
110 typedef std::false_type allocator_is_always_equal;
111#endif
113
114public:
118 explicit uvector(const allocator_type& allocator = Alloc()) noexcept
119 : Alloc(allocator), _begin(nullptr), _end(nullptr), _endOfStorage(nullptr)
120 {
121 }
122
129 explicit uvector(size_t n) :
130 _begin(allocate(n)),
131 _end(_begin + n),
133 {
134 }
135
142 uvector(size_t n, const value_type& val, const allocator_type& allocator = Alloc()) :
143 Alloc(allocator),
144 _begin(allocate(n)),
145 _end(_begin + n),
147 {
148 std::uninitialized_fill_n<Tp*,size_t>(_begin, n, val);
149 }
150
156 template<class InputIterator>
157 uvector(InputIterator first, InputIterator last, const allocator_type& allocator = Alloc()) :
158 Alloc(allocator)
159 {
160 construct_from_range<InputIterator>(first, last, std::is_integral<InputIterator>());
161 }
162
169 Alloc(std::allocator_traits<Alloc>::select_on_container_copy_construction(static_cast<allocator_type>(other))),
170 _begin(allocate(other.size())),
171 _end(_begin + other.size()),
173 {
174 std::copy(other._begin, other._end, _begin);
175 }
176
181 uvector(const uvector<Tp,Alloc>& other, const allocator_type& allocator) :
182 Alloc(allocator),
183 _begin(allocate(other.size())),
184 _end(_begin + other.size()),
186 {
187 std::copy(other._begin, other._end, _begin);
188 }
189
193 uvector(uvector<Tp,Alloc>&& other) noexcept :
194 Alloc(std::move(other)),
195 _begin(other._begin),
196 _end(other._end),
197 _endOfStorage(other._endOfStorage)
198 {
199 other._begin = nullptr;
200 other._end = nullptr;
201 other._endOfStorage = nullptr;
202 }
203
208 uvector(uvector<Tp,Alloc>&& other, const allocator_type& allocator) noexcept :
209 Alloc(allocator),
210 _begin(other._begin),
211 _end(other._end),
212 _endOfStorage(other._endOfStorage)
213 {
214 other._begin = nullptr;
215 other._end = nullptr;
216 other._endOfStorage = nullptr;
217 }
218
223 uvector(std::initializer_list<Tp> initlist, const allocator_type& allocator = Alloc()) :
224 Alloc(allocator),
225 _begin(allocate(initlist.size())),
226 _end(_begin + initlist.size()),
228 {
229 iterator destIter = _begin;
230 for(typename std::initializer_list<Tp>::const_iterator i=initlist.begin(); i!=initlist.end(); ++i)
231 {
232 *destIter = *i;
233 ++destIter;
234 }
235 }
236
238 ~uvector() noexcept
239 {
240 deallocate();
241 }
242
248 {
249 return assign_copy_from(other, typename std::allocator_traits<Alloc>::propagate_on_container_copy_assignment());
250 }
251
257 std::allocator_traits<Alloc>::propagate_on_container_move_assignment::value||
258 allocator_is_always_equal::value)
259 {
260 return assign_move_from(std::move(other), typename std::allocator_traits<Alloc>::propagate_on_container_move_assignment());
261 }
262
264 iterator begin() noexcept { return _begin; }
265
267 const_iterator begin() const noexcept { return _begin; }
268
270 iterator end() noexcept { return _end; }
271
273 const_iterator end() const noexcept { return _end; }
274
276 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
277
280
282 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
283
286
288 const_iterator cbegin() const noexcept { return _begin; }
289
291 const_iterator cend() const noexcept { return _end; }
292
295
298
300 size_t size() const noexcept { return _end - _begin; }
301
303 size_t max_size() const noexcept { return Alloc::max_size(); }
304
314 void resize(size_t n)
315 {
316 if(capacity() < n)
317 {
318 size_t newSize = enlarge_size(n);
319 pointer newStorage = allocate(newSize);
320 std::move(_begin, _end, newStorage);
321 deallocate();
322 _begin = newStorage;
323 _endOfStorage = _begin + newSize;
324 }
325 _end = _begin + n;
326 }
327
337 void resize(size_t n, const Tp& val)
338 {
339 size_t oldSize = size();
340 if(capacity() < n)
341 {
342 pointer newStorage = allocate(n);
343 std::move(_begin, _end, newStorage);
344 deallocate();
345 _begin = newStorage;
346 _endOfStorage = _begin + n;
347 }
348 _end = _begin + n;
349 if(oldSize < n)
350 std::uninitialized_fill<Tp*,size_t>(_begin + oldSize, _end, val);
351 }
352
354 size_t capacity() const noexcept { return _endOfStorage - _begin; }
355
358 bool empty() const noexcept { return _begin == _end; }
359
369 void reserve(size_t n)
370 {
371 if(capacity() < n)
372 {
373 const size_t curSize = size();
374 pointer newStorage = allocate(n);
375 std::move(_begin, _begin + curSize, newStorage);
376 deallocate();
377 _begin = newStorage;
378 _end = newStorage + curSize;
379 _endOfStorage = _begin + n;
380 }
381 }
382
390 {
391 const size_t curSize = size();
392 if(curSize == 0)
393 {
394 deallocate();
395 _begin = nullptr;
396 _end = nullptr;
397 _endOfStorage = nullptr;
398 }
399 else if(curSize < capacity()) {
400 pointer newStorage = allocate(curSize);
401 std::move(_begin, _begin + curSize, newStorage);
402 deallocate();
403 _begin = newStorage;
404 _end = newStorage + curSize;
405 _endOfStorage = _begin + curSize;
406 }
407 }
408
410 Tp& operator[](size_t index) noexcept { return _begin[index]; }
411
413 const Tp& operator[](size_t index) const noexcept { return _begin[index]; }
414
418 Tp& at(size_t index)
419 {
420 check_bounds(index);
421 return _begin[index];
422 }
423
427 const Tp& at(size_t index) const
428 {
429 check_bounds(index);
430 return _begin[index];
431 }
432
434 Tp& front() noexcept { return *_begin; }
435
437 const Tp& front() const noexcept { return *_begin; }
438
440 Tp& back() noexcept { return *(_end - 1); }
441
443 const Tp& back() const noexcept { return *(_end - 1); }
444
446 Tp* data() noexcept { return _begin; }
447
449 const Tp* data() const noexcept { return _begin; }
450
457 template<class InputIterator>
458 void assign(InputIterator first, InputIterator last)
459 {
460 assign_from_range<InputIterator>(first, last, std::is_integral<InputIterator>());
461 }
462
468 void assign(size_t n, const Tp& val)
469 {
470 if(n > capacity())
471 {
472 iterator newStorage = allocate(n);
473 deallocate();
474 _begin = newStorage;
475 _endOfStorage = _begin + n;
476 }
477 _end = _begin + n;
478 std::uninitialized_fill_n<Tp*,size_t>(_begin, n, val);
479 }
480
486 void assign(std::initializer_list<Tp> initlist)
487 {
488 if(initlist.size() > capacity())
489 {
490 iterator newStorage = allocate(initlist.size());
491 deallocate();
492 _begin = newStorage;
493 _endOfStorage = _begin + initlist.size();
494 }
495 _end = _begin + initlist.size();
496 iterator destIter = _begin;
497 for(typename std::initializer_list<Tp>::const_iterator i=initlist.begin(); i!=initlist.end(); ++i)
498 {
499 *destIter = *i;
500 ++destIter;
501 }
502 }
503
508 void push_back(const Tp& item)
509 {
510 if(_end == _endOfStorage)
512 *_end = item;
513 ++_end;
514 }
515
523 void push_back(Tp&& item)
524 {
525 if(_end == _endOfStorage)
527 *_end = std::move(item);
528 ++_end;
529 }
530
532 void pop_back()
533 {
534 --_end;
535 }
536
545 iterator insert(const_iterator position, const Tp& item)
546 {
547 if(_end == _endOfStorage)
548 {
549 size_t index = position - _begin;
550 enlarge_for_insert(enlarge_size(1), index, 1);
551 position = _begin + index;
552 }
553 else {
554 std::move_backward(const_cast<iterator>(position), _end, _end+1);
555 ++_end;
556 }
557 *const_cast<iterator>(position) = item;
558 return const_cast<iterator>(position);
559 }
560
570 iterator insert(const_iterator position, size_t n, const Tp& val)
571 {
572 if(capacity() < size() + n)
573 {
574 size_t index = position - _begin;
575 enlarge_for_insert(enlarge_size(n), index, n);
576 position = _begin + index;
577 }
578 else {
579 std::move_backward(const_cast<iterator>(position), _end, _end+n);
580 _end += n;
581 }
582 std::uninitialized_fill_n<Tp*,size_t>(const_cast<iterator>(position), n, val);
583 return const_cast<iterator>(position);
584 }
585
595 template <class InputIterator>
596 iterator insert(const_iterator position, InputIterator first, InputIterator last)
597 {
598 return insert_from_range<InputIterator>(position, first, last, std::is_integral<InputIterator>());
599 }
600
613 iterator insert(const_iterator position, Tp&& item)
614 {
615 if(_end == _endOfStorage)
616 {
617 size_t index = position - _begin;
618 enlarge_for_insert(enlarge_size(1), index, 1);
619 position = _begin + index;
620 }
621 else {
622 std::move_backward(const_cast<iterator>(position), _end, _end+1);
623 ++_end;
624 }
625 *const_cast<iterator>(position) = std::move(item);
626 return const_cast<iterator>(position);
627 }
628
637 iterator insert(const_iterator position, std::initializer_list<Tp> initlist)
638 {
639 if(capacity() < size() + initlist.size())
640 {
641 size_t index = position - _begin;
642 enlarge_for_insert(enlarge_size(initlist.size()), index, initlist.size());
643 position = _begin + index;
644 }
645 else {
646 std::move_backward(const_cast<iterator>(position), _end, _end+initlist.size());
647 _end += initlist.size();
648 }
649 iterator destIter = const_cast<iterator>(position);
650 for(typename std::initializer_list<Tp>::const_iterator i=initlist.begin(); i!=initlist.end(); ++i)
651 {
652 *destIter = *i;
653 ++destIter;
654 }
655 return const_cast<iterator>(position);
656 }
657
665 {
666 std::move(const_cast<iterator>(position)+1, _end, const_cast<iterator>(position));
667 --_end;
668 return const_cast<iterator>(position);
669 }
670
679 {
680 std::move(const_cast<iterator>(last), _end, const_cast<iterator>(first));
681 _end -= last - first;
682 return const_cast<iterator>(first);
683 }
684
696 void swap(uvector<Tp, Alloc>& other) noexcept
697 {
698 swap(other, typename std::allocator_traits<Alloc>::propagate_on_container_swap());
699 }
700
702 void clear()
703 {
704 _end = _begin;
705 }
706
715 template<typename... Args>
716 iterator emplace(const_iterator position, Args&&... args)
717 {
718 if(_end == _endOfStorage)
719 {
720 size_t index = position - _begin;
721 enlarge_for_insert(enlarge_size(1), index, 1);
722 position = _begin + index;
723 }
724 else {
725 std::move_backward(const_cast<iterator>(position), _end, _end+1);
726 ++_end;
727 }
728 *const_cast<iterator>(position) = Tp(std::forward<Args>(args)...);
729 return const_cast<iterator>(position);
730 }
731
736 template<typename... Args>
737 void emplace_back(Args&&... args)
738 {
739 if(_end == _endOfStorage)
741 *_end = Tp(std::forward<Args>(args)...);
742 ++_end;
743 }
744
747 {
748 return *this;
749 }
750
751 // --- NON STANDARD METHODS ---
752
764 {
765 if(capacity() < size() + n)
766 {
767 size_t index = position - _begin;
768 enlarge_for_insert(enlarge_size(n), index, n);
769 position = _begin + index;
770 }
771 else {
772 std::move_backward(const_cast<iterator>(position), _end, _end+n);
773 _end += n;
774 }
775 return const_cast<iterator>(position);
776 }
777
785 template <class InputIterator>
786 void push_back(InputIterator first, InputIterator last)
787 {
788 push_back_range<InputIterator>(first, last, std::is_integral<InputIterator>());
789 }
790
798 void push_back(size_t n, const Tp& val)
799 {
800 if(capacity() - size() < n)
801 {
803 }
804 std::uninitialized_fill_n<Tp*,size_t>(_end, n, val);
805 _end += n;
806 }
807
814 void push_back(std::initializer_list<Tp> initlist)
815 {
816 if(capacity() - size() < initlist.size())
817 {
818 enlarge(enlarge_size(initlist.size()));
819 }
820 for(typename std::initializer_list<Tp>::iterator i = initlist.begin(); i != initlist.end(); ++i)
821 {
822 *_end = *i;
823 ++_end;
824 }
825 }
826
834 {
835 resize(size() + n);
836 }
837
838private:
839
841 {
842 return Alloc::allocate(n);
843 }
844
845 void deallocate() noexcept
846 {
848 }
849
850 void deallocate(pointer begin, size_t n) noexcept
851 {
852 if(begin != nullptr)
853 Alloc::deallocate(begin, n);
854 }
855
856 template<typename InputIterator>
857 void construct_from_range(InputIterator first, InputIterator last, std::false_type)
858 {
859 construct_from_range<InputIterator>(first, last, typename std::iterator_traits<InputIterator>::iterator_category());
860 }
861
862 template<typename Integral>
863 void construct_from_range(Integral n, Integral val, std::true_type)
864 {
865 _begin = allocate(n);
866 _end = _begin + n;
868 std::uninitialized_fill_n<Tp*,size_t>(_begin, n, val);
869 }
870
871 template<typename InputIterator>
872 void construct_from_range(InputIterator first, InputIterator last, std::forward_iterator_tag)
873 {
874 size_t n = std::distance(first, last);
875 _begin = allocate(n);
876 _end = _begin + n;
877 _endOfStorage = _begin + n;
878 Tp* destIter = _begin;
879 while(first != last)
880 {
881 *destIter = *first;
882 ++destIter; ++first;
883 }
884 }
885
886 template<typename InputIterator>
887 void assign_from_range(InputIterator first, InputIterator last, std::false_type)
888 {
889 assign_from_range<InputIterator>(first, last, typename std::iterator_traits<InputIterator>::iterator_category());
890 }
891
892 // This function is called from assign(iter,iter) when Tp is an integral. In that case,
893 // the user tried to call assign(n, &val), but it got caught by the wrong overload.
894 template<typename Integral>
895 void assign_from_range(Integral n, Integral val, std::true_type)
896 {
897 if(size_t(n) > capacity())
898 {
899 iterator newStorage = allocate(n);
900 deallocate();
901 _begin = newStorage;
902 _endOfStorage = _begin + n;
903 }
904 _end = _begin + n;
905 std::uninitialized_fill_n<Tp*,size_t>(_begin, n, val);
906 }
907
908 template<typename InputIterator>
909 void assign_from_range(InputIterator first, InputIterator last, std::forward_iterator_tag)
910 {
911 size_t n = std::distance(first, last);
912 if(n > capacity())
913 {
914 iterator newStorage = allocate(n);
915 deallocate();
916 _begin = newStorage;
917 _endOfStorage = _begin + n;
918 }
919 _end = _begin + n;
920 Tp* destIter = _begin;
921 while(first != last)
922 {
923 *destIter = *first;
924 ++destIter; ++first;
925 }
926 }
927
928 template<typename InputIterator>
929 iterator insert_from_range(const_iterator position, InputIterator first, InputIterator last, std::false_type)
930 {
931 return insert_from_range<InputIterator>(position, first, last,
932 typename std::iterator_traits<InputIterator>::iterator_category());
933 }
934
935 template<typename Integral>
936 iterator insert_from_range(const_iterator position, Integral n, Integral val, std::true_type)
937 {
938 if(capacity() < size() + n)
939 {
940 size_t index = position - _begin;
941 enlarge_for_insert(enlarge_size(n), index, n);
942 position = _begin + index;
943 }
944 else {
945 std::move_backward(const_cast<iterator>(position), _end, _end+n);
946 _end += n;
947 }
948 std::uninitialized_fill_n<Tp*,size_t>(const_cast<iterator>(position), n, val);
949 return const_cast<iterator>(position);
950 }
951
952 template<typename InputIterator>
953 iterator insert_from_range(const_iterator position, InputIterator first, InputIterator last, std::forward_iterator_tag)
954 {
955 size_t n = std::distance(first, last);
956 if(capacity() < size() + n)
957 {
958 size_t index = position - _begin;
959 enlarge_for_insert(enlarge_size(n), index, n);
960 position = _begin + index;
961 }
962 else {
963 std::move_backward(const_cast<iterator>(position), _end, _end+n);
964 _end += n;
965 }
966 Tp* destIter = const_cast<iterator>(position);
967 while(first != last)
968 {
969 *destIter = *first;
970 ++destIter; ++first;
971 }
972 return const_cast<iterator>(position);
973 }
974
975 void check_bounds(size_t index) const
976 {
977 if(index >= size())
978 throw std::out_of_range("Access to element in uvector past end");
979 }
980
981 size_t enlarge_size(size_t extra_space_needed) const noexcept
982 {
983 return size() + std::max(size(), extra_space_needed);
984 }
985
986 void enlarge(size_t newSize)
987 {
988 pointer newStorage = allocate(newSize);
989 std::copy(_begin, _end, newStorage);
990 deallocate();
991 _end = newStorage + size();
992 _begin = newStorage;
993 _endOfStorage = _begin + newSize;
994 }
995
996 void enlarge_for_insert(size_t newSize, size_t insert_position, size_t insert_count)
997 {
998 pointer newStorage = allocate(newSize);
999 std::copy(_begin, _begin + insert_position, newStorage);
1000 std::copy(_begin + insert_position, _end, newStorage + insert_position + insert_count);
1001 deallocate();
1002 _end = newStorage + size() + insert_count;
1003 _begin = newStorage;
1004 _endOfStorage = _begin + newSize;
1005 }
1006
1007 // implementation of operator=(const&) without propagate_on_container_copy_assignment
1008 uvector& assign_copy_from(const uvector<Tp,Alloc>& other, std::false_type)
1009 {
1010 const size_t n = other.size();
1011 if(n > capacity()) {
1012 iterator newStorage = allocate(n);
1013 deallocate();
1014 _begin = newStorage;
1015 _end = _begin + n;
1017 }
1018 std::copy(other._begin, other._begin + n, _begin);
1019 return *this;
1020 }
1021
1022 // implementation of operator=(const&) with propagate_on_container_copy_assignment
1023 uvector& assign_copy_from(const uvector<Tp,Alloc>& other, std::true_type)
1024 {
1025 if(allocator_is_always_equal() || static_cast<Alloc&>(other) == static_cast<Alloc&>(*this))
1026 {
1027 assign_copy_from(other, std::false_type());
1028 }
1029 else {
1030 const size_t n = other.size();
1031 iterator newStorage = static_cast<Alloc&>(other).allocate(n);
1032 deallocate();
1033 _begin = newStorage;
1034 _end = _begin + n;
1036 std::copy(other._begin, other._begin + n, _begin);
1037 Alloc::operator=(static_cast<Alloc&>(other));
1038 }
1039 return *this;
1040 }
1041
1042 // implementation of operator=() without propagate_on_container_move_assignment
1043 uvector& assign_move_from(uvector<Tp,Alloc>&& other, std::false_type) noexcept(allocator_is_always_equal::value)
1044 {
1045 if(allocator_is_always_equal::value || static_cast<Alloc&>(other) == static_cast<Alloc&>(*this))
1046 {
1047 deallocate();
1048 _begin = other._begin;
1049 _end = other._end;
1050 _endOfStorage = other._endOfStorage;
1051 other._begin = nullptr;
1052 other._end = nullptr;
1053 other._endOfStorage = nullptr;
1054 }
1055 else {
1056 // We should not propagate the allocator and the allocators are different.
1057 // This means we can not swap the allocated space, since then we would
1058 // deallocate the space with a different allocator type. Therefore, we
1059 // need to copy:
1060 assign_copy_from(other, std::false_type());
1061 }
1062 return *this;
1063 }
1064
1065 // implementation of operator=() with propagate_on_container_move_assignment
1066 uvector& assign_move_from(uvector<Tp,Alloc>&& other, std::true_type) noexcept
1067 {
1068 deallocate();
1069 Alloc::operator=(std::move(static_cast<Alloc&>(other)));
1070 _begin = other._begin;
1071 _end = other._end;
1072 _endOfStorage = other._endOfStorage;
1073 other._begin = nullptr;
1074 other._end = nullptr;
1075 other._endOfStorage = nullptr;
1076 return *this;
1077 }
1078
1079 // implementation of swap with propagate_on_container_swap
1080 void swap(uvector<Tp,Alloc>& other, std::true_type) noexcept
1081 {
1082 std::swap(_begin, other._begin);
1083 std::swap(_end, other._end);
1084 std::swap(_endOfStorage, other._endOfStorage);
1085 std::swap(static_cast<Alloc&>(other), static_cast<Alloc&>(*this));
1086 }
1087
1088 // implementation of swap without propagate_on_container_swap
1089 void swap(uvector<Tp,Alloc>& other, std::false_type) noexcept
1090 {
1091 std::swap(_begin, other._begin);
1092 std::swap(_end, other._end);
1093 std::swap(_endOfStorage, other._endOfStorage);
1115 }
1116
1117 template<typename InputIterator>
1118 void push_back_range(InputIterator first, InputIterator last, std::false_type)
1119 {
1120 push_back_range<InputIterator>(first, last, typename std::iterator_traits<InputIterator>::iterator_category());
1121 }
1122
1123 // This function is called from push_back(iter,iter) when Tp is an integral. In that case,
1124 // the user tried to call push_back(n, &val), but it got caught by the wrong overload.
1125 template<typename Integral>
1126 void push_back_range(Integral n, Integral val, std::true_type)
1127 {
1128 if(capacity() - size() < size_t(n))
1129 {
1131 }
1132 std::uninitialized_fill_n<Tp*,size_t>(_end, n, val);
1133 _end += n;
1134 }
1135
1136 template<typename InputIterator>
1137 void push_back_range(InputIterator first, InputIterator last, std::forward_iterator_tag)
1138 {
1139 size_t n = std::distance(first, last);
1140 if(n > capacity() - size())
1141 {
1143 }
1144 while(first != last)
1145 {
1146 *_end = *first;
1147 ++_end;
1148 ++first;
1149 }
1150 }
1151
1152};
1153
1155template<class Tp, class Alloc>
1156inline bool operator==(const uvector<Tp,Alloc>& lhs, const uvector<Tp,Alloc>& rhs) noexcept
1157{
1158 return lhs.size()==rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1159}
1160
1162template<class Tp, class Alloc>
1163inline bool operator!=(const uvector<Tp,Alloc>& lhs, const uvector<Tp,Alloc>& rhs) noexcept
1164{
1165 return !(lhs == rhs);
1166}
1167
1172template <class Tp, class Alloc>
1173inline bool operator<(const uvector<Tp,Alloc>& lhs, const uvector<Tp,Alloc>& rhs) noexcept
1174{
1175 const size_t minSize = std::min(lhs.size(), rhs.size());
1176 for(size_t i=0; i!=minSize; ++i)
1177 {
1178 if(lhs[i] < rhs[i])
1179 return true;
1180 else if(lhs[i] > rhs[i])
1181 return false;
1182 }
1183 return lhs.size() < rhs.size();
1184}
1185
1190template <class Tp, class Alloc>
1191inline bool operator<=(const uvector<Tp,Alloc>& lhs, const uvector<Tp,Alloc>& rhs) noexcept
1192{
1193 const size_t minSize = std::min(lhs.size(), rhs.size());
1194 for(size_t i=0; i!=minSize; ++i)
1195 {
1196 if(lhs[i] < rhs[i])
1197 return true;
1198 else if(lhs[i] > rhs[i])
1199 return false;
1200 }
1201 return lhs.size() <= rhs.size();
1202}
1203
1208template <class Tp, class Alloc>
1209inline bool operator>(const uvector<Tp,Alloc>& lhs, const uvector<Tp,Alloc>& rhs) noexcept
1210{
1211 return rhs < lhs;
1212}
1213
1218template <class Tp, class Alloc>
1219inline bool operator>=(const uvector<Tp,Alloc>& lhs, const uvector<Tp,Alloc>& rhs) noexcept
1220{
1221 return rhs <= lhs;
1222}
1223
1234template <class Tp, class Alloc>
1236{
1237 x.swap(y);
1238}
1239
1242} // end of namespace ao
1243
1244#endif // AO_UVECTOR_H
1245
A container similar to std::vector, but one that allows construction without initializing its element...
Definition uvector.h:74
const Tp * const_iterator
Iterator type of constant elements.
Definition uvector.h:93
void assign_from_range(InputIterator first, InputIterator last, std::forward_iterator_tag)
Definition uvector.h:909
iterator insert_uninitialized(const_iterator position, size_t n)
— NON STANDARD METHODS —
Definition uvector.h:763
~uvector() noexcept
Destructor.
Definition uvector.h:238
void deallocate() noexcept
Definition uvector.h:845
Tp * data() noexcept
Get pointer to internal storage.
Definition uvector.h:446
void shrink_to_fit()
Change the capacity of the container such that no extra space is hold.
Definition uvector.h:389
uvector(const allocator_type &allocator=Alloc()) noexcept
Construct an empty uvector.
Definition uvector.h:118
void push_back_uninitialized(size_t n)
Add elements at the end without initializing them.
Definition uvector.h:833
void push_back(std::initializer_list< Tp > initlist)
Add elements from an initializer list to the end of the container.
Definition uvector.h:814
Tp & operator[](size_t index) noexcept
Get a reference to the element at the given index.
Definition uvector.h:410
void push_back_range(InputIterator first, InputIterator last, std::false_type)
Definition uvector.h:1118
const_reverse_iterator crend() const noexcept
Get constant reverse iterator to element before first element.
Definition uvector.h:297
const Tp & const_reference
Constant reference to element type.
Definition uvector.h:85
void deallocate(pointer begin, size_t n) noexcept
Definition uvector.h:850
const_reverse_iterator rbegin() const noexcept
Get constant reverse iterator to last element.
Definition uvector.h:279
const Tp * data() const noexcept
Get constant pointer to internal storage.
Definition uvector.h:449
uvector & assign_copy_from(const uvector< Tp, Alloc > &other, std::true_type)
implementation of operator=(const&) with propagate_on_container_copy_assignment
Definition uvector.h:1023
uvector(const uvector< Tp, Alloc > &other, const allocator_type &allocator)
Copy construct a uvector with custom allocator.
Definition uvector.h:181
uvector(uvector< Tp, Alloc > &&other) noexcept
Move construct a uvector.
Definition uvector.h:193
uvector & assign_move_from(uvector< Tp, Alloc > &&other, std::false_type) noexcept(allocator_is_always_equal::value)
implementation of operator=() without propagate_on_container_move_assignment
Definition uvector.h:1043
size_t capacity() const noexcept
Get the number of elements the container can currently hold without reallocating storage.
Definition uvector.h:354
pointer _endOfStorage
Definition uvector.h:112
size_t size() const noexcept
Get number of elements in container.
Definition uvector.h:300
void push_back_range(InputIterator first, InputIterator last, std::forward_iterator_tag)
Definition uvector.h:1137
Tp & at(size_t index)
Get a reference to the element at the given index with bounds checking.
Definition uvector.h:418
void construct_from_range(InputIterator first, InputIterator last, std::false_type)
Definition uvector.h:857
std::reverse_iterator< iterator > reverse_iterator
Reverse iterator type.
Definition uvector.h:95
void resize(size_t n)
Change the number of elements in the container.
Definition uvector.h:314
iterator insert_from_range(const_iterator position, InputIterator first, InputIterator last, std::forward_iterator_tag)
Definition uvector.h:953
void assign_from_range(Integral n, Integral val, std::true_type)
This function is called from assign(iter,iter) when Tp is an integral.
Definition uvector.h:895
void swap(uvector< Tp, Alloc > &other, std::false_type) noexcept
implementation of swap without propagate_on_container_swap
Definition uvector.h:1089
const_iterator cbegin() const noexcept
Get constant iterator to first element.
Definition uvector.h:288
Tp * pointer
Pointer to element type.
Definition uvector.h:87
void push_back_range(Integral n, Integral val, std::true_type)
This function is called from push_back(iter,iter) when Tp is an integral.
Definition uvector.h:1126
reverse_iterator rend() noexcept
Get reverse iterator to element before first element.
Definition uvector.h:282
void push_back(size_t n, const Tp &val)
Add elements at the end and initialize them with a value.
Definition uvector.h:798
Tp * iterator
Iterator type.
Definition uvector.h:91
uvector & operator=(uvector< Tp, Alloc > &&other) noexcept(std::allocator_traits< Alloc >::propagate_on_container_move_assignment::value||allocator_is_always_equal::value)
Assign another uvector to this uvector.
Definition uvector.h:256
void reserve(size_t n)
Reserve space for a number of elements, to prevent the overhead of extra reallocations.
Definition uvector.h:369
const_reverse_iterator rend() const noexcept
Get constant reverse iterator to element before first element.
Definition uvector.h:285
void assign(std::initializer_list< Tp > initlist)
Assign this container to an initializer list.
Definition uvector.h:486
Tp & reference
Reference to element type.
Definition uvector.h:83
Tp & back() noexcept
Get reference to last element in container.
Definition uvector.h:440
const Tp * const_pointer
Pointer to constant element type.
Definition uvector.h:89
uvector & assign_move_from(uvector< Tp, Alloc > &&other, std::true_type) noexcept
implementation of operator=() with propagate_on_container_move_assignment
Definition uvector.h:1066
Alloc allocator_type
Type of allocator used to allocate and deallocate space.
Definition uvector.h:81
void enlarge(size_t newSize)
Definition uvector.h:986
void assign(size_t n, const Tp &val)
Resize the container and assign the given value to all elements.
Definition uvector.h:468
Tp value_type
Element type.
Definition uvector.h:79
iterator begin() noexcept
Get iterator to first element.
Definition uvector.h:264
const_iterator begin() const noexcept
Get constant iterator to first element.
Definition uvector.h:267
uvector(InputIterator first, InputIterator last, const allocator_type &allocator=Alloc())
Construct a vector by copying elements from a range.
Definition uvector.h:157
iterator insert(const_iterator position, InputIterator first, InputIterator last)
Insert elements at a given position and initialize them from a range.
Definition uvector.h:596
void clear()
Remove all elements from the container.
Definition uvector.h:702
bool empty() const noexcept
Determine if the container is currently empty.
Definition uvector.h:358
iterator erase(const_iterator position)
Delete an element from the container.
Definition uvector.h:664
void resize(size_t n, const Tp &val)
Change the number of elements in the container.
Definition uvector.h:337
const_iterator cend() const noexcept
Get constant iterator to element past last element.
Definition uvector.h:291
iterator insert_from_range(const_iterator position, Integral n, Integral val, std::true_type)
Definition uvector.h:936
iterator insert(const_iterator position, std::initializer_list< Tp > initlist)
Insert elements at a given position and initialize them from a initializer list.
Definition uvector.h:637
std::false_type allocator_is_always_equal
Definition uvector.h:110
void swap(uvector< Tp, Alloc > &other, std::true_type) noexcept
implementation of swap with propagate_on_container_swap
Definition uvector.h:1080
iterator end() noexcept
Get iterator to element past last element.
Definition uvector.h:270
void emplace_back(Args &&... args)
Add the given value to the end of the container by constructing it in place.
Definition uvector.h:737
const Tp & at(size_t index) const
Get a constant reference to the element at the given index with bounds checking.
Definition uvector.h:427
const_iterator end() const noexcept
Get constant iterator to element past last element.
Definition uvector.h:273
pointer allocate(size_t n)
Definition uvector.h:840
iterator insert(const_iterator position, size_t n, const Tp &val)
Insert elements at a given position and initialize them with a value.
Definition uvector.h:570
const Tp & front() const noexcept
Get constant reference to first element in container.
Definition uvector.h:437
size_t enlarge_size(size_t extra_space_needed) const noexcept
Definition uvector.h:981
void pop_back()
Remove the last element from the container.
Definition uvector.h:532
const Tp & back() const noexcept
Get constant reference to last element in container.
Definition uvector.h:443
iterator insert(const_iterator position, Tp &&item)
Insert an element at a given position by moving it in.
Definition uvector.h:613
const Tp & operator[](size_t index) const noexcept
Get a constant reference to the element at the given index.
Definition uvector.h:413
void enlarge_for_insert(size_t newSize, size_t insert_position, size_t insert_count)
Definition uvector.h:996
uvector(const uvector< Tp, Alloc > &other)
Copy construct a uvector.
Definition uvector.h:168
void push_back(InputIterator first, InputIterator last)
Add a range of items to the end of the container.
Definition uvector.h:786
uvector & assign_copy_from(const uvector< Tp, Alloc > &other, std::false_type)
implementation of operator=(const&) without propagate_on_container_copy_assignment
Definition uvector.h:1008
reverse_iterator rbegin() noexcept
Get reverse iterator to last element.
Definition uvector.h:276
std::reverse_iterator< const_iterator > const_reverse_iterator
Reverse iterator of constant elements.
Definition uvector.h:97
uvector(std::initializer_list< Tp > initlist, const allocator_type &allocator=Alloc())
Construct a uvector from a initializer list.
Definition uvector.h:223
pointer _end
Definition uvector.h:112
void assign(InputIterator first, InputIterator last)
Assign this container to be equal to the given range.
Definition uvector.h:458
const_reverse_iterator crbegin() const noexcept
Get constant reverse iterator to last element.
Definition uvector.h:294
Tp & front() noexcept
Get reference to first element in container.
Definition uvector.h:434
void construct_from_range(Integral n, Integral val, std::true_type)
Definition uvector.h:863
uvector & operator=(const uvector< Tp, Alloc > &other)
Assign another uvector to this uvector.
Definition uvector.h:247
void assign_from_range(InputIterator first, InputIterator last, std::false_type)
Definition uvector.h:887
iterator erase(const_iterator first, const_iterator last)
Delete a range of elements from the container.
Definition uvector.h:678
void push_back(const Tp &item)
Add the given value to the end of the container.
Definition uvector.h:508
void swap(uvector< Tp, Alloc > &other) noexcept
Swap the contents of this uvector with the given uvector.
Definition uvector.h:696
std::ptrdiff_t difference_type
Difference between to iterators.
Definition uvector.h:99
void push_back(Tp &&item)
Add the given value to the end of the container by moving it in.
Definition uvector.h:523
void construct_from_range(InputIterator first, InputIterator last, std::forward_iterator_tag)
Definition uvector.h:872
uvector(size_t n)
Construct a vector with given amount of elements, without initializing these.
Definition uvector.h:129
uvector(size_t n, const value_type &val, const allocator_type &allocator=Alloc())
Construct a vector with given amount of elements and set these to a specific value.
Definition uvector.h:142
pointer _begin
Definition uvector.h:112
size_t max_size() const noexcept
Get maximum number of elements that this container can hold.
Definition uvector.h:303
allocator_type get_allocator() const noexcept
Get a copy of the allocator.
Definition uvector.h:746
iterator emplace(const_iterator position, Args &&... args)
Insert an element at a given position by constructing it in place.
Definition uvector.h:716
void check_bounds(size_t index) const
Definition uvector.h:975
std::size_t size_t
Type used for indexing elements.
Definition uvector.h:101
iterator insert(const_iterator position, const Tp &item)
Insert an element at a given position.
Definition uvector.h:545
uvector(uvector< Tp, Alloc > &&other, const allocator_type &allocator) noexcept
Move construct a uvector with custom allocator.
Definition uvector.h:208
iterator insert_from_range(const_iterator position, InputIterator first, InputIterator last, std::false_type)
Definition uvector.h:929
std::size_t size_type
Type used for indexing elements.
Definition uvector.h:103
bool operator==(const uvector< Tp, Alloc > &lhs, const uvector< Tp, Alloc > &rhs) noexcept
Compare two uvectors for equality.
Definition uvector.h:1156
void swap(uvector< Tp, Alloc > &x, uvector< Tp, Alloc > &y)
Swap the contents of the two uvectors.
Definition uvector.h:1235
bool operator!=(const uvector< Tp, Alloc > &lhs, const uvector< Tp, Alloc > &rhs) noexcept
Compare two uvectors for inequality.
Definition uvector.h:1163
struct Node * first
Definition malloc.h:328
Definition uvector.h:18
Define real & complex conjugation for non-complex types and put comparisons into std namespace.
Definition Complex.h:350