Blender V4.3
BLI_vector.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
27#include <algorithm>
28
29#include "BLI_allocator.hh"
30#include "BLI_index_range.hh"
31#include "BLI_memory_utils.hh"
32#include "BLI_span.hh"
33#include "BLI_utildefines.h"
34
35namespace blender {
36
37namespace internal {
38void vector_print_stats(const char *name,
39 const void *address,
40 int64_t size,
41 int64_t capacity,
42 int64_t inlineCapacity,
43 int64_t memorySize);
44}
45
46template<
50 typename T,
59 int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T)),
64 typename Allocator = GuardedAllocator>
65class Vector {
66 public:
67 using value_type = T;
68 using pointer = T *;
69 using const_pointer = const T *;
70 using reference = T &;
71 using const_reference = const T &;
72 using iterator = T *;
73 using const_iterator = const T *;
75 using allocator_type = Allocator;
76
77 private:
84 T *begin_;
85 T *end_;
86 T *capacity_end_;
87
89 BLI_NO_UNIQUE_ADDRESS Allocator allocator_;
90
93
99#ifndef NDEBUG
100 int64_t debug_size_;
101# define UPDATE_VECTOR_SIZE(ptr) (ptr)->debug_size_ = int64_t((ptr)->end_ - (ptr)->begin_)
102#else
103# define UPDATE_VECTOR_SIZE(ptr) ((void)0)
104#endif
105
110 template<typename OtherT, int64_t OtherInlineBufferCapacity, typename OtherAllocator>
111 friend class Vector;
112
114 static constexpr bool is_nothrow_move_constructible()
115 {
116 if constexpr (InlineBufferCapacity == 0) {
117 return true;
118 }
119 else {
120 return std::is_nothrow_move_constructible_v<T>;
121 }
122 }
123
124 public:
129 Vector(Allocator allocator = {}) noexcept : allocator_(allocator)
130 {
131 begin_ = inline_buffer_;
132 end_ = begin_;
133 capacity_end_ = begin_ + InlineBufferCapacity;
134 UPDATE_VECTOR_SIZE(this);
135 }
136
137 Vector(NoExceptConstructor, Allocator allocator = {}) noexcept : Vector(allocator) {}
138
144 explicit Vector(int64_t size, Allocator allocator = {})
145 : Vector(NoExceptConstructor(), allocator)
146 {
147 this->resize(size);
148 }
149
153 Vector(int64_t size, const T &value, Allocator allocator = {})
154 : Vector(NoExceptConstructor(), allocator)
155 {
156 this->resize(size, value);
157 }
158
162 template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
163 Vector(Span<U> values, Allocator allocator = {}) : Vector(NoExceptConstructor(), allocator)
164 {
165 const int64_t size = values.size();
166 this->reserve(size);
167 uninitialized_convert_n<U, T>(values.data(), size, begin_);
168 this->increase_size_by_unchecked(size);
169 }
170
171 template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
172 explicit Vector(MutableSpan<U> values, Allocator allocator = {})
173 : Vector(values.as_span(), allocator)
174 {
175 }
176
183 template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
184 Vector(const std::initializer_list<U> &values) : Vector(Span<U>(values))
185 {
186 }
187
188 Vector(const std::initializer_list<T> &values) : Vector(Span<T>(values)) {}
189
190 template<typename U, size_t N, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
191 Vector(const std::array<U, N> &values) : Vector(Span(values))
192 {
193 }
194
195 template<typename InputIt,
196 /* This constructor should not be called with e.g. Vector(3, 10), because that is
197 * expected to produce the vector (10, 10, 10). */
198 BLI_ENABLE_IF((!std::is_convertible_v<InputIt, int>))>
199 Vector(InputIt first, InputIt last, Allocator allocator = {})
200 : Vector(NoExceptConstructor(), allocator)
201 {
202 for (InputIt current = first; current != last; ++current) {
203 this->append(*current);
204 }
205 }
206
211 Vector(const Vector &other) : Vector(other.as_span(), other.allocator_) {}
212
217 template<int64_t OtherInlineBufferCapacity>
219 : Vector(other.as_span(), other.allocator_)
220 {
221 }
222
227 template<int64_t OtherInlineBufferCapacity>
229 is_nothrow_move_constructible())
230 : Vector(NoExceptConstructor(), other.allocator_)
231 {
232 const int64_t size = other.size();
233
234 if (other.is_inline()) {
235 if (size <= InlineBufferCapacity) {
236 /* Copy between inline buffers. */
237 uninitialized_relocate_n(other.begin_, size, begin_);
238 end_ = begin_ + size;
239 }
240 else {
241 /* Copy from inline buffer to newly allocated buffer. */
242 const int64_t capacity = size;
243 begin_ = static_cast<T *>(
244 allocator_.allocate(sizeof(T) * size_t(capacity), alignof(T), AT));
245 capacity_end_ = begin_ + capacity;
246 uninitialized_relocate_n(other.begin_, size, begin_);
247 end_ = begin_ + size;
248 }
249 }
250 else {
251 /* Steal the pointer. */
252 begin_ = other.begin_;
253 end_ = other.end_;
254 capacity_end_ = other.capacity_end_;
255 }
256
257 other.begin_ = other.inline_buffer_;
258 other.end_ = other.begin_;
259 other.capacity_end_ = other.begin_ + OtherInlineBufferCapacity;
260 UPDATE_VECTOR_SIZE(this);
261 UPDATE_VECTOR_SIZE(&other);
262 }
263
265 {
266 destruct_n(begin_, this->size());
267 if (!this->is_inline()) {
268 allocator_.deallocate(begin_);
269 }
270 }
271
272 Vector &operator=(const Vector &other)
273 {
274 return copy_assign_container(*this, other);
275 }
276
278 {
279 return move_assign_container(*this, std::move(other));
280 }
281
286 const T &operator[](int64_t index) const
287 {
288 BLI_assert(index >= 0);
289 BLI_assert(index < this->size());
290 return begin_[index];
291 }
292
294 {
295 BLI_assert(index >= 0);
296 BLI_assert(index < this->size());
297 return begin_[index];
298 }
299
300 operator Span<T>() const
301 {
302 return Span<T>(begin_, this->size());
303 }
304
305 operator MutableSpan<T>()
306 {
307 return MutableSpan<T>(begin_, this->size());
308 }
309
310 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<T, U>))>
311 operator Span<U>() const
312 {
313 return Span<U>(begin_, this->size());
314 }
315
316 template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<T, U>))>
317 operator MutableSpan<U>()
318 {
319 return MutableSpan<U>(begin_, this->size());
320 }
321
323 {
324 return *this;
325 }
326
328 {
329 return *this;
330 }
331
337 void reserve(const int64_t min_capacity)
338 {
339 if (min_capacity > this->capacity()) {
340 this->realloc_to_at_least(min_capacity);
341 }
342 }
343
350 void resize(const int64_t new_size)
351 {
352 BLI_assert(new_size >= 0);
353 const int64_t old_size = this->size();
354 if (new_size > old_size) {
355 this->reserve(new_size);
356 default_construct_n(begin_ + old_size, new_size - old_size);
357 }
358 else {
359 destruct_n(begin_ + new_size, old_size - new_size);
360 }
361 end_ = begin_ + new_size;
362 UPDATE_VECTOR_SIZE(this);
363 }
364
371 void resize(const int64_t new_size, const T &value)
372 {
373 BLI_assert(new_size >= 0);
374 const int64_t old_size = this->size();
375 if (new_size > old_size) {
376 this->reserve(new_size);
377 uninitialized_fill_n(begin_ + old_size, new_size - old_size, value);
378 }
379 else {
380 destruct_n(begin_ + new_size, old_size - new_size);
381 }
382 end_ = begin_ + new_size;
383 UPDATE_VECTOR_SIZE(this);
384 }
385
390 void reinitialize(const int64_t new_size)
391 {
392 this->clear();
393 this->resize(new_size);
394 }
395
400 void clear()
401 {
402 destruct_n(begin_, this->size());
403 end_ = begin_;
404 UPDATE_VECTOR_SIZE(this);
405 }
406
412 {
413 destruct_n(begin_, this->size());
414 if (!this->is_inline()) {
415 allocator_.deallocate(begin_);
416 }
417
418 begin_ = inline_buffer_;
419 end_ = begin_;
420 capacity_end_ = begin_ + InlineBufferCapacity;
421 UPDATE_VECTOR_SIZE(this);
422 }
423
430 void append(const T &value)
431 {
432 this->append_as(value);
433 }
434 void append(T &&value)
435 {
436 this->append_as(std::move(value));
437 }
438 /* This is similar to `std::vector::emplace_back`. */
439 template<typename... ForwardValue> void append_as(ForwardValue &&...value)
440 {
441 this->ensure_space_for_one();
442 this->append_unchecked_as(std::forward<ForwardValue>(value)...);
443 }
444
450 {
451 return this->append_and_get_index_as(value);
452 }
454 {
455 return this->append_and_get_index_as(std::move(value));
456 }
457 template<typename... ForwardValue> int64_t append_and_get_index_as(ForwardValue &&...value)
458 {
459 const int64_t index = this->size();
460 this->append_as(std::forward<ForwardValue>(value)...);
461 return index;
462 }
463
469 void append_non_duplicates(const T &value)
470 {
471 if (!this->contains(value)) {
472 this->append(value);
473 }
474 }
475
481 void append_unchecked(const T &value)
482 {
483 this->append_unchecked_as(value);
484 }
485 void append_unchecked(T &&value)
486 {
487 this->append_unchecked_as(std::move(value));
488 }
489 template<typename... ForwardT> void append_unchecked_as(ForwardT &&...value)
490 {
491 BLI_assert(end_ < capacity_end_);
492 new (end_) T(std::forward<ForwardT>(value)...);
493 end_++;
494 UPDATE_VECTOR_SIZE(this);
495 }
496
501 void append_n_times(const T &value, const int64_t n)
502 {
503 BLI_assert(n >= 0);
504 this->reserve(this->size() + n);
505 uninitialized_fill_n(end_, n, value);
507 }
508
515 void increase_size_by_unchecked(const int64_t n) noexcept
516 {
517 BLI_assert(end_ + n <= capacity_end_);
518 end_ += n;
519 UPDATE_VECTOR_SIZE(this);
520 }
521
528 {
529 this->extend(array.data(), array.size());
530 }
531 void extend(const T *start, int64_t amount)
532 {
533 this->reserve(this->size() + amount);
534 this->extend_unchecked(start, amount);
535 }
536
543 {
544 for (const T &value : array) {
545 this->append_non_duplicates(value);
546 }
547 }
548
554 {
555 this->extend_unchecked(array.data(), array.size());
556 }
557 void extend_unchecked(const T *start, int64_t amount)
558 {
559 BLI_assert(amount >= 0);
560 BLI_assert(begin_ + amount <= capacity_end_);
561 uninitialized_copy_n(start, amount, end_);
562 end_ += amount;
563 UPDATE_VECTOR_SIZE(this);
564 }
565
566 template<typename InputIt> void extend(InputIt first, InputIt last)
567 {
568 this->insert(this->end(), first, last);
569 }
570
576 void insert(const int64_t insert_index, const T &value)
577 {
578 this->insert(insert_index, Span<T>(&value, 1));
579 }
580 void insert(const int64_t insert_index, T &&value)
581 {
582 this->insert(
583 insert_index, std::make_move_iterator(&value), std::make_move_iterator(&value + 1));
584 }
585 void insert(const int64_t insert_index, Span<T> array)
586 {
587 this->insert(begin_ + insert_index, array.begin(), array.end());
588 }
589 template<typename InputIt> void insert(const T *insert_position, InputIt first, InputIt last)
590 {
591 const int64_t insert_index = insert_position - begin_;
592 this->insert(insert_index, first, last);
593 }
594 template<typename InputIt> void insert(const int64_t insert_index, InputIt first, InputIt last)
595 {
596 BLI_assert(insert_index >= 0);
597 BLI_assert(insert_index <= this->size());
598
599 const int64_t insert_amount = std::distance(first, last);
600 const int64_t old_size = this->size();
601 const int64_t new_size = old_size + insert_amount;
602 const int64_t move_amount = old_size - insert_index;
603
604 this->reserve(new_size);
605 for (int64_t i = 0; i < move_amount; i++) {
606 const int64_t src_index = insert_index + move_amount - i - 1;
607 const int64_t dst_index = new_size - i - 1;
608 try {
609 new (static_cast<void *>(begin_ + dst_index)) T(std::move(begin_[src_index]));
610 }
611 catch (...) {
612 /* Destruct all values that have been moved already. */
613 destruct_n(begin_ + dst_index + 1, i);
614 end_ = begin_ + src_index + 1;
615 UPDATE_VECTOR_SIZE(this);
616 throw;
617 }
618 begin_[src_index].~T();
619 }
620
621 try {
622 std::uninitialized_copy_n(first, insert_amount, begin_ + insert_index);
623 }
624 catch (...) {
625 /* Destruct all values that have been moved. */
626 destruct_n(begin_ + new_size - move_amount, move_amount);
627 end_ = begin_ + insert_index;
628 UPDATE_VECTOR_SIZE(this);
629 throw;
630 }
631 end_ = begin_ + new_size;
632 UPDATE_VECTOR_SIZE(this);
633 }
634
639 void prepend(const T &value)
640 {
641 this->insert(0, value);
642 }
643 void prepend(T &&value)
644 {
645 this->insert(0, std::move(value));
646 }
647 void prepend(Span<T> values)
648 {
649 this->insert(0, values);
650 }
651 template<typename InputIt> void prepend(InputIt first, InputIt last)
652 {
653 this->insert(0, first, last);
654 }
655
660 const T &last(const int64_t n = 0) const
661 {
662 BLI_assert(n >= 0);
663 BLI_assert(n < this->size());
664 return *(end_ - 1 - n);
665 }
666 T &last(const int64_t n = 0)
667 {
668 BLI_assert(n >= 0);
669 BLI_assert(n < this->size());
670 return *(end_ - 1 - n);
671 }
672
677 const T &first() const
678 {
679 BLI_assert(this->size() > 0);
680 return *begin_;
681 }
682 T &first()
683 {
684 BLI_assert(this->size() > 0);
685 return *begin_;
686 }
687
691 int64_t size() const
692 {
693 const int64_t current_size = int64_t(end_ - begin_);
694 BLI_assert(debug_size_ == current_size);
695 return current_size;
696 }
697
703 bool is_empty() const
704 {
705 return begin_ == end_;
706 }
707
713 {
714 BLI_assert(!this->is_empty());
715 end_--;
716 end_->~T();
717 UPDATE_VECTOR_SIZE(this);
718 }
719
727 {
728 BLI_assert(!this->is_empty());
729 T value = std::move(*(end_ - 1));
730 end_--;
731 end_->~T();
732 UPDATE_VECTOR_SIZE(this);
733 return value;
734 }
735
740 void remove_and_reorder(const int64_t index)
741 {
742 BLI_assert(index >= 0);
743 BLI_assert(index < this->size());
744 T *element_to_remove = begin_ + index;
745 T *last_element = end_ - 1;
746 if (element_to_remove < last_element) {
747 *element_to_remove = std::move(*last_element);
748 }
749 end_ = last_element;
750 last_element->~T();
751 UPDATE_VECTOR_SIZE(this);
752 }
753
759 {
760 const int64_t index = this->first_index_of(value);
761 this->remove_and_reorder(index);
762 }
763
771 void remove(const int64_t index)
772 {
773 BLI_assert(index >= 0);
774 BLI_assert(index < this->size());
775 const int64_t last_index = this->size() - 1;
776 for (int64_t i = index; i < last_index; i++) {
777 begin_[i] = std::move(begin_[i + 1]);
778 }
779 begin_[last_index].~T();
780 end_--;
781 UPDATE_VECTOR_SIZE(this);
782 }
783
790 void remove(const int64_t start_index, const int64_t amount)
791 {
792 const int64_t old_size = this->size();
793 BLI_assert(start_index >= 0);
794 BLI_assert(amount >= 0);
795 BLI_assert(start_index + amount <= old_size);
796 const int64_t move_amount = old_size - start_index - amount;
797 for (int64_t i = 0; i < move_amount; i++) {
798 begin_[start_index + i] = std::move(begin_[start_index + amount + i]);
799 }
800 destruct_n(end_ - amount, amount);
801 end_ -= amount;
802 UPDATE_VECTOR_SIZE(this);
803 }
804
811 template<typename Predicate> int64_t remove_if(Predicate &&predicate)
812 {
813 const T *prev_end = this->end();
814 end_ = std::remove_if(this->begin(), this->end(), predicate);
815 destruct_n(end_, prev_end - end_);
816 UPDATE_VECTOR_SIZE(this);
817 return int64_t(prev_end - end_);
818 }
819
824 int64_t first_index_of_try(const T &value) const
825 {
826 for (const T *current = begin_; current != end_; current++) {
827 if (*current == value) {
828 return int64_t(current - begin_);
829 }
830 }
831 return -1;
832 }
833
838 int64_t first_index_of(const T &value) const
839 {
840 const int64_t index = this->first_index_of_try(value);
841 BLI_assert(index >= 0);
842 return index;
843 }
844
849 bool contains(const T &value) const
850 {
851 return this->first_index_of_try(value) != -1;
852 }
853
857 void fill(const T &value) const
858 {
859 initialized_fill_n(begin_, this->size(), value);
860 }
861
865 T *data()
866 {
867 return begin_;
868 }
869
873 const T *data() const
874 {
875 return begin_;
876 }
877
878 T *begin()
879 {
880 return begin_;
881 }
882 T *end()
883 {
884 return end_;
885 }
886
887 const T *begin() const
888 {
889 return begin_;
890 }
891 const T *end() const
892 {
893 return end_;
894 }
895
896 std::reverse_iterator<T *> rbegin()
897 {
898 return std::reverse_iterator<T *>(this->end());
899 }
900 std::reverse_iterator<T *> rend()
901 {
902 return std::reverse_iterator<T *>(this->begin());
903 }
904
905 std::reverse_iterator<const T *> rbegin() const
906 {
907 return std::reverse_iterator<const T *>(this->end());
908 }
909 std::reverse_iterator<const T *> rend() const
910 {
911 return std::reverse_iterator<const T *>(this->begin());
912 }
913
919 {
920 return int64_t(capacity_end_ - begin_);
921 }
922
923 bool is_at_capacity() const
924 {
925 return end_ == capacity_end_;
926 }
927
938 {
939 return IndexRange(this->size());
940 }
941
943 {
944 return this->as_span().hash();
945 }
946
947 static uint64_t hash_as(const Span<T> values)
948 {
949 return values.hash();
950 }
951
952 friend bool operator==(const Vector &a, const Vector &b)
953 {
954 return a.as_span() == b.as_span();
955 }
956
957 friend bool operator!=(const Vector &a, const Vector &b)
958 {
959 return !(a == b);
960 }
961
965 void print_stats(const char *name) const
966 {
968 name, this, this->size(), capacity_end_ - begin_, InlineBufferCapacity, sizeof(*this));
969 }
970
971 private:
972 bool is_inline() const
973 {
974 return begin_ == inline_buffer_;
975 }
976
977 void ensure_space_for_one()
978 {
979 if (UNLIKELY(end_ >= capacity_end_)) {
980 this->realloc_to_at_least(this->size() + 1);
981 }
982 }
983
984 BLI_NOINLINE void realloc_to_at_least(const int64_t min_capacity)
985 {
986 if (this->capacity() >= min_capacity) {
987 return;
988 }
989
990 /* At least double the size of the previous allocation. Otherwise consecutive calls to grow can
991 * cause a reallocation every time even though min_capacity only increments. */
992 const int64_t min_new_capacity = this->capacity() * 2;
993
994 const int64_t new_capacity = std::max(min_capacity, min_new_capacity);
995 const int64_t size = this->size();
996
997 T *new_array = static_cast<T *>(
998 allocator_.allocate(size_t(new_capacity) * sizeof(T), alignof(T), AT));
999 try {
1000 uninitialized_relocate_n(begin_, size, new_array);
1001 }
1002 catch (...) {
1003 allocator_.deallocate(new_array);
1004 throw;
1005 }
1006
1007 if (!this->is_inline()) {
1008 allocator_.deallocate(begin_);
1009 }
1010
1011 begin_ = new_array;
1012 end_ = begin_ + size;
1013 capacity_end_ = begin_ + new_capacity;
1014 }
1015};
1016
1017#undef UPDATE_VECTOR_SIZE
1018
1023template<typename T, int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T))>
1025
1026} /* namespace blender */
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_NOINLINE
#define BLI_ENABLE_IF(condition)
#define UNLIKELY(x)
#define BLI_NO_UNIQUE_ADDRESS
#define UPDATE_VECTOR_SIZE(ptr)
unsigned int U
Definition btGjkEpa3.h:78
size_t size() const
constexpr const T * data() const
Definition BLI_span.hh:216
void insert(const int64_t insert_index, T &&value)
std::reverse_iterator< const T * > rbegin() const
int64_t size() const
std::reverse_iterator< T * > rbegin()
void remove_and_reorder(const int64_t index)
Vector(const Vector< T, OtherInlineBufferCapacity, Allocator > &other)
void print_stats(const char *name) const
int64_t remove_if(Predicate &&predicate)
Vector(const Vector &other)
Vector(Allocator allocator={}) noexcept
int64_t append_and_get_index(const T &value)
void prepend(const T &value)
bool contains(const T &value) const
Vector & operator=(Vector &&other)
bool is_at_capacity() const
void append(const T &value)
void insert(const int64_t insert_index, const T &value)
friend bool operator==(const Vector &a, const Vector &b)
void prepend(T &&value)
const T & last(const int64_t n=0) const
Vector(InputIt first, InputIt last, Allocator allocator={})
void append_unchecked_as(ForwardT &&...value)
void remove(const int64_t index)
uint64_t hash() const
bool is_empty() const
void resize(const int64_t new_size, const T &value)
Allocator allocator_type
Definition BLI_vector.hh:75
void remove_first_occurrence_and_reorder(const T &value)
IndexRange index_range() const
int64_t append_and_get_index_as(ForwardValue &&...value)
void prepend(InputIt first, InputIt last)
void resize(const int64_t new_size)
int64_t first_index_of(const T &value) const
MutableSpan< T > as_mutable_span()
void extend_unchecked(Span< T > array)
T & operator[](int64_t index)
void append_unchecked(const T &value)
void prepend(Span< T > values)
static uint64_t hash_as(const Span< T > values)
Vector(NoExceptConstructor, Allocator allocator={}) noexcept
const T & operator[](int64_t index) const
Vector(Span< U > values, Allocator allocator={})
void reserve(const int64_t min_capacity)
const T & const_reference
Definition BLI_vector.hh:71
const T * end() const
std::reverse_iterator< T * > rend()
int64_t size_type
Definition BLI_vector.hh:74
void remove(const int64_t start_index, const int64_t amount)
void extend(Span< T > array)
void append(T &&value)
std::reverse_iterator< const T * > rend() const
void insert(const T *insert_position, InputIt first, InputIt last)
void append_unchecked(T &&value)
void extend_non_duplicates(Span< T > array)
Vector & operator=(const Vector &other)
void reinitialize(const int64_t new_size)
Vector(int64_t size, const T &value, Allocator allocator={})
void append_non_duplicates(const T &value)
void fill(const T &value) const
void insert(const int64_t insert_index, InputIt first, InputIt last)
Vector(const std::array< U, N > &values)
Span< T > as_span() const
const T * data() const
Vector(int64_t size, Allocator allocator={})
const T * const_pointer
Definition BLI_vector.hh:69
const T & first() const
T & last(const int64_t n=0)
void insert(const int64_t insert_index, Span< T > array)
Vector(Vector< T, OtherInlineBufferCapacity, Allocator > &&other) noexcept(is_nothrow_move_constructible())
void append_as(ForwardValue &&...value)
int64_t append_and_get_index(T &&value)
void extend(InputIt first, InputIt last)
void extend(const T *start, int64_t amount)
Vector(const std::initializer_list< U > &values)
void clear_and_shrink()
friend bool operator!=(const Vector &a, const Vector &b)
void extend_unchecked(const T *start, int64_t amount)
void increase_size_by_unchecked(const int64_t n) noexcept
int64_t capacity() const
Vector(MutableSpan< U > values, Allocator allocator={})
const T * begin() const
int64_t first_index_of_try(const T &value) const
void append_n_times(const T &value, const int64_t n)
const T * const_iterator
Definition BLI_vector.hh:73
Vector(const std::initializer_list< T > &values)
local_group_size(16, 16) .push_constant(Type b
append
#define T
void vector_print_stats(const char *name, const void *address, int64_t size, int64_t capacity, int64_t inlineCapacity, int64_t memorySize)
Definition vector.cc:10
void default_construct_n(T *ptr, int64_t n)
void initialized_fill_n(T *dst, int64_t n, const T &value)
Container & copy_assign_container(Container &dst, const Container &src)
Container & move_assign_container(Container &dst, Container &&src) noexcept(std::is_nothrow_move_constructible_v< Container >)
constexpr int64_t default_inline_buffer_capacity(size_t element_size)
void uninitialized_fill_n(T *dst, int64_t n, const T &value)
void uninitialized_relocate_n(T *src, int64_t n, T *dst)
void uninitialized_convert_n(const From *src, int64_t n, To *dst)
void destruct_n(T *ptr, int64_t n)
void uninitialized_copy_n(const T *src, int64_t n, T *dst)
__int64 int64_t
Definition stdint.h:89
unsigned __int64 uint64_t
Definition stdint.h:90