HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
lean_vector.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
8#pragma once
9
10#include "cast.hpp"
11#include "memory.hpp"
12#include <bit>
13#include <new>
14#include <cstddef>
15#include <memory>
16#include <algorithm>
17#include <iterator>
18
19namespace hi { inline namespace v1 {
20
25template<typename T>
27public:
28 using value_type = T;
29 using pointer = value_type *;
30 using const_pointer = value_type const *;
31 using reference = value_type&;
32 using const_reference = value_type const&;
33 using iterator = value_type *;
34 using const_iterator = value_type const *;
35 using reverse_iterator = std::reverse_iterator<iterator>;
36 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
37 using size_type = std::size_t;
38 using difference_type = std::ptrdiff_t;
39 using allocator_type = std::allocator<value_type>;
40
41 constexpr static size_t value_alignment = alignof(value_type);
42
45 constexpr allocator_type get_allocator() const noexcept
46 {
48 return allocator_type{};
49 }
50
53 constexpr lean_vector() noexcept = default;
54
58 {
59 clear();
61 }
62
71 {
72 hilet other_size = other.size();
73 hilet update = _reserve<false>(other_size);
74 std::uninitialized_copy_n(other.begin(), other_size, update.ptr);
75 _reserve_update(update, other_size);
76 }
77
86 {
87 if (other._is_short()) {
88 hilet other_size = other._short_size();
89 std::uninitialized_move_n(other.begin(), other_size, begin());
90 other._set_short_size(0);
91 _set_short_size(other_size);
92
93 } else {
94 _ptr = std::exchange(other._ptr, nullptr);
95 _end = std::exchange(other._end, nullptr);
96 _cap = std::exchange(other._cap, nullptr);
97 }
98 }
99
108 {
109 hi_return_on_self_assignment(other);
110
111 hilet other_size = other.size();
112
113 clear();
114 hilet update = _reserve<false>(other_size);
115 std::uninitialized_copy_n(other.begin(), other_size, update.ptr);
116 _reserve_update(update, other_size);
117
118 return *this;
119 }
120
130 {
131 hi_return_on_self_assignment(other);
132
133 if (not _is_short() and not other._is_short()) {
134 std::swap(_ptr, other._ptr);
135 std::swap(_end, other._end);
136 std::swap(_cap, other._cap);
137
138 } else {
139 clear();
141
142 if (other._is_short()) {
143 hilet other_size = other._short_size();
144 std::uninitialized_move_n(other.begin(), other_size, _short_data());
145 _set_short_size(other_size);
146
147 } else {
148 _ptr = std::exchange(other._ptr, nullptr);
149 _end = std::exchange(other._end, nullptr);
150 _cap = std::exchange(other._cap, nullptr);
151 }
152 }
153
154 return *this;
155 }
156
157 void swap(lean_vector& other) noexcept
158 {
159 hilet this_is_short = this->_is_short();
160 hilet other_is_short = other._is_short();
161 if (this_is_short) {
162 // By moving other to tmp, we make other short.
164 other = std::move(*this);
165 *this = std::move(tmp);
166
167 } else if (other_is_short) {
168 // By moving this to tmp, we make this short.
169 lean_vector tmp = std::move(*this);
170 *this = std::move(other);
171 other = std::move(tmp);
172
173 } else {
174 std::swap(this->_ptr, other._ptr);
175 std::swap(this->_end, other._end);
176 std::swap(this->_cap, other._cap);
177 }
178 }
179
180 explicit lean_vector(size_type count)
181 {
182 if (count <= short_capacity()) {
183 std::uninitialized_value_construct_n(_short_data(), count);
184 _set_short_size(count);
185
186 } else {
187 hilet update = _reserve<false>(count);
188 std::uninitialized_value_construct_n(update.ptr, count);
189 _reserve_update(update, count);
190 }
191 }
192
193 lean_vector(size_type count, value_type const& value)
194 {
195 if (count <= short_capacity()) {
196 std::uninitialized_fill_n(_short_data(), count, value);
197 _set_short_size(count);
198
199 } else {
200 hilet update = _reserve<false>(count);
201 std::uninitialized_fill_n(update.ptr, count, value);
202 _reserve_update(update, count);
203 }
204 }
205
211 lean_vector(std::input_iterator auto first, std::input_iterator auto last)
212 {
213 insert(_short_data(), first, last);
214 }
215
221 {
222 insert(_short_data(), list.begin(), list.end());
223 }
224
230 void assign(size_type count, value_type const& value)
231 {
232 clear();
233 insert(begin(), count, value);
234 }
235
241 void assign(std::input_iterator auto first, std::input_iterator auto last)
242 {
243 clear();
244 insert(begin(), first, last);
245 }
246
252 {
253 clear();
254 insert(begin(), list.begin(), list.end());
255 }
256
261 [[nodiscard]] pointer data() noexcept
262 {
263 if (_is_short()) {
264 if (_short_size() == 0) {
265 return nullptr;
266 } else {
267 return _short_data();
268 }
269 } else {
270 if (_ptr == _end) {
271 return nullptr;
272 } else {
273 return _long_data();
274 }
275 }
276 }
277
282 [[nodiscard]] const_pointer data() const noexcept
283 {
284 return const_cast<lean_vector *>(this)->data();
285 }
286
292 [[nodiscard]] constexpr bool empty() const noexcept
293 {
294 if (_is_short()) {
295 return _short_size() == 0;
296 } else {
297 return _ptr == _end;
298 }
299 }
300
305 [[nodiscard]] constexpr size_type size() const noexcept
306 {
307 if (_is_short()) {
308 return _short_size();
309 } else {
310 hi_axiom(_ptr <= _end);
311 return truncate<size_type>(_long_size());
312 }
313 }
314
315 [[nodiscard]] constexpr size_type max_size() const noexcept
316 {
317 auto a = get_allocator();
319 }
320
323 [[nodiscard]] constexpr size_t short_capacity() const noexcept
324 {
325 if constexpr (std::endian::native == std::endian::little) {
326 // The first alignment can not be used.
327 return (sizeof(pointer) * 3 - alignof(value_type)) / sizeof(value_type);
328 } else {
329 // The last byte can not be used to store values.
330 return (sizeof(pointer) * 3 - 1) / sizeof(value_type);
331 }
332 }
333
338 [[nodiscard]] size_t capacity() const noexcept
339 {
340 if (_is_short()) {
341 return short_capacity();
342 } else {
343 return _long_capacity();
344 }
345 }
346
353 [[nodiscard]] reference at(size_type index)
354 {
355 hilet is_short = _is_short();
356 hilet size_ = is_short ? _short_size() : _long_size();
357 if (index < size_) {
358 return _begin_data(is_short)[index];
359 } else {
360 throw std::out_of_range("lean_vector::at()");
361 }
362 }
363
370 [[nodiscard]] const_reference at(size_type index) const
371 {
372 return const_cast<lean_vector *>(this)->at(index);
373 }
374
381 [[nodiscard]] reference operator[](size_type index) noexcept
382 {
383 hi_axiom(index < size());
384 return _begin_data(_is_short())[index];
385 }
386
393 [[nodiscard]] const_reference operator[](size_type index) const noexcept
394 {
395 return const_cast<lean_vector *>(this)->operator[](index);
396 }
397
403 [[nodiscard]] reference front() noexcept
404 {
405 hi_axiom(not empty());
406 return *_begin_data(_is_short());
407 }
408
414 [[nodiscard]] const_reference front() const noexcept
415 {
416 return const_cast<lean_vector *>(this)->front();
417 }
418
424 [[nodiscard]] reference back() noexcept
425 {
426 hi_axiom(not empty());
427 return *(_end_data(_is_short()) - 1);
428 }
429
435 [[nodiscard]] const_reference back() const noexcept
436 {
437 return const_cast<lean_vector *>(this)->back();
438 }
439
444 [[nodiscard]] iterator begin() noexcept
445 {
446 return _begin_data(_is_short());
447 }
448
453 [[nodiscard]] const_iterator begin() const noexcept
454 {
455 return _begin_data(_is_short());
456 }
457
462 [[nodiscard]] const_iterator cbegin() const noexcept
463 {
464 return begin();
465 }
466
471 [[nodiscard]] iterator end() noexcept
472 {
473 return _end_data(_is_short());
474 }
475
480 [[nodiscard]] const_iterator end() const noexcept
481 {
482 return const_cast<lean_vector *>(this)->end();
483 }
484
489 [[nodiscard]] const_iterator cend() const noexcept
490 {
491 return end();
492 }
493
498 void clear() noexcept
499 {
500 hilet is_short = _is_short();
501 std::destroy(_begin_data(is_short), _end_data(is_short));
502 _set_size(0, is_short);
503 }
504
513 void reserve(size_type new_capacity)
514 {
515 hilet update = _reserve<false>(new_capacity);
516 _reserve_update(update);
517 }
518
528 {
529 if (_is_short()) {
530 return;
531 }
532
533 hilet old_ptr = _ptr;
534 hilet old_size = size();
535 hilet old_capacity = capacity();
536
537 if (old_size <= short_capacity()) {
538 _set_short_size(old_size);
539 } else {
540 auto a = get_allocator();
542 _end = _ptr + old_size;
543 _cap = _ptr + old_size;
544 }
545
546 std::uninitialized_move_n(old_ptr, old_size, begin());
547 std::destroy_n(old_ptr, old_size);
548 auto a = get_allocator();
550 }
551
561 template<typename... Args>
562 iterator emplace(const_iterator pos, Args&&...args)
563 {
564 hilet index = pos - begin();
565 hilet new_size = size() + 1;
566
567 hilet update = _reserve<true>(new_size);
568 std::construct_at(update.end, std::forward<Args>(args)...);
569 _reserve_update(update, new_size);
570
571 hilet new_pos = begin() + index;
572 std::rotate(new_pos, end() - 1, end());
573 return new_pos;
574 }
575
585 iterator insert(const_iterator pos, value_type const& value)
586 {
587 hilet index = pos - begin();
588 hilet new_size = size() + 1;
589
590 hilet update = _reserve<true>(new_size);
591 std::uninitialized_copy_n(std::addressof(value), 1, update.end);
592 _reserve_update(update, new_size);
593
594 hilet new_pos = begin() + index;
595 std::rotate(new_pos, end() - 1, end());
596 return new_pos;
597 }
598
608 iterator insert(const_iterator pos, value_type&& value)
609 {
610 hilet index = pos - begin();
611 hilet new_size = size() + 1;
612
613 hilet update = _reserve<true>(new_size);
614 std::uninitialized_move_n(std::addressof(value), 1, update.end);
615 _reserve_update(update, new_size);
616
617 hilet new_pos = begin() + index;
618 std::rotate(new_pos, end() - 1, end());
619 return new_pos;
620 }
621
632 iterator insert(const_iterator pos, size_type count, value_type const& value)
633 {
634 hilet index = pos - begin();
635 hilet new_size = size() + count;
636
637 hilet update = _reserve<true>(new_size);
638 std::uninitialized_fill_n(update.end, count, value);
639 _reserve_update(update, new_size);
640
641 hilet new_pos = begin() + index;
642 std::rotate(new_pos, end() - count, end());
643 return new_pos;
644 }
645
656 iterator insert(const_iterator pos, std::input_iterator auto first, std::input_iterator auto last)
657 {
658 if constexpr (requires { std::distance(first, last); }) {
659 hilet n = std::distance(first, last);
660
661 hilet index = pos - begin();
662 hilet new_size = size() + n;
663
664 hilet update = _reserve<true>(new_size);
665 std::uninitialized_move_n(first, n, update.end);
666 _reserve_update(update, new_size);
667
668 hilet new_pos = begin() + index;
669 std::rotate(new_pos, end() - n, end());
670 return new_pos;
671
672 } else {
673 for (auto it = first; it != last; ++it) {
674 pos = insert(pos, *it) + 1;
675 }
676 }
677 }
678
688 iterator insert(const_iterator pos, std::initializer_list<value_type> list)
689 {
690 return insert(pos, list.begin(), list.end());
691 }
692
705 iterator erase(const_iterator pos)
706 {
707 hi_axiom(pos >= begin() and pos <= end());
708 hilet new_pos = begin() + std::distance(cbegin(), pos);
709 std::move(new_pos + 1, end(), new_pos);
710
711 hilet is_short = _is_short();
712 _set_size(size() - 1, is_short);
713 std::destroy_at(_end_data(is_short));
714 return new_pos;
715 }
716
728 iterator erase(const_iterator first, const_iterator last)
729 {
730 hilet first_ = begin() + std::distance(cbegin(), first);
731 hilet last_ = begin() + std::distance(cbegin(), last);
732 hilet n = std::distance(first_, last_);
733 std::move(last_, end(), first_);
734 std::destroy(end() - n, end());
735 _set_size(size() - n, _is_short());
736 return first_;
737 }
738
746 template<typename... Args>
747 reference emplace_back(Args&&...args)
748 {
749 hilet new_size = size() + 1;
750
751 hilet update = _reserve<true>(new_size);
752 hilet obj = std::construct_at(update.end, std::forward<Args>(args)...);
753 _reserve_update(update, new_size);
754
755 return *obj;
756 }
757
762 void push_back(value_type const& value)
763 {
764 hilet new_size = size() + 1;
765
766 hilet update = _reserve<true>(new_size);
767 std::uninitialized_copy_n(std::addressof(value), 1, update.end);
768 _reserve_update(update, new_size);
769 }
770
775 void push_back(value_type&& value)
776 {
777 hilet new_size = size() + 1;
778
779 hilet update = _reserve<true>(new_size);
780 std::uninitialized_move_n(std::addressof(value), 1, update.end);
781 _reserve_update(update, new_size);
782 }
783
790 void pop_back()
791 {
792 hi_axiom(not empty());
793
794 hilet is_short = _is_short();
795 _set_size(size() - 1, is_short);
796 std::destroy_at(_end_data(is_short));
797 }
798
809 void resize(size_type new_size)
810 {
811 if (hilet old_size = size(); new_size > old_size) {
812 hilet n = new_size - old_size;
813
814 hilet update = _reserve<true>(new_size);
815 std::uninitialized_value_construct_n(update.end, n);
816 _reserve_update(update, new_size);
817
818 } else {
819 hilet is_short = _is_short();
820 hilet n = old_size - new_size;
821 std::destroy(_end_data(is_short) - n, _end_data(is_short));
822 _set_size(new_size, is_short);
823 }
824 }
825
837 void resize(size_type new_size, value_type const& value)
838 {
839 if (hilet old_size = size(); new_size > old_size) {
840 hilet n = new_size - old_size;
841
842 hilet update = _reserve<true>(new_size);
843 std::uninitialized_fill_n(update.end, n, value);
844 _reserve_update(update, new_size);
845
846 } else {
847 hilet is_short = _is_short();
848 hilet n = old_size - new_size;
849 std::destroy(end() - n, end());
850 _set_size(new_size, is_short);
851 }
852 }
853
860 friend bool operator==(lean_vector const& lhs, lean_vector const& rhs) noexcept
861 {
862 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
863 }
864
871 friend auto operator<=>(lean_vector const& lhs, lean_vector const& rhs) noexcept
872 {
873 return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
874 }
875
882 friend size_type erase(lean_vector& c, value_type const& value)
883 {
884 auto it = std::remove(c.begin(), c.end(), value);
885 auto r = std::distance(it, c.end());
886 c.erase(it, c.end());
887 return r;
888 }
889
896 template<typename Pred>
897 friend size_type erase(lean_vector& c, Pred pred)
898 {
899 auto it = std::remove(c.begin(), c.end(), pred);
900 auto r = std::distance(it, c.end());
901 c.erase(it, c.end());
902 return r;
903 }
904
905 friend void swap(lean_vector& lhs, lean_vector& rhs) noexcept
906 {
907 lhs.swap(rhs);
908 }
909
910private:
911 pointer _ptr = nullptr;
912 pointer _end = nullptr;
913 pointer _cap = nullptr;
914
915 [[nodiscard]] constexpr bool _is_short() const noexcept
916 {
917 if constexpr (std::endian::native == std::endian::little) {
918 if (_ptr == nullptr) {
919 return true;
920 } else {
921 return to_bool(to_int(_ptr) & 1);
922 }
923 } else {
924 if (_cap == nullptr) {
925 return true;
926 } else {
927 return to_bool(to_int(_cap) & 1);
928 }
929 }
930 }
931
932 [[nodiscard]] pointer _short_data() const noexcept
933 {
934 static_assert(alignof(value_type) <= alignof(pointer));
935
936 void *p = const_cast<lean_vector *>(this);
937 if constexpr (std::endian::native == std::endian::little) {
938 p = ceil(advance_bytes(p, 1), alignof(value_type));
939 }
940 return std::launder(reinterpret_cast<pointer>(p));
941 }
942
943 [[nodiscard]] pointer _long_data() const noexcept
944 {
945 return _ptr;
946 }
947
948 [[nodiscard]] constexpr size_type _short_size() const noexcept
949 {
950 if constexpr (std::endian::native == std::endian::little) {
951 if (_ptr == nullptr) {
952 return 0;
953 } else {
954 return (to_int(_ptr) >> 1) & 0x1f;
955 }
956 } else {
957 if (_cap == nullptr) {
958 return 0;
959 } else {
960 return (to_int(_cap) >> 1) & 0x1f;
961 }
962 }
963 }
964
965 [[nodiscard]] constexpr size_type _long_size() const noexcept
966 {
967 hi_axiom(_ptr <= _end);
968 return _end - _ptr;
969 }
970
971 [[nodiscard]] constexpr size_type _long_capacity() const noexcept
972 {
973 hi_axiom(_ptr <= _cap);
974 return _cap - _ptr;
975 }
976
977 void _set_short_size(size_t new_size) noexcept
978 {
979 constexpr auto mask = ~intptr_t{0xff};
980
981 new_size <<= 1;
982 new_size |= 1;
983 if constexpr (std::endian::native == std::endian::little) {
984 _ptr = to_ptr<pointer>((to_int(_ptr) & mask) | new_size);
985 } else {
986 _cap = to_ptr<pointer>((to_int(_cap) & mask) | new_size);
987 }
988 }
989
990 void _set_size(size_t new_size, bool is_short) noexcept
991 {
992 if (is_short) {
993 hi_axiom(new_size <= short_capacity());
994 _set_short_size(new_size);
995 } else {
996 _end = _ptr + new_size;
997 }
998 }
999
1000 [[nodiscard]] pointer _begin_data(bool is_short) const noexcept
1001 {
1002 if (is_short) {
1003 return _short_data();
1004 } else {
1005 return _long_data();
1006 }
1007 }
1008
1009 [[nodiscard]] pointer _end_data(bool is_short) const noexcept
1010 {
1011 if (is_short) {
1012 return _short_data() + _short_size();
1013 } else {
1014 return _end;
1015 }
1016 }
1017
1018 struct _reserve_type {
1019 pointer ptr;
1020 pointer end;
1021 pointer cap;
1022 bool resized;
1023 bool is_short;
1024 };
1025
1030 template<bool ForInsert>
1031 [[nodiscard]] _reserve_type _reserve(size_type new_capacity) const
1032 {
1033 hilet is_short = _is_short();
1034 hilet capacity = is_short ? short_capacity() : _long_capacity();
1035 if (new_capacity <= capacity) {
1036 [[likely]] return {_begin_data(is_short), _end_data(is_short), nullptr, false, is_short};
1037 }
1038
1039 if constexpr (ForInsert) {
1040 auto next_capacity = capacity + capacity / 2;
1041 if (new_capacity > next_capacity) {
1042 next_capacity = new_capacity + new_capacity / 2;
1043 }
1044 new_capacity = next_capacity;
1045 }
1046
1047 auto a = get_allocator();
1048 hilet new_ptr = std::allocator_traits<allocator_type>::allocate(a, new_capacity);
1049
1050 hilet size_ = is_short ? _short_size() : _long_size();
1051 return {new_ptr, new_ptr + size_, new_ptr + new_capacity, true, false};
1052 }
1053
1054 void _reserve_update(_reserve_type update)
1055 {
1056 if (not update.resized) {
1057 return;
1058 }
1059
1060 hilet is_short = _is_short();
1061 hilet old_size = is_short ? _short_size() : _long_size();
1062 hilet old_ptr = is_short ? _short_data() : _long_data();
1063
1064 std::uninitialized_move_n(old_ptr, old_size, update.ptr);
1065 std::destroy_n(old_ptr, old_size);
1066
1067 if (not is_short) {
1068 auto a = get_allocator();
1069 std::allocator_traits<allocator_type>::deallocate(a, _long_data(), _long_capacity());
1070 }
1071
1072 _ptr = update.ptr;
1073 _end = update.end;
1074 _cap = update.cap;
1075 }
1076
1077 void _reserve_update(_reserve_type update, size_type new_size)
1078 {
1079 _reserve_update(update);
1080 _set_size(new_size, update.is_short);
1081 }
1082};
1083
1084template<std::input_iterator It, std::input_iterator ItEnd>
1085lean_vector(It first, ItEnd last) -> lean_vector<typename std::iterator_traits<It>::value_type>;
1086
1087}} // namespace hi::v1
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
@ other
The gui_event does not have associated data.
DOXYGEN BUG.
Definition algorithm.hpp:15
void * advance_bytes(void *ptr, std::ptrdiff_t distance) noexcept
Advance a pointer by a number of bytes.
Definition memory.hpp:192
geometry/margins.hpp
Definition assert.hpp:18
Lean-vector with (SVO) short-vector-optimization.
Definition lean_vector.hpp:26
lean_vector(lean_vector const &other)
Copy-construct a vector.
Definition lean_vector.hpp:70
iterator insert(const_iterator pos, std::input_iterator auto first, std::input_iterator auto last)
Insert new items.
Definition lean_vector.hpp:656
const_reference front() const noexcept
Get a const-reference to the first item in the vector.
Definition lean_vector.hpp:414
size_t capacity() const noexcept
Get the current capacity of the vector.
Definition lean_vector.hpp:338
reference back() noexcept
Get a reference to the last item in the vector.
Definition lean_vector.hpp:424
void push_back(value_type &&value)
Move an item to the end of the vector.
Definition lean_vector.hpp:775
const_iterator end() const noexcept
Get an const-iterator beyond the last item in the vector.
Definition lean_vector.hpp:480
lean_vector & operator=(lean_vector &&other) noexcept
Move-assign a vector.
Definition lean_vector.hpp:129
void clear() noexcept
Remove all items from the vector.
Definition lean_vector.hpp:498
void push_back(value_type const &value)
Copy an item to the end of the vector.
Definition lean_vector.hpp:762
constexpr size_t short_capacity() const noexcept
The maximum number of items that can fit without allocation.
Definition lean_vector.hpp:323
lean_vector(std::initializer_list< value_type > list)
Construct a vector with the given initializer list.
Definition lean_vector.hpp:220
iterator end() noexcept
Get an iterator beyond the last item in the vector.
Definition lean_vector.hpp:471
const_iterator cend() const noexcept
Get an const-iterator beyond the last item in the vector.
Definition lean_vector.hpp:489
iterator begin() noexcept
Get an iterator to the first item in the vector.
Definition lean_vector.hpp:444
iterator insert(const_iterator pos, std::initializer_list< value_type > list)
Insert new items.
Definition lean_vector.hpp:688
iterator erase(const_iterator pos)
Erase an item at position.
Definition lean_vector.hpp:705
void resize(size_type new_size, value_type const &value)
Resize a vector.
Definition lean_vector.hpp:837
friend size_type erase(lean_vector &c, value_type const &value)
Erase items of a value from a vector.
Definition lean_vector.hpp:882
reference emplace_back(Args &&...args)
In-place construct an item at the end of the vector.
Definition lean_vector.hpp:747
const_pointer data() const noexcept
Get a const-pointer to the first item.
Definition lean_vector.hpp:282
void resize(size_type new_size)
Resize a vector.
Definition lean_vector.hpp:809
pointer data() noexcept
Get a pointer to the first item.
Definition lean_vector.hpp:261
constexpr bool empty() const noexcept
Check if the vector is empty.
Definition lean_vector.hpp:292
friend bool operator==(lean_vector const &lhs, lean_vector const &rhs) noexcept
Compare two vectors.
Definition lean_vector.hpp:860
iterator insert(const_iterator pos, value_type &&value)
Insert a new item.
Definition lean_vector.hpp:608
friend auto operator<=>(lean_vector const &lhs, lean_vector const &rhs) noexcept
Compare two vectors lexicographically.
Definition lean_vector.hpp:871
void assign(std::initializer_list< value_type > list)
Replace the data in the vector.
Definition lean_vector.hpp:251
lean_vector(lean_vector &&other) noexcept
Move-construct a vector.
Definition lean_vector.hpp:85
const_iterator begin() const noexcept
Get an const-iterator to the first item in the vector.
Definition lean_vector.hpp:453
friend size_type erase(lean_vector &c, Pred pred)
Erase items of a value from a vector.
Definition lean_vector.hpp:897
const_iterator cbegin() const noexcept
Get an const-iterator to the first item in the vector.
Definition lean_vector.hpp:462
void assign(std::input_iterator auto first, std::input_iterator auto last)
Replace the data in the vector.
Definition lean_vector.hpp:241
iterator insert(const_iterator pos, size_type count, value_type const &value)
Insert a new item.
Definition lean_vector.hpp:632
const_reference operator[](size_type index) const noexcept
Get a const-reference to an item in the vector.
Definition lean_vector.hpp:393
constexpr lean_vector() noexcept=default
Construct an empty vector.
reference at(size_type index)
Get a reference to an item in the vector.
Definition lean_vector.hpp:353
constexpr size_type size() const noexcept
Get the number of items in the vector.
Definition lean_vector.hpp:305
void shrink_to_fit()
Shrink the allocation to fit the current number of items.
Definition lean_vector.hpp:527
void pop_back()
Remove the last item from the vector.
Definition lean_vector.hpp:790
lean_vector & operator=(lean_vector const &other) noexcept
Copy-assign a vector.
Definition lean_vector.hpp:107
const_reference at(size_type index) const
Get a const-reference to an item in the vector.
Definition lean_vector.hpp:370
reference front() noexcept
Get a reference to the first item in the vector.
Definition lean_vector.hpp:403
iterator emplace(const_iterator pos, Args &&...args)
Construct in-place a new item.
Definition lean_vector.hpp:562
const_reference back() const noexcept
Get a const-reference to the last item in the vector.
Definition lean_vector.hpp:435
constexpr allocator_type get_allocator() const noexcept
The allocator_type used to allocate items.
Definition lean_vector.hpp:45
lean_vector(std::input_iterator auto first, std::input_iterator auto last)
Construct a vector with the data pointed by iterators.
Definition lean_vector.hpp:211
void assign(size_type count, value_type const &value)
Replace the data in the vector.
Definition lean_vector.hpp:230
reference operator[](size_type index) noexcept
Get a reference to an item in the vector.
Definition lean_vector.hpp:381
iterator erase(const_iterator first, const_iterator last)
Erase an items.
Definition lean_vector.hpp:728
void reserve(size_type new_capacity)
Reserve capacity for items.
Definition lean_vector.hpp:513
iterator insert(const_iterator pos, value_type const &value)
Insert a new item.
Definition lean_vector.hpp:585
T addressof(T... args)
T allocate(T... args)
T ceil(T... args)
T deallocate(T... args)
T distance(T... args)
T equal(T... args)
T max_size(T... args)
T move(T... args)
T remove(T... args)
T rotate(T... args)
T swap(T... args)
T uninitialized_copy_n(T... args)
T uninitialized_fill_n(T... args)