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