10#include <initializer_list>
20namespace tf {
namespace detail {
28inline uint64_t NextCapacity(uint64_t A) {
47struct IsPod : std::integral_constant<bool, std::is_standard_layout<T>::value &&
48 std::is_trivial<T>::value> {};
53class SmallVectorBase {
55 void *BeginX, *EndX, *CapacityX;
58 SmallVectorBase(
void *FirstEl,
size_t Size)
59 : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {}
63 void grow_pod(
void *FirstEl,
size_t MinSizeInBytes,
size_t TSize){
64 size_t CurSizeBytes = size_in_bytes();
65 size_t NewCapacityInBytes = 2 * capacity_in_bytes() + TSize;
66 if (NewCapacityInBytes < MinSizeInBytes) {
67 NewCapacityInBytes = MinSizeInBytes;
71 if (BeginX == FirstEl) {
72 NewElts = std::malloc(NewCapacityInBytes);
75 memcpy(NewElts, this->BeginX, CurSizeBytes);
78 NewElts = realloc(this->BeginX, NewCapacityInBytes);
82 this->EndX = (
char*)NewElts+CurSizeBytes;
83 this->BeginX = NewElts;
84 this->CapacityX = (
char*)this->BeginX + NewCapacityInBytes;
92 size_t size_in_bytes()
const {
93 return size_t((
char*)EndX - (
char*)BeginX);
100 size_t capacity_in_bytes()
const {
101 return size_t((
char*)CapacityX - (
char*)BeginX);
104 bool empty()
const {
return BeginX == EndX; }
110template <
typename T,
unsigned N>
struct SmallVectorStorage;
115template <
typename T,
typename =
void>
116class SmallVectorTemplateCommon :
public SmallVectorBase {
119 template <
typename,
unsigned>
friend struct SmallVectorStorage;
126 template <
typename X>
127 struct AlignedUnionType {
128 static constexpr std::size_t max_size = (
sizeof(std::byte) >
sizeof(X)) ?
sizeof(std::byte) :
sizeof(X);
129 alignas(X) std::byte buff[max_size];
138 typedef AlignedUnionType<T> U;
144 SmallVectorTemplateCommon(
size_t Size) : SmallVectorBase(&FirstEl, Size) {}
146 void grow_pod(
size_t MinSizeInBytes,
size_t TSize) {
147 SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize);
152 bool isSmall()
const {
153 return BeginX ==
static_cast<const void*
>(&FirstEl);
157 void resetToSmall() {
158 BeginX = EndX = CapacityX = &FirstEl;
161 void setEnd(T *P) { this->EndX = P; }
164 typedef size_t size_type;
165 typedef ptrdiff_t difference_type;
166 typedef T value_type;
168 typedef const T *const_iterator;
170 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
171 typedef std::reverse_iterator<iterator> reverse_iterator;
173 typedef T &reference;
174 typedef const T &const_reference;
176 typedef const T *const_pointer;
179 inline iterator begin() {
return (iterator)this->BeginX; }
180 inline const_iterator begin()
const {
return (const_iterator)this->BeginX; }
181 inline iterator end() {
return (iterator)this->EndX; }
182 inline const_iterator end()
const {
return (const_iterator)this->EndX; }
186 iterator capacity_ptr() {
return (iterator)this->CapacityX; }
187 const_iterator capacity_ptr()
const {
return (const_iterator)this->CapacityX;}
192 reverse_iterator rbegin() {
return reverse_iterator(end()); }
193 const_reverse_iterator rbegin()
const{
return const_reverse_iterator(end()); }
194 reverse_iterator rend() {
return reverse_iterator(begin()); }
195 const_reverse_iterator rend()
const {
return const_reverse_iterator(begin());}
197 inline size_type size()
const {
return end()-begin(); }
198 inline size_type max_size()
const {
return size_type(-1) /
sizeof(T); }
201 size_t capacity()
const {
return capacity_ptr() - begin(); }
204 pointer data() {
return pointer(begin()); }
206 const_pointer data()
const {
return const_pointer(begin()); }
208 inline reference operator[](size_type idx) {
213 inline const_reference operator[](size_type idx)
const {
223 const_reference front()
const {
233 const_reference back()
const {
242template <
typename T,
bool isPodLike>
243class SmallVectorTemplateBase :
public SmallVectorTemplateCommon<T> {
246 SmallVectorTemplateBase(
size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
248 static void destroy_range(T *S, T *E) {
257 template<
typename It1,
typename It2>
258 static void uninitialized_move(It1 I, It1 E, It2 Dest) {
259 std::uninitialized_copy(std::make_move_iterator(I),
260 std::make_move_iterator(E), Dest);
265 template<
typename It1,
typename It2>
266 static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
267 std::uninitialized_copy(I, E, Dest);
273 void grow(
size_t MinSize = 0);
276 void push_back(
const T &Elt) {
277 if ((this->EndX >= this->CapacityX)) [[unlikely]]
279 ::new ((
void*) this->end()) T(Elt);
280 this->setEnd(this->end()+1);
283 void push_back(T &&Elt) {
284 if ((this->EndX >= this->CapacityX)) [[unlikely]]
286 ::new ((
void*) this->end()) T(::std::move(Elt));
287 this->setEnd(this->end()+1);
291 this->setEnd(this->end()-1);
299template <
typename T,
bool isPodLike>
300void SmallVectorTemplateBase<T, isPodLike>::grow(
size_t MinSize) {
301 size_t CurCapacity = this->capacity();
302 size_t CurSize = this->size();
304 size_t NewCapacity = size_t(tf::detail::NextCapacity(CurCapacity+2));
305 if (NewCapacity < MinSize)
306 NewCapacity = MinSize;
307 T *NewElts =
static_cast<T*
>(std::malloc(NewCapacity*
sizeof(T)));
310 this->uninitialized_move(this->begin(), this->end(), NewElts);
313 destroy_range(this->begin(), this->end());
316 if (!this->isSmall())
317 std::free(this->begin());
319 this->setEnd(NewElts+CurSize);
320 this->BeginX = NewElts;
321 this->CapacityX = this->begin()+NewCapacity;
328class SmallVectorTemplateBase<T, true> :
public SmallVectorTemplateCommon<T> {
330 SmallVectorTemplateBase(
size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
333 static void destroy_range(T *, T *) {}
337 template<
typename It1,
typename It2>
338 static void uninitialized_move(It1 I, It1 E, It2 Dest) {
340 uninitialized_copy(I, E, Dest);
345 template<
typename It1,
typename It2>
346 static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
348 std::uninitialized_copy(I, E, Dest);
353 template <
typename T1,
typename T2>
354 static void uninitialized_copy(
355 T1 *I, T1 *E, T2 *Dest,
356 typename std::enable_if<std::is_same<
typename std::remove_const<T1>::type,
357 T2>::value>::type * =
nullptr) {
363 memcpy(Dest, I, (E - I) *
sizeof(T));
368 void grow(
size_t MinSize = 0) {
369 this->grow_pod(MinSize*
sizeof(T),
sizeof(T));
372 void push_back(
const T &Elt) {
373 if ((this->EndX >= this->CapacityX)) [[unlikely]]
375 memcpy(this->end(), &Elt,
sizeof(T));
376 this->setEnd(this->end()+1);
380 this->setEnd(this->end()-1);
388class SmallVectorImpl :
public SmallVectorTemplateBase<T, IsPod<T>::value> {
389 typedef SmallVectorTemplateBase<T, IsPod<T>::value> SuperClass;
391 SmallVectorImpl(
const SmallVectorImpl&) =
delete;
394 typedef typename SuperClass::iterator iterator;
395 typedef typename SuperClass::const_iterator const_iterator;
396 typedef typename SuperClass::size_type size_type;
400 explicit SmallVectorImpl(
unsigned N)
401 : SmallVectorTemplateBase<T, IsPod<T>::value>(N*sizeof(T)) {
407 this->destroy_range(this->begin(), this->end());
410 if (!this->isSmall())
411 std::free(this->begin());
416 this->destroy_range(this->begin(), this->end());
417 this->EndX = this->BeginX;
420 void resize(size_type N) {
421 if (N < this->size()) {
422 this->destroy_range(this->begin()+N, this->end());
423 this->setEnd(this->begin()+N);
424 }
else if (N > this->size()) {
425 if (this->capacity() < N)
427 for (
auto I = this->end(), E = this->begin() + N; I != E; ++I)
429 this->setEnd(this->begin()+N);
433 void resize(size_type N,
const T &NV) {
434 if (N < this->size()) {
435 this->destroy_range(this->begin()+N, this->end());
436 this->setEnd(this->begin()+N);
437 }
else if (N > this->size()) {
438 if (this->capacity() < N)
440 std::uninitialized_fill(this->end(), this->begin()+N, NV);
441 this->setEnd(this->begin()+N);
445 void reserve(size_type N) {
446 if (this->capacity() < N)
451 T Result = ::std::move(this->back());
456 void swap(SmallVectorImpl &RHS);
459 template<
typename in_iter>
460 void append(in_iter in_start, in_iter in_end) {
461 size_type NumInputs = std::distance(in_start, in_end);
463 if (NumInputs > size_type(this->capacity_ptr()-this->end()))
464 this->grow(this->size()+NumInputs);
467 this->uninitialized_copy(in_start, in_end, this->end());
468 this->setEnd(this->end() + NumInputs);
472 void append(size_type NumInputs,
const T &Elt) {
474 if (NumInputs > size_type(this->capacity_ptr()-this->end()))
475 this->grow(this->size()+NumInputs);
478 std::uninitialized_fill_n(this->end(), NumInputs, Elt);
479 this->setEnd(this->end() + NumInputs);
482 void append(std::initializer_list<T> IL) {
483 append(IL.begin(), IL.end());
486 void assign(size_type NumElts,
const T &Elt) {
488 if (this->capacity() < NumElts)
490 this->setEnd(this->begin()+NumElts);
491 std::uninitialized_fill(this->begin(), this->end(), Elt);
494 void assign(std::initializer_list<T> IL) {
499 iterator erase(const_iterator CI) {
501 iterator I =
const_cast<iterator
>(CI);
508 std::move(I+1, this->end(), I);
514 iterator erase(const_iterator CS, const_iterator CE) {
516 iterator S =
const_cast<iterator
>(CS);
517 iterator E =
const_cast<iterator
>(CE);
525 iterator I = std::move(E, this->end(), S);
527 this->destroy_range(I, this->end());
532 iterator insert(iterator I, T &&Elt) {
533 if (I == this->end()) {
534 this->push_back(::std::move(Elt));
535 return this->end()-1;
541 if (this->EndX >= this->CapacityX) {
542 size_t EltNo = I-this->begin();
544 I = this->begin()+EltNo;
547 ::new ((
void*) this->end()) T(::std::move(this->back()));
549 std::move_backward(I, this->end()-1, this->end());
550 this->setEnd(this->end()+1);
555 if (I <= EltPtr && EltPtr < this->EndX)
558 *I = ::std::move(*EltPtr);
562 iterator insert(iterator I, const T &Elt) {
563 if (I == this->end()) {
564 this->push_back(Elt);
565 return this->end()-1;
571 if (this->EndX >= this->CapacityX) {
572 size_t EltNo = I-this->begin();
574 I = this->begin()+EltNo;
576 ::new ((
void*) this->end()) T(std::move(this->back()));
578 std::move_backward(I, this->end()-1, this->end());
579 this->setEnd(this->end()+1);
583 const T *EltPtr = &Elt;
584 if (I <= EltPtr && EltPtr < this->EndX)
591 iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
593 size_t InsertElt = I - this->begin();
595 if (I == this->end()) {
596 append(NumToInsert, Elt);
597 return this->begin()+InsertElt;
604 reserve(this->size() + NumToInsert);
607 I = this->begin()+InsertElt;
613 if (
size_t(this->end()-I) >= NumToInsert) {
614 T *OldEnd = this->end();
615 append(std::move_iterator<iterator>(this->end() - NumToInsert),
616 std::move_iterator<iterator>(this->end()));
619 std::move_backward(I, OldEnd-NumToInsert, OldEnd);
621 std::fill_n(I, NumToInsert, Elt);
629 T *OldEnd = this->end();
630 this->setEnd(this->end() + NumToInsert);
631 size_t NumOverwritten = OldEnd-I;
632 this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
635 std::fill_n(I, NumOverwritten, Elt);
638 std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
642 template<
typename ItTy>
643 iterator insert(iterator I, ItTy From, ItTy To) {
645 size_t InsertElt = I - this->begin();
647 if (I == this->end()) {
649 return this->begin()+InsertElt;
655 size_t NumToInsert = std::distance(From, To);
658 reserve(this->size() + NumToInsert);
661 I = this->begin()+InsertElt;
667 if (
size_t(this->end()-I) >= NumToInsert) {
668 T *OldEnd = this->end();
669 append(std::move_iterator<iterator>(this->end() - NumToInsert),
670 std::move_iterator<iterator>(this->end()));
673 std::move_backward(I, OldEnd-NumToInsert, OldEnd);
675 std::copy(From, To, I);
683 T *OldEnd = this->end();
684 this->setEnd(this->end() + NumToInsert);
685 size_t NumOverwritten = OldEnd-I;
686 this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
689 for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
695 this->uninitialized_copy(From, To, OldEnd);
699 void insert(iterator I, std::initializer_list<T> IL) {
700 insert(I, IL.begin(), IL.end());
703 template <
typename... ArgTypes>
void emplace_back(ArgTypes &&... Args) {
704 if ((this->EndX >= this->CapacityX)) [[unlikely]]
706 ::new ((
void *)this->end()) T(std::forward<ArgTypes>(Args)...);
707 this->setEnd(this->end() + 1);
710 SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
712 SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
714 bool operator==(const SmallVectorImpl &RHS)
const {
715 if (this->size() != RHS.size())
return false;
716 return std::equal(this->begin(), this->end(), RHS.begin());
718 bool operator!=(
const SmallVectorImpl &RHS)
const {
719 return !(*
this == RHS);
722 bool operator<(
const SmallVectorImpl &RHS)
const {
723 return std::lexicographical_compare(this->begin(), this->end(),
724 RHS.begin(), RHS.end());
736 void set_size(size_type N) {
738 this->setEnd(this->begin() + N);
744void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
745 if (
this == &RHS)
return;
748 if (!this->isSmall() && !RHS.isSmall()) {
749 std::swap(this->BeginX, RHS.BeginX);
750 std::swap(this->EndX, RHS.EndX);
751 std::swap(this->CapacityX, RHS.CapacityX);
754 if (RHS.size() > this->capacity())
755 this->grow(RHS.size());
756 if (this->size() > RHS.capacity())
757 RHS.grow(this->size());
760 size_t NumShared = this->size();
761 if (NumShared > RHS.size()) NumShared = RHS.size();
762 for (size_type i = 0; i != NumShared; ++i)
763 std::swap((*
this)[i], RHS[i]);
766 if (this->size() > RHS.size()) {
767 size_t EltDiff = this->size() - RHS.size();
768 this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
769 RHS.setEnd(RHS.end()+EltDiff);
770 this->destroy_range(this->begin()+NumShared, this->end());
771 this->setEnd(this->begin()+NumShared);
772 }
else if (RHS.size() > this->size()) {
773 size_t EltDiff = RHS.size() - this->size();
774 this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
775 this->setEnd(this->end() + EltDiff);
776 this->destroy_range(RHS.begin()+NumShared, RHS.end());
777 RHS.setEnd(RHS.begin()+NumShared);
782SmallVectorImpl<T> &SmallVectorImpl<T>::
783 operator=(
const SmallVectorImpl<T> &RHS) {
785 if (
this == &RHS)
return *
this;
789 size_t RHSSize = RHS.size();
790 size_t CurSize = this->size();
791 if (CurSize >= RHSSize) {
795 NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
797 NewEnd = this->begin();
800 this->destroy_range(NewEnd, this->end());
803 this->setEnd(NewEnd);
810 if (this->capacity() < RHSSize) {
812 this->destroy_range(this->begin(), this->end());
813 this->setEnd(this->begin());
816 }
else if (CurSize) {
818 std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
822 this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
823 this->begin()+CurSize);
826 this->setEnd(this->begin()+RHSSize);
831SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
833 if (
this == &RHS)
return *
this;
836 if (!RHS.isSmall()) {
837 this->destroy_range(this->begin(), this->end());
838 if (!this->isSmall()) std::free(this->begin());
839 this->BeginX = RHS.BeginX;
840 this->EndX = RHS.EndX;
841 this->CapacityX = RHS.CapacityX;
848 size_t RHSSize = RHS.size();
849 size_t CurSize = this->size();
850 if (CurSize >= RHSSize) {
852 iterator NewEnd = this->begin();
854 NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
857 this->destroy_range(NewEnd, this->end());
858 this->setEnd(NewEnd);
870 if (this->capacity() < RHSSize) {
872 this->destroy_range(this->begin(), this->end());
873 this->setEnd(this->begin());
876 }
else if (CurSize) {
878 std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
882 this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
883 this->begin()+CurSize);
886 this->setEnd(this->begin()+RHSSize);
895template <
typename T,
unsigned N>
896struct SmallVectorStorage {
900 typename SmallVectorTemplateCommon<T>::U InlineElts[N - 1];
906template <
typename T>
struct SmallVectorStorage<T, 1> {};
911template <
typename T>
struct SmallVectorStorage<T, 0> {};
930template <
typename T,
unsigned N = 2>
933 SmallVectorStorage<T, N> Storage;
947 : SmallVectorImpl<T>(N) {
948 this->assign(Size, Value);
955 template<
typename ItTy>
969 SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
978 SmallVectorImpl<T>::operator=(RHS);
986 SmallVectorImpl<T>::operator=(::std::move(RHS));
993 SmallVectorImpl<T>::operator=(RHS);
1001 SmallVectorImpl<T>::operator=(::std::move(RHS));
1010 SmallVectorImpl<T>::operator=(::std::move(RHS));
1017 SmallVectorImpl<T>::operator=(::std::move(RHS));
1033template<
typename T,
unsigned N>
1034inline size_t capacity_in_bytes(
const SmallVector<T, N> &X) {
1035 return X.capacity_in_bytes();
1042 template<
typename T>
1044 swap(tf::SmallVectorImpl<T> &LHS, tf::SmallVectorImpl<T> &RHS) {
1049 template<
typename T,
unsigned N>
1051 swap(tf::SmallVector<T, N> &LHS, tf::SmallVector<T, N> &RHS) {
SmallVector(size_t Size, const T &Value=T())
constructs a vector with Size copies of elements with value value
Definition small_vector.hpp:946
const SmallVector & operator=(std::initializer_list< T > IL)
replaces the contents with the copy of the contents of an initializer list IL
Definition small_vector.hpp:1024
SmallVector(ItTy S, ItTy E)
constructs a vector with the contents of the range [S, E)
Definition small_vector.hpp:956
SmallVector(SmallVectorImpl< T > &&RHS)
constructs a vector with the contents of RHS using move semantics
Definition small_vector.hpp:1008
const SmallVector & operator=(const SmallVector &RHS)
replaces the contents with a copy of the contents of RHS
Definition small_vector.hpp:992
const SmallVector & operator=(SmallVector &&RHS)
replaces the contents with the contents of RHS using move semantics
Definition small_vector.hpp:1000
SmallVector()
constructs an empty vector
Definition small_vector.hpp:940
SmallVector(const SmallVector &RHS)
constructs the vector with the copy of the contents of RHS
Definition small_vector.hpp:976
SmallVector(SmallVector &&RHS)
constructs the vector with the contents of RHS using move semantics
Definition small_vector.hpp:984
SmallVector(std::initializer_list< T > IL)
constructs a vector with the contents of the initializer list IL
Definition small_vector.hpp:969
const SmallVector & operator=(SmallVectorImpl< T > &&RHS)
replaces the contents with the contents of RHS using move semantics
Definition small_vector.hpp:1016
taskflow namespace
Definition small_vector.hpp:20