1*da0073e9SAndroid Build Coastguard Worker //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
2*da0073e9SAndroid Build Coastguard Worker //
3*da0073e9SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*da0073e9SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*da0073e9SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*da0073e9SAndroid Build Coastguard Worker //
7*da0073e9SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*da0073e9SAndroid Build Coastguard Worker //
9*da0073e9SAndroid Build Coastguard Worker // This file defines the SmallVector class.
10*da0073e9SAndroid Build Coastguard Worker //
11*da0073e9SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
12*da0073e9SAndroid Build Coastguard Worker
13*da0073e9SAndroid Build Coastguard Worker // ATen: modified from llvm::SmallVector.
14*da0073e9SAndroid Build Coastguard Worker // used std::is_trivially_{copy,move}_constructible
15*da0073e9SAndroid Build Coastguard Worker // replaced iterator_range constructor with inline Container&& constructor
16*da0073e9SAndroid Build Coastguard Worker // replaced LLVM_NODISCARD, LLVM_LIKELY, and LLVM_UNLIKELY with c10 equivalents
17*da0073e9SAndroid Build Coastguard Worker // removed LLVM_GSL_OWNER
18*da0073e9SAndroid Build Coastguard Worker // added SmallVector::at
19*da0073e9SAndroid Build Coastguard Worker // added operator<< for std::ostream
20*da0073e9SAndroid Build Coastguard Worker // added C10_API to export SmallVectorBase
21*da0073e9SAndroid Build Coastguard Worker
22*da0073e9SAndroid Build Coastguard Worker #pragma once
23*da0073e9SAndroid Build Coastguard Worker
24*da0073e9SAndroid Build Coastguard Worker #include <c10/macros/Macros.h>
25*da0073e9SAndroid Build Coastguard Worker #include <c10/util/AlignOf.h>
26*da0073e9SAndroid Build Coastguard Worker
27*da0073e9SAndroid Build Coastguard Worker #include <algorithm>
28*da0073e9SAndroid Build Coastguard Worker #include <cassert>
29*da0073e9SAndroid Build Coastguard Worker #include <cstddef>
30*da0073e9SAndroid Build Coastguard Worker #include <cstdlib>
31*da0073e9SAndroid Build Coastguard Worker #include <cstring>
32*da0073e9SAndroid Build Coastguard Worker #include <functional>
33*da0073e9SAndroid Build Coastguard Worker #include <initializer_list>
34*da0073e9SAndroid Build Coastguard Worker #include <iterator>
35*da0073e9SAndroid Build Coastguard Worker #include <limits>
36*da0073e9SAndroid Build Coastguard Worker #include <memory>
37*da0073e9SAndroid Build Coastguard Worker #include <ostream>
38*da0073e9SAndroid Build Coastguard Worker #include <type_traits>
39*da0073e9SAndroid Build Coastguard Worker #include <utility>
40*da0073e9SAndroid Build Coastguard Worker
41*da0073e9SAndroid Build Coastguard Worker namespace c10 {
42*da0073e9SAndroid Build Coastguard Worker
43*da0073e9SAndroid Build Coastguard Worker /// This is all the stuff common to all SmallVectors.
44*da0073e9SAndroid Build Coastguard Worker ///
45*da0073e9SAndroid Build Coastguard Worker /// The template parameter specifies the type which should be used to hold the
46*da0073e9SAndroid Build Coastguard Worker /// Size and Capacity of the SmallVector, so it can be adjusted.
47*da0073e9SAndroid Build Coastguard Worker /// Using 32 bit size is desirable to shrink the size of the SmallVector.
48*da0073e9SAndroid Build Coastguard Worker /// Using 64 bit size is desirable for cases like SmallVector<char>, where a
49*da0073e9SAndroid Build Coastguard Worker /// 32 bit size would limit the vector to ~4GB. SmallVectors are used for
50*da0073e9SAndroid Build Coastguard Worker /// buffering bitcode output - which can exceed 4GB.
51*da0073e9SAndroid Build Coastguard Worker template <class Size_T>
52*da0073e9SAndroid Build Coastguard Worker class C10_API SmallVectorBase {
53*da0073e9SAndroid Build Coastguard Worker protected:
54*da0073e9SAndroid Build Coastguard Worker void* BeginX;
55*da0073e9SAndroid Build Coastguard Worker Size_T Size = 0, Capacity;
56*da0073e9SAndroid Build Coastguard Worker
57*da0073e9SAndroid Build Coastguard Worker /// The maximum value of the Size_T used.
SizeTypeMax()58*da0073e9SAndroid Build Coastguard Worker static constexpr size_t SizeTypeMax() {
59*da0073e9SAndroid Build Coastguard Worker return std::numeric_limits<Size_T>::max();
60*da0073e9SAndroid Build Coastguard Worker }
61*da0073e9SAndroid Build Coastguard Worker
SmallVectorBase(void * FirstEl,size_t TotalCapacity)62*da0073e9SAndroid Build Coastguard Worker SmallVectorBase(void* FirstEl, size_t TotalCapacity)
63*da0073e9SAndroid Build Coastguard Worker : BeginX(FirstEl), Capacity(TotalCapacity) {}
64*da0073e9SAndroid Build Coastguard Worker
65*da0073e9SAndroid Build Coastguard Worker /// This is a helper for \a grow() that's out of line to reduce code
66*da0073e9SAndroid Build Coastguard Worker /// duplication. This function will report a fatal error if it can't grow at
67*da0073e9SAndroid Build Coastguard Worker /// least to \p MinSize.
68*da0073e9SAndroid Build Coastguard Worker void* mallocForGrow(size_t MinSize, size_t TSize, size_t& NewCapacity);
69*da0073e9SAndroid Build Coastguard Worker
70*da0073e9SAndroid Build Coastguard Worker /// This is an implementation of the grow() method which only works
71*da0073e9SAndroid Build Coastguard Worker /// on POD-like data types and is out of line to reduce code duplication.
72*da0073e9SAndroid Build Coastguard Worker /// This function will report a fatal error if it cannot increase capacity.
73*da0073e9SAndroid Build Coastguard Worker void grow_pod(const void* FirstEl, size_t MinSize, size_t TSize);
74*da0073e9SAndroid Build Coastguard Worker
75*da0073e9SAndroid Build Coastguard Worker public:
76*da0073e9SAndroid Build Coastguard Worker SmallVectorBase() = delete;
size()77*da0073e9SAndroid Build Coastguard Worker size_t size() const {
78*da0073e9SAndroid Build Coastguard Worker return Size;
79*da0073e9SAndroid Build Coastguard Worker }
capacity()80*da0073e9SAndroid Build Coastguard Worker size_t capacity() const {
81*da0073e9SAndroid Build Coastguard Worker return Capacity;
82*da0073e9SAndroid Build Coastguard Worker }
83*da0073e9SAndroid Build Coastguard Worker
empty()84*da0073e9SAndroid Build Coastguard Worker C10_NODISCARD bool empty() const {
85*da0073e9SAndroid Build Coastguard Worker return !Size;
86*da0073e9SAndroid Build Coastguard Worker }
87*da0073e9SAndroid Build Coastguard Worker
88*da0073e9SAndroid Build Coastguard Worker /// Set the array size to \p N, which the current array must have enough
89*da0073e9SAndroid Build Coastguard Worker /// capacity for.
90*da0073e9SAndroid Build Coastguard Worker ///
91*da0073e9SAndroid Build Coastguard Worker /// This does not construct or destroy any elements in the vector.
92*da0073e9SAndroid Build Coastguard Worker ///
93*da0073e9SAndroid Build Coastguard Worker /// Clients can use this in conjunction with capacity() to write past the end
94*da0073e9SAndroid Build Coastguard Worker /// of the buffer when they know that more elements are available, and only
95*da0073e9SAndroid Build Coastguard Worker /// update the size later. This avoids the cost of value initializing elements
96*da0073e9SAndroid Build Coastguard Worker /// which will only be overwritten.
set_size(size_t N)97*da0073e9SAndroid Build Coastguard Worker void set_size(size_t N) {
98*da0073e9SAndroid Build Coastguard Worker assert(N <= capacity());
99*da0073e9SAndroid Build Coastguard Worker Size = N;
100*da0073e9SAndroid Build Coastguard Worker }
101*da0073e9SAndroid Build Coastguard Worker };
102*da0073e9SAndroid Build Coastguard Worker
103*da0073e9SAndroid Build Coastguard Worker template <class T>
104*da0073e9SAndroid Build Coastguard Worker using SmallVectorSizeType =
105*da0073e9SAndroid Build Coastguard Worker std::conditional_t<sizeof(T) < 4 && sizeof(void*) >= 8, uint64_t, uint32_t>;
106*da0073e9SAndroid Build Coastguard Worker
107*da0073e9SAndroid Build Coastguard Worker /// Figure out the offset of the first element.
108*da0073e9SAndroid Build Coastguard Worker template <class T, typename = void>
109*da0073e9SAndroid Build Coastguard Worker struct SmallVectorAlignmentAndSize {
110*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(*c-arrays*)
111*da0073e9SAndroid Build Coastguard Worker alignas(SmallVectorBase<SmallVectorSizeType<T>>) char Base[sizeof(
112*da0073e9SAndroid Build Coastguard Worker SmallVectorBase<SmallVectorSizeType<T>>)];
113*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(*c-arrays*)
114*da0073e9SAndroid Build Coastguard Worker alignas(T) char FirstEl[sizeof(T)];
115*da0073e9SAndroid Build Coastguard Worker };
116*da0073e9SAndroid Build Coastguard Worker
117*da0073e9SAndroid Build Coastguard Worker /// This is the part of SmallVectorTemplateBase which does not depend on whether
118*da0073e9SAndroid Build Coastguard Worker /// the type T is a POD. The extra dummy template argument is used by ArrayRef
119*da0073e9SAndroid Build Coastguard Worker /// to avoid unnecessarily requiring T to be complete.
120*da0073e9SAndroid Build Coastguard Worker template <typename T, typename = void>
121*da0073e9SAndroid Build Coastguard Worker class SmallVectorTemplateCommon
122*da0073e9SAndroid Build Coastguard Worker : public SmallVectorBase<SmallVectorSizeType<T>> {
123*da0073e9SAndroid Build Coastguard Worker using Base = SmallVectorBase<SmallVectorSizeType<T>>;
124*da0073e9SAndroid Build Coastguard Worker
125*da0073e9SAndroid Build Coastguard Worker /// Find the address of the first element. For this pointer math to be valid
126*da0073e9SAndroid Build Coastguard Worker /// with small-size of 0 for T with lots of alignment, it's important that
127*da0073e9SAndroid Build Coastguard Worker /// SmallVectorStorage is properly-aligned even for small-size of 0.
getFirstEl()128*da0073e9SAndroid Build Coastguard Worker void* getFirstEl() const {
129*da0073e9SAndroid Build Coastguard Worker return const_cast<void*>(reinterpret_cast<const void*>(
130*da0073e9SAndroid Build Coastguard Worker reinterpret_cast<const char*>(this) +
131*da0073e9SAndroid Build Coastguard Worker offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)));
132*da0073e9SAndroid Build Coastguard Worker }
133*da0073e9SAndroid Build Coastguard Worker // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
134*da0073e9SAndroid Build Coastguard Worker
135*da0073e9SAndroid Build Coastguard Worker protected:
SmallVectorTemplateCommon(size_t Size)136*da0073e9SAndroid Build Coastguard Worker SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {}
137*da0073e9SAndroid Build Coastguard Worker
grow_pod(size_t MinSize,size_t TSize)138*da0073e9SAndroid Build Coastguard Worker void grow_pod(size_t MinSize, size_t TSize) {
139*da0073e9SAndroid Build Coastguard Worker Base::grow_pod(getFirstEl(), MinSize, TSize);
140*da0073e9SAndroid Build Coastguard Worker }
141*da0073e9SAndroid Build Coastguard Worker
142*da0073e9SAndroid Build Coastguard Worker /// Return true if this is a smallvector which has not had dynamic
143*da0073e9SAndroid Build Coastguard Worker /// memory allocated for it.
isSmall()144*da0073e9SAndroid Build Coastguard Worker bool isSmall() const {
145*da0073e9SAndroid Build Coastguard Worker return this->BeginX == getFirstEl();
146*da0073e9SAndroid Build Coastguard Worker }
147*da0073e9SAndroid Build Coastguard Worker
148*da0073e9SAndroid Build Coastguard Worker /// Put this vector in a state of being small.
resetToSmall()149*da0073e9SAndroid Build Coastguard Worker void resetToSmall() {
150*da0073e9SAndroid Build Coastguard Worker this->BeginX = getFirstEl();
151*da0073e9SAndroid Build Coastguard Worker this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect.
152*da0073e9SAndroid Build Coastguard Worker }
153*da0073e9SAndroid Build Coastguard Worker
154*da0073e9SAndroid Build Coastguard Worker /// Return true if V is an internal reference to the given range.
isReferenceToRange(const void * V,const void * First,const void * Last)155*da0073e9SAndroid Build Coastguard Worker bool isReferenceToRange(const void* V, const void* First, const void* Last)
156*da0073e9SAndroid Build Coastguard Worker const {
157*da0073e9SAndroid Build Coastguard Worker // Use std::less to avoid UB.
158*da0073e9SAndroid Build Coastguard Worker std::less<> LessThan;
159*da0073e9SAndroid Build Coastguard Worker return !LessThan(V, First) && LessThan(V, Last);
160*da0073e9SAndroid Build Coastguard Worker }
161*da0073e9SAndroid Build Coastguard Worker
162*da0073e9SAndroid Build Coastguard Worker /// Return true if V is an internal reference to this vector.
isReferenceToStorage(const void * V)163*da0073e9SAndroid Build Coastguard Worker bool isReferenceToStorage(const void* V) const {
164*da0073e9SAndroid Build Coastguard Worker return isReferenceToRange(V, this->begin(), this->end());
165*da0073e9SAndroid Build Coastguard Worker }
166*da0073e9SAndroid Build Coastguard Worker
167*da0073e9SAndroid Build Coastguard Worker /// Return true if First and Last form a valid (possibly empty) range in this
168*da0073e9SAndroid Build Coastguard Worker /// vector's storage.
isRangeInStorage(const void * First,const void * Last)169*da0073e9SAndroid Build Coastguard Worker bool isRangeInStorage(const void* First, const void* Last) const {
170*da0073e9SAndroid Build Coastguard Worker // Use std::less to avoid UB.
171*da0073e9SAndroid Build Coastguard Worker std::less<> LessThan;
172*da0073e9SAndroid Build Coastguard Worker return !LessThan(First, this->begin()) && !LessThan(Last, First) &&
173*da0073e9SAndroid Build Coastguard Worker !LessThan(this->end(), Last);
174*da0073e9SAndroid Build Coastguard Worker }
175*da0073e9SAndroid Build Coastguard Worker
176*da0073e9SAndroid Build Coastguard Worker /// Return true unless Elt will be invalidated by resizing the vector to
177*da0073e9SAndroid Build Coastguard Worker /// NewSize.
isSafeToReferenceAfterResize(const void * Elt,size_t NewSize)178*da0073e9SAndroid Build Coastguard Worker bool isSafeToReferenceAfterResize(const void* Elt, size_t NewSize) {
179*da0073e9SAndroid Build Coastguard Worker // Past the end.
180*da0073e9SAndroid Build Coastguard Worker if (C10_LIKELY(!isReferenceToStorage(Elt)))
181*da0073e9SAndroid Build Coastguard Worker return true;
182*da0073e9SAndroid Build Coastguard Worker
183*da0073e9SAndroid Build Coastguard Worker // Return false if Elt will be destroyed by shrinking.
184*da0073e9SAndroid Build Coastguard Worker if (NewSize <= this->size())
185*da0073e9SAndroid Build Coastguard Worker return Elt < this->begin() + NewSize;
186*da0073e9SAndroid Build Coastguard Worker
187*da0073e9SAndroid Build Coastguard Worker // Return false if we need to grow.
188*da0073e9SAndroid Build Coastguard Worker return NewSize <= this->capacity();
189*da0073e9SAndroid Build Coastguard Worker }
190*da0073e9SAndroid Build Coastguard Worker
191*da0073e9SAndroid Build Coastguard Worker /// Check whether Elt will be invalidated by resizing the vector to NewSize.
assertSafeToReferenceAfterResize(const void * Elt,size_t NewSize)192*da0073e9SAndroid Build Coastguard Worker void assertSafeToReferenceAfterResize(const void* Elt, size_t NewSize) {
193*da0073e9SAndroid Build Coastguard Worker (void)Elt; // Suppress unused variable warning
194*da0073e9SAndroid Build Coastguard Worker (void)NewSize; // Suppress unused variable warning
195*da0073e9SAndroid Build Coastguard Worker assert(
196*da0073e9SAndroid Build Coastguard Worker isSafeToReferenceAfterResize(Elt, NewSize) &&
197*da0073e9SAndroid Build Coastguard Worker "Attempting to reference an element of the vector in an operation "
198*da0073e9SAndroid Build Coastguard Worker "that invalidates it");
199*da0073e9SAndroid Build Coastguard Worker }
200*da0073e9SAndroid Build Coastguard Worker
201*da0073e9SAndroid Build Coastguard Worker /// Check whether Elt will be invalidated by increasing the size of the
202*da0073e9SAndroid Build Coastguard Worker /// vector by N.
203*da0073e9SAndroid Build Coastguard Worker void assertSafeToAdd(const void* Elt, size_t N = 1) {
204*da0073e9SAndroid Build Coastguard Worker this->assertSafeToReferenceAfterResize(Elt, this->size() + N);
205*da0073e9SAndroid Build Coastguard Worker }
206*da0073e9SAndroid Build Coastguard Worker
207*da0073e9SAndroid Build Coastguard Worker /// Check whether any part of the range will be invalidated by clearing.
assertSafeToReferenceAfterClear(const T * From,const T * To)208*da0073e9SAndroid Build Coastguard Worker void assertSafeToReferenceAfterClear(const T* From, const T* To) {
209*da0073e9SAndroid Build Coastguard Worker if (From == To)
210*da0073e9SAndroid Build Coastguard Worker return;
211*da0073e9SAndroid Build Coastguard Worker this->assertSafeToReferenceAfterResize(From, 0);
212*da0073e9SAndroid Build Coastguard Worker this->assertSafeToReferenceAfterResize(To - 1, 0);
213*da0073e9SAndroid Build Coastguard Worker }
214*da0073e9SAndroid Build Coastguard Worker template <
215*da0073e9SAndroid Build Coastguard Worker class ItTy,
216*da0073e9SAndroid Build Coastguard Worker std::enable_if_t<!std::is_same_v<std::remove_const_t<ItTy>, T*>, bool> =
217*da0073e9SAndroid Build Coastguard Worker false>
assertSafeToReferenceAfterClear(ItTy,ItTy)218*da0073e9SAndroid Build Coastguard Worker void assertSafeToReferenceAfterClear(ItTy, ItTy) {}
219*da0073e9SAndroid Build Coastguard Worker
220*da0073e9SAndroid Build Coastguard Worker /// Check whether any part of the range will be invalidated by growing.
assertSafeToAddRange(const T * From,const T * To)221*da0073e9SAndroid Build Coastguard Worker void assertSafeToAddRange(const T* From, const T* To) {
222*da0073e9SAndroid Build Coastguard Worker if (From == To)
223*da0073e9SAndroid Build Coastguard Worker return;
224*da0073e9SAndroid Build Coastguard Worker this->assertSafeToAdd(From, To - From);
225*da0073e9SAndroid Build Coastguard Worker this->assertSafeToAdd(To - 1, To - From);
226*da0073e9SAndroid Build Coastguard Worker }
227*da0073e9SAndroid Build Coastguard Worker template <
228*da0073e9SAndroid Build Coastguard Worker class ItTy,
229*da0073e9SAndroid Build Coastguard Worker std::enable_if_t<!std::is_same_v<std::remove_const_t<ItTy>, T*>, bool> =
230*da0073e9SAndroid Build Coastguard Worker false>
assertSafeToAddRange(ItTy,ItTy)231*da0073e9SAndroid Build Coastguard Worker void assertSafeToAddRange(ItTy, ItTy) {}
232*da0073e9SAndroid Build Coastguard Worker
233*da0073e9SAndroid Build Coastguard Worker /// Reserve enough space to add one element, and return the updated element
234*da0073e9SAndroid Build Coastguard Worker /// pointer in case it was a reference to the storage.
235*da0073e9SAndroid Build Coastguard Worker template <class U>
reserveForParamAndGetAddressImpl(U * This,const T & Elt,size_t N)236*da0073e9SAndroid Build Coastguard Worker static const T* reserveForParamAndGetAddressImpl(
237*da0073e9SAndroid Build Coastguard Worker U* This,
238*da0073e9SAndroid Build Coastguard Worker const T& Elt,
239*da0073e9SAndroid Build Coastguard Worker size_t N) {
240*da0073e9SAndroid Build Coastguard Worker size_t NewSize = This->size() + N;
241*da0073e9SAndroid Build Coastguard Worker if (C10_LIKELY(NewSize <= This->capacity()))
242*da0073e9SAndroid Build Coastguard Worker return &Elt;
243*da0073e9SAndroid Build Coastguard Worker
244*da0073e9SAndroid Build Coastguard Worker bool ReferencesStorage = false;
245*da0073e9SAndroid Build Coastguard Worker int64_t Index = -1;
246*da0073e9SAndroid Build Coastguard Worker if constexpr (!U::TakesParamByValue) {
247*da0073e9SAndroid Build Coastguard Worker if (C10_UNLIKELY(This->isReferenceToStorage(&Elt))) {
248*da0073e9SAndroid Build Coastguard Worker ReferencesStorage = true;
249*da0073e9SAndroid Build Coastguard Worker Index = &Elt - This->begin();
250*da0073e9SAndroid Build Coastguard Worker }
251*da0073e9SAndroid Build Coastguard Worker }
252*da0073e9SAndroid Build Coastguard Worker This->grow(NewSize);
253*da0073e9SAndroid Build Coastguard Worker return ReferencesStorage ? This->begin() + Index : &Elt;
254*da0073e9SAndroid Build Coastguard Worker }
255*da0073e9SAndroid Build Coastguard Worker
256*da0073e9SAndroid Build Coastguard Worker public:
257*da0073e9SAndroid Build Coastguard Worker using size_type = size_t;
258*da0073e9SAndroid Build Coastguard Worker using difference_type = ptrdiff_t;
259*da0073e9SAndroid Build Coastguard Worker using value_type = T;
260*da0073e9SAndroid Build Coastguard Worker using iterator = T*;
261*da0073e9SAndroid Build Coastguard Worker using const_iterator = const T*;
262*da0073e9SAndroid Build Coastguard Worker
263*da0073e9SAndroid Build Coastguard Worker using const_reverse_iterator = std::reverse_iterator<const_iterator>;
264*da0073e9SAndroid Build Coastguard Worker using reverse_iterator = std::reverse_iterator<iterator>;
265*da0073e9SAndroid Build Coastguard Worker
266*da0073e9SAndroid Build Coastguard Worker using reference = T&;
267*da0073e9SAndroid Build Coastguard Worker using const_reference = const T&;
268*da0073e9SAndroid Build Coastguard Worker using pointer = T*;
269*da0073e9SAndroid Build Coastguard Worker using const_pointer = const T*;
270*da0073e9SAndroid Build Coastguard Worker
271*da0073e9SAndroid Build Coastguard Worker using Base::capacity;
272*da0073e9SAndroid Build Coastguard Worker using Base::empty;
273*da0073e9SAndroid Build Coastguard Worker using Base::size;
274*da0073e9SAndroid Build Coastguard Worker
275*da0073e9SAndroid Build Coastguard Worker // forward iterator creation methods.
begin()276*da0073e9SAndroid Build Coastguard Worker iterator begin() {
277*da0073e9SAndroid Build Coastguard Worker return (iterator)this->BeginX;
278*da0073e9SAndroid Build Coastguard Worker }
begin()279*da0073e9SAndroid Build Coastguard Worker const_iterator begin() const {
280*da0073e9SAndroid Build Coastguard Worker return (const_iterator)this->BeginX;
281*da0073e9SAndroid Build Coastguard Worker }
end()282*da0073e9SAndroid Build Coastguard Worker iterator end() {
283*da0073e9SAndroid Build Coastguard Worker return begin() + size();
284*da0073e9SAndroid Build Coastguard Worker }
end()285*da0073e9SAndroid Build Coastguard Worker const_iterator end() const {
286*da0073e9SAndroid Build Coastguard Worker return begin() + size();
287*da0073e9SAndroid Build Coastguard Worker }
288*da0073e9SAndroid Build Coastguard Worker
289*da0073e9SAndroid Build Coastguard Worker // reverse iterator creation methods.
rbegin()290*da0073e9SAndroid Build Coastguard Worker reverse_iterator rbegin() {
291*da0073e9SAndroid Build Coastguard Worker return reverse_iterator(end());
292*da0073e9SAndroid Build Coastguard Worker }
rbegin()293*da0073e9SAndroid Build Coastguard Worker const_reverse_iterator rbegin() const {
294*da0073e9SAndroid Build Coastguard Worker return const_reverse_iterator(end());
295*da0073e9SAndroid Build Coastguard Worker }
rend()296*da0073e9SAndroid Build Coastguard Worker reverse_iterator rend() {
297*da0073e9SAndroid Build Coastguard Worker return reverse_iterator(begin());
298*da0073e9SAndroid Build Coastguard Worker }
rend()299*da0073e9SAndroid Build Coastguard Worker const_reverse_iterator rend() const {
300*da0073e9SAndroid Build Coastguard Worker return const_reverse_iterator(begin());
301*da0073e9SAndroid Build Coastguard Worker }
302*da0073e9SAndroid Build Coastguard Worker
size_in_bytes()303*da0073e9SAndroid Build Coastguard Worker size_type size_in_bytes() const {
304*da0073e9SAndroid Build Coastguard Worker return size() * sizeof(T);
305*da0073e9SAndroid Build Coastguard Worker }
max_size()306*da0073e9SAndroid Build Coastguard Worker constexpr size_type max_size() const {
307*da0073e9SAndroid Build Coastguard Worker return std::min(this->SizeTypeMax(), size_type(-1) / sizeof(T));
308*da0073e9SAndroid Build Coastguard Worker }
309*da0073e9SAndroid Build Coastguard Worker
capacity_in_bytes()310*da0073e9SAndroid Build Coastguard Worker size_t capacity_in_bytes() const {
311*da0073e9SAndroid Build Coastguard Worker return capacity() * sizeof(T);
312*da0073e9SAndroid Build Coastguard Worker }
313*da0073e9SAndroid Build Coastguard Worker
314*da0073e9SAndroid Build Coastguard Worker /// Return a pointer to the vector's buffer, even if empty().
data()315*da0073e9SAndroid Build Coastguard Worker pointer data() {
316*da0073e9SAndroid Build Coastguard Worker return pointer(begin());
317*da0073e9SAndroid Build Coastguard Worker }
318*da0073e9SAndroid Build Coastguard Worker /// Return a pointer to the vector's buffer, even if empty().
data()319*da0073e9SAndroid Build Coastguard Worker const_pointer data() const {
320*da0073e9SAndroid Build Coastguard Worker return const_pointer(begin());
321*da0073e9SAndroid Build Coastguard Worker }
322*da0073e9SAndroid Build Coastguard Worker
323*da0073e9SAndroid Build Coastguard Worker // SmallVector::at is NOT from LLVM.
at(size_type idx)324*da0073e9SAndroid Build Coastguard Worker reference at(size_type idx) {
325*da0073e9SAndroid Build Coastguard Worker assert(idx < size());
326*da0073e9SAndroid Build Coastguard Worker return begin()[idx];
327*da0073e9SAndroid Build Coastguard Worker }
at(size_type idx)328*da0073e9SAndroid Build Coastguard Worker const_reference at(size_type idx) const {
329*da0073e9SAndroid Build Coastguard Worker assert(idx < size());
330*da0073e9SAndroid Build Coastguard Worker return begin()[idx];
331*da0073e9SAndroid Build Coastguard Worker }
332*da0073e9SAndroid Build Coastguard Worker reference operator[](size_type idx) {
333*da0073e9SAndroid Build Coastguard Worker assert(idx < size());
334*da0073e9SAndroid Build Coastguard Worker return begin()[idx];
335*da0073e9SAndroid Build Coastguard Worker }
336*da0073e9SAndroid Build Coastguard Worker const_reference operator[](size_type idx) const {
337*da0073e9SAndroid Build Coastguard Worker assert(idx < size());
338*da0073e9SAndroid Build Coastguard Worker return begin()[idx];
339*da0073e9SAndroid Build Coastguard Worker }
340*da0073e9SAndroid Build Coastguard Worker
front()341*da0073e9SAndroid Build Coastguard Worker reference front() {
342*da0073e9SAndroid Build Coastguard Worker assert(!empty());
343*da0073e9SAndroid Build Coastguard Worker return begin()[0];
344*da0073e9SAndroid Build Coastguard Worker }
front()345*da0073e9SAndroid Build Coastguard Worker const_reference front() const {
346*da0073e9SAndroid Build Coastguard Worker assert(!empty());
347*da0073e9SAndroid Build Coastguard Worker return begin()[0];
348*da0073e9SAndroid Build Coastguard Worker }
349*da0073e9SAndroid Build Coastguard Worker
back()350*da0073e9SAndroid Build Coastguard Worker reference back() {
351*da0073e9SAndroid Build Coastguard Worker assert(!empty());
352*da0073e9SAndroid Build Coastguard Worker return end()[-1];
353*da0073e9SAndroid Build Coastguard Worker }
back()354*da0073e9SAndroid Build Coastguard Worker const_reference back() const {
355*da0073e9SAndroid Build Coastguard Worker assert(!empty());
356*da0073e9SAndroid Build Coastguard Worker return end()[-1];
357*da0073e9SAndroid Build Coastguard Worker }
358*da0073e9SAndroid Build Coastguard Worker };
359*da0073e9SAndroid Build Coastguard Worker
360*da0073e9SAndroid Build Coastguard Worker /// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put
361*da0073e9SAndroid Build Coastguard Worker /// method implementations that are designed to work with non-trivial T's.
362*da0073e9SAndroid Build Coastguard Worker ///
363*da0073e9SAndroid Build Coastguard Worker /// We approximate is_trivially_copyable with trivial move/copy construction and
364*da0073e9SAndroid Build Coastguard Worker /// trivial destruction. While the standard doesn't specify that you're allowed
365*da0073e9SAndroid Build Coastguard Worker /// copy these types with memcpy, there is no way for the type to observe this.
366*da0073e9SAndroid Build Coastguard Worker /// This catches the important case of std::pair<POD, POD>, which is not
367*da0073e9SAndroid Build Coastguard Worker /// trivially assignable.
368*da0073e9SAndroid Build Coastguard Worker ///
369*da0073e9SAndroid Build Coastguard Worker /// XXX: if build fails here fall back to C10_IS_TRIVIALLY_COPYABLE and make a
370*da0073e9SAndroid Build Coastguard Worker /// note
371*da0073e9SAndroid Build Coastguard Worker template <
372*da0073e9SAndroid Build Coastguard Worker typename T,
373*da0073e9SAndroid Build Coastguard Worker bool = (std::is_trivially_copy_constructible_v<T>)&&(
374*da0073e9SAndroid Build Coastguard Worker std::is_trivially_move_constructible_v<
375*da0073e9SAndroid Build Coastguard Worker T>)&&std::is_trivially_destructible_v<T>>
376*da0073e9SAndroid Build Coastguard Worker class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
377*da0073e9SAndroid Build Coastguard Worker friend class SmallVectorTemplateCommon<T>;
378*da0073e9SAndroid Build Coastguard Worker
379*da0073e9SAndroid Build Coastguard Worker protected:
380*da0073e9SAndroid Build Coastguard Worker static constexpr bool TakesParamByValue = false;
381*da0073e9SAndroid Build Coastguard Worker using ValueParamT = const T&;
382*da0073e9SAndroid Build Coastguard Worker
SmallVectorTemplateBase(size_t Size)383*da0073e9SAndroid Build Coastguard Worker SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
384*da0073e9SAndroid Build Coastguard Worker
destroy_range(T * S,T * E)385*da0073e9SAndroid Build Coastguard Worker static void destroy_range(T* S, T* E) {
386*da0073e9SAndroid Build Coastguard Worker while (S != E) {
387*da0073e9SAndroid Build Coastguard Worker --E;
388*da0073e9SAndroid Build Coastguard Worker E->~T();
389*da0073e9SAndroid Build Coastguard Worker }
390*da0073e9SAndroid Build Coastguard Worker }
391*da0073e9SAndroid Build Coastguard Worker
392*da0073e9SAndroid Build Coastguard Worker /// Move the range [I, E) into the uninitialized memory starting with "Dest",
393*da0073e9SAndroid Build Coastguard Worker /// constructing elements as needed.
394*da0073e9SAndroid Build Coastguard Worker template <typename It1, typename It2>
uninitialized_move(It1 I,It1 E,It2 Dest)395*da0073e9SAndroid Build Coastguard Worker static void uninitialized_move(It1 I, It1 E, It2 Dest) {
396*da0073e9SAndroid Build Coastguard Worker std::uninitialized_copy(
397*da0073e9SAndroid Build Coastguard Worker std::make_move_iterator(I), std::make_move_iterator(E), Dest);
398*da0073e9SAndroid Build Coastguard Worker }
399*da0073e9SAndroid Build Coastguard Worker
400*da0073e9SAndroid Build Coastguard Worker /// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
401*da0073e9SAndroid Build Coastguard Worker /// constructing elements as needed.
402*da0073e9SAndroid Build Coastguard Worker template <typename It1, typename It2>
uninitialized_copy(It1 I,It1 E,It2 Dest)403*da0073e9SAndroid Build Coastguard Worker static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
404*da0073e9SAndroid Build Coastguard Worker std::uninitialized_copy(I, E, Dest);
405*da0073e9SAndroid Build Coastguard Worker }
406*da0073e9SAndroid Build Coastguard Worker
407*da0073e9SAndroid Build Coastguard Worker /// Grow the allocated memory (without initializing new elements), doubling
408*da0073e9SAndroid Build Coastguard Worker /// the size of the allocated memory. Guarantees space for at least one more
409*da0073e9SAndroid Build Coastguard Worker /// element, or MinSize more elements if specified.
410*da0073e9SAndroid Build Coastguard Worker void grow(size_t MinSize = 0);
411*da0073e9SAndroid Build Coastguard Worker
412*da0073e9SAndroid Build Coastguard Worker /// Create a new allocation big enough for \p MinSize and pass back its size
413*da0073e9SAndroid Build Coastguard Worker /// in \p NewCapacity. This is the first section of \a grow().
mallocForGrow(size_t MinSize,size_t & NewCapacity)414*da0073e9SAndroid Build Coastguard Worker T* mallocForGrow(size_t MinSize, size_t& NewCapacity) {
415*da0073e9SAndroid Build Coastguard Worker return static_cast<T*>(
416*da0073e9SAndroid Build Coastguard Worker SmallVectorBase<SmallVectorSizeType<T>>::mallocForGrow(
417*da0073e9SAndroid Build Coastguard Worker MinSize, sizeof(T), NewCapacity));
418*da0073e9SAndroid Build Coastguard Worker }
419*da0073e9SAndroid Build Coastguard Worker
420*da0073e9SAndroid Build Coastguard Worker /// Move existing elements over to the new allocation \p NewElts, the middle
421*da0073e9SAndroid Build Coastguard Worker /// section of \a grow().
422*da0073e9SAndroid Build Coastguard Worker void moveElementsForGrow(T* NewElts);
423*da0073e9SAndroid Build Coastguard Worker
424*da0073e9SAndroid Build Coastguard Worker /// Transfer ownership of the allocation, finishing up \a grow().
425*da0073e9SAndroid Build Coastguard Worker void takeAllocationForGrow(T* NewElts, size_t NewCapacity);
426*da0073e9SAndroid Build Coastguard Worker
427*da0073e9SAndroid Build Coastguard Worker /// Reserve enough space to add one element, and return the updated element
428*da0073e9SAndroid Build Coastguard Worker /// pointer in case it was a reference to the storage.
429*da0073e9SAndroid Build Coastguard Worker const T* reserveForParamAndGetAddress(const T& Elt, size_t N = 1) {
430*da0073e9SAndroid Build Coastguard Worker return this->reserveForParamAndGetAddressImpl(this, Elt, N);
431*da0073e9SAndroid Build Coastguard Worker }
432*da0073e9SAndroid Build Coastguard Worker
433*da0073e9SAndroid Build Coastguard Worker /// Reserve enough space to add one element, and return the updated element
434*da0073e9SAndroid Build Coastguard Worker /// pointer in case it was a reference to the storage.
435*da0073e9SAndroid Build Coastguard Worker T* reserveForParamAndGetAddress(T& Elt, size_t N = 1) {
436*da0073e9SAndroid Build Coastguard Worker return const_cast<T*>(this->reserveForParamAndGetAddressImpl(this, Elt, N));
437*da0073e9SAndroid Build Coastguard Worker }
438*da0073e9SAndroid Build Coastguard Worker
forward_value_param(T && V)439*da0073e9SAndroid Build Coastguard Worker static T&& forward_value_param(T&& V) {
440*da0073e9SAndroid Build Coastguard Worker return std::move(V);
441*da0073e9SAndroid Build Coastguard Worker }
forward_value_param(const T & V)442*da0073e9SAndroid Build Coastguard Worker static const T& forward_value_param(const T& V) {
443*da0073e9SAndroid Build Coastguard Worker return V;
444*da0073e9SAndroid Build Coastguard Worker }
445*da0073e9SAndroid Build Coastguard Worker
growAndAssign(size_t NumElts,const T & Elt)446*da0073e9SAndroid Build Coastguard Worker void growAndAssign(size_t NumElts, const T& Elt) {
447*da0073e9SAndroid Build Coastguard Worker // Grow manually in case Elt is an internal reference.
448*da0073e9SAndroid Build Coastguard Worker size_t NewCapacity = 0;
449*da0073e9SAndroid Build Coastguard Worker T* NewElts = mallocForGrow(NumElts, NewCapacity);
450*da0073e9SAndroid Build Coastguard Worker std::uninitialized_fill_n(NewElts, NumElts, Elt);
451*da0073e9SAndroid Build Coastguard Worker this->destroy_range(this->begin(), this->end());
452*da0073e9SAndroid Build Coastguard Worker takeAllocationForGrow(NewElts, NewCapacity);
453*da0073e9SAndroid Build Coastguard Worker this->set_size(NumElts);
454*da0073e9SAndroid Build Coastguard Worker }
455*da0073e9SAndroid Build Coastguard Worker
456*da0073e9SAndroid Build Coastguard Worker template <typename... ArgTypes>
growAndEmplaceBack(ArgTypes &&...Args)457*da0073e9SAndroid Build Coastguard Worker T& growAndEmplaceBack(ArgTypes&&... Args) {
458*da0073e9SAndroid Build Coastguard Worker // Grow manually in case one of Args is an internal reference.
459*da0073e9SAndroid Build Coastguard Worker size_t NewCapacity = 0;
460*da0073e9SAndroid Build Coastguard Worker T* NewElts = mallocForGrow(0, NewCapacity);
461*da0073e9SAndroid Build Coastguard Worker ::new ((void*)(NewElts + this->size())) T(std::forward<ArgTypes>(Args)...);
462*da0073e9SAndroid Build Coastguard Worker moveElementsForGrow(NewElts);
463*da0073e9SAndroid Build Coastguard Worker takeAllocationForGrow(NewElts, NewCapacity);
464*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + 1);
465*da0073e9SAndroid Build Coastguard Worker return this->back();
466*da0073e9SAndroid Build Coastguard Worker }
467*da0073e9SAndroid Build Coastguard Worker
468*da0073e9SAndroid Build Coastguard Worker public:
push_back(const T & Elt)469*da0073e9SAndroid Build Coastguard Worker void push_back(const T& Elt) {
470*da0073e9SAndroid Build Coastguard Worker const T* EltPtr = reserveForParamAndGetAddress(Elt);
471*da0073e9SAndroid Build Coastguard Worker ::new ((void*)this->end()) T(*EltPtr);
472*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + 1);
473*da0073e9SAndroid Build Coastguard Worker }
474*da0073e9SAndroid Build Coastguard Worker
475*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
push_back(T && Elt)476*da0073e9SAndroid Build Coastguard Worker void push_back(T&& Elt) {
477*da0073e9SAndroid Build Coastguard Worker T* EltPtr = reserveForParamAndGetAddress(Elt);
478*da0073e9SAndroid Build Coastguard Worker ::new ((void*)this->end()) T(::std::move(*EltPtr));
479*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + 1);
480*da0073e9SAndroid Build Coastguard Worker }
481*da0073e9SAndroid Build Coastguard Worker
pop_back()482*da0073e9SAndroid Build Coastguard Worker void pop_back() {
483*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() - 1);
484*da0073e9SAndroid Build Coastguard Worker this->end()->~T();
485*da0073e9SAndroid Build Coastguard Worker }
486*da0073e9SAndroid Build Coastguard Worker };
487*da0073e9SAndroid Build Coastguard Worker
488*da0073e9SAndroid Build Coastguard Worker // Define this out-of-line to dissuade the C++ compiler from inlining it.
489*da0073e9SAndroid Build Coastguard Worker template <typename T, bool TriviallyCopyable>
grow(size_t MinSize)490*da0073e9SAndroid Build Coastguard Worker void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) {
491*da0073e9SAndroid Build Coastguard Worker size_t NewCapacity = 0;
492*da0073e9SAndroid Build Coastguard Worker T* NewElts = mallocForGrow(MinSize, NewCapacity);
493*da0073e9SAndroid Build Coastguard Worker moveElementsForGrow(NewElts);
494*da0073e9SAndroid Build Coastguard Worker takeAllocationForGrow(NewElts, NewCapacity);
495*da0073e9SAndroid Build Coastguard Worker }
496*da0073e9SAndroid Build Coastguard Worker
497*da0073e9SAndroid Build Coastguard Worker // Define this out-of-line to dissuade the C++ compiler from inlining it.
498*da0073e9SAndroid Build Coastguard Worker template <typename T, bool TriviallyCopyable>
moveElementsForGrow(T * NewElts)499*da0073e9SAndroid Build Coastguard Worker void SmallVectorTemplateBase<T, TriviallyCopyable>::moveElementsForGrow(
500*da0073e9SAndroid Build Coastguard Worker T* NewElts) {
501*da0073e9SAndroid Build Coastguard Worker // Move the elements over.
502*da0073e9SAndroid Build Coastguard Worker this->uninitialized_move(this->begin(), this->end(), NewElts);
503*da0073e9SAndroid Build Coastguard Worker
504*da0073e9SAndroid Build Coastguard Worker // Destroy the original elements.
505*da0073e9SAndroid Build Coastguard Worker destroy_range(this->begin(), this->end());
506*da0073e9SAndroid Build Coastguard Worker }
507*da0073e9SAndroid Build Coastguard Worker
508*da0073e9SAndroid Build Coastguard Worker // Define this out-of-line to dissuade the C++ compiler from inlining it.
509*da0073e9SAndroid Build Coastguard Worker template <typename T, bool TriviallyCopyable>
takeAllocationForGrow(T * NewElts,size_t NewCapacity)510*da0073e9SAndroid Build Coastguard Worker void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow(
511*da0073e9SAndroid Build Coastguard Worker T* NewElts,
512*da0073e9SAndroid Build Coastguard Worker size_t NewCapacity) {
513*da0073e9SAndroid Build Coastguard Worker // If this wasn't grown from the inline copy, deallocate the old space.
514*da0073e9SAndroid Build Coastguard Worker if (!this->isSmall())
515*da0073e9SAndroid Build Coastguard Worker free(this->begin());
516*da0073e9SAndroid Build Coastguard Worker
517*da0073e9SAndroid Build Coastguard Worker this->BeginX = NewElts;
518*da0073e9SAndroid Build Coastguard Worker this->Capacity = NewCapacity;
519*da0073e9SAndroid Build Coastguard Worker }
520*da0073e9SAndroid Build Coastguard Worker
521*da0073e9SAndroid Build Coastguard Worker /// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
522*da0073e9SAndroid Build Coastguard Worker /// method implementations that are designed to work with trivially copyable
523*da0073e9SAndroid Build Coastguard Worker /// T's. This allows using memcpy in place of copy/move construction and
524*da0073e9SAndroid Build Coastguard Worker /// skipping destruction.
525*da0073e9SAndroid Build Coastguard Worker template <typename T>
526*da0073e9SAndroid Build Coastguard Worker class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
527*da0073e9SAndroid Build Coastguard Worker friend class SmallVectorTemplateCommon<T>;
528*da0073e9SAndroid Build Coastguard Worker
529*da0073e9SAndroid Build Coastguard Worker protected:
530*da0073e9SAndroid Build Coastguard Worker /// True if it's cheap enough to take parameters by value. Doing so avoids
531*da0073e9SAndroid Build Coastguard Worker /// overhead related to mitigations for reference invalidation.
532*da0073e9SAndroid Build Coastguard Worker static constexpr bool TakesParamByValue = sizeof(T) <= 2 * sizeof(void*);
533*da0073e9SAndroid Build Coastguard Worker
534*da0073e9SAndroid Build Coastguard Worker /// Either const T& or T, depending on whether it's cheap enough to take
535*da0073e9SAndroid Build Coastguard Worker /// parameters by value.
536*da0073e9SAndroid Build Coastguard Worker using ValueParamT = std::conditional_t<TakesParamByValue, T, const T&>;
537*da0073e9SAndroid Build Coastguard Worker
SmallVectorTemplateBase(size_t Size)538*da0073e9SAndroid Build Coastguard Worker SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
539*da0073e9SAndroid Build Coastguard Worker
540*da0073e9SAndroid Build Coastguard Worker // No need to do a destroy loop for POD's.
destroy_range(T *,T *)541*da0073e9SAndroid Build Coastguard Worker static void destroy_range(T*, T*) {}
542*da0073e9SAndroid Build Coastguard Worker
543*da0073e9SAndroid Build Coastguard Worker /// Move the range [I, E) onto the uninitialized memory
544*da0073e9SAndroid Build Coastguard Worker /// starting with "Dest", constructing elements into it as needed.
545*da0073e9SAndroid Build Coastguard Worker template <typename It1, typename It2>
uninitialized_move(It1 I,It1 E,It2 Dest)546*da0073e9SAndroid Build Coastguard Worker static void uninitialized_move(It1 I, It1 E, It2 Dest) {
547*da0073e9SAndroid Build Coastguard Worker // Just do a copy.
548*da0073e9SAndroid Build Coastguard Worker uninitialized_copy(I, E, Dest);
549*da0073e9SAndroid Build Coastguard Worker }
550*da0073e9SAndroid Build Coastguard Worker
551*da0073e9SAndroid Build Coastguard Worker /// Copy the range [I, E) onto the uninitialized memory
552*da0073e9SAndroid Build Coastguard Worker /// starting with "Dest", constructing elements into it as needed.
553*da0073e9SAndroid Build Coastguard Worker template <typename It1, typename It2>
uninitialized_copy(It1 I,It1 E,It2 Dest)554*da0073e9SAndroid Build Coastguard Worker static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
555*da0073e9SAndroid Build Coastguard Worker // Arbitrary iterator types; just use the basic implementation.
556*da0073e9SAndroid Build Coastguard Worker std::uninitialized_copy(I, E, Dest);
557*da0073e9SAndroid Build Coastguard Worker }
558*da0073e9SAndroid Build Coastguard Worker
559*da0073e9SAndroid Build Coastguard Worker /// Copy the range [I, E) onto the uninitialized memory
560*da0073e9SAndroid Build Coastguard Worker /// starting with "Dest", constructing elements into it as needed.
561*da0073e9SAndroid Build Coastguard Worker template <typename T1, typename T2>
562*da0073e9SAndroid Build Coastguard Worker static void uninitialized_copy(
563*da0073e9SAndroid Build Coastguard Worker T1* I,
564*da0073e9SAndroid Build Coastguard Worker T1* E,
565*da0073e9SAndroid Build Coastguard Worker T2* Dest,
566*da0073e9SAndroid Build Coastguard Worker std::enable_if_t<std::is_same_v<std::remove_const_t<T1>, T2>>* =
567*da0073e9SAndroid Build Coastguard Worker nullptr) {
568*da0073e9SAndroid Build Coastguard Worker // Use memcpy for PODs iterated by pointers (which includes SmallVector
569*da0073e9SAndroid Build Coastguard Worker // iterators): std::uninitialized_copy optimizes to memmove, but we can
570*da0073e9SAndroid Build Coastguard Worker // use memcpy here. Note that I and E are iterators and thus might be
571*da0073e9SAndroid Build Coastguard Worker // invalid for memcpy if they are equal.
572*da0073e9SAndroid Build Coastguard Worker if (I != E)
573*da0073e9SAndroid Build Coastguard Worker memcpy(reinterpret_cast<void*>(Dest), I, (E - I) * sizeof(T));
574*da0073e9SAndroid Build Coastguard Worker }
575*da0073e9SAndroid Build Coastguard Worker
576*da0073e9SAndroid Build Coastguard Worker /// Double the size of the allocated memory, guaranteeing space for at
577*da0073e9SAndroid Build Coastguard Worker /// least one more element or MinSize if specified.
578*da0073e9SAndroid Build Coastguard Worker void grow(size_t MinSize = 0) {
579*da0073e9SAndroid Build Coastguard Worker this->grow_pod(MinSize, sizeof(T));
580*da0073e9SAndroid Build Coastguard Worker }
581*da0073e9SAndroid Build Coastguard Worker
582*da0073e9SAndroid Build Coastguard Worker /// Reserve enough space to add one element, and return the updated element
583*da0073e9SAndroid Build Coastguard Worker /// pointer in case it was a reference to the storage.
584*da0073e9SAndroid Build Coastguard Worker const T* reserveForParamAndGetAddress(const T& Elt, size_t N = 1) {
585*da0073e9SAndroid Build Coastguard Worker return this->reserveForParamAndGetAddressImpl(this, Elt, N);
586*da0073e9SAndroid Build Coastguard Worker }
587*da0073e9SAndroid Build Coastguard Worker
588*da0073e9SAndroid Build Coastguard Worker /// Reserve enough space to add one element, and return the updated element
589*da0073e9SAndroid Build Coastguard Worker /// pointer in case it was a reference to the storage.
590*da0073e9SAndroid Build Coastguard Worker T* reserveForParamAndGetAddress(T& Elt, size_t N = 1) {
591*da0073e9SAndroid Build Coastguard Worker return const_cast<T*>(this->reserveForParamAndGetAddressImpl(this, Elt, N));
592*da0073e9SAndroid Build Coastguard Worker }
593*da0073e9SAndroid Build Coastguard Worker
594*da0073e9SAndroid Build Coastguard Worker /// Copy \p V or return a reference, depending on \a ValueParamT.
forward_value_param(ValueParamT V)595*da0073e9SAndroid Build Coastguard Worker static ValueParamT forward_value_param(ValueParamT V) {
596*da0073e9SAndroid Build Coastguard Worker return V;
597*da0073e9SAndroid Build Coastguard Worker }
598*da0073e9SAndroid Build Coastguard Worker
growAndAssign(size_t NumElts,T Elt)599*da0073e9SAndroid Build Coastguard Worker void growAndAssign(size_t NumElts, T Elt) {
600*da0073e9SAndroid Build Coastguard Worker // Elt has been copied in case it's an internal reference, side-stepping
601*da0073e9SAndroid Build Coastguard Worker // reference invalidation problems without losing the realloc optimization.
602*da0073e9SAndroid Build Coastguard Worker this->set_size(0);
603*da0073e9SAndroid Build Coastguard Worker this->grow(NumElts);
604*da0073e9SAndroid Build Coastguard Worker std::uninitialized_fill_n(this->begin(), NumElts, Elt);
605*da0073e9SAndroid Build Coastguard Worker this->set_size(NumElts);
606*da0073e9SAndroid Build Coastguard Worker }
607*da0073e9SAndroid Build Coastguard Worker
608*da0073e9SAndroid Build Coastguard Worker template <typename... ArgTypes>
growAndEmplaceBack(ArgTypes &&...Args)609*da0073e9SAndroid Build Coastguard Worker T& growAndEmplaceBack(ArgTypes&&... Args) {
610*da0073e9SAndroid Build Coastguard Worker // Use push_back with a copy in case Args has an internal reference,
611*da0073e9SAndroid Build Coastguard Worker // side-stepping reference invalidation problems without losing the realloc
612*da0073e9SAndroid Build Coastguard Worker // optimization.
613*da0073e9SAndroid Build Coastguard Worker push_back(T(std::forward<ArgTypes>(Args)...));
614*da0073e9SAndroid Build Coastguard Worker return this->back();
615*da0073e9SAndroid Build Coastguard Worker }
616*da0073e9SAndroid Build Coastguard Worker
617*da0073e9SAndroid Build Coastguard Worker public:
push_back(ValueParamT Elt)618*da0073e9SAndroid Build Coastguard Worker void push_back(ValueParamT Elt) {
619*da0073e9SAndroid Build Coastguard Worker const T* EltPtr = reserveForParamAndGetAddress(Elt);
620*da0073e9SAndroid Build Coastguard Worker memcpy(reinterpret_cast<void*>(this->end()), EltPtr, sizeof(T));
621*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + 1);
622*da0073e9SAndroid Build Coastguard Worker }
623*da0073e9SAndroid Build Coastguard Worker
pop_back()624*da0073e9SAndroid Build Coastguard Worker void pop_back() {
625*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() - 1);
626*da0073e9SAndroid Build Coastguard Worker }
627*da0073e9SAndroid Build Coastguard Worker };
628*da0073e9SAndroid Build Coastguard Worker
629*da0073e9SAndroid Build Coastguard Worker /// This class consists of common code factored out of the SmallVector class to
630*da0073e9SAndroid Build Coastguard Worker /// reduce code duplication based on the SmallVector 'N' template parameter.
631*da0073e9SAndroid Build Coastguard Worker template <typename T>
632*da0073e9SAndroid Build Coastguard Worker class SmallVectorImpl : public SmallVectorTemplateBase<T> {
633*da0073e9SAndroid Build Coastguard Worker using SuperClass = SmallVectorTemplateBase<T>;
634*da0073e9SAndroid Build Coastguard Worker
635*da0073e9SAndroid Build Coastguard Worker public:
636*da0073e9SAndroid Build Coastguard Worker using iterator = typename SuperClass::iterator;
637*da0073e9SAndroid Build Coastguard Worker using const_iterator = typename SuperClass::const_iterator;
638*da0073e9SAndroid Build Coastguard Worker using reference = typename SuperClass::reference;
639*da0073e9SAndroid Build Coastguard Worker using size_type = typename SuperClass::size_type;
640*da0073e9SAndroid Build Coastguard Worker
641*da0073e9SAndroid Build Coastguard Worker protected:
642*da0073e9SAndroid Build Coastguard Worker using SmallVectorTemplateBase<T>::TakesParamByValue;
643*da0073e9SAndroid Build Coastguard Worker using ValueParamT = typename SuperClass::ValueParamT;
644*da0073e9SAndroid Build Coastguard Worker
645*da0073e9SAndroid Build Coastguard Worker // Default ctor - Initialize to empty.
SmallVectorImpl(unsigned N)646*da0073e9SAndroid Build Coastguard Worker explicit SmallVectorImpl(unsigned N) : SmallVectorTemplateBase<T>(N) {}
647*da0073e9SAndroid Build Coastguard Worker
648*da0073e9SAndroid Build Coastguard Worker public:
649*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl(const SmallVectorImpl&) = delete;
650*da0073e9SAndroid Build Coastguard Worker
~SmallVectorImpl()651*da0073e9SAndroid Build Coastguard Worker ~SmallVectorImpl() {
652*da0073e9SAndroid Build Coastguard Worker // Subclass has already destructed this vector's elements.
653*da0073e9SAndroid Build Coastguard Worker // If this wasn't grown from the inline copy, deallocate the old space.
654*da0073e9SAndroid Build Coastguard Worker if (!this->isSmall())
655*da0073e9SAndroid Build Coastguard Worker free(this->begin());
656*da0073e9SAndroid Build Coastguard Worker }
657*da0073e9SAndroid Build Coastguard Worker
clear()658*da0073e9SAndroid Build Coastguard Worker void clear() {
659*da0073e9SAndroid Build Coastguard Worker this->destroy_range(this->begin(), this->end());
660*da0073e9SAndroid Build Coastguard Worker this->Size = 0;
661*da0073e9SAndroid Build Coastguard Worker }
662*da0073e9SAndroid Build Coastguard Worker
663*da0073e9SAndroid Build Coastguard Worker private:
664*da0073e9SAndroid Build Coastguard Worker template <bool ForOverwrite>
resizeImpl(size_type N)665*da0073e9SAndroid Build Coastguard Worker void resizeImpl(size_type N) {
666*da0073e9SAndroid Build Coastguard Worker if (N < this->size()) {
667*da0073e9SAndroid Build Coastguard Worker this->pop_back_n(this->size() - N);
668*da0073e9SAndroid Build Coastguard Worker } else if (N > this->size()) {
669*da0073e9SAndroid Build Coastguard Worker this->reserve(N);
670*da0073e9SAndroid Build Coastguard Worker for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
671*da0073e9SAndroid Build Coastguard Worker if (ForOverwrite)
672*da0073e9SAndroid Build Coastguard Worker new (&*I) T;
673*da0073e9SAndroid Build Coastguard Worker else
674*da0073e9SAndroid Build Coastguard Worker new (&*I) T();
675*da0073e9SAndroid Build Coastguard Worker this->set_size(N);
676*da0073e9SAndroid Build Coastguard Worker }
677*da0073e9SAndroid Build Coastguard Worker }
678*da0073e9SAndroid Build Coastguard Worker
679*da0073e9SAndroid Build Coastguard Worker public:
resize(size_type N)680*da0073e9SAndroid Build Coastguard Worker void resize(size_type N) {
681*da0073e9SAndroid Build Coastguard Worker resizeImpl<false>(N);
682*da0073e9SAndroid Build Coastguard Worker }
683*da0073e9SAndroid Build Coastguard Worker
684*da0073e9SAndroid Build Coastguard Worker /// Like resize, but \ref T is POD, the new values won't be initialized.
resize_for_overwrite(size_type N)685*da0073e9SAndroid Build Coastguard Worker void resize_for_overwrite(size_type N) {
686*da0073e9SAndroid Build Coastguard Worker resizeImpl<true>(N);
687*da0073e9SAndroid Build Coastguard Worker }
688*da0073e9SAndroid Build Coastguard Worker
resize(size_type N,ValueParamT NV)689*da0073e9SAndroid Build Coastguard Worker void resize(size_type N, ValueParamT NV) {
690*da0073e9SAndroid Build Coastguard Worker if (N == this->size())
691*da0073e9SAndroid Build Coastguard Worker return;
692*da0073e9SAndroid Build Coastguard Worker
693*da0073e9SAndroid Build Coastguard Worker if (N < this->size()) {
694*da0073e9SAndroid Build Coastguard Worker this->pop_back_n(this->size() - N);
695*da0073e9SAndroid Build Coastguard Worker return;
696*da0073e9SAndroid Build Coastguard Worker }
697*da0073e9SAndroid Build Coastguard Worker
698*da0073e9SAndroid Build Coastguard Worker // N > this->size(). Defer to append.
699*da0073e9SAndroid Build Coastguard Worker this->append(N - this->size(), NV);
700*da0073e9SAndroid Build Coastguard Worker }
701*da0073e9SAndroid Build Coastguard Worker
reserve(size_type N)702*da0073e9SAndroid Build Coastguard Worker void reserve(size_type N) {
703*da0073e9SAndroid Build Coastguard Worker if (this->capacity() < N)
704*da0073e9SAndroid Build Coastguard Worker this->grow(N);
705*da0073e9SAndroid Build Coastguard Worker }
706*da0073e9SAndroid Build Coastguard Worker
pop_back_n(size_type NumItems)707*da0073e9SAndroid Build Coastguard Worker void pop_back_n(size_type NumItems) {
708*da0073e9SAndroid Build Coastguard Worker assert(this->size() >= NumItems);
709*da0073e9SAndroid Build Coastguard Worker this->destroy_range(this->end() - NumItems, this->end());
710*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() - NumItems);
711*da0073e9SAndroid Build Coastguard Worker }
712*da0073e9SAndroid Build Coastguard Worker
pop_back_val()713*da0073e9SAndroid Build Coastguard Worker C10_NODISCARD T pop_back_val() {
714*da0073e9SAndroid Build Coastguard Worker T Result = ::std::move(this->back());
715*da0073e9SAndroid Build Coastguard Worker this->pop_back();
716*da0073e9SAndroid Build Coastguard Worker return Result;
717*da0073e9SAndroid Build Coastguard Worker }
718*da0073e9SAndroid Build Coastguard Worker
719*da0073e9SAndroid Build Coastguard Worker void swap(SmallVectorImpl& RHS) noexcept;
720*da0073e9SAndroid Build Coastguard Worker
721*da0073e9SAndroid Build Coastguard Worker /// Add the specified range to the end of the SmallVector.
722*da0073e9SAndroid Build Coastguard Worker template <
723*da0073e9SAndroid Build Coastguard Worker typename in_iter,
724*da0073e9SAndroid Build Coastguard Worker typename = std::enable_if_t<std::is_convertible_v<
725*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<in_iter>::iterator_category,
726*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag>>>
append(in_iter in_start,in_iter in_end)727*da0073e9SAndroid Build Coastguard Worker void append(in_iter in_start, in_iter in_end) {
728*da0073e9SAndroid Build Coastguard Worker this->assertSafeToAddRange(in_start, in_end);
729*da0073e9SAndroid Build Coastguard Worker size_type NumInputs = std::distance(in_start, in_end);
730*da0073e9SAndroid Build Coastguard Worker this->reserve(this->size() + NumInputs);
731*da0073e9SAndroid Build Coastguard Worker this->uninitialized_copy(in_start, in_end, this->end());
732*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + NumInputs);
733*da0073e9SAndroid Build Coastguard Worker }
734*da0073e9SAndroid Build Coastguard Worker
735*da0073e9SAndroid Build Coastguard Worker /// Append \p NumInputs copies of \p Elt to the end.
append(size_type NumInputs,ValueParamT Elt)736*da0073e9SAndroid Build Coastguard Worker void append(size_type NumInputs, ValueParamT Elt) {
737*da0073e9SAndroid Build Coastguard Worker const T* EltPtr = this->reserveForParamAndGetAddress(Elt, NumInputs);
738*da0073e9SAndroid Build Coastguard Worker std::uninitialized_fill_n(this->end(), NumInputs, *EltPtr);
739*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + NumInputs);
740*da0073e9SAndroid Build Coastguard Worker }
741*da0073e9SAndroid Build Coastguard Worker
append(std::initializer_list<T> IL)742*da0073e9SAndroid Build Coastguard Worker void append(std::initializer_list<T> IL) {
743*da0073e9SAndroid Build Coastguard Worker append(IL.begin(), IL.end());
744*da0073e9SAndroid Build Coastguard Worker }
745*da0073e9SAndroid Build Coastguard Worker
append(const SmallVectorImpl & RHS)746*da0073e9SAndroid Build Coastguard Worker void append(const SmallVectorImpl& RHS) {
747*da0073e9SAndroid Build Coastguard Worker append(RHS.begin(), RHS.end());
748*da0073e9SAndroid Build Coastguard Worker }
749*da0073e9SAndroid Build Coastguard Worker
assign(size_type NumElts,ValueParamT Elt)750*da0073e9SAndroid Build Coastguard Worker void assign(size_type NumElts, ValueParamT Elt) {
751*da0073e9SAndroid Build Coastguard Worker // Note that Elt could be an internal reference.
752*da0073e9SAndroid Build Coastguard Worker if (NumElts > this->capacity()) {
753*da0073e9SAndroid Build Coastguard Worker this->growAndAssign(NumElts, Elt);
754*da0073e9SAndroid Build Coastguard Worker return;
755*da0073e9SAndroid Build Coastguard Worker }
756*da0073e9SAndroid Build Coastguard Worker
757*da0073e9SAndroid Build Coastguard Worker // Assign over existing elements.
758*da0073e9SAndroid Build Coastguard Worker std::fill_n(this->begin(), std::min(NumElts, this->size()), Elt);
759*da0073e9SAndroid Build Coastguard Worker if (NumElts > this->size())
760*da0073e9SAndroid Build Coastguard Worker std::uninitialized_fill_n(this->end(), NumElts - this->size(), Elt);
761*da0073e9SAndroid Build Coastguard Worker else if (NumElts < this->size())
762*da0073e9SAndroid Build Coastguard Worker this->destroy_range(this->begin() + NumElts, this->end());
763*da0073e9SAndroid Build Coastguard Worker this->set_size(NumElts);
764*da0073e9SAndroid Build Coastguard Worker }
765*da0073e9SAndroid Build Coastguard Worker
766*da0073e9SAndroid Build Coastguard Worker // FIXME: Consider assigning over existing elements, rather than clearing &
767*da0073e9SAndroid Build Coastguard Worker // re-initializing them - for all assign(...) variants.
768*da0073e9SAndroid Build Coastguard Worker
769*da0073e9SAndroid Build Coastguard Worker template <
770*da0073e9SAndroid Build Coastguard Worker typename in_iter,
771*da0073e9SAndroid Build Coastguard Worker typename = std::enable_if_t<std::is_convertible_v<
772*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<in_iter>::iterator_category,
773*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag>>>
assign(in_iter in_start,in_iter in_end)774*da0073e9SAndroid Build Coastguard Worker void assign(in_iter in_start, in_iter in_end) {
775*da0073e9SAndroid Build Coastguard Worker this->assertSafeToReferenceAfterClear(in_start, in_end);
776*da0073e9SAndroid Build Coastguard Worker clear();
777*da0073e9SAndroid Build Coastguard Worker append(in_start, in_end);
778*da0073e9SAndroid Build Coastguard Worker }
779*da0073e9SAndroid Build Coastguard Worker
assign(std::initializer_list<T> IL)780*da0073e9SAndroid Build Coastguard Worker void assign(std::initializer_list<T> IL) {
781*da0073e9SAndroid Build Coastguard Worker clear();
782*da0073e9SAndroid Build Coastguard Worker append(IL);
783*da0073e9SAndroid Build Coastguard Worker }
784*da0073e9SAndroid Build Coastguard Worker
assign(const SmallVectorImpl & RHS)785*da0073e9SAndroid Build Coastguard Worker void assign(const SmallVectorImpl& RHS) {
786*da0073e9SAndroid Build Coastguard Worker assign(RHS.begin(), RHS.end());
787*da0073e9SAndroid Build Coastguard Worker }
788*da0073e9SAndroid Build Coastguard Worker
erase(iterator I)789*da0073e9SAndroid Build Coastguard Worker iterator erase(iterator I) {
790*da0073e9SAndroid Build Coastguard Worker assert(
791*da0073e9SAndroid Build Coastguard Worker this->isReferenceToStorage(I) && "Iterator to erase is out of bounds.");
792*da0073e9SAndroid Build Coastguard Worker
793*da0073e9SAndroid Build Coastguard Worker iterator N = I;
794*da0073e9SAndroid Build Coastguard Worker // Shift all elts down one.
795*da0073e9SAndroid Build Coastguard Worker std::move(I + 1, this->end(), I);
796*da0073e9SAndroid Build Coastguard Worker // Drop the last elt.
797*da0073e9SAndroid Build Coastguard Worker this->pop_back();
798*da0073e9SAndroid Build Coastguard Worker return (N);
799*da0073e9SAndroid Build Coastguard Worker }
800*da0073e9SAndroid Build Coastguard Worker
erase(iterator S,iterator E)801*da0073e9SAndroid Build Coastguard Worker iterator erase(iterator S, iterator E) {
802*da0073e9SAndroid Build Coastguard Worker assert(this->isRangeInStorage(S, E) && "Range to erase is out of bounds.");
803*da0073e9SAndroid Build Coastguard Worker
804*da0073e9SAndroid Build Coastguard Worker iterator N = S;
805*da0073e9SAndroid Build Coastguard Worker // Shift all elts down.
806*da0073e9SAndroid Build Coastguard Worker iterator I = std::move(E, this->end(), S);
807*da0073e9SAndroid Build Coastguard Worker // Drop the last elts.
808*da0073e9SAndroid Build Coastguard Worker this->destroy_range(I, this->end());
809*da0073e9SAndroid Build Coastguard Worker this->set_size(I - this->begin());
810*da0073e9SAndroid Build Coastguard Worker return (N);
811*da0073e9SAndroid Build Coastguard Worker }
812*da0073e9SAndroid Build Coastguard Worker
813*da0073e9SAndroid Build Coastguard Worker private:
814*da0073e9SAndroid Build Coastguard Worker template <class ArgType>
insert_one_impl(iterator I,ArgType && Elt)815*da0073e9SAndroid Build Coastguard Worker iterator insert_one_impl(iterator I, ArgType&& Elt) {
816*da0073e9SAndroid Build Coastguard Worker // Callers ensure that ArgType is derived from T.
817*da0073e9SAndroid Build Coastguard Worker static_assert(
818*da0073e9SAndroid Build Coastguard Worker std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>, T>::
819*da0073e9SAndroid Build Coastguard Worker value,
820*da0073e9SAndroid Build Coastguard Worker "ArgType must be derived from T!");
821*da0073e9SAndroid Build Coastguard Worker
822*da0073e9SAndroid Build Coastguard Worker if (I == this->end()) { // Important special case for empty vector.
823*da0073e9SAndroid Build Coastguard Worker this->push_back(::std::forward<ArgType>(Elt));
824*da0073e9SAndroid Build Coastguard Worker return this->end() - 1;
825*da0073e9SAndroid Build Coastguard Worker }
826*da0073e9SAndroid Build Coastguard Worker
827*da0073e9SAndroid Build Coastguard Worker assert(
828*da0073e9SAndroid Build Coastguard Worker this->isReferenceToStorage(I) &&
829*da0073e9SAndroid Build Coastguard Worker "Insertion iterator is out of bounds.");
830*da0073e9SAndroid Build Coastguard Worker
831*da0073e9SAndroid Build Coastguard Worker // Grow if necessary.
832*da0073e9SAndroid Build Coastguard Worker size_t Index = I - this->begin();
833*da0073e9SAndroid Build Coastguard Worker std::remove_reference_t<ArgType>* EltPtr =
834*da0073e9SAndroid Build Coastguard Worker this->reserveForParamAndGetAddress(Elt);
835*da0073e9SAndroid Build Coastguard Worker I = this->begin() + Index;
836*da0073e9SAndroid Build Coastguard Worker
837*da0073e9SAndroid Build Coastguard Worker ::new ((void*)this->end()) T(::std::move(this->back()));
838*da0073e9SAndroid Build Coastguard Worker // Push everything else over.
839*da0073e9SAndroid Build Coastguard Worker std::move_backward(I, this->end() - 1, this->end());
840*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + 1);
841*da0073e9SAndroid Build Coastguard Worker
842*da0073e9SAndroid Build Coastguard Worker // If we just moved the element we're inserting, be sure to update
843*da0073e9SAndroid Build Coastguard Worker // the reference (never happens if TakesParamByValue).
844*da0073e9SAndroid Build Coastguard Worker static_assert(
845*da0073e9SAndroid Build Coastguard Worker !TakesParamByValue || std::is_same<ArgType, T>::value,
846*da0073e9SAndroid Build Coastguard Worker "ArgType must be 'T' when taking by value!");
847*da0073e9SAndroid Build Coastguard Worker if (!TakesParamByValue && this->isReferenceToRange(EltPtr, I, this->end()))
848*da0073e9SAndroid Build Coastguard Worker ++EltPtr;
849*da0073e9SAndroid Build Coastguard Worker
850*da0073e9SAndroid Build Coastguard Worker *I = ::std::forward<ArgType>(*EltPtr);
851*da0073e9SAndroid Build Coastguard Worker return I;
852*da0073e9SAndroid Build Coastguard Worker }
853*da0073e9SAndroid Build Coastguard Worker
854*da0073e9SAndroid Build Coastguard Worker public:
insert(iterator I,T && Elt)855*da0073e9SAndroid Build Coastguard Worker iterator insert(iterator I, T&& Elt) {
856*da0073e9SAndroid Build Coastguard Worker return insert_one_impl(I, this->forward_value_param(std::move(Elt)));
857*da0073e9SAndroid Build Coastguard Worker }
858*da0073e9SAndroid Build Coastguard Worker
insert(iterator I,const T & Elt)859*da0073e9SAndroid Build Coastguard Worker iterator insert(iterator I, const T& Elt) {
860*da0073e9SAndroid Build Coastguard Worker return insert_one_impl(I, this->forward_value_param(Elt));
861*da0073e9SAndroid Build Coastguard Worker }
862*da0073e9SAndroid Build Coastguard Worker
insert(iterator I,size_type NumToInsert,ValueParamT Elt)863*da0073e9SAndroid Build Coastguard Worker iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt) {
864*da0073e9SAndroid Build Coastguard Worker // Convert iterator to elt# to avoid invalidating iterator when we reserve()
865*da0073e9SAndroid Build Coastguard Worker size_t InsertElt = I - this->begin();
866*da0073e9SAndroid Build Coastguard Worker
867*da0073e9SAndroid Build Coastguard Worker if (I == this->end()) { // Important special case for empty vector.
868*da0073e9SAndroid Build Coastguard Worker append(NumToInsert, Elt);
869*da0073e9SAndroid Build Coastguard Worker return this->begin() + InsertElt;
870*da0073e9SAndroid Build Coastguard Worker }
871*da0073e9SAndroid Build Coastguard Worker
872*da0073e9SAndroid Build Coastguard Worker assert(
873*da0073e9SAndroid Build Coastguard Worker this->isReferenceToStorage(I) &&
874*da0073e9SAndroid Build Coastguard Worker "Insertion iterator is out of bounds.");
875*da0073e9SAndroid Build Coastguard Worker
876*da0073e9SAndroid Build Coastguard Worker // Ensure there is enough space, and get the (maybe updated) address of
877*da0073e9SAndroid Build Coastguard Worker // Elt.
878*da0073e9SAndroid Build Coastguard Worker const T* EltPtr = this->reserveForParamAndGetAddress(Elt, NumToInsert);
879*da0073e9SAndroid Build Coastguard Worker
880*da0073e9SAndroid Build Coastguard Worker // Uninvalidate the iterator.
881*da0073e9SAndroid Build Coastguard Worker I = this->begin() + InsertElt;
882*da0073e9SAndroid Build Coastguard Worker
883*da0073e9SAndroid Build Coastguard Worker // If there are more elements between the insertion point and the end of the
884*da0073e9SAndroid Build Coastguard Worker // range than there are being inserted, we can use a simple approach to
885*da0073e9SAndroid Build Coastguard Worker // insertion. Since we already reserved space, we know that this won't
886*da0073e9SAndroid Build Coastguard Worker // reallocate the vector.
887*da0073e9SAndroid Build Coastguard Worker if (size_t(this->end() - I) >= NumToInsert) {
888*da0073e9SAndroid Build Coastguard Worker T* OldEnd = this->end();
889*da0073e9SAndroid Build Coastguard Worker append(
890*da0073e9SAndroid Build Coastguard Worker std::move_iterator<iterator>(this->end() - NumToInsert),
891*da0073e9SAndroid Build Coastguard Worker std::move_iterator<iterator>(this->end()));
892*da0073e9SAndroid Build Coastguard Worker
893*da0073e9SAndroid Build Coastguard Worker // Copy the existing elements that get replaced.
894*da0073e9SAndroid Build Coastguard Worker std::move_backward(I, OldEnd - NumToInsert, OldEnd);
895*da0073e9SAndroid Build Coastguard Worker
896*da0073e9SAndroid Build Coastguard Worker // If we just moved the element we're inserting, be sure to update
897*da0073e9SAndroid Build Coastguard Worker // the reference (never happens if TakesParamByValue).
898*da0073e9SAndroid Build Coastguard Worker if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
899*da0073e9SAndroid Build Coastguard Worker EltPtr += NumToInsert;
900*da0073e9SAndroid Build Coastguard Worker
901*da0073e9SAndroid Build Coastguard Worker std::fill_n(I, NumToInsert, *EltPtr);
902*da0073e9SAndroid Build Coastguard Worker return I;
903*da0073e9SAndroid Build Coastguard Worker }
904*da0073e9SAndroid Build Coastguard Worker
905*da0073e9SAndroid Build Coastguard Worker // Otherwise, we're inserting more elements than exist already, and we're
906*da0073e9SAndroid Build Coastguard Worker // not inserting at the end.
907*da0073e9SAndroid Build Coastguard Worker
908*da0073e9SAndroid Build Coastguard Worker // Move over the elements that we're about to overwrite.
909*da0073e9SAndroid Build Coastguard Worker T* OldEnd = this->end();
910*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + NumToInsert);
911*da0073e9SAndroid Build Coastguard Worker size_t NumOverwritten = OldEnd - I;
912*da0073e9SAndroid Build Coastguard Worker this->uninitialized_move(I, OldEnd, this->end() - NumOverwritten);
913*da0073e9SAndroid Build Coastguard Worker
914*da0073e9SAndroid Build Coastguard Worker // If we just moved the element we're inserting, be sure to update
915*da0073e9SAndroid Build Coastguard Worker // the reference (never happens if TakesParamByValue).
916*da0073e9SAndroid Build Coastguard Worker if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
917*da0073e9SAndroid Build Coastguard Worker EltPtr += NumToInsert;
918*da0073e9SAndroid Build Coastguard Worker
919*da0073e9SAndroid Build Coastguard Worker // Replace the overwritten part.
920*da0073e9SAndroid Build Coastguard Worker std::fill_n(I, NumOverwritten, *EltPtr);
921*da0073e9SAndroid Build Coastguard Worker
922*da0073e9SAndroid Build Coastguard Worker // Insert the non-overwritten middle part.
923*da0073e9SAndroid Build Coastguard Worker std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr);
924*da0073e9SAndroid Build Coastguard Worker return I;
925*da0073e9SAndroid Build Coastguard Worker }
926*da0073e9SAndroid Build Coastguard Worker
927*da0073e9SAndroid Build Coastguard Worker template <
928*da0073e9SAndroid Build Coastguard Worker typename ItTy,
929*da0073e9SAndroid Build Coastguard Worker typename = std::enable_if_t<std::is_convertible_v<
930*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<ItTy>::iterator_category,
931*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag>>>
insert(iterator I,ItTy From,ItTy To)932*da0073e9SAndroid Build Coastguard Worker iterator insert(iterator I, ItTy From, ItTy To) {
933*da0073e9SAndroid Build Coastguard Worker // Convert iterator to elt# to avoid invalidating iterator when we reserve()
934*da0073e9SAndroid Build Coastguard Worker size_t InsertElt = I - this->begin();
935*da0073e9SAndroid Build Coastguard Worker
936*da0073e9SAndroid Build Coastguard Worker if (I == this->end()) { // Important special case for empty vector.
937*da0073e9SAndroid Build Coastguard Worker append(From, To);
938*da0073e9SAndroid Build Coastguard Worker return this->begin() + InsertElt;
939*da0073e9SAndroid Build Coastguard Worker }
940*da0073e9SAndroid Build Coastguard Worker
941*da0073e9SAndroid Build Coastguard Worker assert(
942*da0073e9SAndroid Build Coastguard Worker this->isReferenceToStorage(I) &&
943*da0073e9SAndroid Build Coastguard Worker "Insertion iterator is out of bounds.");
944*da0073e9SAndroid Build Coastguard Worker
945*da0073e9SAndroid Build Coastguard Worker // Check that the reserve that follows doesn't invalidate the iterators.
946*da0073e9SAndroid Build Coastguard Worker this->assertSafeToAddRange(From, To);
947*da0073e9SAndroid Build Coastguard Worker
948*da0073e9SAndroid Build Coastguard Worker size_t NumToInsert = std::distance(From, To);
949*da0073e9SAndroid Build Coastguard Worker
950*da0073e9SAndroid Build Coastguard Worker // Ensure there is enough space.
951*da0073e9SAndroid Build Coastguard Worker reserve(this->size() + NumToInsert);
952*da0073e9SAndroid Build Coastguard Worker
953*da0073e9SAndroid Build Coastguard Worker // Uninvalidate the iterator.
954*da0073e9SAndroid Build Coastguard Worker I = this->begin() + InsertElt;
955*da0073e9SAndroid Build Coastguard Worker
956*da0073e9SAndroid Build Coastguard Worker // If there are more elements between the insertion point and the end of the
957*da0073e9SAndroid Build Coastguard Worker // range than there are being inserted, we can use a simple approach to
958*da0073e9SAndroid Build Coastguard Worker // insertion. Since we already reserved space, we know that this won't
959*da0073e9SAndroid Build Coastguard Worker // reallocate the vector.
960*da0073e9SAndroid Build Coastguard Worker if (size_t(this->end() - I) >= NumToInsert) {
961*da0073e9SAndroid Build Coastguard Worker T* OldEnd = this->end();
962*da0073e9SAndroid Build Coastguard Worker append(
963*da0073e9SAndroid Build Coastguard Worker std::move_iterator<iterator>(this->end() - NumToInsert),
964*da0073e9SAndroid Build Coastguard Worker std::move_iterator<iterator>(this->end()));
965*da0073e9SAndroid Build Coastguard Worker
966*da0073e9SAndroid Build Coastguard Worker // Copy the existing elements that get replaced.
967*da0073e9SAndroid Build Coastguard Worker std::move_backward(I, OldEnd - NumToInsert, OldEnd);
968*da0073e9SAndroid Build Coastguard Worker
969*da0073e9SAndroid Build Coastguard Worker std::copy(From, To, I);
970*da0073e9SAndroid Build Coastguard Worker return I;
971*da0073e9SAndroid Build Coastguard Worker }
972*da0073e9SAndroid Build Coastguard Worker
973*da0073e9SAndroid Build Coastguard Worker // Otherwise, we're inserting more elements than exist already, and we're
974*da0073e9SAndroid Build Coastguard Worker // not inserting at the end.
975*da0073e9SAndroid Build Coastguard Worker
976*da0073e9SAndroid Build Coastguard Worker // Move over the elements that we're about to overwrite.
977*da0073e9SAndroid Build Coastguard Worker T* OldEnd = this->end();
978*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + NumToInsert);
979*da0073e9SAndroid Build Coastguard Worker size_t NumOverwritten = OldEnd - I;
980*da0073e9SAndroid Build Coastguard Worker this->uninitialized_move(I, OldEnd, this->end() - NumOverwritten);
981*da0073e9SAndroid Build Coastguard Worker
982*da0073e9SAndroid Build Coastguard Worker // Replace the overwritten part.
983*da0073e9SAndroid Build Coastguard Worker for (T* J = I; NumOverwritten > 0; --NumOverwritten) {
984*da0073e9SAndroid Build Coastguard Worker *J = *From;
985*da0073e9SAndroid Build Coastguard Worker ++J;
986*da0073e9SAndroid Build Coastguard Worker ++From;
987*da0073e9SAndroid Build Coastguard Worker }
988*da0073e9SAndroid Build Coastguard Worker
989*da0073e9SAndroid Build Coastguard Worker // Insert the non-overwritten middle part.
990*da0073e9SAndroid Build Coastguard Worker this->uninitialized_copy(From, To, OldEnd);
991*da0073e9SAndroid Build Coastguard Worker return I;
992*da0073e9SAndroid Build Coastguard Worker }
993*da0073e9SAndroid Build Coastguard Worker
insert(iterator I,std::initializer_list<T> IL)994*da0073e9SAndroid Build Coastguard Worker void insert(iterator I, std::initializer_list<T> IL) {
995*da0073e9SAndroid Build Coastguard Worker insert(I, IL.begin(), IL.end());
996*da0073e9SAndroid Build Coastguard Worker }
997*da0073e9SAndroid Build Coastguard Worker
998*da0073e9SAndroid Build Coastguard Worker template <typename... ArgTypes>
emplace_back(ArgTypes &&...Args)999*da0073e9SAndroid Build Coastguard Worker reference emplace_back(ArgTypes&&... Args) {
1000*da0073e9SAndroid Build Coastguard Worker if (C10_UNLIKELY(this->size() >= this->capacity()))
1001*da0073e9SAndroid Build Coastguard Worker return this->growAndEmplaceBack(std::forward<ArgTypes>(Args)...);
1002*da0073e9SAndroid Build Coastguard Worker
1003*da0073e9SAndroid Build Coastguard Worker ::new ((void*)this->end()) T(std::forward<ArgTypes>(Args)...);
1004*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + 1);
1005*da0073e9SAndroid Build Coastguard Worker return this->back();
1006*da0073e9SAndroid Build Coastguard Worker }
1007*da0073e9SAndroid Build Coastguard Worker
1008*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl& operator=(const SmallVectorImpl& RHS);
1009*da0073e9SAndroid Build Coastguard Worker
1010*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl& operator=(SmallVectorImpl&& RHS) noexcept(
1011*da0073e9SAndroid Build Coastguard Worker std::is_nothrow_move_constructible_v<T> &&
1012*da0073e9SAndroid Build Coastguard Worker std::is_nothrow_destructible_v<T>);
1013*da0073e9SAndroid Build Coastguard Worker
1014*da0073e9SAndroid Build Coastguard Worker bool operator==(const SmallVectorImpl& RHS) const {
1015*da0073e9SAndroid Build Coastguard Worker if (this->size() != RHS.size())
1016*da0073e9SAndroid Build Coastguard Worker return false;
1017*da0073e9SAndroid Build Coastguard Worker return std::equal(this->begin(), this->end(), RHS.begin());
1018*da0073e9SAndroid Build Coastguard Worker }
1019*da0073e9SAndroid Build Coastguard Worker bool operator!=(const SmallVectorImpl& RHS) const {
1020*da0073e9SAndroid Build Coastguard Worker return !(*this == RHS);
1021*da0073e9SAndroid Build Coastguard Worker }
1022*da0073e9SAndroid Build Coastguard Worker
1023*da0073e9SAndroid Build Coastguard Worker bool operator<(const SmallVectorImpl& RHS) const {
1024*da0073e9SAndroid Build Coastguard Worker return std::lexicographical_compare(
1025*da0073e9SAndroid Build Coastguard Worker this->begin(), this->end(), RHS.begin(), RHS.end());
1026*da0073e9SAndroid Build Coastguard Worker }
1027*da0073e9SAndroid Build Coastguard Worker };
1028*da0073e9SAndroid Build Coastguard Worker
1029*da0073e9SAndroid Build Coastguard Worker template <typename T>
swap(SmallVectorImpl<T> & RHS)1030*da0073e9SAndroid Build Coastguard Worker void SmallVectorImpl<T>::swap(SmallVectorImpl<T>& RHS) noexcept {
1031*da0073e9SAndroid Build Coastguard Worker if (this == &RHS)
1032*da0073e9SAndroid Build Coastguard Worker return;
1033*da0073e9SAndroid Build Coastguard Worker
1034*da0073e9SAndroid Build Coastguard Worker // We can only avoid copying elements if neither vector is small.
1035*da0073e9SAndroid Build Coastguard Worker if (!this->isSmall() && !RHS.isSmall()) {
1036*da0073e9SAndroid Build Coastguard Worker std::swap(this->BeginX, RHS.BeginX);
1037*da0073e9SAndroid Build Coastguard Worker std::swap(this->Size, RHS.Size);
1038*da0073e9SAndroid Build Coastguard Worker std::swap(this->Capacity, RHS.Capacity);
1039*da0073e9SAndroid Build Coastguard Worker return;
1040*da0073e9SAndroid Build Coastguard Worker }
1041*da0073e9SAndroid Build Coastguard Worker this->reserve(RHS.size());
1042*da0073e9SAndroid Build Coastguard Worker RHS.reserve(this->size());
1043*da0073e9SAndroid Build Coastguard Worker
1044*da0073e9SAndroid Build Coastguard Worker // Swap the shared elements.
1045*da0073e9SAndroid Build Coastguard Worker size_t NumShared = this->size();
1046*da0073e9SAndroid Build Coastguard Worker if (NumShared > RHS.size())
1047*da0073e9SAndroid Build Coastguard Worker NumShared = RHS.size();
1048*da0073e9SAndroid Build Coastguard Worker for (size_type i = 0; i != NumShared; ++i)
1049*da0073e9SAndroid Build Coastguard Worker std::swap((*this)[i], RHS[i]);
1050*da0073e9SAndroid Build Coastguard Worker
1051*da0073e9SAndroid Build Coastguard Worker // Copy over the extra elts.
1052*da0073e9SAndroid Build Coastguard Worker if (this->size() > RHS.size()) {
1053*da0073e9SAndroid Build Coastguard Worker size_t EltDiff = this->size() - RHS.size();
1054*da0073e9SAndroid Build Coastguard Worker this->uninitialized_copy(this->begin() + NumShared, this->end(), RHS.end());
1055*da0073e9SAndroid Build Coastguard Worker RHS.set_size(RHS.size() + EltDiff);
1056*da0073e9SAndroid Build Coastguard Worker this->destroy_range(this->begin() + NumShared, this->end());
1057*da0073e9SAndroid Build Coastguard Worker this->set_size(NumShared);
1058*da0073e9SAndroid Build Coastguard Worker } else if (RHS.size() > this->size()) {
1059*da0073e9SAndroid Build Coastguard Worker size_t EltDiff = RHS.size() - this->size();
1060*da0073e9SAndroid Build Coastguard Worker this->uninitialized_copy(RHS.begin() + NumShared, RHS.end(), this->end());
1061*da0073e9SAndroid Build Coastguard Worker this->set_size(this->size() + EltDiff);
1062*da0073e9SAndroid Build Coastguard Worker this->destroy_range(RHS.begin() + NumShared, RHS.end());
1063*da0073e9SAndroid Build Coastguard Worker RHS.set_size(NumShared);
1064*da0073e9SAndroid Build Coastguard Worker }
1065*da0073e9SAndroid Build Coastguard Worker }
1066*da0073e9SAndroid Build Coastguard Worker
1067*da0073e9SAndroid Build Coastguard Worker template <typename T>
1068*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl<T>& SmallVectorImpl<T>::operator=(
1069*da0073e9SAndroid Build Coastguard Worker const SmallVectorImpl<T>& RHS) {
1070*da0073e9SAndroid Build Coastguard Worker // Avoid self-assignment.
1071*da0073e9SAndroid Build Coastguard Worker if (this == &RHS)
1072*da0073e9SAndroid Build Coastguard Worker return *this;
1073*da0073e9SAndroid Build Coastguard Worker
1074*da0073e9SAndroid Build Coastguard Worker // If we already have sufficient space, assign the common elements, then
1075*da0073e9SAndroid Build Coastguard Worker // destroy any excess.
1076*da0073e9SAndroid Build Coastguard Worker size_t RHSSize = RHS.size();
1077*da0073e9SAndroid Build Coastguard Worker size_t CurSize = this->size();
1078*da0073e9SAndroid Build Coastguard Worker if (CurSize >= RHSSize) {
1079*da0073e9SAndroid Build Coastguard Worker // Assign common elements.
1080*da0073e9SAndroid Build Coastguard Worker iterator NewEnd;
1081*da0073e9SAndroid Build Coastguard Worker if (RHSSize)
1082*da0073e9SAndroid Build Coastguard Worker NewEnd = std::copy(RHS.begin(), RHS.begin() + RHSSize, this->begin());
1083*da0073e9SAndroid Build Coastguard Worker else
1084*da0073e9SAndroid Build Coastguard Worker NewEnd = this->begin();
1085*da0073e9SAndroid Build Coastguard Worker
1086*da0073e9SAndroid Build Coastguard Worker // Destroy excess elements.
1087*da0073e9SAndroid Build Coastguard Worker this->destroy_range(NewEnd, this->end());
1088*da0073e9SAndroid Build Coastguard Worker
1089*da0073e9SAndroid Build Coastguard Worker // Trim.
1090*da0073e9SAndroid Build Coastguard Worker this->set_size(RHSSize);
1091*da0073e9SAndroid Build Coastguard Worker return *this;
1092*da0073e9SAndroid Build Coastguard Worker }
1093*da0073e9SAndroid Build Coastguard Worker
1094*da0073e9SAndroid Build Coastguard Worker // If we have to grow to have enough elements, destroy the current elements.
1095*da0073e9SAndroid Build Coastguard Worker // This allows us to avoid copying them during the grow.
1096*da0073e9SAndroid Build Coastguard Worker // FIXME: don't do this if they're efficiently moveable.
1097*da0073e9SAndroid Build Coastguard Worker if (this->capacity() < RHSSize) {
1098*da0073e9SAndroid Build Coastguard Worker // Destroy current elements.
1099*da0073e9SAndroid Build Coastguard Worker this->clear();
1100*da0073e9SAndroid Build Coastguard Worker CurSize = 0;
1101*da0073e9SAndroid Build Coastguard Worker this->grow(RHSSize);
1102*da0073e9SAndroid Build Coastguard Worker } else if (CurSize) {
1103*da0073e9SAndroid Build Coastguard Worker // Otherwise, use assignment for the already-constructed elements.
1104*da0073e9SAndroid Build Coastguard Worker std::copy(RHS.begin(), RHS.begin() + CurSize, this->begin());
1105*da0073e9SAndroid Build Coastguard Worker }
1106*da0073e9SAndroid Build Coastguard Worker
1107*da0073e9SAndroid Build Coastguard Worker // Copy construct the new elements in place.
1108*da0073e9SAndroid Build Coastguard Worker this->uninitialized_copy(
1109*da0073e9SAndroid Build Coastguard Worker RHS.begin() + CurSize, RHS.end(), this->begin() + CurSize);
1110*da0073e9SAndroid Build Coastguard Worker
1111*da0073e9SAndroid Build Coastguard Worker // Set end.
1112*da0073e9SAndroid Build Coastguard Worker this->set_size(RHSSize);
1113*da0073e9SAndroid Build Coastguard Worker return *this;
1114*da0073e9SAndroid Build Coastguard Worker }
1115*da0073e9SAndroid Build Coastguard Worker
1116*da0073e9SAndroid Build Coastguard Worker template <typename T>
1117*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl<T>& SmallVectorImpl<T>::
noexcept(std::is_nothrow_move_constructible_v<T> && std::is_nothrow_destructible_v<T>)1118*da0073e9SAndroid Build Coastguard Worker operator=(SmallVectorImpl<T>&& RHS) noexcept(
1119*da0073e9SAndroid Build Coastguard Worker std::is_nothrow_move_constructible_v<T> &&
1120*da0073e9SAndroid Build Coastguard Worker std::is_nothrow_destructible_v<T>) {
1121*da0073e9SAndroid Build Coastguard Worker // Avoid self-assignment.
1122*da0073e9SAndroid Build Coastguard Worker if (this == &RHS)
1123*da0073e9SAndroid Build Coastguard Worker return *this;
1124*da0073e9SAndroid Build Coastguard Worker
1125*da0073e9SAndroid Build Coastguard Worker // If the RHS isn't small, clear this vector and then steal its buffer.
1126*da0073e9SAndroid Build Coastguard Worker if (!RHS.isSmall()) {
1127*da0073e9SAndroid Build Coastguard Worker this->destroy_range(this->begin(), this->end());
1128*da0073e9SAndroid Build Coastguard Worker if (!this->isSmall())
1129*da0073e9SAndroid Build Coastguard Worker free(this->begin());
1130*da0073e9SAndroid Build Coastguard Worker this->BeginX = RHS.BeginX;
1131*da0073e9SAndroid Build Coastguard Worker this->Size = RHS.Size;
1132*da0073e9SAndroid Build Coastguard Worker this->Capacity = RHS.Capacity;
1133*da0073e9SAndroid Build Coastguard Worker RHS.resetToSmall();
1134*da0073e9SAndroid Build Coastguard Worker return *this;
1135*da0073e9SAndroid Build Coastguard Worker }
1136*da0073e9SAndroid Build Coastguard Worker
1137*da0073e9SAndroid Build Coastguard Worker // If we already have sufficient space, assign the common elements, then
1138*da0073e9SAndroid Build Coastguard Worker // destroy any excess.
1139*da0073e9SAndroid Build Coastguard Worker size_t RHSSize = RHS.size();
1140*da0073e9SAndroid Build Coastguard Worker size_t CurSize = this->size();
1141*da0073e9SAndroid Build Coastguard Worker if (CurSize >= RHSSize) {
1142*da0073e9SAndroid Build Coastguard Worker // Assign common elements.
1143*da0073e9SAndroid Build Coastguard Worker iterator NewEnd = this->begin();
1144*da0073e9SAndroid Build Coastguard Worker if (RHSSize)
1145*da0073e9SAndroid Build Coastguard Worker NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
1146*da0073e9SAndroid Build Coastguard Worker
1147*da0073e9SAndroid Build Coastguard Worker // Destroy excess elements and trim the bounds.
1148*da0073e9SAndroid Build Coastguard Worker this->destroy_range(NewEnd, this->end());
1149*da0073e9SAndroid Build Coastguard Worker this->set_size(RHSSize);
1150*da0073e9SAndroid Build Coastguard Worker
1151*da0073e9SAndroid Build Coastguard Worker // Clear the RHS.
1152*da0073e9SAndroid Build Coastguard Worker RHS.clear();
1153*da0073e9SAndroid Build Coastguard Worker
1154*da0073e9SAndroid Build Coastguard Worker return *this;
1155*da0073e9SAndroid Build Coastguard Worker }
1156*da0073e9SAndroid Build Coastguard Worker
1157*da0073e9SAndroid Build Coastguard Worker // If we have to grow to have enough elements, destroy the current elements.
1158*da0073e9SAndroid Build Coastguard Worker // This allows us to avoid copying them during the grow.
1159*da0073e9SAndroid Build Coastguard Worker // FIXME: this may not actually make any sense if we can efficiently move
1160*da0073e9SAndroid Build Coastguard Worker // elements.
1161*da0073e9SAndroid Build Coastguard Worker if (this->capacity() < RHSSize) {
1162*da0073e9SAndroid Build Coastguard Worker // Destroy current elements.
1163*da0073e9SAndroid Build Coastguard Worker this->clear();
1164*da0073e9SAndroid Build Coastguard Worker CurSize = 0;
1165*da0073e9SAndroid Build Coastguard Worker this->grow(RHSSize);
1166*da0073e9SAndroid Build Coastguard Worker } else if (CurSize) {
1167*da0073e9SAndroid Build Coastguard Worker // Otherwise, use assignment for the already-constructed elements.
1168*da0073e9SAndroid Build Coastguard Worker std::move(RHS.begin(), RHS.begin() + CurSize, this->begin());
1169*da0073e9SAndroid Build Coastguard Worker }
1170*da0073e9SAndroid Build Coastguard Worker
1171*da0073e9SAndroid Build Coastguard Worker // Move-construct the new elements in place.
1172*da0073e9SAndroid Build Coastguard Worker this->uninitialized_move(
1173*da0073e9SAndroid Build Coastguard Worker RHS.begin() + CurSize, RHS.end(), this->begin() + CurSize);
1174*da0073e9SAndroid Build Coastguard Worker
1175*da0073e9SAndroid Build Coastguard Worker // Set end.
1176*da0073e9SAndroid Build Coastguard Worker this->set_size(RHSSize);
1177*da0073e9SAndroid Build Coastguard Worker
1178*da0073e9SAndroid Build Coastguard Worker RHS.clear();
1179*da0073e9SAndroid Build Coastguard Worker return *this;
1180*da0073e9SAndroid Build Coastguard Worker }
1181*da0073e9SAndroid Build Coastguard Worker
1182*da0073e9SAndroid Build Coastguard Worker /// Storage for the SmallVector elements. This is specialized for the N=0 case
1183*da0073e9SAndroid Build Coastguard Worker /// to avoid allocating unnecessary storage.
1184*da0073e9SAndroid Build Coastguard Worker template <typename T, unsigned N>
1185*da0073e9SAndroid Build Coastguard Worker struct SmallVectorStorage {
1186*da0073e9SAndroid Build Coastguard Worker alignas(T) char InlineElts[N * sizeof(T)];
1187*da0073e9SAndroid Build Coastguard Worker };
1188*da0073e9SAndroid Build Coastguard Worker
1189*da0073e9SAndroid Build Coastguard Worker /// We need the storage to be properly aligned even for small-size of 0 so that
1190*da0073e9SAndroid Build Coastguard Worker /// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is
1191*da0073e9SAndroid Build Coastguard Worker /// well-defined.
1192*da0073e9SAndroid Build Coastguard Worker template <typename T>
1193*da0073e9SAndroid Build Coastguard Worker struct alignas(T) SmallVectorStorage<T, 0> {};
1194*da0073e9SAndroid Build Coastguard Worker
1195*da0073e9SAndroid Build Coastguard Worker /// Forward declaration of SmallVector so that
1196*da0073e9SAndroid Build Coastguard Worker /// calculateSmallVectorDefaultInlinedElements can reference
1197*da0073e9SAndroid Build Coastguard Worker /// `sizeof(SmallVector<T, 0>)`.
1198*da0073e9SAndroid Build Coastguard Worker template <typename T, unsigned N>
1199*da0073e9SAndroid Build Coastguard Worker class /* LLVM_GSL_OWNER */ SmallVector;
1200*da0073e9SAndroid Build Coastguard Worker
1201*da0073e9SAndroid Build Coastguard Worker /// Helper class for calculating the default number of inline elements for
1202*da0073e9SAndroid Build Coastguard Worker /// `SmallVector<T>`.
1203*da0073e9SAndroid Build Coastguard Worker ///
1204*da0073e9SAndroid Build Coastguard Worker /// This should be migrated to a constexpr function when our minimum
1205*da0073e9SAndroid Build Coastguard Worker /// compiler support is enough for multi-statement constexpr functions.
1206*da0073e9SAndroid Build Coastguard Worker template <typename T>
1207*da0073e9SAndroid Build Coastguard Worker struct CalculateSmallVectorDefaultInlinedElements {
1208*da0073e9SAndroid Build Coastguard Worker // Parameter controlling the default number of inlined elements
1209*da0073e9SAndroid Build Coastguard Worker // for `SmallVector<T>`.
1210*da0073e9SAndroid Build Coastguard Worker //
1211*da0073e9SAndroid Build Coastguard Worker // The default number of inlined elements ensures that
1212*da0073e9SAndroid Build Coastguard Worker // 1. There is at least one inlined element.
1213*da0073e9SAndroid Build Coastguard Worker // 2. `sizeof(SmallVector<T>) <= kPreferredSmallVectorSizeof` unless
1214*da0073e9SAndroid Build Coastguard Worker // it contradicts 1.
1215*da0073e9SAndroid Build Coastguard Worker static constexpr size_t kPreferredSmallVectorSizeof = 64;
1216*da0073e9SAndroid Build Coastguard Worker
1217*da0073e9SAndroid Build Coastguard Worker // static_assert that sizeof(T) is not "too big".
1218*da0073e9SAndroid Build Coastguard Worker //
1219*da0073e9SAndroid Build Coastguard Worker // Because our policy guarantees at least one inlined element, it is possible
1220*da0073e9SAndroid Build Coastguard Worker // for an arbitrarily large inlined element to allocate an arbitrarily large
1221*da0073e9SAndroid Build Coastguard Worker // amount of inline storage. We generally consider it an antipattern for a
1222*da0073e9SAndroid Build Coastguard Worker // SmallVector to allocate an excessive amount of inline storage, so we want
1223*da0073e9SAndroid Build Coastguard Worker // to call attention to these cases and make sure that users are making an
1224*da0073e9SAndroid Build Coastguard Worker // intentional decision if they request a lot of inline storage.
1225*da0073e9SAndroid Build Coastguard Worker //
1226*da0073e9SAndroid Build Coastguard Worker // We want this assertion to trigger in pathological cases, but otherwise
1227*da0073e9SAndroid Build Coastguard Worker // not be too easy to hit. To accomplish that, the cutoff is actually somewhat
1228*da0073e9SAndroid Build Coastguard Worker // larger than kPreferredSmallVectorSizeof (otherwise,
1229*da0073e9SAndroid Build Coastguard Worker // `SmallVector<SmallVector<T>>` would be one easy way to trip it, and that
1230*da0073e9SAndroid Build Coastguard Worker // pattern seems useful in practice).
1231*da0073e9SAndroid Build Coastguard Worker //
1232*da0073e9SAndroid Build Coastguard Worker // One wrinkle is that this assertion is in theory non-portable, since
1233*da0073e9SAndroid Build Coastguard Worker // sizeof(T) is in general platform-dependent. However, we don't expect this
1234*da0073e9SAndroid Build Coastguard Worker // to be much of an issue, because most LLVM development happens on 64-bit
1235*da0073e9SAndroid Build Coastguard Worker // hosts, and therefore sizeof(T) is expected to *decrease* when compiled for
1236*da0073e9SAndroid Build Coastguard Worker // 32-bit hosts, dodging the issue. The reverse situation, where development
1237*da0073e9SAndroid Build Coastguard Worker // happens on a 32-bit host and then fails due to sizeof(T) *increasing* on a
1238*da0073e9SAndroid Build Coastguard Worker // 64-bit host, is expected to be very rare.
1239*da0073e9SAndroid Build Coastguard Worker static_assert(
1240*da0073e9SAndroid Build Coastguard Worker sizeof(T) <= 256,
1241*da0073e9SAndroid Build Coastguard Worker "You are trying to use a default number of inlined elements for "
1242*da0073e9SAndroid Build Coastguard Worker "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
1243*da0073e9SAndroid Build Coastguard Worker "explicit number of inlined elements with `SmallVector<T, N>` to make "
1244*da0073e9SAndroid Build Coastguard Worker "sure you really want that much inline storage.");
1245*da0073e9SAndroid Build Coastguard Worker
1246*da0073e9SAndroid Build Coastguard Worker // Discount the size of the header itself when calculating the maximum inline
1247*da0073e9SAndroid Build Coastguard Worker // bytes.
1248*da0073e9SAndroid Build Coastguard Worker static constexpr size_t PreferredInlineBytes =
1249*da0073e9SAndroid Build Coastguard Worker kPreferredSmallVectorSizeof - sizeof(SmallVector<T, 0>);
1250*da0073e9SAndroid Build Coastguard Worker static constexpr size_t NumElementsThatFit = PreferredInlineBytes / sizeof(T);
1251*da0073e9SAndroid Build Coastguard Worker static constexpr size_t value =
1252*da0073e9SAndroid Build Coastguard Worker NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
1253*da0073e9SAndroid Build Coastguard Worker };
1254*da0073e9SAndroid Build Coastguard Worker
1255*da0073e9SAndroid Build Coastguard Worker /// This is a 'vector' (really, a variable-sized array), optimized
1256*da0073e9SAndroid Build Coastguard Worker /// for the case when the array is small. It contains some number of elements
1257*da0073e9SAndroid Build Coastguard Worker /// in-place, which allows it to avoid heap allocation when the actual number of
1258*da0073e9SAndroid Build Coastguard Worker /// elements is below that threshold. This allows normal "small" cases to be
1259*da0073e9SAndroid Build Coastguard Worker /// fast without losing generality for large inputs.
1260*da0073e9SAndroid Build Coastguard Worker ///
1261*da0073e9SAndroid Build Coastguard Worker /// \note
1262*da0073e9SAndroid Build Coastguard Worker /// In the absence of a well-motivated choice for the number of inlined
1263*da0073e9SAndroid Build Coastguard Worker /// elements \p N, it is recommended to use \c SmallVector<T> (that is,
1264*da0073e9SAndroid Build Coastguard Worker /// omitting the \p N). This will choose a default number of inlined elements
1265*da0073e9SAndroid Build Coastguard Worker /// reasonable for allocation on the stack (for example, trying to keep \c
1266*da0073e9SAndroid Build Coastguard Worker /// sizeof(SmallVector<T>) around 64 bytes).
1267*da0073e9SAndroid Build Coastguard Worker ///
1268*da0073e9SAndroid Build Coastguard Worker /// \warning This does not attempt to be exception safe.
1269*da0073e9SAndroid Build Coastguard Worker ///
1270*da0073e9SAndroid Build Coastguard Worker /// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h
1271*da0073e9SAndroid Build Coastguard Worker template <
1272*da0073e9SAndroid Build Coastguard Worker typename T,
1273*da0073e9SAndroid Build Coastguard Worker unsigned N = CalculateSmallVectorDefaultInlinedElements<T>::value>
1274*da0073e9SAndroid Build Coastguard Worker class /* LLVM_GSL_OWNER */ SmallVector : public SmallVectorImpl<T>,
1275*da0073e9SAndroid Build Coastguard Worker SmallVectorStorage<T, N> {
1276*da0073e9SAndroid Build Coastguard Worker public:
1277*da0073e9SAndroid Build Coastguard Worker SmallVector() : SmallVectorImpl<T>(N) {}
1278*da0073e9SAndroid Build Coastguard Worker
1279*da0073e9SAndroid Build Coastguard Worker ~SmallVector() {
1280*da0073e9SAndroid Build Coastguard Worker // Destroy the constructed elements in the vector.
1281*da0073e9SAndroid Build Coastguard Worker this->destroy_range(this->begin(), this->end());
1282*da0073e9SAndroid Build Coastguard Worker }
1283*da0073e9SAndroid Build Coastguard Worker
1284*da0073e9SAndroid Build Coastguard Worker explicit SmallVector(size_t Size, const T& Value = T())
1285*da0073e9SAndroid Build Coastguard Worker : SmallVectorImpl<T>(N) {
1286*da0073e9SAndroid Build Coastguard Worker this->assign(Size, Value);
1287*da0073e9SAndroid Build Coastguard Worker }
1288*da0073e9SAndroid Build Coastguard Worker
1289*da0073e9SAndroid Build Coastguard Worker template <
1290*da0073e9SAndroid Build Coastguard Worker typename ItTy,
1291*da0073e9SAndroid Build Coastguard Worker typename = std::enable_if_t<std::is_convertible_v<
1292*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<ItTy>::iterator_category,
1293*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag>>>
1294*da0073e9SAndroid Build Coastguard Worker SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
1295*da0073e9SAndroid Build Coastguard Worker this->append(S, E);
1296*da0073e9SAndroid Build Coastguard Worker }
1297*da0073e9SAndroid Build Coastguard Worker
1298*da0073e9SAndroid Build Coastguard Worker // note: The enable_if restricts Container to types that have a .begin() and
1299*da0073e9SAndroid Build Coastguard Worker // .end() that return valid input iterators.
1300*da0073e9SAndroid Build Coastguard Worker template <
1301*da0073e9SAndroid Build Coastguard Worker typename Container,
1302*da0073e9SAndroid Build Coastguard Worker std::enable_if_t<
1303*da0073e9SAndroid Build Coastguard Worker std::is_convertible_v<
1304*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<
1305*da0073e9SAndroid Build Coastguard Worker decltype(std::declval<Container>()
1306*da0073e9SAndroid Build Coastguard Worker .begin())>::iterator_category,
1307*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag> &&
1308*da0073e9SAndroid Build Coastguard Worker std::is_convertible_v<
1309*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<
1310*da0073e9SAndroid Build Coastguard Worker decltype(std::declval<Container>()
1311*da0073e9SAndroid Build Coastguard Worker .end())>::iterator_category,
1312*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag>,
1313*da0073e9SAndroid Build Coastguard Worker int> = 0>
1314*da0073e9SAndroid Build Coastguard Worker explicit SmallVector(Container&& c) : SmallVectorImpl<T>(N) {
1315*da0073e9SAndroid Build Coastguard Worker this->append(c.begin(), c.end());
1316*da0073e9SAndroid Build Coastguard Worker }
1317*da0073e9SAndroid Build Coastguard Worker
1318*da0073e9SAndroid Build Coastguard Worker SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
1319*da0073e9SAndroid Build Coastguard Worker this->assign(IL);
1320*da0073e9SAndroid Build Coastguard Worker }
1321*da0073e9SAndroid Build Coastguard Worker
1322*da0073e9SAndroid Build Coastguard Worker SmallVector(const SmallVector& RHS) : SmallVectorImpl<T>(N) {
1323*da0073e9SAndroid Build Coastguard Worker if (!RHS.empty())
1324*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl<T>::operator=(RHS);
1325*da0073e9SAndroid Build Coastguard Worker }
1326*da0073e9SAndroid Build Coastguard Worker
1327*da0073e9SAndroid Build Coastguard Worker SmallVector& operator=(const SmallVector& RHS) {
1328*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl<T>::operator=(RHS);
1329*da0073e9SAndroid Build Coastguard Worker return *this;
1330*da0073e9SAndroid Build Coastguard Worker }
1331*da0073e9SAndroid Build Coastguard Worker
1332*da0073e9SAndroid Build Coastguard Worker SmallVector(SmallVector&& RHS) noexcept(
1333*da0073e9SAndroid Build Coastguard Worker std::is_nothrow_move_assignable_v<SmallVectorImpl<T>>)
1334*da0073e9SAndroid Build Coastguard Worker : SmallVectorImpl<T>(N) {
1335*da0073e9SAndroid Build Coastguard Worker if (!RHS.empty())
1336*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl<T>::operator=(::std::move(RHS));
1337*da0073e9SAndroid Build Coastguard Worker }
1338*da0073e9SAndroid Build Coastguard Worker
1339*da0073e9SAndroid Build Coastguard Worker // note: The enable_if restricts Container to types that have a .begin() and
1340*da0073e9SAndroid Build Coastguard Worker // .end() that return valid input iterators.
1341*da0073e9SAndroid Build Coastguard Worker template <
1342*da0073e9SAndroid Build Coastguard Worker typename Container,
1343*da0073e9SAndroid Build Coastguard Worker std::enable_if_t<
1344*da0073e9SAndroid Build Coastguard Worker std::is_convertible_v<
1345*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<
1346*da0073e9SAndroid Build Coastguard Worker decltype(std::declval<Container>()
1347*da0073e9SAndroid Build Coastguard Worker .begin())>::iterator_category,
1348*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag> &&
1349*da0073e9SAndroid Build Coastguard Worker std::is_convertible_v<
1350*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<
1351*da0073e9SAndroid Build Coastguard Worker decltype(std::declval<Container>()
1352*da0073e9SAndroid Build Coastguard Worker .end())>::iterator_category,
1353*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag>,
1354*da0073e9SAndroid Build Coastguard Worker int> = 0>
1355*da0073e9SAndroid Build Coastguard Worker SmallVector& operator=(const Container& RHS) {
1356*da0073e9SAndroid Build Coastguard Worker this->assign(RHS.begin(), RHS.end());
1357*da0073e9SAndroid Build Coastguard Worker return *this;
1358*da0073e9SAndroid Build Coastguard Worker }
1359*da0073e9SAndroid Build Coastguard Worker
1360*da0073e9SAndroid Build Coastguard Worker SmallVector(SmallVectorImpl<T>&& RHS) noexcept(
1361*da0073e9SAndroid Build Coastguard Worker std::is_nothrow_move_assignable_v<SmallVectorImpl<T>>)
1362*da0073e9SAndroid Build Coastguard Worker : SmallVectorImpl<T>(N) {
1363*da0073e9SAndroid Build Coastguard Worker if (!RHS.empty())
1364*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl<T>::operator=(::std::move(RHS));
1365*da0073e9SAndroid Build Coastguard Worker }
1366*da0073e9SAndroid Build Coastguard Worker
1367*da0073e9SAndroid Build Coastguard Worker SmallVector& operator=(SmallVector&& RHS) noexcept(
1368*da0073e9SAndroid Build Coastguard Worker std::is_nothrow_move_assignable_v<SmallVectorImpl<T>>) {
1369*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl<T>::operator=(::std::move(RHS));
1370*da0073e9SAndroid Build Coastguard Worker return *this;
1371*da0073e9SAndroid Build Coastguard Worker }
1372*da0073e9SAndroid Build Coastguard Worker
1373*da0073e9SAndroid Build Coastguard Worker SmallVector& operator=(SmallVectorImpl<T>&& RHS) noexcept(
1374*da0073e9SAndroid Build Coastguard Worker std::is_nothrow_move_constructible_v<SmallVectorImpl<T>>) {
1375*da0073e9SAndroid Build Coastguard Worker SmallVectorImpl<T>::operator=(::std::move(RHS));
1376*da0073e9SAndroid Build Coastguard Worker return *this;
1377*da0073e9SAndroid Build Coastguard Worker }
1378*da0073e9SAndroid Build Coastguard Worker
1379*da0073e9SAndroid Build Coastguard Worker // note: The enable_if restricts Container to types that have a .begin() and
1380*da0073e9SAndroid Build Coastguard Worker // .end() that return valid input iterators.
1381*da0073e9SAndroid Build Coastguard Worker template <
1382*da0073e9SAndroid Build Coastguard Worker typename Container,
1383*da0073e9SAndroid Build Coastguard Worker std::enable_if_t<
1384*da0073e9SAndroid Build Coastguard Worker std::is_convertible_v<
1385*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<
1386*da0073e9SAndroid Build Coastguard Worker decltype(std::declval<Container>()
1387*da0073e9SAndroid Build Coastguard Worker .begin())>::iterator_category,
1388*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag> &&
1389*da0073e9SAndroid Build Coastguard Worker std::is_convertible_v<
1390*da0073e9SAndroid Build Coastguard Worker typename std::iterator_traits<
1391*da0073e9SAndroid Build Coastguard Worker decltype(std::declval<Container>()
1392*da0073e9SAndroid Build Coastguard Worker .end())>::iterator_category,
1393*da0073e9SAndroid Build Coastguard Worker std::input_iterator_tag>,
1394*da0073e9SAndroid Build Coastguard Worker int> = 0>
1395*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
1396*da0073e9SAndroid Build Coastguard Worker SmallVector& operator=(Container&& C) {
1397*da0073e9SAndroid Build Coastguard Worker this->assign(C.begin(), C.end());
1398*da0073e9SAndroid Build Coastguard Worker return *this;
1399*da0073e9SAndroid Build Coastguard Worker }
1400*da0073e9SAndroid Build Coastguard Worker
1401*da0073e9SAndroid Build Coastguard Worker SmallVector& operator=(std::initializer_list<T> IL) {
1402*da0073e9SAndroid Build Coastguard Worker this->assign(IL);
1403*da0073e9SAndroid Build Coastguard Worker return *this;
1404*da0073e9SAndroid Build Coastguard Worker }
1405*da0073e9SAndroid Build Coastguard Worker };
1406*da0073e9SAndroid Build Coastguard Worker
1407*da0073e9SAndroid Build Coastguard Worker template <typename T, unsigned N>
1408*da0073e9SAndroid Build Coastguard Worker inline size_t capacity_in_bytes(const SmallVector<T, N>& X) {
1409*da0073e9SAndroid Build Coastguard Worker return X.capacity_in_bytes();
1410*da0073e9SAndroid Build Coastguard Worker }
1411*da0073e9SAndroid Build Coastguard Worker
1412*da0073e9SAndroid Build Coastguard Worker template <typename T, unsigned N>
1413*da0073e9SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, const SmallVector<T, N>& list) {
1414*da0073e9SAndroid Build Coastguard Worker int i = 0;
1415*da0073e9SAndroid Build Coastguard Worker out << "[";
1416*da0073e9SAndroid Build Coastguard Worker for (auto e : list) {
1417*da0073e9SAndroid Build Coastguard Worker if (i++ > 0)
1418*da0073e9SAndroid Build Coastguard Worker out << ", ";
1419*da0073e9SAndroid Build Coastguard Worker out << e;
1420*da0073e9SAndroid Build Coastguard Worker }
1421*da0073e9SAndroid Build Coastguard Worker out << "]";
1422*da0073e9SAndroid Build Coastguard Worker return out;
1423*da0073e9SAndroid Build Coastguard Worker }
1424*da0073e9SAndroid Build Coastguard Worker
1425*da0073e9SAndroid Build Coastguard Worker template <typename RangeType>
1426*da0073e9SAndroid Build Coastguard Worker using ValueTypeFromRangeType = std::remove_const_t<
1427*da0073e9SAndroid Build Coastguard Worker std::remove_reference_t<decltype(*std::begin(std::declval<RangeType&>()))>>;
1428*da0073e9SAndroid Build Coastguard Worker
1429*da0073e9SAndroid Build Coastguard Worker /// Given a range of type R, iterate the entire range and return a
1430*da0073e9SAndroid Build Coastguard Worker /// SmallVector with elements of the vector. This is useful, for example,
1431*da0073e9SAndroid Build Coastguard Worker /// when you want to iterate a range and then sort the results.
1432*da0073e9SAndroid Build Coastguard Worker template <unsigned Size, typename R>
1433*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
1434*da0073e9SAndroid Build Coastguard Worker SmallVector<ValueTypeFromRangeType<R>, Size> to_vector(R&& Range) {
1435*da0073e9SAndroid Build Coastguard Worker return {std::begin(Range), std::end(Range)};
1436*da0073e9SAndroid Build Coastguard Worker }
1437*da0073e9SAndroid Build Coastguard Worker template <typename R>
1438*da0073e9SAndroid Build Coastguard Worker SmallVector<
1439*da0073e9SAndroid Build Coastguard Worker ValueTypeFromRangeType<R>,
1440*da0073e9SAndroid Build Coastguard Worker CalculateSmallVectorDefaultInlinedElements<
1441*da0073e9SAndroid Build Coastguard Worker ValueTypeFromRangeType<R>>::value>
1442*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
1443*da0073e9SAndroid Build Coastguard Worker to_vector(R&& Range) {
1444*da0073e9SAndroid Build Coastguard Worker return {std::begin(Range), std::end(Range)};
1445*da0073e9SAndroid Build Coastguard Worker }
1446*da0073e9SAndroid Build Coastguard Worker
1447*da0073e9SAndroid Build Coastguard Worker } // end namespace c10
1448*da0073e9SAndroid Build Coastguard Worker
1449*da0073e9SAndroid Build Coastguard Worker namespace std {
1450*da0073e9SAndroid Build Coastguard Worker
1451*da0073e9SAndroid Build Coastguard Worker /// Implement std::swap in terms of SmallVector swap.
1452*da0073e9SAndroid Build Coastguard Worker template <typename T>
1453*da0073e9SAndroid Build Coastguard Worker inline void swap(
1454*da0073e9SAndroid Build Coastguard Worker c10::SmallVectorImpl<T>& LHS,
1455*da0073e9SAndroid Build Coastguard Worker c10::SmallVectorImpl<T>& RHS) noexcept {
1456*da0073e9SAndroid Build Coastguard Worker LHS.swap(RHS);
1457*da0073e9SAndroid Build Coastguard Worker }
1458*da0073e9SAndroid Build Coastguard Worker
1459*da0073e9SAndroid Build Coastguard Worker /// Implement std::swap in terms of SmallVector swap.
1460*da0073e9SAndroid Build Coastguard Worker template <typename T, unsigned N>
1461*da0073e9SAndroid Build Coastguard Worker inline void swap(
1462*da0073e9SAndroid Build Coastguard Worker c10::SmallVector<T, N>& LHS,
1463*da0073e9SAndroid Build Coastguard Worker c10::SmallVector<T, N>& RHS) noexcept {
1464*da0073e9SAndroid Build Coastguard Worker LHS.swap(RHS);
1465*da0073e9SAndroid Build Coastguard Worker }
1466*da0073e9SAndroid Build Coastguard Worker
1467*da0073e9SAndroid Build Coastguard Worker } // end namespace std
1468