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
19
20
21hi_warning_push();
22// C26450: You called an STL function '' with raw pointer... (stl.1)
23// Using an iterator requires a lot of code which will not make it safer.
24hi_warning_ignore_msvc(26459);
25
26namespace hi { inline namespace v1 {
27
32template<typename T>
34public:
35 using value_type = T;
36 using pointer = value_type *;
37 using const_pointer = value_type const *;
38 using reference = value_type&;
39 using const_reference = value_type const&;
40 using iterator = value_type *;
41 using const_iterator = value_type const *;
42 using reverse_iterator = std::reverse_iterator<iterator>;
43 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
44 using size_type = std::size_t;
45 using difference_type = std::ptrdiff_t;
46 using allocator_type = std::allocator<value_type>;
47
48 constexpr static size_t value_alignment = alignof(value_type);
49
57
61
65 {
66 clear();
68 }
69
78 {
79 hilet other_size = other.size();
80 hilet update = _reserve<false>(other_size);
81 std::uninitialized_copy_n(other.begin(), other_size, update.ptr);
82 _reserve_update(update, other_size);
83 }
84
92 lean_vector(lean_vector&& other) noexcept(std::is_nothrow_move_constructible_v<value_type>)
93 {
94 if (other._is_short()) {
95 hilet other_size = other._short_size();
96 std::uninitialized_move_n(other.begin(), other_size, begin());
97 other._set_short_size(0);
98 _set_short_size(other_size);
99
100 } else {
101 _ptr = std::exchange(other._ptr, nullptr);
102 _end = std::exchange(other._end, nullptr);
103 _cap = std::exchange(other._cap, nullptr);
104 }
105 }
106
115 {
116 hi_return_on_self_assignment(other);
117
118 hilet other_size = other.size();
119
120 clear();
121 hilet update = _reserve<false>(other_size);
122 std::uninitialized_copy_n(other.begin(), other_size, update.ptr);
123 _reserve_update(update, other_size);
124
125 return *this;
126 }
127
137 {
138 hi_return_on_self_assignment(other);
139
140 if (not _is_short() and not other._is_short()) {
141 std::swap(_ptr, other._ptr);
142 std::swap(_end, other._end);
143 std::swap(_cap, other._cap);
144
145 } else {
146 clear();
148
149 if (other._is_short()) {
150 hilet other_size = other._short_size();
151 std::uninitialized_move_n(other.begin(), other_size, _short_data());
152 _set_short_size(other_size);
153
154 } else {
155 _ptr = std::exchange(other._ptr, nullptr);
156 _end = std::exchange(other._end, nullptr);
157 _cap = std::exchange(other._cap, nullptr);
158 }
159 }
160
161 return *this;
162 }
163
164 void swap(lean_vector& other) noexcept
165 {
166 hilet this_is_short = this->_is_short();
167 hilet other_is_short = other._is_short();
168 if (this_is_short) {
169 // By moving other to tmp, we make other short.
171 other = std::move(*this);
172 *this = std::move(tmp);
173
174 } else if (other_is_short) {
175 // By moving this to tmp, we make this short.
176 lean_vector tmp = std::move(*this);
177 *this = std::move(other);
179
180 } else {
181 std::swap(this->_ptr, other._ptr);
182 std::swap(this->_end, other._end);
183 std::swap(this->_cap, other._cap);
184 }
185 }
186
187 explicit lean_vector(size_type count)
188 {
189 if (count <= short_capacity()) {
190 std::uninitialized_value_construct_n(_short_data(), count);
191 _set_short_size(count);
192
193 } else {
194 hilet update = _reserve<false>(count);
195 std::uninitialized_value_construct_n(update.ptr, count);
196 _reserve_update(update, count);
197 }
198 }
199
200 lean_vector(size_type count, value_type const& value)
201 {
202 if (count <= short_capacity()) {
203 std::uninitialized_fill_n(_short_data(), count, value);
204 _set_short_size(count);
205
206 } else {
207 hilet update = _reserve<false>(count);
208 std::uninitialized_fill_n(update.ptr, count, value);
209 _reserve_update(update, count);
210 }
211 }
212
218 lean_vector(std::input_iterator auto first, std::input_iterator auto last)
219 {
220 insert(_short_data(), first, last);
221 }
222
228 {
229 insert(_short_data(), list.begin(), list.end());
230 }
231
237 void assign(size_type count, value_type const& value)
238 {
239 clear();
240 insert(begin(), count, value);
241 }
242
248 void assign(std::input_iterator auto first, std::input_iterator auto last)
249 {
250 clear();
251 insert(begin(), first, last);
252 }
253
259 {
260 clear();
261 insert(begin(), list.begin(), list.end());
262 }
263
269 {
270 if (_is_short()) {
271 if (_short_size() == 0) {
272 return nullptr;
273 } else {
274 return _short_data();
275 }
276 } else {
277 if (_ptr == _end) {
278 return nullptr;
279 } else {
280 return _long_data();
281 }
282 }
283 }
284
289 [[nodiscard]] const_pointer data() const noexcept
290 {
291 return const_cast<lean_vector *>(this)->data();
292 }
293
299 [[nodiscard]] constexpr bool empty() const noexcept
300 {
301 if (_is_short()) {
302 return _short_size() == 0;
303 } else {
304 return _ptr == _end;
305 }
306 }
307
313 {
314 if (_is_short()) {
315 return _short_size();
316 } else {
317 hi_axiom(_ptr <= _end);
318 return truncate<size_type>(_long_size());
319 }
320 }
321
322 [[nodiscard]] constexpr size_type max_size() const noexcept
323 {
324 auto a = get_allocator();
326 }
327
330 [[nodiscard]] constexpr size_t short_capacity() const noexcept
331 {
332 if constexpr (std::endian::native == std::endian::little) {
333 // The first alignment can not be used.
334 return (sizeof(pointer) * 3 - alignof(value_type)) / sizeof(value_type);
335 } else {
336 // The last byte can not be used to store values.
337 return (sizeof(pointer) * 3 - 1) / sizeof(value_type);
338 }
339 }
340
346 {
347 if (_is_short()) {
348 return short_capacity();
349 } else {
350 return _long_capacity();
351 }
352 }
353
361 {
362 hilet is_short = _is_short();
363 hilet size_ = is_short ? _short_size() : _long_size();
364 if (index < size_) {
365 return _begin_data(is_short)[index];
366 } else {
367 throw std::out_of_range("lean_vector::at()");
368 }
369 }
370
377 [[nodiscard]] const_reference at(size_type index) const
378 {
379 return const_cast<lean_vector *>(this)->at(index);
380 }
381
389 {
390 hi_axiom(index < size());
391 return _begin_data(_is_short())[index];
392 }
393
400 [[nodiscard]] const_reference operator[](size_type index) const noexcept
401 {
402 return const_cast<lean_vector *>(this)->operator[](index);
403 }
404
411 {
412 hi_axiom(not empty());
413 return *_begin_data(_is_short());
414 }
415
421 [[nodiscard]] const_reference front() const noexcept
422 {
423 return const_cast<lean_vector *>(this)->front();
424 }
425
432 {
433 hi_axiom(not empty());
434 return *(_end_data(_is_short()) - 1);
435 }
436
442 [[nodiscard]] const_reference back() const noexcept
443 {
444 return const_cast<lean_vector *>(this)->back();
445 }
446
451 [[nodiscard]] iterator begin() noexcept
452 {
453 return _begin_data(_is_short());
454 }
455
460 [[nodiscard]] const_iterator begin() const noexcept
461 {
462 return _begin_data(_is_short());
463 }
464
469 [[nodiscard]] const_iterator cbegin() const noexcept
470 {
471 return begin();
472 }
473
478 [[nodiscard]] iterator end() noexcept
479 {
480 return _end_data(_is_short());
481 }
482
487 [[nodiscard]] const_iterator end() const noexcept
488 {
489 return const_cast<lean_vector *>(this)->end();
490 }
491
496 [[nodiscard]] const_iterator cend() const noexcept
497 {
498 return end();
499 }
500
506 {
507 hilet is_short = _is_short();
508 std::destroy(_begin_data(is_short), _end_data(is_short));
509 _set_size(0, is_short);
510 }
511
521 {
522 hilet update = _reserve<false>(new_capacity);
523 _reserve_update(update);
524 }
525
535 {
536 if (_is_short()) {
537 return;
538 }
539
540 hilet old_ptr = _ptr;
541 hilet old_size = size();
542 hilet old_capacity = capacity();
543
544 if (old_size <= short_capacity()) {
545 _set_short_size(old_size);
546 } else {
547 auto a = get_allocator();
549 _end = _ptr + old_size;
550 _cap = _ptr + old_size;
551 }
552
553 std::uninitialized_move_n(old_ptr, old_size, begin());
554 std::destroy_n(old_ptr, old_size);
555 auto a = get_allocator();
557 }
558
568 template<typename... Args>
569 iterator emplace(const_iterator pos, Args&&...args)
570 {
571 hilet index = pos - begin();
572 hilet new_size = size() + 1;
573
574 hilet update = _reserve<true>(new_size);
575 std::construct_at(update.end, std::forward<Args>(args)...);
576 _reserve_update(update, new_size);
577
578 hilet new_pos = begin() + index;
579 std::rotate(new_pos, end() - 1, end());
580 return new_pos;
581 }
582
592 iterator insert(const_iterator pos, value_type const& value)
593 {
594 hilet index = pos - begin();
595 hilet new_size = size() + 1;
596
597 hilet update = _reserve<true>(new_size);
598 std::uninitialized_copy_n(std::addressof(value), 1, update.end);
599 _reserve_update(update, new_size);
600
601 hilet new_pos = begin() + index;
602 std::rotate(new_pos, end() - 1, end());
603 return new_pos;
604 }
605
615 iterator insert(const_iterator pos, value_type&& value)
616 {
617 hilet index = pos - begin();
618 hilet new_size = size() + 1;
619
620 hilet update = _reserve<true>(new_size);
621 std::uninitialized_move_n(std::addressof(value), 1, update.end);
622 _reserve_update(update, new_size);
623
624 hilet new_pos = begin() + index;
625 std::rotate(new_pos, end() - 1, end());
626 return new_pos;
627 }
628
639 iterator insert(const_iterator pos, size_type count, value_type const& value)
640 {
641 hilet index = pos - begin();
642 hilet new_size = size() + count;
643
644 hilet update = _reserve<true>(new_size);
645 std::uninitialized_fill_n(update.end, count, value);
646 _reserve_update(update, new_size);
647
648 hilet new_pos = begin() + index;
649 std::rotate(new_pos, end() - count, end());
650 return new_pos;
651 }
652
663 iterator insert(const_iterator pos, std::input_iterator auto first, std::input_iterator auto last)
664 {
665 if constexpr (requires { std::distance(first, last); }) {
666 hilet n = std::distance(first, last);
667
668 hilet index = pos - begin();
669 hilet new_size = size() + n;
670
671 hilet update = _reserve<true>(new_size);
672 std::uninitialized_move_n(first, n, update.end);
673 _reserve_update(update, new_size);
674
675 hilet new_pos = begin() + index;
676 std::rotate(new_pos, end() - n, end());
677 return new_pos;
678
679 } else {
680 for (auto it = first; it != last; ++it) {
681 pos = insert(pos, *it) + 1;
682 }
683 }
684 }
685
695 iterator insert(const_iterator pos, std::initializer_list<value_type> list)
696 {
697 return insert(pos, list.begin(), list.end());
698 }
699
712 iterator erase(const_iterator pos)
713 {
714 hi_axiom(pos >= begin() and pos <= end());
715 hilet new_pos = begin() + std::distance(cbegin(), pos);
716 std::move(new_pos + 1, end(), new_pos);
717
718 hilet is_short = _is_short();
719 _set_size(size() - 1, is_short);
720 std::destroy_at(_end_data(is_short));
721 return new_pos;
722 }
723
736 iterator erase(const_iterator first, const_iterator last)
737 {
738 hilet first_ = begin() + std::distance(cbegin(), first);
739 hilet last_ = begin() + std::distance(cbegin(), last);
740 hilet n = std::distance(first_, last_);
742 std::destroy(end() - n, end());
743 _set_size(size() - n, _is_short());
744 return first_;
745 }
746
754 template<typename... Args>
756 {
757 hilet new_size = size() + 1;
758
759 hilet update = _reserve<true>(new_size);
760 hilet obj = std::construct_at(update.end, std::forward<Args>(args)...);
761 _reserve_update(update, new_size);
762
763 return *obj;
764 }
765
770 void push_back(value_type const& value)
771 {
772 hilet new_size = size() + 1;
773
774 hilet update = _reserve<true>(new_size);
775 std::uninitialized_copy_n(std::addressof(value), 1, update.end);
776 _reserve_update(update, new_size);
777 }
778
783 void push_back(value_type&& value)
784 {
785 hilet new_size = size() + 1;
786
787 hilet update = _reserve<true>(new_size);
788 std::uninitialized_move_n(std::addressof(value), 1, update.end);
789 _reserve_update(update, new_size);
790 }
791
798 void pop_back()
799 {
800 hi_axiom(not empty());
801
802 hilet is_short = _is_short();
803 _set_size(size() - 1, is_short);
804 std::destroy_at(_end_data(is_short));
805 }
806
818 {
819 if (hilet old_size = size(); new_size > old_size) {
820 hilet n = new_size - old_size;
821
822 hilet update = _reserve<true>(new_size);
823 std::uninitialized_value_construct_n(update.end, n);
824 _reserve_update(update, new_size);
825
826 } else {
827 hilet is_short = _is_short();
828 hilet n = old_size - new_size;
829 std::destroy(_end_data(is_short) - n, _end_data(is_short));
830 _set_size(new_size, is_short);
831 }
832 }
833
845 void resize(size_type new_size, value_type const& value)
846 {
847 if (hilet old_size = size(); new_size > old_size) {
848 hilet n = new_size - old_size;
849
850 hilet update = _reserve<true>(new_size);
851 std::uninitialized_fill_n(update.end, n, value);
852 _reserve_update(update, new_size);
853
854 } else {
855 hilet is_short = _is_short();
856 hilet n = old_size - new_size;
857 std::destroy(end() - n, end());
858 _set_size(new_size, is_short);
859 }
860 }
861
868 friend bool operator==(lean_vector const& lhs, lean_vector const& rhs) noexcept
869 {
870 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
871 }
872
879 friend auto operator<=>(lean_vector const& lhs, lean_vector const& rhs) noexcept
880 {
881 return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
882 }
883
890 friend size_type erase(lean_vector& c, value_type const& value)
891 {
892 auto it = std::remove(c.begin(), c.end(), value);
893 auto r = std::distance(it, c.end());
894 c.erase(it, c.end());
895 return r;
896 }
897
904 template<typename Pred>
906 {
907 auto it = std::remove(c.begin(), c.end(), pred);
908 auto r = std::distance(it, c.end());
909 c.erase(it, c.end());
910 return r;
911 }
912
913 friend void swap(lean_vector& lhs, lean_vector& rhs) noexcept
914 {
915 lhs.swap(rhs);
916 }
917
918private:
919 pointer _ptr = nullptr;
920 pointer _end = nullptr;
921 pointer _cap = nullptr;
922
923 [[nodiscard]] constexpr bool _is_short() const noexcept
924 {
925 if constexpr (std::endian::native == std::endian::little) {
926 if (_ptr == nullptr) {
927 return true;
928 } else {
929 return to_bool(to_int(_ptr) & 1);
930 }
931 } else {
932 if (_cap == nullptr) {
933 return true;
934 } else {
935 return to_bool(to_int(_cap) & 1);
936 }
937 }
938 }
939
940 [[nodiscard]] pointer _short_data() const noexcept
941 {
942 static_assert(alignof(value_type) <= alignof(pointer));
943
944 void *p = const_cast<lean_vector *>(this);
945 if constexpr (std::endian::native == std::endian::little) {
946 p = ceil(advance_bytes(p, 1), alignof(value_type));
947 }
948 return std::launder(static_cast<pointer>(p));
949 }
950
951 [[nodiscard]] pointer _long_data() const noexcept
952 {
953 return _ptr;
954 }
955
956 [[nodiscard]] constexpr size_type _short_size() const noexcept
957 {
958 if constexpr (std::endian::native == std::endian::little) {
959 if (_ptr == nullptr) {
960 return 0;
961 } else {
962 return (to_int(_ptr) >> 1) & 0x1f;
963 }
964 } else {
965 if (_cap == nullptr) {
966 return 0;
967 } else {
968 return (to_int(_cap) >> 1) & 0x1f;
969 }
970 }
971 }
972
973 [[nodiscard]] constexpr size_type _long_size() const noexcept
974 {
975 hi_axiom(_ptr <= _end);
976 return _end - _ptr;
977 }
978
979 [[nodiscard]] constexpr size_type _long_capacity() const noexcept
980 {
981 hi_axiom(_ptr <= _cap);
982 return _cap - _ptr;
983 }
984
985 void _set_short_size(size_t new_size) noexcept
986 {
987 constexpr auto mask = ~intptr_t{0xff};
988
989 new_size <<= 1;
990 new_size |= 1;
991 if constexpr (std::endian::native == std::endian::little) {
992 _ptr = to_ptr<pointer>((to_int(_ptr) & mask) | new_size);
993 } else {
994 _cap = to_ptr<pointer>((to_int(_cap) & mask) | new_size);
995 }
996 }
997
998 void _set_size(size_t new_size, bool is_short) noexcept
999 {
1000 if (is_short) {
1001 hi_axiom(new_size <= short_capacity());
1002 _set_short_size(new_size);
1003 } else {
1004 _end = _ptr + new_size;
1005 }
1006 }
1007
1008 [[nodiscard]] pointer _begin_data(bool is_short) const noexcept
1009 {
1010 if (is_short) {
1011 return _short_data();
1012 } else {
1013 return _long_data();
1014 }
1015 }
1016
1017 [[nodiscard]] pointer _end_data(bool is_short) const noexcept
1018 {
1019 if (is_short) {
1020 return _short_data() + _short_size();
1021 } else {
1022 return _end;
1023 }
1024 }
1025
1026 struct _reserve_type {
1027 pointer ptr;
1028 pointer end;
1029 pointer cap;
1030 bool resized;
1031 bool is_short;
1032 };
1033
1038 template<bool ForInsert>
1039 [[nodiscard]] _reserve_type _reserve(size_type new_capacity) const
1040 {
1041 hilet is_short = _is_short();
1042 hilet capacity = is_short ? short_capacity() : _long_capacity();
1043 if (new_capacity <= capacity) {
1044 [[likely]] return {_begin_data(is_short), _end_data(is_short), nullptr, false, is_short};
1045 }
1046
1047 if constexpr (ForInsert) {
1048 auto next_capacity = capacity + capacity / 2;
1051 }
1053 }
1054
1055 auto a = get_allocator();
1057
1058 hilet size_ = is_short ? _short_size() : _long_size();
1059 return {new_ptr, new_ptr + size_, new_ptr + new_capacity, true, false};
1060 }
1061
1062 void _reserve_update(_reserve_type update)
1063 {
1064 if (not update.resized) {
1065 return;
1066 }
1067
1068 hilet is_short = _is_short();
1069 hilet old_size = is_short ? _short_size() : _long_size();
1070 hilet old_ptr = is_short ? _short_data() : _long_data();
1071
1072 std::uninitialized_move_n(old_ptr, old_size, update.ptr);
1073 std::destroy_n(old_ptr, old_size);
1074
1075 if (not is_short) {
1076 auto a = get_allocator();
1077 std::allocator_traits<allocator_type>::deallocate(a, _long_data(), _long_capacity());
1078 }
1079
1080 _ptr = update.ptr;
1081 _end = update.end;
1082 _cap = update.cap;
1083 }
1084
1085 void _reserve_update(_reserve_type update, size_type new_size)
1086 {
1087 _reserve_update(update);
1088 _set_size(new_size, update.is_short);
1089 }
1090};
1091
1092template<std::input_iterator It, std::input_iterator ItEnd>
1093lean_vector(It first, ItEnd last) -> lean_vector<typename std::iterator_traits<It>::value_type>;
1094
1095}} // namespace hi::v1
1096
1097hi_warning_pop();
@ other
The gui_event does not have associated data.
DOXYGEN BUG.
Definition algorithm.hpp:16
void * advance_bytes(void *ptr, std::ptrdiff_t distance) noexcept
Advance a pointer by a number of bytes.
Definition memory.hpp:195
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
Lean-vector with (SVO) short-vector-optimization.
Definition lean_vector.hpp:33
lean_vector(lean_vector const &other)
Copy-construct a vector.
Definition lean_vector.hpp:77
iterator insert(const_iterator pos, std::input_iterator auto first, std::input_iterator auto last)
Insert new items.
Definition lean_vector.hpp:663
const_reference front() const noexcept
Get a const-reference to the first item in the vector.
Definition lean_vector.hpp:421
size_t capacity() const noexcept
Get the current capacity of the vector.
Definition lean_vector.hpp:345
reference back() noexcept
Get a reference to the last item in the vector.
Definition lean_vector.hpp:431
void push_back(value_type &&value)
Move an item to the end of the vector.
Definition lean_vector.hpp:783
const_iterator end() const noexcept
Get an const-iterator beyond the last item in the vector.
Definition lean_vector.hpp:487
lean_vector & operator=(lean_vector &&other) noexcept
Move-assign a vector.
Definition lean_vector.hpp:136
void clear() noexcept
Remove all items from the vector.
Definition lean_vector.hpp:505
void push_back(value_type const &value)
Copy an item to the end of the vector.
Definition lean_vector.hpp:770
constexpr size_t short_capacity() const noexcept
The maximum number of items that can fit without allocation.
Definition lean_vector.hpp:330
lean_vector(std::initializer_list< value_type > list)
Construct a vector with the given initializer list.
Definition lean_vector.hpp:227
iterator end() noexcept
Get an iterator beyond the last item in the vector.
Definition lean_vector.hpp:478
const_iterator cend() const noexcept
Get an const-iterator beyond the last item in the vector.
Definition lean_vector.hpp:496
iterator begin() noexcept
Get an iterator to the first item in the vector.
Definition lean_vector.hpp:451
iterator insert(const_iterator pos, std::initializer_list< value_type > list)
Insert new items.
Definition lean_vector.hpp:695
iterator erase(const_iterator pos)
Erase an item at position.
Definition lean_vector.hpp:712
void resize(size_type new_size, value_type const &value)
Resize a vector.
Definition lean_vector.hpp:845
friend size_type erase(lean_vector &c, value_type const &value)
Erase items of a value from a vector.
Definition lean_vector.hpp:890
reference emplace_back(Args &&...args)
In-place construct an item at the end of the vector.
Definition lean_vector.hpp:755
const_pointer data() const noexcept
Get a const-pointer to the first item.
Definition lean_vector.hpp:289
void resize(size_type new_size)
Resize a vector.
Definition lean_vector.hpp:817
pointer data() noexcept
Get a pointer to the first item.
Definition lean_vector.hpp:268
lean_vector(lean_vector &&other) noexcept(std::is_nothrow_move_constructible_v< value_type >)
Move-construct a vector.
Definition lean_vector.hpp:92
constexpr bool empty() const noexcept
Check if the vector is empty.
Definition lean_vector.hpp:299
friend bool operator==(lean_vector const &lhs, lean_vector const &rhs) noexcept
Compare two vectors.
Definition lean_vector.hpp:868
iterator insert(const_iterator pos, value_type &&value)
Insert a new item.
Definition lean_vector.hpp:615
friend auto operator<=>(lean_vector const &lhs, lean_vector const &rhs) noexcept
Compare two vectors lexicographically.
Definition lean_vector.hpp:879
void assign(std::initializer_list< value_type > list)
Replace the data in the vector.
Definition lean_vector.hpp:258
const_iterator begin() const noexcept
Get an const-iterator to the first item in the vector.
Definition lean_vector.hpp:460
friend size_type erase(lean_vector &c, Pred pred)
Erase items of a value from a vector.
Definition lean_vector.hpp:905
const_iterator cbegin() const noexcept
Get an const-iterator to the first item in the vector.
Definition lean_vector.hpp:469
void assign(std::input_iterator auto first, std::input_iterator auto last)
Replace the data in the vector.
Definition lean_vector.hpp:248
iterator insert(const_iterator pos, size_type count, value_type const &value)
Insert a new item.
Definition lean_vector.hpp:639
const_reference operator[](size_type index) const noexcept
Get a const-reference to an item in the vector.
Definition lean_vector.hpp:400
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:360
constexpr size_type size() const noexcept
Get the number of items in the vector.
Definition lean_vector.hpp:312
void shrink_to_fit()
Shrink the allocation to fit the current number of items.
Definition lean_vector.hpp:534
void pop_back()
Remove the last item from the vector.
Definition lean_vector.hpp:798
lean_vector & operator=(lean_vector const &other) noexcept
Copy-assign a vector.
Definition lean_vector.hpp:114
const_reference at(size_type index) const
Get a const-reference to an item in the vector.
Definition lean_vector.hpp:377
reference front() noexcept
Get a reference to the first item in the vector.
Definition lean_vector.hpp:410
iterator emplace(const_iterator pos, Args &&...args)
Construct in-place a new item.
Definition lean_vector.hpp:569
const_reference back() const noexcept
Get a const-reference to the last item in the vector.
Definition lean_vector.hpp:442
constexpr allocator_type get_allocator() const noexcept
The allocator_type used to allocate items.
Definition lean_vector.hpp:52
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:218
void assign(size_type count, value_type const &value)
Replace the data in the vector.
Definition lean_vector.hpp:237
reference operator[](size_type index) noexcept
Get a reference to an item in the vector.
Definition lean_vector.hpp:388
iterator erase(const_iterator first, const_iterator last)
Erase an items.
Definition lean_vector.hpp:736
void reserve(size_type new_capacity)
Reserve capacity for items.
Definition lean_vector.hpp:520
iterator insert(const_iterator pos, value_type const &value)
Insert a new item.
Definition lean_vector.hpp:592
Definition concepts.hpp:39
Definition concepts.hpp:42
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)