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 "../utility/utility.hpp"
11#include "../macros.hpp"
12#include <bit>
13#include <new>
14#include <cstddef>
15#include <memory>
16#include <algorithm>
17#include <iterator>
18#include <stdexcept>
19
20hi_export_module(hikogui.container.lean_vector);
21
22
23hi_warning_push();
24// C26450: You called an STL function '' with raw pointer... (stl.1)
25// Using an iterator requires a lot of code which will not make it safer.
26hi_warning_ignore_msvc(26459);
27
28hi_export namespace hi { inline namespace v1 {
29
34template<typename T>
36public:
37 using value_type = T;
38 using pointer = value_type *;
39 using const_pointer = value_type const *;
40 using reference = value_type&;
41 using const_reference = value_type const&;
42 using iterator = value_type *;
43 using const_iterator = value_type const *;
44 using reverse_iterator = std::reverse_iterator<iterator>;
45 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
46 using size_type = std::size_t;
47 using difference_type = std::ptrdiff_t;
48 using allocator_type = std::allocator<value_type>;
49
50 constexpr static size_t value_alignment = alignof(value_type);
51
59
63
67 {
68 clear();
70 }
71
80 {
81 auto const other_size = other.size();
82 auto const update = _reserve<false>(other_size);
83 std::uninitialized_copy_n(other.begin(), other_size, update.ptr);
84 _reserve_update(update, other_size);
85 }
86
94 lean_vector(lean_vector&& other) noexcept(std::is_nothrow_move_constructible_v<value_type>)
95 {
96 if (other._is_short()) {
97 auto const other_size = other._short_size();
98 std::uninitialized_move_n(other.begin(), other_size, begin());
99 other._set_short_size(0);
100 _set_short_size(other_size);
101
102 } else {
103 _ptr = std::exchange(other._ptr, nullptr);
104 _end = std::exchange(other._end, nullptr);
105 _cap = std::exchange(other._cap, nullptr);
106 }
107 }
108
117 {
118 hi_return_on_self_assignment(other);
119
120 auto const other_size = other.size();
121
122 clear();
123 auto const update = _reserve<false>(other_size);
124 std::uninitialized_copy_n(other.begin(), other_size, update.ptr);
125 _reserve_update(update, other_size);
126
127 return *this;
128 }
129
139 {
140 hi_return_on_self_assignment(other);
141
142 if (not _is_short() and not other._is_short()) {
143 std::swap(_ptr, other._ptr);
144 std::swap(_end, other._end);
145 std::swap(_cap, other._cap);
146
147 } else {
148 clear();
150
151 if (other._is_short()) {
152 auto const other_size = other._short_size();
153 std::uninitialized_move_n(other.begin(), other_size, _short_data());
154 _set_short_size(other_size);
155
156 } else {
157 _ptr = std::exchange(other._ptr, nullptr);
158 _end = std::exchange(other._end, nullptr);
159 _cap = std::exchange(other._cap, nullptr);
160 }
161 }
162
163 return *this;
164 }
165
166 void swap(lean_vector& other) noexcept
167 {
168 auto const this_is_short = this->_is_short();
169 auto const other_is_short = other._is_short();
170 if (this_is_short) {
171 // By moving other to tmp, we make other short.
173 other = std::move(*this);
174 *this = std::move(tmp);
175
176 } else if (other_is_short) {
177 // By moving this to tmp, we make this short.
178 lean_vector tmp = std::move(*this);
179 *this = std::move(other);
181
182 } else {
183 std::swap(this->_ptr, other._ptr);
184 std::swap(this->_end, other._end);
185 std::swap(this->_cap, other._cap);
186 }
187 }
188
189 explicit lean_vector(size_type count)
190 {
191 if (count <= short_capacity()) {
192 std::uninitialized_value_construct_n(_short_data(), count);
193 _set_short_size(count);
194
195 } else {
196 auto const update = _reserve<false>(count);
197 std::uninitialized_value_construct_n(update.ptr, count);
198 _reserve_update(update, count);
199 }
200 }
201
202 lean_vector(size_type count, value_type const& value)
203 {
204 if (count <= short_capacity()) {
205 std::uninitialized_fill_n(_short_data(), count, value);
206 _set_short_size(count);
207
208 } else {
209 auto const update = _reserve<false>(count);
210 std::uninitialized_fill_n(update.ptr, count, value);
211 _reserve_update(update, count);
212 }
213 }
214
220 lean_vector(std::input_iterator auto first, std::input_iterator auto last)
221 {
222 insert(_short_data(), first, last);
223 }
224
230 {
231 insert(_short_data(), list.begin(), list.end());
232 }
233
239 void assign(size_type count, value_type const& value)
240 {
241 clear();
242 insert(begin(), count, value);
243 }
244
250 void assign(std::input_iterator auto first, std::input_iterator auto last)
251 {
252 clear();
253 insert(begin(), first, last);
254 }
255
261 {
262 clear();
263 insert(begin(), list.begin(), list.end());
264 }
265
270 [[nodiscard]] pointer data() noexcept
271 {
272 if (_is_short()) {
273 if (_short_size() == 0) {
274 return nullptr;
275 } else {
276 return _short_data();
277 }
278 } else {
279 if (_ptr == _end) {
280 return nullptr;
281 } else {
282 return _long_data();
283 }
284 }
285 }
286
291 [[nodiscard]] const_pointer data() const noexcept
292 {
293 return const_cast<lean_vector *>(this)->data();
294 }
295
301 [[nodiscard]] constexpr bool empty() const noexcept
302 {
303 if (_is_short()) {
304 return _short_size() == 0;
305 } else {
306 return _ptr == _end;
307 }
308 }
309
315 {
316 if (_is_short()) {
317 return _short_size();
318 } else {
319 hi_axiom(_ptr <= _end);
320 return truncate<size_type>(_long_size());
321 }
322 }
323
324 [[nodiscard]] constexpr size_type max_size() const noexcept
325 {
326 auto a = get_allocator();
328 }
329
332 [[nodiscard]] constexpr size_t short_capacity() const noexcept
333 {
334 if constexpr (std::endian::native == std::endian::little) {
335 // The first alignment can not be used.
336 return (sizeof(pointer) * 3 - alignof(value_type)) / sizeof(value_type);
337 } else {
338 // The last byte can not be used to store values.
339 return (sizeof(pointer) * 3 - 1) / sizeof(value_type);
340 }
341 }
342
348 {
349 if (_is_short()) {
350 return short_capacity();
351 } else {
352 return _long_capacity();
353 }
354 }
355
362 [[nodiscard]] reference at(size_type index)
363 {
364 auto const is_short = _is_short();
365 auto const size_ = is_short ? _short_size() : _long_size();
366 if (index < size_) {
367 return _begin_data(is_short)[index];
368 } else {
369 throw std::out_of_range("lean_vector::at()");
370 }
371 }
372
379 [[nodiscard]] const_reference at(size_type index) const
380 {
381 return const_cast<lean_vector *>(this)->at(index);
382 }
383
390 [[nodiscard]] reference operator[](size_type index) noexcept
391 {
392 hi_axiom(index < size());
393 return _begin_data(_is_short())[index];
394 }
395
402 [[nodiscard]] const_reference operator[](size_type index) const noexcept
403 {
404 return const_cast<lean_vector *>(this)->operator[](index);
405 }
406
412 [[nodiscard]] reference front() noexcept
413 {
414 hi_axiom(not empty());
415 return *_begin_data(_is_short());
416 }
417
423 [[nodiscard]] const_reference front() const noexcept
424 {
425 return const_cast<lean_vector *>(this)->front();
426 }
427
433 [[nodiscard]] reference back() noexcept
434 {
435 hi_axiom(not empty());
436 return *(_end_data(_is_short()) - 1);
437 }
438
444 [[nodiscard]] const_reference back() const noexcept
445 {
446 return const_cast<lean_vector *>(this)->back();
447 }
448
453 [[nodiscard]] iterator begin() noexcept
454 {
455 return _begin_data(_is_short());
456 }
457
462 [[nodiscard]] const_iterator begin() const noexcept
463 {
464 return _begin_data(_is_short());
465 }
466
471 [[nodiscard]] const_iterator cbegin() const noexcept
472 {
473 return begin();
474 }
475
480 [[nodiscard]] iterator end() noexcept
481 {
482 return _end_data(_is_short());
483 }
484
489 [[nodiscard]] const_iterator end() const noexcept
490 {
491 return const_cast<lean_vector *>(this)->end();
492 }
493
498 [[nodiscard]] const_iterator cend() const noexcept
499 {
500 return end();
501 }
502
508 {
509 auto const is_short = _is_short();
510 std::destroy(_begin_data(is_short), _end_data(is_short));
511 _set_size(0, is_short);
512 }
513
523 {
524 auto const update = _reserve<false>(new_capacity);
525 _reserve_update(update);
526 }
527
537 {
538 if (_is_short()) {
539 return;
540 }
541
542 auto const old_ptr = _ptr;
543 auto const old_size = size();
544 auto const old_capacity = capacity();
545
546 if (old_size <= short_capacity()) {
547 _set_short_size(old_size);
548 } else {
549 auto a = get_allocator();
551 _end = _ptr + old_size;
552 _cap = _ptr + old_size;
553 }
554
555 std::uninitialized_move_n(old_ptr, old_size, begin());
556 std::destroy_n(old_ptr, old_size);
557 auto a = get_allocator();
559 }
560
570 template<typename... Args>
571 iterator emplace(const_iterator pos, Args&&...args)
572 {
573 auto const index = pos - begin();
574 auto const new_size = size() + 1;
575
576 auto const update = _reserve<true>(new_size);
577 std::construct_at(update.end, std::forward<Args>(args)...);
578 _reserve_update(update, new_size);
579
580 auto const new_pos = begin() + index;
581 std::rotate(new_pos, end() - 1, end());
582 return new_pos;
583 }
584
594 iterator insert(const_iterator pos, value_type const& value)
595 {
596 auto const index = pos - begin();
597 auto const new_size = size() + 1;
598
599 auto const update = _reserve<true>(new_size);
600 std::uninitialized_copy_n(std::addressof(value), 1, update.end);
601 _reserve_update(update, new_size);
602
603 auto const new_pos = begin() + index;
604 std::rotate(new_pos, end() - 1, end());
605 return new_pos;
606 }
607
617 iterator insert(const_iterator pos, value_type&& value)
618 {
619 auto const index = pos - begin();
620 auto const new_size = size() + 1;
621
622 auto const update = _reserve<true>(new_size);
623 std::uninitialized_move_n(std::addressof(value), 1, update.end);
624 _reserve_update(update, new_size);
625
626 auto const new_pos = begin() + index;
627 std::rotate(new_pos, end() - 1, end());
628 return new_pos;
629 }
630
641 iterator insert(const_iterator pos, size_type count, value_type const& value)
642 {
643 auto const index = pos - begin();
644 auto const new_size = size() + count;
645
646 auto const update = _reserve<true>(new_size);
647 std::uninitialized_fill_n(update.end, count, value);
648 _reserve_update(update, new_size);
649
650 auto const new_pos = begin() + index;
651 std::rotate(new_pos, end() - count, end());
652 return new_pos;
653 }
654
665 template<std::input_iterator First, std::input_iterator Last>
666 iterator insert(const_iterator pos, First first, Last last)
667 {
668 if constexpr (requires { std::distance(first, last); }) {
669 auto const n = std::distance(first, last);
670
671 auto const index = pos - begin();
672 auto const new_size = size() + n;
673
674 auto const update = _reserve<true>(new_size);
675 std::uninitialized_move_n(first, n, update.end);
676 _reserve_update(update, new_size);
677
678 auto const new_pos = begin() + index;
679 std::rotate(new_pos, end() - n, end());
680 return new_pos;
681
682 } else {
683 for (auto it = first; it != last; ++it) {
684 pos = insert(pos, *it) + 1;
685 }
686 }
687 }
688
698 iterator insert(const_iterator pos, std::initializer_list<value_type> list)
699 {
700 return insert(pos, list.begin(), list.end());
701 }
702
715 iterator erase(const_iterator pos)
716 {
717 hi_axiom(pos >= begin() and pos <= end());
718 auto const new_pos = begin() + std::distance(cbegin(), pos);
719 std::move(new_pos + 1, end(), new_pos);
720
721 auto const is_short = _is_short();
722 _set_size(size() - 1, is_short);
723 std::destroy_at(_end_data(is_short));
724 return new_pos;
725 }
726
739 iterator erase(const_iterator first, const_iterator last)
740 {
741 auto const first_ = begin() + std::distance(cbegin(), first);
742 auto const last_ = begin() + std::distance(cbegin(), last);
743 auto const n = std::distance(first_, last_);
745 std::destroy(end() - n, end());
746 _set_size(size() - n, _is_short());
747 return first_;
748 }
749
757 template<typename... Args>
758 reference emplace_back(Args&&...args)
759 {
760 auto const new_size = size() + 1;
761
762 auto const update = _reserve<true>(new_size);
763 auto const obj = std::construct_at(update.end, std::forward<Args>(args)...);
764 _reserve_update(update, new_size);
765
766 return *obj;
767 }
768
773 void push_back(value_type const& value)
774 {
775 auto const new_size = size() + 1;
776
777 auto const update = _reserve<true>(new_size);
778 std::uninitialized_copy_n(std::addressof(value), 1, update.end);
779 _reserve_update(update, new_size);
780 }
781
786 void push_back(value_type&& value)
787 {
788 auto const new_size = size() + 1;
789
790 auto const update = _reserve<true>(new_size);
791 std::uninitialized_move_n(std::addressof(value), 1, update.end);
792 _reserve_update(update, new_size);
793 }
794
801 void pop_back()
802 {
803 hi_axiom(not empty());
804
805 auto const is_short = _is_short();
806 _set_size(size() - 1, is_short);
807 std::destroy_at(_end_data(is_short));
808 }
809
821 {
822 if (auto const old_size = size(); new_size > old_size) {
823 auto const n = new_size - old_size;
824
825 auto const update = _reserve<true>(new_size);
826 std::uninitialized_value_construct_n(update.end, n);
827 _reserve_update(update, new_size);
828
829 } else {
830 auto const is_short = _is_short();
831 auto const n = old_size - new_size;
832 std::destroy(_end_data(is_short) - n, _end_data(is_short));
833 _set_size(new_size, is_short);
834 }
835 }
836
848 void resize(size_type new_size, value_type const& value)
849 {
850 if (auto const old_size = size(); new_size > old_size) {
851 auto const n = new_size - old_size;
852
853 auto const update = _reserve<true>(new_size);
854 std::uninitialized_fill_n(update.end, n, value);
855 _reserve_update(update, new_size);
856
857 } else {
858 auto const is_short = _is_short();
859 auto const n = old_size - new_size;
860 std::destroy(end() - n, end());
861 _set_size(new_size, is_short);
862 }
863 }
864
871 friend bool operator==(lean_vector const& lhs, lean_vector const& rhs) noexcept
872 {
873 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
874 }
875
882 friend auto operator<=>(lean_vector const& lhs, lean_vector const& rhs) noexcept
883 {
884 return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
885 }
886
893 friend size_type erase(lean_vector& c, value_type const& value)
894 {
895 auto it = std::remove(c.begin(), c.end(), value);
896 auto r = std::distance(it, c.end());
897 c.erase(it, c.end());
898 return r;
899 }
900
907 template<typename Pred>
909 {
910 auto it = std::remove(c.begin(), c.end(), pred);
911 auto r = std::distance(it, c.end());
912 c.erase(it, c.end());
913 return r;
914 }
915
916 friend void swap(lean_vector& lhs, lean_vector& rhs) noexcept
917 {
918 lhs.swap(rhs);
919 }
920
921private:
922 pointer _ptr = nullptr;
923 pointer _end = nullptr;
924 pointer _cap = nullptr;
925
926 [[nodiscard]] constexpr bool _is_short() const noexcept
927 {
928 if constexpr (std::endian::native == std::endian::little) {
929 if (_ptr == nullptr) {
930 return true;
931 } else {
932 return to_bool(to_int(_ptr) & 1);
933 }
934 } else {
935 if (_cap == nullptr) {
936 return true;
937 } else {
938 return to_bool(to_int(_cap) & 1);
939 }
940 }
941 }
942
943 [[nodiscard]] pointer _short_data() const noexcept
944 {
945 static_assert(alignof(value_type) <= alignof(pointer));
946
947 void *p = const_cast<lean_vector *>(this);
948 if constexpr (std::endian::native == std::endian::little) {
949 p = ceil(advance_bytes(p, 1), alignof(value_type));
950 }
951 return std::launder(static_cast<pointer>(p));
952 }
953
954 [[nodiscard]] pointer _long_data() const noexcept
955 {
956 return _ptr;
957 }
958
959 [[nodiscard]] constexpr size_type _short_size() const noexcept
960 {
961 if constexpr (std::endian::native == std::endian::little) {
962 if (_ptr == nullptr) {
963 return 0;
964 } else {
965 return (to_int(_ptr) >> 1) & 0x1f;
966 }
967 } else {
968 if (_cap == nullptr) {
969 return 0;
970 } else {
971 return (to_int(_cap) >> 1) & 0x1f;
972 }
973 }
974 }
975
976 [[nodiscard]] constexpr size_type _long_size() const noexcept
977 {
978 hi_axiom(_ptr <= _end);
979 return _end - _ptr;
980 }
981
982 [[nodiscard]] constexpr size_type _long_capacity() const noexcept
983 {
984 hi_axiom(_ptr <= _cap);
985 return _cap - _ptr;
986 }
987
988 void _set_short_size(size_t new_size) noexcept
989 {
990 constexpr auto mask = ~intptr_t{0xff};
991
992 new_size <<= 1;
993 new_size |= 1;
994 if constexpr (std::endian::native == std::endian::little) {
995 _ptr = to_ptr<pointer>((to_int(_ptr) & mask) | new_size);
996 } else {
997 _cap = to_ptr<pointer>((to_int(_cap) & mask) | new_size);
998 }
999 }
1000
1001 void _set_size(size_t new_size, bool is_short) noexcept
1002 {
1003 if (is_short) {
1004 hi_axiom(new_size <= short_capacity());
1005 _set_short_size(new_size);
1006 } else {
1007 _end = _ptr + new_size;
1008 }
1009 }
1010
1011 [[nodiscard]] pointer _begin_data(bool is_short) const noexcept
1012 {
1013 if (is_short) {
1014 return _short_data();
1015 } else {
1016 return _long_data();
1017 }
1018 }
1019
1020 [[nodiscard]] pointer _end_data(bool is_short) const noexcept
1021 {
1022 if (is_short) {
1023 return _short_data() + _short_size();
1024 } else {
1025 return _end;
1026 }
1027 }
1028
1029 struct _reserve_type {
1030 pointer ptr;
1031 pointer end;
1032 pointer cap;
1033 bool resized;
1034 bool is_short;
1035 };
1036
1041 template<bool ForInsert>
1042 [[nodiscard]] _reserve_type _reserve(size_type new_capacity) const
1043 {
1044 auto const is_short = _is_short();
1045 auto const capacity = is_short ? short_capacity() : _long_capacity();
1046 if (new_capacity <= capacity) {
1047 [[likely]] return {_begin_data(is_short), _end_data(is_short), nullptr, false, is_short};
1048 }
1049
1050 if constexpr (ForInsert) {
1051 auto next_capacity = capacity + capacity / 2;
1054 }
1056 }
1057
1058 auto a = get_allocator();
1060
1061 auto const size_ = is_short ? _short_size() : _long_size();
1062 return {new_ptr, new_ptr + size_, new_ptr + new_capacity, true, false};
1063 }
1064
1065 void _reserve_update(_reserve_type update)
1066 {
1067 if (not update.resized) {
1068 return;
1069 }
1070
1071 auto const is_short = _is_short();
1072 auto const old_size = is_short ? _short_size() : _long_size();
1073 auto const old_ptr = is_short ? _short_data() : _long_data();
1074
1075 std::uninitialized_move_n(old_ptr, old_size, update.ptr);
1076 std::destroy_n(old_ptr, old_size);
1077
1078 if (not is_short) {
1079 auto a = get_allocator();
1080 std::allocator_traits<allocator_type>::deallocate(a, _long_data(), _long_capacity());
1081 }
1082
1083 _ptr = update.ptr;
1084 _end = update.end;
1085 _cap = update.cap;
1086 }
1087
1088 void _reserve_update(_reserve_type update, size_type new_size)
1089 {
1090 _reserve_update(update);
1091 _set_size(new_size, update.is_short);
1092 }
1093};
1094
1095template<std::input_iterator It, std::input_iterator ItEnd>
1096lean_vector(It first, ItEnd last) -> lean_vector<typename std::iterator_traits<It>::value_type>;
1097
1098
1099template<typename T, std::convertible_to<T>... Args>
1100lean_vector<T> make_lean_vector(Args &&...args) noexcept
1101{
1102 return lean_vector<T>{std::forward<Args>(args)...};
1103}
1104
1105
1106}} // namespace hi::v1
1107
1108hi_warning_pop();
@ other
The gui_event does not have associated data.
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
hi_inline void * advance_bytes(void *ptr, std::ptrdiff_t distance) noexcept
Advance a pointer by a number of bytes.
Definition memory.hpp:253
The HikoGUI namespace.
Definition recursive_iterator.hpp:15
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:378
Lean-vector with (SVO) short-vector-optimization.
Definition lean_vector.hpp:35
lean_vector(lean_vector const &other)
Copy-construct a vector.
Definition lean_vector.hpp:79
const_reference front() const noexcept
Get a const-reference to the first item in the vector.
Definition lean_vector.hpp:423
size_t capacity() const noexcept
Get the current capacity of the vector.
Definition lean_vector.hpp:347
reference back() noexcept
Get a reference to the last item in the vector.
Definition lean_vector.hpp:433
void push_back(value_type &&value)
Move an item to the end of the vector.
Definition lean_vector.hpp:786
const_iterator end() const noexcept
Get an const-iterator beyond the last item in the vector.
Definition lean_vector.hpp:489
lean_vector & operator=(lean_vector &&other) noexcept
Move-assign a vector.
Definition lean_vector.hpp:138
void clear() noexcept
Remove all items from the vector.
Definition lean_vector.hpp:507
void push_back(value_type const &value)
Copy an item to the end of the vector.
Definition lean_vector.hpp:773
constexpr size_t short_capacity() const noexcept
The maximum number of items that can fit without allocation.
Definition lean_vector.hpp:332
lean_vector(std::initializer_list< value_type > list)
Construct a vector with the given initializer list.
Definition lean_vector.hpp:229
iterator end() noexcept
Get an iterator beyond the last item in the vector.
Definition lean_vector.hpp:480
const_iterator cend() const noexcept
Get an const-iterator beyond the last item in the vector.
Definition lean_vector.hpp:498
iterator begin() noexcept
Get an iterator to the first item in the vector.
Definition lean_vector.hpp:453
iterator insert(const_iterator pos, std::initializer_list< value_type > list)
Insert new items.
Definition lean_vector.hpp:698
iterator erase(const_iterator pos)
Erase an item at position.
Definition lean_vector.hpp:715
void resize(size_type new_size, value_type const &value)
Resize a vector.
Definition lean_vector.hpp:848
friend size_type erase(lean_vector &c, value_type const &value)
Erase items of a value from a vector.
Definition lean_vector.hpp:893
reference emplace_back(Args &&...args)
In-place construct an item at the end of the vector.
Definition lean_vector.hpp:758
const_pointer data() const noexcept
Get a const-pointer to the first item.
Definition lean_vector.hpp:291
void resize(size_type new_size)
Resize a vector.
Definition lean_vector.hpp:820
pointer data() noexcept
Get a pointer to the first item.
Definition lean_vector.hpp:270
lean_vector(lean_vector &&other) noexcept(std::is_nothrow_move_constructible_v< value_type >)
Move-construct a vector.
Definition lean_vector.hpp:94
constexpr bool empty() const noexcept
Check if the vector is empty.
Definition lean_vector.hpp:301
friend bool operator==(lean_vector const &lhs, lean_vector const &rhs) noexcept
Compare two vectors.
Definition lean_vector.hpp:871
iterator insert(const_iterator pos, value_type &&value)
Insert a new item.
Definition lean_vector.hpp:617
friend auto operator<=>(lean_vector const &lhs, lean_vector const &rhs) noexcept
Compare two vectors lexicographically.
Definition lean_vector.hpp:882
void assign(std::initializer_list< value_type > list)
Replace the data in the vector.
Definition lean_vector.hpp:260
const_iterator begin() const noexcept
Get an const-iterator to the first item in the vector.
Definition lean_vector.hpp:462
friend size_type erase(lean_vector &c, Pred pred)
Erase items of a value from a vector.
Definition lean_vector.hpp:908
const_iterator cbegin() const noexcept
Get an const-iterator to the first item in the vector.
Definition lean_vector.hpp:471
void assign(std::input_iterator auto first, std::input_iterator auto last)
Replace the data in the vector.
Definition lean_vector.hpp:250
iterator insert(const_iterator pos, size_type count, value_type const &value)
Insert a new item.
Definition lean_vector.hpp:641
const_reference operator[](size_type index) const noexcept
Get a const-reference to an item in the vector.
Definition lean_vector.hpp:402
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:362
constexpr size_type size() const noexcept
Get the number of items in the vector.
Definition lean_vector.hpp:314
void shrink_to_fit()
Shrink the allocation to fit the current number of items.
Definition lean_vector.hpp:536
void pop_back()
Remove the last item from the vector.
Definition lean_vector.hpp:801
lean_vector & operator=(lean_vector const &other) noexcept
Copy-assign a vector.
Definition lean_vector.hpp:116
const_reference at(size_type index) const
Get a const-reference to an item in the vector.
Definition lean_vector.hpp:379
reference front() noexcept
Get a reference to the first item in the vector.
Definition lean_vector.hpp:412
iterator emplace(const_iterator pos, Args &&...args)
Construct in-place a new item.
Definition lean_vector.hpp:571
const_reference back() const noexcept
Get a const-reference to the last item in the vector.
Definition lean_vector.hpp:444
iterator insert(const_iterator pos, First first, Last last)
Insert new items.
Definition lean_vector.hpp:666
constexpr allocator_type get_allocator() const noexcept
The allocator_type used to allocate items.
Definition lean_vector.hpp:54
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:220
void assign(size_type count, value_type const &value)
Replace the data in the vector.
Definition lean_vector.hpp:239
reference operator[](size_type index) noexcept
Get a reference to an item in the vector.
Definition lean_vector.hpp:390
iterator erase(const_iterator first, const_iterator last)
Erase an items.
Definition lean_vector.hpp:739
void reserve(size_type new_capacity)
Reserve capacity for items.
Definition lean_vector.hpp:522
iterator insert(const_iterator pos, value_type const &value)
Insert a new item.
Definition lean_vector.hpp:594
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)