34 #include <initializer_list>
39 #include <type_traits>
48 #ifndef LLVM_NODISCARD
49 #define LLVM_NODISCARD
51 #ifndef LLVM_GSL_OWNER
52 #define LLVM_GSL_OWNER
59 void *Result = std::malloc(Sz);
60 if (Result ==
nullptr) {
65 throw std::bad_alloc();
71 void *Result = std::realloc(Ptr, Sz);
72 if (Result ==
nullptr) {
77 throw std::bad_alloc();
82 template <
typename IteratorT>
93 template <
class Size_T>
111 void *
mallocForGrow(
size_t MinSize,
size_t TSize,
size_t &NewCapacity);
116 void grow_pod(
void *FirstEl,
size_t MinSize,
size_t TSize);
137 typename std::conditional<
sizeof(T) < 4 &&
sizeof(
void *) >= 8,
142 template <
class T,
typename =
void>
152 template <
typename T,
typename =
void>
160 void *getFirstEl()
const {
161 return const_cast<void *
>(
reinterpret_cast<const void *
>(
162 reinterpret_cast<const char *
>(
this) +
181 this->
BeginX = getFirstEl();
189 const void *Last)
const {
191 std::less<> LessThan;
192 return !LessThan(V, First) && LessThan(V, Last);
204 std::less<> LessThan;
205 return !LessThan(First, this->
begin()) && !LessThan(Last, First) &&
206 !LessThan(this->
end(), Last);
216 if (NewSize <= this->
size())
return Elt < this->
begin() + NewSize;
225 "Attempting to reference an element of the vector in an "
227 "that invalidates it");
238 if (From ==
To)
return;
242 template <
class ItTy,
244 !std::is_same<std::remove_const_t<ItTy>, T *>::value,
250 if (From ==
To)
return;
254 template <
class ItTy,
256 !std::is_same<std::remove_const_t<ItTy>, T *>::value,
266 size_t NewSize = This->size() + N;
269 bool ReferencesStorage =
false;
271 if (!U::TakesParamByValue) {
273 ReferencesStorage =
true;
274 Index = &Elt - This->begin();
278 return ReferencesStorage ? This->begin() +
Index : &Elt;
329 assert(idx <
size());
333 assert(idx <
size());
364 template <
typename T,
365 bool = (std::is_trivially_copy_constructible<T>::value) &&
366 (std::is_trivially_move_constructible<T>::value) &&
367 std::is_trivially_destructible<T>::value>
386 template <
typename It1,
typename It2>
388 std::uninitialized_copy(std::make_move_iterator(I),
389 std::make_move_iterator(E), Dest);
394 template <
typename It1,
typename It2>
396 std::uninitialized_copy(I, E, Dest);
402 void grow(
size_t MinSize = 0);
407 return static_cast<T *
>(
409 MinSize,
sizeof(T), NewCapacity));
428 return const_cast<T *
>(
439 std::uninitialized_fill_n(NewElts, NumElts, Elt);
445 template <
typename... ArgTypes>
450 ::new ((
void *)(NewElts + this->
size()))
451 T(std::forward<ArgTypes>(Args)...);
461 ::new ((
void *)this->
end()) T(*EltPtr);
467 ::new ((
void *)this->
end()) T(::std::move(*EltPtr));
478 template <
typename T,
bool TriviallyCopyable>
481 T *NewElts = mallocForGrow(MinSize, NewCapacity);
482 moveElementsForGrow(NewElts);
483 takeAllocationForGrow(NewElts, NewCapacity);
487 template <
typename T,
bool TriviallyCopyable>
491 this->uninitialized_move(this->begin(), this->end(), NewElts);
494 destroy_range(this->begin(), this->end());
498 template <
typename T,
bool TriviallyCopyable>
500 T *NewElts,
size_t NewCapacity) {
502 if (!this->isSmall()) free(this->begin());
504 this->BeginX = NewElts;
505 this->Capacity = NewCapacity;
512 template <
typename T>
533 template <
typename It1,
typename It2>
541 template <
typename It1,
typename It2>
544 std::uninitialized_copy(I, E, Dest);
549 template <
typename T1,
typename T2>
555 T2>::value> * =
nullptr) {
561 memcpy(
reinterpret_cast<void *
>(Dest), I, (E - I) *
sizeof(T));
577 return const_cast<T *
>(
590 std::uninitialized_fill_n(this->
begin(), NumElts, Elt);
594 template <
typename... ArgTypes>
599 push_back(T(std::forward<ArgTypes>(Args)...));
606 memcpy(
reinterpret_cast<void *
>(this->
end()), EltPtr,
sizeof(T));
615 template <
typename T>
635 this->
BeginX = RHS.BeginX;
636 this->
Size = RHS.Size;
659 template <
bool ForOverwrite>
661 if (N == this->
size())
return;
663 if (N < this->
size()) {
669 for (
auto I = this->
end(), E = this->
begin() + N; I != E; ++I)
685 assert(this->
size() >= N &&
"Cannot increase size with truncate");
691 if (N == this->
size())
return;
693 if (N < this->
size()) {
707 assert(this->
size() >= NumItems);
712 T Result = ::std::move(this->
back());
720 template <
typename in_iter,
721 typename = std::enable_if_t<std::is_convertible<
722 typename std::iterator_traits<in_iter>::iterator_category,
723 std::input_iterator_tag>::value>>
724 void append(in_iter in_start, in_iter in_end) {
726 size_type NumInputs = std::distance(in_start, in_end);
735 std::uninitialized_fill_n(this->
end(), NumInputs, *EltPtr);
739 void append(std::initializer_list<T> IL) {
append(IL.begin(), IL.end()); }
752 if (NumElts > this->
size())
753 std::uninitialized_fill_n(this->
end(), NumElts - this->
size(), Elt);
754 else if (NumElts < this->
size())
762 template <
typename in_iter,
763 typename = std::enable_if_t<std::is_convertible<
764 typename std::iterator_traits<in_iter>::iterator_category,
765 std::input_iterator_tag>::value>>
766 void assign(in_iter in_start, in_iter in_end) {
772 void assign(std::initializer_list<T> IL) {
784 "Iterator to erase is out of bounds.");
788 std::move(I + 1, this->
end(), I);
800 "Range to erase is out of bounds.");
812 template <
class ArgType>
817 std::remove_const_t<std::remove_reference_t<ArgType>>,
819 "ArgType must be derived from T!");
821 if (I == this->
end()) {
822 this->
push_back(::std::forward<ArgType>(Elt));
823 return this->
end() - 1;
827 "Insertion iterator is out of bounds.");
831 std::remove_reference_t<ArgType> *EltPtr =
835 ::new ((
void *)this->
end()) T(::
std::move(this->
back()));
837 std::move_backward(I, this->
end() - 1, this->
end());
843 "ArgType must be 'T' when taking by value!");
848 *I = ::
std::forward<ArgType>(*EltPtr);
864 size_t InsertElt = I - this->
begin();
866 if (I == this->
end()) {
868 return this->
begin() + InsertElt;
872 "Insertion iterator is out of bounds.");
879 I = this->
begin() + InsertElt;
885 if (
size_t(this->
end() - I) >= NumToInsert) {
886 T *OldEnd = this->
end();
887 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
888 std::move_iterator<iterator>(this->
end()));
891 std::move_backward(I, OldEnd - NumToInsert, OldEnd);
896 EltPtr += NumToInsert;
898 std::fill_n(I, NumToInsert, *EltPtr);
906 T *OldEnd = this->
end();
908 size_t NumOverwritten = OldEnd - I;
914 EltPtr += NumToInsert;
917 std::fill_n(I, NumOverwritten, *EltPtr);
920 std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten,
925 template <
typename ItTy,
926 typename = std::enable_if_t<std::is_convertible<
927 typename std::iterator_traits<ItTy>::iterator_category,
928 std::input_iterator_tag>::value>>
932 size_t InsertElt = I - this->
begin();
934 if (I == this->
end()) {
936 return this->
begin() + InsertElt;
940 "Insertion iterator is out of bounds.");
945 size_t NumToInsert = std::distance(From,
To);
951 I = this->
begin() + InsertElt;
957 if (
size_t(this->
end() - I) >= NumToInsert) {
958 T *OldEnd = this->
end();
959 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
960 std::move_iterator<iterator>(this->
end()));
963 std::move_backward(I, OldEnd - NumToInsert, OldEnd);
973 T *OldEnd = this->
end();
975 size_t NumOverwritten = OldEnd - I;
979 for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
991 insert(I, IL.begin(), IL.end());
994 template <
typename... ArgTypes>
999 ::new ((
void *)this->
end()) T(std::forward<ArgTypes>(Args)...);
1001 return this->
back();
1009 if (this->
size() != RHS.
size())
return false;
1013 return !(*
this == RHS);
1017 return std::lexicographical_compare(this->
begin(), this->
end(),
1025 template <
typename T>
1027 if (
this == &RHS)
return;
1040 size_t NumShared = this->
size();
1041 if (NumShared > RHS.
size()) NumShared = RHS.
size();
1046 size_t EltDiff = this->
size() - RHS.
size();
1052 }
else if (RHS.
size() > this->size()) {
1053 size_t EltDiff = RHS.
size() - this->
size();
1062 template <
typename T>
1066 if (
this == &RHS)
return *
this;
1070 size_t RHSSize = RHS.
size();
1071 size_t CurSize = this->
size();
1072 if (CurSize >= RHSSize) {
1079 NewEnd = this->
begin();
1096 this->
grow(RHSSize);
1097 }
else if (CurSize) {
1104 this->begin() + CurSize);
1111 template <
typename T>
1114 if (
this == &RHS)
return *
this;
1117 if (!RHS.isSmall()) {
1124 size_t RHSSize = RHS.size();
1125 size_t CurSize = this->
size();
1126 if (CurSize >= RHSSize) {
1129 if (RHSSize) NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
1149 this->
grow(RHSSize);
1150 }
else if (CurSize) {
1152 std::move(RHS.begin(), RHS.begin() + CurSize, this->begin());
1157 this->begin() + CurSize);
1168 template <
typename T,
unsigned N>
1170 alignas(T)
char InlineElts[N *
sizeof(T)];
1176 template <
typename T>
1182 template <
typename T,
unsigned N>
1190 template <
typename T>
1199 static constexpr
size_t kPreferredSmallVectorSizeof = 64;
1226 "You are trying to use a default number of inlined elements for "
1227 "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
1228 "explicit number of inlined elements with `SmallVector<T, N>` to "
1230 "sure you really want that much inline storage.");
1234 static constexpr
size_t PreferredInlineBytes =
1236 static constexpr
size_t NumElementsThatFit =
1237 PreferredInlineBytes /
sizeof(T);
1238 static constexpr
size_t value =
1239 NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
1258 template <
typename T,
1272 this->
assign(Size, Value);
1275 template <
typename ItTy,
1276 typename = std::enable_if_t<std::is_convertible<
1277 typename std::iterator_traits<ItTy>::iterator_category,
1278 std::input_iterator_tag>::value>>
1283 template <
typename RangeTy>
1286 this->
append(R.begin(), R.end());
1317 if (
this == &RHS)
return *
this;
1338 template <
typename T,
unsigned N>
1340 return X.capacity_in_bytes();
1343 template <
typename RangeType>
1345 typename std::remove_reference<decltype(*std::begin(
1351 template <
unsigned Size,
typename R>
1353 return {std::begin(Range), std::end(Range)};
1355 template <
typename R>
1356 SmallVector<ValueTypeFromRangeType<R>,
1357 CalculateSmallVectorDefaultInlinedElements<
1358 ValueTypeFromRangeType<R>>::value>
1360 return {std::begin(Range), std::end(Range)};
1369 template <
typename T>
1376 template <
typename T,
unsigned N>
void * mallocForGrow(size_t MinSize, size_t TSize, size_t &NewCapacity)
SmallVectorBase(void *FirstEl, size_t TotalCapacity)
static constexpr size_t SizeTypeMax()
The maximum value of the Size_T used.
void grow_pod(void *FirstEl, size_t MinSize, size_t TSize)
void swap(SmallVectorImpl &RHS)
bool operator<(const SmallVectorImpl &RHS) const
iterator erase(const_iterator CI)
bool operator==(const SmallVectorImpl &RHS) const
bool operator<=(const SmallVectorImpl &RHS) const
iterator erase(const_iterator CS, const_iterator CE)
typename SuperClass::size_type size_type
void pop_back_n(size_type NumItems)
void append(std::initializer_list< T > IL)
void assign(std::initializer_list< T > IL)
iterator insert(iterator I, T &&Elt)
bool operator!=(const SmallVectorImpl &RHS) const
SmallVectorImpl(unsigned N)
bool operator>(const SmallVectorImpl &RHS) const
typename SuperClass::iterator iterator
void append(const SmallVectorImpl &RHS)
SmallVectorImpl & operator=(const SmallVectorImpl &RHS)
void truncate(size_type N)
Like resize, but requires that N is less than size().
void append(size_type NumInputs, ValueParamT Elt)
Append NumInputs copies of Elt to the end.
void reserve(size_type N)
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
void insert(iterator I, std::initializer_list< T > IL)
void resize_for_overwrite(size_type N)
Like resize, but T is POD, the new values won't be initialized.
void assign(const SmallVectorImpl &RHS)
iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt)
void assign(size_type NumElts, ValueParamT Elt)
iterator insert(iterator I, ItTy From, ItTy To)
void resize(size_type N, ValueParamT NV)
void assign(in_iter in_start, in_iter in_end)
void assignRemote(SmallVectorImpl &&RHS)
SmallVectorImpl(const SmallVectorImpl &)=delete
bool operator>=(const SmallVectorImpl &RHS) const
reference emplace_back(ArgTypes &&...Args)
iterator insert(iterator I, const T &Elt)
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest, std::enable_if_t< std::is_same< typename std::remove_const< T1 >::type, T2 >::value > *=nullptr)
void push_back(ValueParamT Elt)
static void uninitialized_move(It1 I, It1 E, It2 Dest)
T & growAndEmplaceBack(ArgTypes &&...Args)
SmallVectorTemplateBase(size_t Size)
void grow(size_t MinSize=0)
static ValueParamT forward_value_param(ValueParamT V)
Copy V or return a reference, depending on ValueParamT.
void growAndAssign(size_t NumElts, T Elt)
typename std::conditional< TakesParamByValue, T, const T & >::type ValueParamT
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
T * reserveForParamAndGetAddress(T &Elt, size_t N=1)
const T * reserveForParamAndGetAddress(const T &Elt, size_t N=1)
static void destroy_range(T *, T *)
void growAndAssign(size_t NumElts, const T &Elt)
T * reserveForParamAndGetAddress(T &Elt, size_t N=1)
T * mallocForGrow(size_t MinSize, size_t &NewCapacity)
static T && forward_value_param(T &&V)
void push_back(const T &Elt)
SmallVectorTemplateBase(size_t Size)
void moveElementsForGrow(T *NewElts)
static const T & forward_value_param(const T &V)
static constexpr bool TakesParamByValue
static void uninitialized_move(It1 I, It1 E, It2 Dest)
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
static void destroy_range(T *S, T *E)
void takeAllocationForGrow(T *NewElts, size_t NewCapacity)
Transfer ownership of the allocation, finishing up grow().
void grow(size_t MinSize=0)
const T * reserveForParamAndGetAddress(const T &Elt, size_t N=1)
T & growAndEmplaceBack(ArgTypes &&...Args)
reference operator[](size_type idx)
ptrdiff_t difference_type
const_iterator begin() const
void assertSafeToAdd(const void *Elt, size_t N=1)
bool isReferenceToRange(const void *V, const void *First, const void *Last) const
Return true if V is an internal reference to the given range.
void assertSafeToAddRange(const T *From, const T *To)
Check whether any part of the range will be invalidated by growing.
bool isRangeInStorage(const void *First, const void *Last) const
pointer data()
Return a pointer to the vector's buffer, even if empty().
size_t capacity_in_bytes() const
void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize)
Check whether Elt will be invalidated by resizing the vector to NewSize.
const_reverse_iterator rbegin() const
SmallVectorTemplateCommon(size_t Size)
void assertSafeToReferenceAfterClear(ItTy, ItTy)
std::reverse_iterator< const_iterator > const_reverse_iterator
bool isReferenceToStorage(const void *V) const
Return true if V is an internal reference to this vector.
void resetToSmall()
Put this vector in a state of being small.
size_type max_size() const
size_type size_in_bytes() const
const_reference front() const
const_reference operator[](size_type idx) const
std::reverse_iterator< iterator > reverse_iterator
const_pointer data() const
Return a pointer to the vector's buffer, even if empty().
void assertSafeToAddRange(ItTy, ItTy)
void grow_pod(size_t MinSize, size_t TSize)
const_reverse_iterator rend() const
const_iterator end() const
reverse_iterator rbegin()
const T & const_reference
void assertSafeToReferenceAfterClear(const T *From, const T *To)
Check whether any part of the range will be invalidated by clearing.
bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize)
const_reference back() const
static const T * reserveForParamAndGetAddressImpl(U *This, const T &Elt, size_t N)
SmallVector(SmallVector &&RHS)
SmallVector(std::initializer_list< T > IL)
SmallVector & operator=(std::initializer_list< T > IL)
SmallVector(const iterator_range< RangeTy > &R)
SmallVector(size_t Size, const T &Value=T())
SmallVector(ItTy S, ItTy E)
SmallVector & operator=(const SmallVector &RHS)
SmallVector & operator=(SmallVector &&RHS)
SmallVector(const SmallVector &RHS)
SmallVector & operator=(SmallVectorImpl< T > &&RHS)
SmallVector(SmallVectorImpl< T > &&RHS)
typename std::remove_const< typename std::remove_reference< decltype(*std::begin(std::declval< RangeType & >()))>::type >::type ValueTypeFromRangeType
void * safe_malloc(size_t Sz)
typename std::conditional< sizeof(T)< 4 &&sizeof(void *) >=8, uint64_t, uint32_t >::type SmallVectorSizeType
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
void * safe_realloc(void *Ptr, size_t Sz)
void To(const core::Tensor &src, core::Tensor &dst, double scale, double offset)
Generic file read and write utility for python interface.
void swap(cloudViewer::core::SmallVector< T, N > &LHS, cloudViewer::core::SmallVector< T, N > &RHS)
Implement std::swap in terms of SmallVector swap.
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
#define offsetof(STRUCTURE, FIELD)
Figure out the offset of the first element.
char Base[sizeof(SmallVectorBase< SmallVectorSizeType< T >>)]