Blender  V2.93
BLI_vector.hh
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
39 #include <algorithm>
40 #include <cstdlib>
41 #include <cstring>
42 #include <iostream>
43 #include <memory>
44 
45 #include "BLI_allocator.hh"
46 #include "BLI_index_range.hh"
47 #include "BLI_listbase_wrapper.hh"
48 #include "BLI_math_base.h"
49 #include "BLI_memory_utils.hh"
50 #include "BLI_span.hh"
51 #include "BLI_string.h"
52 #include "BLI_string_ref.hh"
53 #include "BLI_utildefines.h"
54 
55 #include "MEM_guardedalloc.h"
56 
57 namespace blender {
58 
59 template<
63  typename T,
72  int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T)),
77  typename Allocator = GuardedAllocator>
78 class Vector {
79  public:
80  using value_type = T;
81  using pointer = T *;
82  using const_pointer = const T *;
83  using reference = T &;
84  using const_reference = const T &;
85  using iterator = T *;
86  using const_iterator = const T *;
87  using size_type = int64_t;
88 
89  private:
96  T *begin_;
97  T *end_;
98  T *capacity_end_;
99 
101  Allocator allocator_;
102 
105 
111 #ifndef NDEBUG
112  int64_t debug_size_;
113 # define UPDATE_VECTOR_SIZE(ptr) \
114  (ptr)->debug_size_ = static_cast<int64_t>((ptr)->end_ - (ptr)->begin_)
115 #else
116 # define UPDATE_VECTOR_SIZE(ptr) ((void)0)
117 #endif
118 
123  template<typename OtherT, int64_t OtherInlineBufferCapacity, typename OtherAllocator>
124  friend class Vector;
125 
126  public:
131  Vector(Allocator allocator = {}) noexcept : allocator_(allocator)
132  {
133  begin_ = inline_buffer_;
134  end_ = begin_;
135  capacity_end_ = begin_ + InlineBufferCapacity;
136  UPDATE_VECTOR_SIZE(this);
137  }
138 
139  Vector(NoExceptConstructor, Allocator allocator = {}) noexcept : Vector(allocator)
140  {
141  }
142 
148  explicit Vector(int64_t size, Allocator allocator = {})
149  : Vector(NoExceptConstructor(), allocator)
150  {
151  this->resize(size);
152  }
153 
157  Vector(int64_t size, const T &value, Allocator allocator = {})
158  : Vector(NoExceptConstructor(), allocator)
159  {
160  this->resize(size, value);
161  }
162 
166  template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr>
167  Vector(Span<U> values, Allocator allocator = {}) : Vector(NoExceptConstructor(), allocator)
168  {
169  const int64_t size = values.size();
170  this->reserve(size);
171  uninitialized_convert_n<U, T>(values.data(), size, begin_);
172  this->increase_size_by_unchecked(size);
173  }
174 
181  template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr>
182  Vector(const std::initializer_list<U> &values) : Vector(Span<U>(values))
183  {
184  }
185 
186  Vector(const std::initializer_list<T> &values) : Vector(Span<T>(values))
187  {
188  }
189 
190  template<typename U,
191  size_t N,
192  typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr>
193  Vector(const std::array<U, N> &values) : Vector(Span(values))
194  {
195  }
196 
197  template<typename InputIt,
198  /* This constructor should not be called with e.g. Vector(3, 10), because that is
199  * expected to produce the vector (10, 10, 10). */
200  typename std::enable_if_t<!std::is_convertible_v<InputIt, int>> * = nullptr>
201  Vector(InputIt first, InputIt last, Allocator allocator = {})
202  : Vector(NoExceptConstructor(), allocator)
203  {
204  for (InputIt current = first; current != last; ++current) {
205  this->append(*current);
206  }
207  }
208 
216  Vector(ListBase &values, Allocator allocator = {}) : Vector(NoExceptConstructor(), allocator)
217  {
218  LISTBASE_FOREACH (T, value, &values) {
219  this->append(value);
220  }
221  }
222 
227  Vector(const Vector &other) : Vector(other.as_span(), other.allocator_)
228  {
229  }
230 
235  template<int64_t OtherInlineBufferCapacity>
237  : Vector(other.as_span(), other.allocator_)
238  {
239  }
240 
245  template<int64_t OtherInlineBufferCapacity>
247  std::is_nothrow_move_constructible_v<T>)
248  : Vector(NoExceptConstructor(), other.allocator_)
249  {
250  const int64_t size = other.size();
251 
252  if (other.is_inline()) {
253  if (size <= InlineBufferCapacity) {
254  /* Copy between inline buffers. */
255  uninitialized_relocate_n(other.begin_, size, begin_);
256  end_ = begin_ + size;
257  }
258  else {
259  /* Copy from inline buffer to newly allocated buffer. */
260  const int64_t capacity = size;
261  begin_ = static_cast<T *>(
262  allocator_.allocate(sizeof(T) * static_cast<size_t>(capacity), alignof(T), AT));
263  capacity_end_ = begin_ + capacity;
264  uninitialized_relocate_n(other.begin_, size, begin_);
265  end_ = begin_ + size;
266  }
267  }
268  else {
269  /* Steal the pointer. */
270  begin_ = other.begin_;
271  end_ = other.end_;
272  capacity_end_ = other.capacity_end_;
273  }
274 
275  other.begin_ = other.inline_buffer_;
276  other.end_ = other.begin_;
277  other.capacity_end_ = other.begin_ + OtherInlineBufferCapacity;
278  UPDATE_VECTOR_SIZE(this);
279  UPDATE_VECTOR_SIZE(&other);
280  }
281 
283  {
284  destruct_n(begin_, this->size());
285  if (!this->is_inline()) {
286  allocator_.deallocate(begin_);
287  }
288  }
289 
290  Vector &operator=(const Vector &other)
291  {
292  return copy_assign_container(*this, other);
293  }
294 
296  {
297  return move_assign_container(*this, std::move(other));
298  }
299 
304  const T &operator[](int64_t index) const
305  {
306  BLI_assert(index >= 0);
307  BLI_assert(index < this->size());
308  return begin_[index];
309  }
310 
312  {
313  BLI_assert(index >= 0);
314  BLI_assert(index < this->size());
315  return begin_[index];
316  }
317 
318  operator Span<T>() const
319  {
320  return Span<T>(begin_, this->size());
321  }
322 
323  operator MutableSpan<T>()
324  {
325  return MutableSpan<T>(begin_, this->size());
326  }
327 
328  template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<T, U>> * = nullptr>
329  operator Span<U>() const
330  {
331  return Span<U>(begin_, this->size());
332  }
333 
334  template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<T, U>> * = nullptr>
335  operator MutableSpan<U>()
336  {
337  return MutableSpan<U>(begin_, this->size());
338  }
339 
340  Span<T> as_span() const
341  {
342  return *this;
343  }
344 
346  {
347  return *this;
348  }
349 
355  void reserve(const int64_t min_capacity)
356  {
357  if (min_capacity > this->capacity()) {
358  this->realloc_to_at_least(min_capacity);
359  }
360  }
361 
368  void resize(const int64_t new_size)
369  {
370  BLI_assert(new_size >= 0);
371  const int64_t old_size = this->size();
372  if (new_size > old_size) {
373  this->reserve(new_size);
374  default_construct_n(begin_ + old_size, new_size - old_size);
375  }
376  else {
377  destruct_n(begin_ + new_size, old_size - new_size);
378  }
379  end_ = begin_ + new_size;
380  UPDATE_VECTOR_SIZE(this);
381  }
382 
389  void resize(const int64_t new_size, const T &value)
390  {
391  BLI_assert(new_size >= 0);
392  const int64_t old_size = this->size();
393  if (new_size > old_size) {
394  this->reserve(new_size);
395  uninitialized_fill_n(begin_ + old_size, new_size - old_size, value);
396  }
397  else {
398  destruct_n(begin_ + new_size, old_size - new_size);
399  }
400  end_ = begin_ + new_size;
401  UPDATE_VECTOR_SIZE(this);
402  }
403 
408  void clear()
409  {
410  destruct_n(begin_, this->size());
411  end_ = begin_;
412  UPDATE_VECTOR_SIZE(this);
413  }
414 
420  {
421  destruct_n(begin_, this->size());
422  if (!this->is_inline()) {
423  allocator_.deallocate(begin_);
424  }
425 
426  begin_ = inline_buffer_;
427  end_ = begin_;
428  capacity_end_ = begin_ + InlineBufferCapacity;
429  UPDATE_VECTOR_SIZE(this);
430  }
431 
438  void append(const T &value)
439  {
440  this->ensure_space_for_one();
441  this->append_unchecked(value);
442  }
443  void append(T &&value)
444  {
445  this->ensure_space_for_one();
446  this->append_unchecked(std::move(value));
447  }
448 
454  {
455  const int64_t index = this->size();
456  this->append(value);
457  return index;
458  }
459 
465  void append_non_duplicates(const T &value)
466  {
467  if (!this->contains(value)) {
468  this->append(value);
469  }
470  }
471 
477  template<typename ForwardT> void append_unchecked(ForwardT &&value)
478  {
479  BLI_assert(end_ < capacity_end_);
480  new (end_) T(std::forward<ForwardT>(value));
481  end_++;
482  UPDATE_VECTOR_SIZE(this);
483  }
484 
489  void append_n_times(const T &value, const int64_t n)
490  {
491  BLI_assert(n >= 0);
492  this->reserve(this->size() + n);
493  uninitialized_fill_n(end_, n, value);
495  }
496 
503  void increase_size_by_unchecked(const int64_t n) noexcept
504  {
505  BLI_assert(end_ + n <= capacity_end_);
506  end_ += n;
507  UPDATE_VECTOR_SIZE(this);
508  }
509 
516  {
517  this->extend(array.data(), array.size());
518  }
519  void extend(const T *start, int64_t amount)
520  {
521  this->reserve(this->size() + amount);
522  this->extend_unchecked(start, amount);
523  }
524 
531  {
532  for (const T &value : array) {
533  this->append_non_duplicates(value);
534  }
535  }
536 
542  {
543  this->extend_unchecked(array.data(), array.size());
544  }
545  void extend_unchecked(const T *start, int64_t amount)
546  {
547  BLI_assert(amount >= 0);
548  BLI_assert(begin_ + amount <= capacity_end_);
549  uninitialized_copy_n(start, amount, end_);
550  end_ += amount;
551  UPDATE_VECTOR_SIZE(this);
552  }
553 
554  template<typename InputIt> void extend(InputIt first, InputIt last)
555  {
556  this->insert(this->end(), first, last);
557  }
558 
564  void insert(const int64_t insert_index, const T &value)
565  {
566  this->insert(insert_index, Span<T>(&value, 1));
567  }
568  void insert(const int64_t insert_index, T &&value)
569  {
570  this->insert(
571  insert_index, std::make_move_iterator(&value), std::make_move_iterator(&value + 1));
572  }
573  void insert(const int64_t insert_index, Span<T> array)
574  {
575  this->insert(begin_ + insert_index, array.begin(), array.end());
576  }
577  template<typename InputIt> void insert(const T *insert_position, InputIt first, InputIt last)
578  {
579  const int64_t insert_index = insert_position - begin_;
580  this->insert(insert_index, first, last);
581  }
582  template<typename InputIt> void insert(const int64_t insert_index, InputIt first, InputIt last)
583  {
584  BLI_assert(insert_index >= 0);
585  BLI_assert(insert_index <= this->size());
586 
587  const int64_t insert_amount = std::distance(first, last);
588  const int64_t old_size = this->size();
589  const int64_t new_size = old_size + insert_amount;
590  const int64_t move_amount = old_size - insert_index;
591 
592  this->reserve(new_size);
593  for (int64_t i = 0; i < move_amount; i++) {
594  const int64_t src_index = insert_index + move_amount - i - 1;
595  const int64_t dst_index = new_size - i - 1;
596  try {
597  new (static_cast<void *>(begin_ + dst_index)) T(std::move(begin_[src_index]));
598  }
599  catch (...) {
600  /* Destruct all values that have been moved already. */
601  destruct_n(begin_ + dst_index + 1, i);
602  end_ = begin_ + src_index + 1;
603  UPDATE_VECTOR_SIZE(this);
604  throw;
605  }
606  begin_[src_index].~T();
607  }
608 
609  try {
610  std::uninitialized_copy_n(first, insert_amount, begin_ + insert_index);
611  }
612  catch (...) {
613  /* Destruct all values that have been moved. */
614  destruct_n(begin_ + new_size - move_amount, move_amount);
615  end_ = begin_ + insert_index;
616  UPDATE_VECTOR_SIZE(this);
617  throw;
618  }
619  end_ = begin_ + new_size;
620  UPDATE_VECTOR_SIZE(this);
621  }
622 
627  void prepend(const T &&value)
628  {
629  this->insert(0, value);
630  }
631  void prepend(T &&value)
632  {
633  this->insert(0, std::move(value));
634  }
635  void prepend(Span<T> values)
636  {
637  this->insert(0, values);
638  }
639  template<typename InputIt> void prepend(InputIt first, InputIt last)
640  {
641  this->insert(0, first, last);
642  }
643 
648  const T &last() const
649  {
650  BLI_assert(this->size() > 0);
651  return *(end_ - 1);
652  }
653  T &last()
654  {
655  BLI_assert(this->size() > 0);
656  return *(end_ - 1);
657  }
658 
662  int64_t size() const
663  {
664  const int64_t current_size = static_cast<int64_t>(end_ - begin_);
665  BLI_assert(debug_size_ == current_size);
666  return current_size;
667  }
668 
674  bool is_empty() const
675  {
676  return begin_ == end_;
677  }
678 
683  void remove_last()
684  {
685  BLI_assert(!this->is_empty());
686  end_--;
687  end_->~T();
688  UPDATE_VECTOR_SIZE(this);
689  }
690 
698  {
699  BLI_assert(!this->is_empty());
700  T value = std::move(*(end_ - 1));
701  end_--;
702  end_->~T();
703  UPDATE_VECTOR_SIZE(this);
704  return value;
705  }
706 
711  void remove_and_reorder(const int64_t index)
712  {
713  BLI_assert(index >= 0);
714  BLI_assert(index < this->size());
715  T *element_to_remove = begin_ + index;
716  if (element_to_remove < end_) {
717  *element_to_remove = std::move(*(end_ - 1));
718  }
719  end_--;
720  end_->~T();
721  UPDATE_VECTOR_SIZE(this);
722  }
723 
729  {
730  const int64_t index = this->first_index_of(value);
731  this->remove_and_reorder(index);
732  }
733 
741  void remove(const int64_t index)
742  {
743  BLI_assert(index >= 0);
744  BLI_assert(index < this->size());
745  const int64_t last_index = this->size() - 1;
746  for (int64_t i = index; i < last_index; i++) {
747  begin_[i] = std::move(begin_[i + 1]);
748  }
749  begin_[last_index].~T();
750  end_--;
751  UPDATE_VECTOR_SIZE(this);
752  }
753 
760  void remove(const int64_t start_index, const int64_t amount)
761  {
762  const int64_t old_size = this->size();
763  BLI_assert(start_index >= 0);
764  BLI_assert(amount >= 0);
765  BLI_assert(start_index + amount <= old_size);
766  const int64_t move_amount = old_size - start_index - amount;
767  for (int64_t i = 0; i < move_amount; i++) {
768  begin_[start_index + i] = std::move(begin_[start_index + amount + i]);
769  }
770  destruct_n(end_ - amount, amount);
771  end_ -= amount;
772  UPDATE_VECTOR_SIZE(this);
773  }
774 
779  int64_t first_index_of_try(const T &value) const
780  {
781  for (const T *current = begin_; current != end_; current++) {
782  if (*current == value) {
783  return static_cast<int64_t>(current - begin_);
784  }
785  }
786  return -1;
787  }
788 
793  int64_t first_index_of(const T &value) const
794  {
795  const int64_t index = this->first_index_of_try(value);
796  BLI_assert(index >= 0);
797  return index;
798  }
799 
804  bool contains(const T &value) const
805  {
806  return this->first_index_of_try(value) != -1;
807  }
808 
812  void fill(const T &value) const
813  {
814  initialized_fill_n(begin_, this->size(), value);
815  }
816 
820  T *data()
821  {
822  return begin_;
823  }
824 
828  const T *data() const
829  {
830  return begin_;
831  }
832 
833  T *begin()
834  {
835  return begin_;
836  }
837  T *end()
838  {
839  return end_;
840  }
841 
842  const T *begin() const
843  {
844  return begin_;
845  }
846  const T *end() const
847  {
848  return end_;
849  }
850 
851  std::reverse_iterator<T *> rbegin()
852  {
853  return std::reverse_iterator<T *>(this->end());
854  }
855  std::reverse_iterator<T *> rend()
856  {
857  return std::reverse_iterator<T *>(this->begin());
858  }
859 
860  std::reverse_iterator<const T *> rbegin() const
861  {
862  return std::reverse_iterator<T *>(this->end());
863  }
864  std::reverse_iterator<const T *> rend() const
865  {
866  return std::reverse_iterator<T *>(this->begin());
867  }
868 
874  {
875  return static_cast<int64_t>(capacity_end_ - begin_);
876  }
877 
888  {
889  return IndexRange(this->size());
890  }
891 
892  friend bool operator==(const Vector &a, const Vector &b)
893  {
894  return a.as_span() == b.as_span();
895  }
896 
897  friend bool operator!=(const Vector &a, const Vector &b)
898  {
899  return !(a == b);
900  }
901 
905  void print_stats(StringRef name = "") const
906  {
907  std::cout << "Vector Stats: " << name << "\n";
908  std::cout << " Address: " << this << "\n";
909  std::cout << " Elements: " << this->size() << "\n";
910  std::cout << " Capacity: " << (capacity_end_ - begin_) << "\n";
911  std::cout << " Inline Capacity: " << InlineBufferCapacity << "\n";
912 
913  char memory_size_str[15];
914  BLI_str_format_byte_unit(memory_size_str, sizeof(*this), true);
915  std::cout << " Size on Stack: " << memory_size_str << "\n";
916  }
917 
918  private:
919  bool is_inline() const
920  {
921  return begin_ == inline_buffer_;
922  }
923 
924  void ensure_space_for_one()
925  {
926  if (UNLIKELY(end_ >= capacity_end_)) {
927  this->realloc_to_at_least(this->size() + 1);
928  }
929  }
930 
931  BLI_NOINLINE void realloc_to_at_least(const int64_t min_capacity)
932  {
933  if (this->capacity() >= min_capacity) {
934  return;
935  }
936 
937  /* At least double the size of the previous allocation. Otherwise consecutive calls to grow can
938  * cause a reallocation every time even though min_capacity only increments. */
939  const int64_t min_new_capacity = this->capacity() * 2;
940 
941  const int64_t new_capacity = std::max(min_capacity, min_new_capacity);
942  const int64_t size = this->size();
943 
944  T *new_array = static_cast<T *>(
945  allocator_.allocate(static_cast<size_t>(new_capacity) * sizeof(T), alignof(T), AT));
946  try {
947  uninitialized_relocate_n(begin_, size, new_array);
948  }
949  catch (...) {
950  allocator_.deallocate(new_array);
951  throw;
952  }
953 
954  if (!this->is_inline()) {
955  allocator_.deallocate(begin_);
956  }
957 
958  begin_ = new_array;
959  end_ = begin_ + size;
960  capacity_end_ = begin_ + new_capacity;
961  }
962 };
963 
964 #undef UPDATE_VECTOR_SIZE
965 
970 template<typename T, int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T))>
972 
973 } /* namespace blender */
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_NOINLINE
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10) ATTR_NONNULL()
Definition: string.c:1206
#define UNLIKELY(x)
#define AT
#define UPDATE_VECTOR_SIZE(ptr)
Definition: BLI_vector.hh:113
Read Guarded memory(de)allocation.
#define U
unsigned int U
Definition: btGjkEpa3.h:78
T * end()
Definition: util_array.h:234
size_t size() const
Definition: util_array.h:203
T * begin()
Definition: util_array.h:224
constexpr const T * data() const
Definition: BLI_span.hh:217
constexpr int64_t size() const
Definition: BLI_span.hh:254
T & operator[](int64_t index)
Definition: BLI_vector.hh:311
void insert(const int64_t insert_index, T &&value)
Definition: BLI_vector.hh:568
std::reverse_iterator< T * > rbegin()
Definition: BLI_vector.hh:851
int64_t size() const
Definition: BLI_vector.hh:662
void remove_and_reorder(const int64_t index)
Definition: BLI_vector.hh:711
Vector(const Vector< T, OtherInlineBufferCapacity, Allocator > &other)
Definition: BLI_vector.hh:236
MutableSpan< T > as_mutable_span()
Definition: BLI_vector.hh:345
Vector(const Vector &other)
Definition: BLI_vector.hh:227
Vector(Allocator allocator={}) noexcept
Definition: BLI_vector.hh:131
int64_t append_and_get_index(const T &value)
Definition: BLI_vector.hh:453
bool contains(const T &value) const
Definition: BLI_vector.hh:804
void append_unchecked(ForwardT &&value)
Definition: BLI_vector.hh:477
void append(const T &value)
Definition: BLI_vector.hh:438
void insert(const int64_t insert_index, const T &value)
Definition: BLI_vector.hh:564
friend bool operator==(const Vector &a, const Vector &b)
Definition: BLI_vector.hh:892
void prepend(T &&value)
Definition: BLI_vector.hh:631
Vector(ListBase &values, Allocator allocator={})
Definition: BLI_vector.hh:216
Vector(InputIt first, InputIt last, Allocator allocator={})
Definition: BLI_vector.hh:201
void remove(const int64_t index)
Definition: BLI_vector.hh:741
Span< T > as_span() const
Definition: BLI_vector.hh:340
friend class Vector
Definition: BLI_vector.hh:124
bool is_empty() const
Definition: BLI_vector.hh:674
void resize(const int64_t new_size, const T &value)
Definition: BLI_vector.hh:389
const T & operator[](int64_t index) const
Definition: BLI_vector.hh:304
void remove_first_occurrence_and_reorder(const T &value)
Definition: BLI_vector.hh:728
void print_stats(StringRef name="") const
Definition: BLI_vector.hh:905
std::reverse_iterator< const T * > rbegin() const
Definition: BLI_vector.hh:860
IndexRange index_range() const
Definition: BLI_vector.hh:887
void prepend(InputIt first, InputIt last)
Definition: BLI_vector.hh:639
void resize(const int64_t new_size)
Definition: BLI_vector.hh:368
int64_t first_index_of(const T &value) const
Definition: BLI_vector.hh:793
void clear_and_make_inline()
Definition: BLI_vector.hh:419
void extend_unchecked(Span< T > array)
Definition: BLI_vector.hh:541
void remove_last()
Definition: BLI_vector.hh:683
void prepend(Span< T > values)
Definition: BLI_vector.hh:635
Vector(NoExceptConstructor, Allocator allocator={}) noexcept
Definition: BLI_vector.hh:139
Vector(Span< U > values, Allocator allocator={})
Definition: BLI_vector.hh:167
std::reverse_iterator< T * > rend()
Definition: BLI_vector.hh:855
void reserve(const int64_t min_capacity)
Definition: BLI_vector.hh:355
const T & const_reference
Definition: BLI_vector.hh:84
const T * end() const
Definition: BLI_vector.hh:846
int64_t size_type
Definition: BLI_vector.hh:87
void remove(const int64_t start_index, const int64_t amount)
Definition: BLI_vector.hh:760
void extend(Span< T > array)
Definition: BLI_vector.hh:515
void append(T &&value)
Definition: BLI_vector.hh:443
void insert(const T *insert_position, InputIt first, InputIt last)
Definition: BLI_vector.hh:577
void prepend(const T &&value)
Definition: BLI_vector.hh:627
void extend_non_duplicates(Span< T > array)
Definition: BLI_vector.hh:530
Vector(int64_t size, const T &value, Allocator allocator={})
Definition: BLI_vector.hh:157
void append_non_duplicates(const T &value)
Definition: BLI_vector.hh:465
const T & last() const
Definition: BLI_vector.hh:648
void fill(const T &value) const
Definition: BLI_vector.hh:812
void insert(const int64_t insert_index, InputIt first, InputIt last)
Definition: BLI_vector.hh:582
Vector(const std::array< U, N > &values)
Definition: BLI_vector.hh:193
const T * begin() const
Definition: BLI_vector.hh:842
Vector(int64_t size, Allocator allocator={})
Definition: BLI_vector.hh:148
const T * const_pointer
Definition: BLI_vector.hh:82
void insert(const int64_t insert_index, Span< T > array)
Definition: BLI_vector.hh:573
const T * data() const
Definition: BLI_vector.hh:828
void extend(InputIt first, InputIt last)
Definition: BLI_vector.hh:554
void extend(const T *start, int64_t amount)
Definition: BLI_vector.hh:519
Vector & operator=(Vector &&other)
Definition: BLI_vector.hh:295
Vector(const std::initializer_list< U > &values)
Definition: BLI_vector.hh:182
friend bool operator!=(const Vector &a, const Vector &b)
Definition: BLI_vector.hh:897
void extend_unchecked(const T *start, int64_t amount)
Definition: BLI_vector.hh:545
void increase_size_by_unchecked(const int64_t n) noexcept
Definition: BLI_vector.hh:503
int64_t capacity() const
Definition: BLI_vector.hh:873
std::reverse_iterator< const T * > rend() const
Definition: BLI_vector.hh:864
Vector & operator=(const Vector &other)
Definition: BLI_vector.hh:290
int64_t first_index_of_try(const T &value) const
Definition: BLI_vector.hh:779
void append_n_times(const T &value, const int64_t n)
Definition: BLI_vector.hh:489
const T * const_iterator
Definition: BLI_vector.hh:86
Vector(Vector< T, OtherInlineBufferCapacity, Allocator > &&other) noexcept(std::is_nothrow_move_constructible_v< T >)
Definition: BLI_vector.hh:246
Vector(const std::initializer_list< T > &values)
Definition: BLI_vector.hh:186
#define T
static unsigned a[3]
Definition: RandGen.cpp:92
Container & move_assign_container(Container &dst, Container &&src) noexcept(std::is_nothrow_move_constructible_v< Container >)
void default_construct_n(T *ptr, int64_t n)
Container & copy_assign_container(Container &dst, const Container &src)
void initialized_fill_n(T *dst, int64_t n, const T &value)
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 destruct_n(T *ptr, int64_t n)
void uninitialized_copy_n(const T *src, int64_t n, T *dst)
params N
__int64 int64_t
Definition: stdint.h:92
float max
ccl_device_inline float distance(const float2 &a, const float2 &b)