xref: /aosp_15_r20/external/abseil-cpp/absl/container/inlined_vector.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2019 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker //
15*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
16*9356374aSAndroid Build Coastguard Worker // File: inlined_vector.h
17*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
18*9356374aSAndroid Build Coastguard Worker //
19*9356374aSAndroid Build Coastguard Worker // This header file contains the declaration and definition of an "inlined
20*9356374aSAndroid Build Coastguard Worker // vector" which behaves in an equivalent fashion to a `std::vector`, except
21*9356374aSAndroid Build Coastguard Worker // that storage for small sequences of the vector are provided inline without
22*9356374aSAndroid Build Coastguard Worker // requiring any heap allocation.
23*9356374aSAndroid Build Coastguard Worker //
24*9356374aSAndroid Build Coastguard Worker // An `absl::InlinedVector<T, N>` specifies the default capacity `N` as one of
25*9356374aSAndroid Build Coastguard Worker // its template parameters. Instances where `size() <= N` hold contained
26*9356374aSAndroid Build Coastguard Worker // elements in inline space. Typically `N` is very small so that sequences that
27*9356374aSAndroid Build Coastguard Worker // are expected to be short do not require allocations.
28*9356374aSAndroid Build Coastguard Worker //
29*9356374aSAndroid Build Coastguard Worker // An `absl::InlinedVector` does not usually require a specific allocator. If
30*9356374aSAndroid Build Coastguard Worker // the inlined vector grows beyond its initial constraints, it will need to
31*9356374aSAndroid Build Coastguard Worker // allocate (as any normal `std::vector` would). This is usually performed with
32*9356374aSAndroid Build Coastguard Worker // the default allocator (defined as `std::allocator<T>`). Optionally, a custom
33*9356374aSAndroid Build Coastguard Worker // allocator type may be specified as `A` in `absl::InlinedVector<T, N, A>`.
34*9356374aSAndroid Build Coastguard Worker 
35*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_CONTAINER_INLINED_VECTOR_H_
36*9356374aSAndroid Build Coastguard Worker #define ABSL_CONTAINER_INLINED_VECTOR_H_
37*9356374aSAndroid Build Coastguard Worker 
38*9356374aSAndroid Build Coastguard Worker #include <algorithm>
39*9356374aSAndroid Build Coastguard Worker #include <cstddef>
40*9356374aSAndroid Build Coastguard Worker #include <cstdlib>
41*9356374aSAndroid Build Coastguard Worker #include <cstring>
42*9356374aSAndroid Build Coastguard Worker #include <initializer_list>
43*9356374aSAndroid Build Coastguard Worker #include <iterator>
44*9356374aSAndroid Build Coastguard Worker #include <memory>
45*9356374aSAndroid Build Coastguard Worker #include <type_traits>
46*9356374aSAndroid Build Coastguard Worker #include <utility>
47*9356374aSAndroid Build Coastguard Worker 
48*9356374aSAndroid Build Coastguard Worker #include "absl/algorithm/algorithm.h"
49*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/throw_delegate.h"
50*9356374aSAndroid Build Coastguard Worker #include "absl/base/macros.h"
51*9356374aSAndroid Build Coastguard Worker #include "absl/base/optimization.h"
52*9356374aSAndroid Build Coastguard Worker #include "absl/base/port.h"
53*9356374aSAndroid Build Coastguard Worker #include "absl/container/internal/inlined_vector.h"
54*9356374aSAndroid Build Coastguard Worker #include "absl/memory/memory.h"
55*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h"
56*9356374aSAndroid Build Coastguard Worker 
57*9356374aSAndroid Build Coastguard Worker namespace absl {
58*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
59*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
60*9356374aSAndroid Build Coastguard Worker // InlinedVector
61*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
62*9356374aSAndroid Build Coastguard Worker //
63*9356374aSAndroid Build Coastguard Worker // An `absl::InlinedVector` is designed to be a drop-in replacement for
64*9356374aSAndroid Build Coastguard Worker // `std::vector` for use cases where the vector's size is sufficiently small
65*9356374aSAndroid Build Coastguard Worker // that it can be inlined. If the inlined vector does grow beyond its estimated
66*9356374aSAndroid Build Coastguard Worker // capacity, it will trigger an initial allocation on the heap, and will behave
67*9356374aSAndroid Build Coastguard Worker // as a `std::vector`. The API of the `absl::InlinedVector` within this file is
68*9356374aSAndroid Build Coastguard Worker // designed to cover the same API footprint as covered by `std::vector`.
69*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A = std::allocator<T>>
70*9356374aSAndroid Build Coastguard Worker class InlinedVector {
71*9356374aSAndroid Build Coastguard Worker   static_assert(N > 0, "`absl::InlinedVector` requires an inlined capacity.");
72*9356374aSAndroid Build Coastguard Worker 
73*9356374aSAndroid Build Coastguard Worker   using Storage = inlined_vector_internal::Storage<T, N, A>;
74*9356374aSAndroid Build Coastguard Worker 
75*9356374aSAndroid Build Coastguard Worker   template <typename TheA>
76*9356374aSAndroid Build Coastguard Worker   using AllocatorTraits = inlined_vector_internal::AllocatorTraits<TheA>;
77*9356374aSAndroid Build Coastguard Worker   template <typename TheA>
78*9356374aSAndroid Build Coastguard Worker   using MoveIterator = inlined_vector_internal::MoveIterator<TheA>;
79*9356374aSAndroid Build Coastguard Worker   template <typename TheA>
80*9356374aSAndroid Build Coastguard Worker   using IsMoveAssignOk = inlined_vector_internal::IsMoveAssignOk<TheA>;
81*9356374aSAndroid Build Coastguard Worker 
82*9356374aSAndroid Build Coastguard Worker   template <typename TheA, typename Iterator>
83*9356374aSAndroid Build Coastguard Worker   using IteratorValueAdapter =
84*9356374aSAndroid Build Coastguard Worker       inlined_vector_internal::IteratorValueAdapter<TheA, Iterator>;
85*9356374aSAndroid Build Coastguard Worker   template <typename TheA>
86*9356374aSAndroid Build Coastguard Worker   using CopyValueAdapter = inlined_vector_internal::CopyValueAdapter<TheA>;
87*9356374aSAndroid Build Coastguard Worker   template <typename TheA>
88*9356374aSAndroid Build Coastguard Worker   using DefaultValueAdapter =
89*9356374aSAndroid Build Coastguard Worker       inlined_vector_internal::DefaultValueAdapter<TheA>;
90*9356374aSAndroid Build Coastguard Worker 
91*9356374aSAndroid Build Coastguard Worker   template <typename Iterator>
92*9356374aSAndroid Build Coastguard Worker   using EnableIfAtLeastForwardIterator = absl::enable_if_t<
93*9356374aSAndroid Build Coastguard Worker       inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
94*9356374aSAndroid Build Coastguard Worker   template <typename Iterator>
95*9356374aSAndroid Build Coastguard Worker   using DisableIfAtLeastForwardIterator = absl::enable_if_t<
96*9356374aSAndroid Build Coastguard Worker       !inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
97*9356374aSAndroid Build Coastguard Worker 
98*9356374aSAndroid Build Coastguard Worker   using MemcpyPolicy = typename Storage::MemcpyPolicy;
99*9356374aSAndroid Build Coastguard Worker   using ElementwiseAssignPolicy = typename Storage::ElementwiseAssignPolicy;
100*9356374aSAndroid Build Coastguard Worker   using ElementwiseConstructPolicy =
101*9356374aSAndroid Build Coastguard Worker       typename Storage::ElementwiseConstructPolicy;
102*9356374aSAndroid Build Coastguard Worker   using MoveAssignmentPolicy = typename Storage::MoveAssignmentPolicy;
103*9356374aSAndroid Build Coastguard Worker 
104*9356374aSAndroid Build Coastguard Worker  public:
105*9356374aSAndroid Build Coastguard Worker   using allocator_type = A;
106*9356374aSAndroid Build Coastguard Worker   using value_type = inlined_vector_internal::ValueType<A>;
107*9356374aSAndroid Build Coastguard Worker   using pointer = inlined_vector_internal::Pointer<A>;
108*9356374aSAndroid Build Coastguard Worker   using const_pointer = inlined_vector_internal::ConstPointer<A>;
109*9356374aSAndroid Build Coastguard Worker   using size_type = inlined_vector_internal::SizeType<A>;
110*9356374aSAndroid Build Coastguard Worker   using difference_type = inlined_vector_internal::DifferenceType<A>;
111*9356374aSAndroid Build Coastguard Worker   using reference = inlined_vector_internal::Reference<A>;
112*9356374aSAndroid Build Coastguard Worker   using const_reference = inlined_vector_internal::ConstReference<A>;
113*9356374aSAndroid Build Coastguard Worker   using iterator = inlined_vector_internal::Iterator<A>;
114*9356374aSAndroid Build Coastguard Worker   using const_iterator = inlined_vector_internal::ConstIterator<A>;
115*9356374aSAndroid Build Coastguard Worker   using reverse_iterator = inlined_vector_internal::ReverseIterator<A>;
116*9356374aSAndroid Build Coastguard Worker   using const_reverse_iterator =
117*9356374aSAndroid Build Coastguard Worker       inlined_vector_internal::ConstReverseIterator<A>;
118*9356374aSAndroid Build Coastguard Worker 
119*9356374aSAndroid Build Coastguard Worker   // ---------------------------------------------------------------------------
120*9356374aSAndroid Build Coastguard Worker   // InlinedVector Constructors and Destructor
121*9356374aSAndroid Build Coastguard Worker   // ---------------------------------------------------------------------------
122*9356374aSAndroid Build Coastguard Worker 
123*9356374aSAndroid Build Coastguard Worker   // Creates an empty inlined vector with a value-initialized allocator.
noexcept(noexcept (allocator_type ()))124*9356374aSAndroid Build Coastguard Worker   InlinedVector() noexcept(noexcept(allocator_type())) : storage_() {}
125*9356374aSAndroid Build Coastguard Worker 
126*9356374aSAndroid Build Coastguard Worker   // Creates an empty inlined vector with a copy of `allocator`.
InlinedVector(const allocator_type & allocator)127*9356374aSAndroid Build Coastguard Worker   explicit InlinedVector(const allocator_type& allocator) noexcept
128*9356374aSAndroid Build Coastguard Worker       : storage_(allocator) {}
129*9356374aSAndroid Build Coastguard Worker 
130*9356374aSAndroid Build Coastguard Worker   // Creates an inlined vector with `n` copies of `value_type()`.
131*9356374aSAndroid Build Coastguard Worker   explicit InlinedVector(size_type n,
132*9356374aSAndroid Build Coastguard Worker                          const allocator_type& allocator = allocator_type())
storage_(allocator)133*9356374aSAndroid Build Coastguard Worker       : storage_(allocator) {
134*9356374aSAndroid Build Coastguard Worker     storage_.Initialize(DefaultValueAdapter<A>(), n);
135*9356374aSAndroid Build Coastguard Worker   }
136*9356374aSAndroid Build Coastguard Worker 
137*9356374aSAndroid Build Coastguard Worker   // Creates an inlined vector with `n` copies of `v`.
138*9356374aSAndroid Build Coastguard Worker   InlinedVector(size_type n, const_reference v,
139*9356374aSAndroid Build Coastguard Worker                 const allocator_type& allocator = allocator_type())
storage_(allocator)140*9356374aSAndroid Build Coastguard Worker       : storage_(allocator) {
141*9356374aSAndroid Build Coastguard Worker     storage_.Initialize(CopyValueAdapter<A>(std::addressof(v)), n);
142*9356374aSAndroid Build Coastguard Worker   }
143*9356374aSAndroid Build Coastguard Worker 
144*9356374aSAndroid Build Coastguard Worker   // Creates an inlined vector with copies of the elements of `list`.
145*9356374aSAndroid Build Coastguard Worker   InlinedVector(std::initializer_list<value_type> list,
146*9356374aSAndroid Build Coastguard Worker                 const allocator_type& allocator = allocator_type())
147*9356374aSAndroid Build Coastguard Worker       : InlinedVector(list.begin(), list.end(), allocator) {}
148*9356374aSAndroid Build Coastguard Worker 
149*9356374aSAndroid Build Coastguard Worker   // Creates an inlined vector with elements constructed from the provided
150*9356374aSAndroid Build Coastguard Worker   // forward iterator range [`first`, `last`).
151*9356374aSAndroid Build Coastguard Worker   //
152*9356374aSAndroid Build Coastguard Worker   // NOTE: the `enable_if` prevents ambiguous interpretation between a call to
153*9356374aSAndroid Build Coastguard Worker   // this constructor with two integral arguments and a call to the above
154*9356374aSAndroid Build Coastguard Worker   // `InlinedVector(size_type, const_reference)` constructor.
155*9356374aSAndroid Build Coastguard Worker   template <typename ForwardIterator,
156*9356374aSAndroid Build Coastguard Worker             EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
157*9356374aSAndroid Build Coastguard Worker   InlinedVector(ForwardIterator first, ForwardIterator last,
158*9356374aSAndroid Build Coastguard Worker                 const allocator_type& allocator = allocator_type())
storage_(allocator)159*9356374aSAndroid Build Coastguard Worker       : storage_(allocator) {
160*9356374aSAndroid Build Coastguard Worker     storage_.Initialize(IteratorValueAdapter<A, ForwardIterator>(first),
161*9356374aSAndroid Build Coastguard Worker                         static_cast<size_t>(std::distance(first, last)));
162*9356374aSAndroid Build Coastguard Worker   }
163*9356374aSAndroid Build Coastguard Worker 
164*9356374aSAndroid Build Coastguard Worker   // Creates an inlined vector with elements constructed from the provided input
165*9356374aSAndroid Build Coastguard Worker   // iterator range [`first`, `last`).
166*9356374aSAndroid Build Coastguard Worker   template <typename InputIterator,
167*9356374aSAndroid Build Coastguard Worker             DisableIfAtLeastForwardIterator<InputIterator> = 0>
168*9356374aSAndroid Build Coastguard Worker   InlinedVector(InputIterator first, InputIterator last,
169*9356374aSAndroid Build Coastguard Worker                 const allocator_type& allocator = allocator_type())
storage_(allocator)170*9356374aSAndroid Build Coastguard Worker       : storage_(allocator) {
171*9356374aSAndroid Build Coastguard Worker     std::copy(first, last, std::back_inserter(*this));
172*9356374aSAndroid Build Coastguard Worker   }
173*9356374aSAndroid Build Coastguard Worker 
174*9356374aSAndroid Build Coastguard Worker   // Creates an inlined vector by copying the contents of `other` using
175*9356374aSAndroid Build Coastguard Worker   // `other`'s allocator.
InlinedVector(const InlinedVector & other)176*9356374aSAndroid Build Coastguard Worker   InlinedVector(const InlinedVector& other)
177*9356374aSAndroid Build Coastguard Worker       : InlinedVector(other, other.storage_.GetAllocator()) {}
178*9356374aSAndroid Build Coastguard Worker 
179*9356374aSAndroid Build Coastguard Worker   // Creates an inlined vector by copying the contents of `other` using the
180*9356374aSAndroid Build Coastguard Worker   // provided `allocator`.
InlinedVector(const InlinedVector & other,const allocator_type & allocator)181*9356374aSAndroid Build Coastguard Worker   InlinedVector(const InlinedVector& other, const allocator_type& allocator)
182*9356374aSAndroid Build Coastguard Worker       : storage_(allocator) {
183*9356374aSAndroid Build Coastguard Worker     // Fast path: if the other vector is empty, there's nothing for us to do.
184*9356374aSAndroid Build Coastguard Worker     if (other.empty()) {
185*9356374aSAndroid Build Coastguard Worker       return;
186*9356374aSAndroid Build Coastguard Worker     }
187*9356374aSAndroid Build Coastguard Worker 
188*9356374aSAndroid Build Coastguard Worker     // Fast path: if the value type is trivially copy constructible, we know the
189*9356374aSAndroid Build Coastguard Worker     // allocator doesn't do anything fancy, and there is nothing on the heap
190*9356374aSAndroid Build Coastguard Worker     // then we know it is legal for us to simply memcpy the other vector's
191*9356374aSAndroid Build Coastguard Worker     // inlined bytes to form our copy of its elements.
192*9356374aSAndroid Build Coastguard Worker     if (absl::is_trivially_copy_constructible<value_type>::value &&
193*9356374aSAndroid Build Coastguard Worker         std::is_same<A, std::allocator<value_type>>::value &&
194*9356374aSAndroid Build Coastguard Worker         !other.storage_.GetIsAllocated()) {
195*9356374aSAndroid Build Coastguard Worker       storage_.MemcpyFrom(other.storage_);
196*9356374aSAndroid Build Coastguard Worker       return;
197*9356374aSAndroid Build Coastguard Worker     }
198*9356374aSAndroid Build Coastguard Worker 
199*9356374aSAndroid Build Coastguard Worker     storage_.InitFrom(other.storage_);
200*9356374aSAndroid Build Coastguard Worker   }
201*9356374aSAndroid Build Coastguard Worker 
202*9356374aSAndroid Build Coastguard Worker   // Creates an inlined vector by moving in the contents of `other` without
203*9356374aSAndroid Build Coastguard Worker   // allocating. If `other` contains allocated memory, the newly-created inlined
204*9356374aSAndroid Build Coastguard Worker   // vector will take ownership of that memory. However, if `other` does not
205*9356374aSAndroid Build Coastguard Worker   // contain allocated memory, the newly-created inlined vector will perform
206*9356374aSAndroid Build Coastguard Worker   // element-wise move construction of the contents of `other`.
207*9356374aSAndroid Build Coastguard Worker   //
208*9356374aSAndroid Build Coastguard Worker   // NOTE: since no allocation is performed for the inlined vector in either
209*9356374aSAndroid Build Coastguard Worker   // case, the `noexcept(...)` specification depends on whether moving the
210*9356374aSAndroid Build Coastguard Worker   // underlying objects can throw. It is assumed assumed that...
211*9356374aSAndroid Build Coastguard Worker   //  a) move constructors should only throw due to allocation failure.
212*9356374aSAndroid Build Coastguard Worker   //  b) if `value_type`'s move constructor allocates, it uses the same
213*9356374aSAndroid Build Coastguard Worker   //     allocation function as the inlined vector's allocator.
214*9356374aSAndroid Build Coastguard Worker   // Thus, the move constructor is non-throwing if the allocator is non-throwing
215*9356374aSAndroid Build Coastguard Worker   // or `value_type`'s move constructor is specified as `noexcept`.
216*9356374aSAndroid Build Coastguard Worker   InlinedVector(InlinedVector&& other) noexcept(
217*9356374aSAndroid Build Coastguard Worker       absl::allocator_is_nothrow<allocator_type>::value ||
218*9356374aSAndroid Build Coastguard Worker       std::is_nothrow_move_constructible<value_type>::value)
219*9356374aSAndroid Build Coastguard Worker       : storage_(other.storage_.GetAllocator()) {
220*9356374aSAndroid Build Coastguard Worker     // Fast path: if the value type can be trivially relocated (i.e. moved from
221*9356374aSAndroid Build Coastguard Worker     // and destroyed), and we know the allocator doesn't do anything fancy, then
222*9356374aSAndroid Build Coastguard Worker     // it's safe for us to simply adopt the contents of the storage for `other`
223*9356374aSAndroid Build Coastguard Worker     // and remove its own reference to them. It's as if we had individually
224*9356374aSAndroid Build Coastguard Worker     // move-constructed each value and then destroyed the original.
225*9356374aSAndroid Build Coastguard Worker     if (absl::is_trivially_relocatable<value_type>::value &&
226*9356374aSAndroid Build Coastguard Worker         std::is_same<A, std::allocator<value_type>>::value) {
227*9356374aSAndroid Build Coastguard Worker       storage_.MemcpyFrom(other.storage_);
228*9356374aSAndroid Build Coastguard Worker       other.storage_.SetInlinedSize(0);
229*9356374aSAndroid Build Coastguard Worker       return;
230*9356374aSAndroid Build Coastguard Worker     }
231*9356374aSAndroid Build Coastguard Worker 
232*9356374aSAndroid Build Coastguard Worker     // Fast path: if the other vector is on the heap, we can simply take over
233*9356374aSAndroid Build Coastguard Worker     // its allocation.
234*9356374aSAndroid Build Coastguard Worker     if (other.storage_.GetIsAllocated()) {
235*9356374aSAndroid Build Coastguard Worker       storage_.SetAllocation({other.storage_.GetAllocatedData(),
236*9356374aSAndroid Build Coastguard Worker                               other.storage_.GetAllocatedCapacity()});
237*9356374aSAndroid Build Coastguard Worker       storage_.SetAllocatedSize(other.storage_.GetSize());
238*9356374aSAndroid Build Coastguard Worker 
239*9356374aSAndroid Build Coastguard Worker       other.storage_.SetInlinedSize(0);
240*9356374aSAndroid Build Coastguard Worker       return;
241*9356374aSAndroid Build Coastguard Worker     }
242*9356374aSAndroid Build Coastguard Worker 
243*9356374aSAndroid Build Coastguard Worker     // Otherwise we must move each element individually.
244*9356374aSAndroid Build Coastguard Worker     IteratorValueAdapter<A, MoveIterator<A>> other_values(
245*9356374aSAndroid Build Coastguard Worker         MoveIterator<A>(other.storage_.GetInlinedData()));
246*9356374aSAndroid Build Coastguard Worker 
247*9356374aSAndroid Build Coastguard Worker     inlined_vector_internal::ConstructElements<A>(
248*9356374aSAndroid Build Coastguard Worker         storage_.GetAllocator(), storage_.GetInlinedData(), other_values,
249*9356374aSAndroid Build Coastguard Worker         other.storage_.GetSize());
250*9356374aSAndroid Build Coastguard Worker 
251*9356374aSAndroid Build Coastguard Worker     storage_.SetInlinedSize(other.storage_.GetSize());
252*9356374aSAndroid Build Coastguard Worker   }
253*9356374aSAndroid Build Coastguard Worker 
254*9356374aSAndroid Build Coastguard Worker   // Creates an inlined vector by moving in the contents of `other` with a copy
255*9356374aSAndroid Build Coastguard Worker   // of `allocator`.
256*9356374aSAndroid Build Coastguard Worker   //
257*9356374aSAndroid Build Coastguard Worker   // NOTE: if `other`'s allocator is not equal to `allocator`, even if `other`
258*9356374aSAndroid Build Coastguard Worker   // contains allocated memory, this move constructor will still allocate. Since
259*9356374aSAndroid Build Coastguard Worker   // allocation is performed, this constructor can only be `noexcept` if the
260*9356374aSAndroid Build Coastguard Worker   // specified allocator is also `noexcept`.
InlinedVector(InlinedVector && other,const allocator_type & allocator)261*9356374aSAndroid Build Coastguard Worker   InlinedVector(
262*9356374aSAndroid Build Coastguard Worker       InlinedVector&& other,
263*9356374aSAndroid Build Coastguard Worker       const allocator_type&
264*9356374aSAndroid Build Coastguard Worker           allocator) noexcept(absl::allocator_is_nothrow<allocator_type>::value)
265*9356374aSAndroid Build Coastguard Worker       : storage_(allocator) {
266*9356374aSAndroid Build Coastguard Worker     // Fast path: if the value type can be trivially relocated (i.e. moved from
267*9356374aSAndroid Build Coastguard Worker     // and destroyed), and we know the allocator doesn't do anything fancy, then
268*9356374aSAndroid Build Coastguard Worker     // it's safe for us to simply adopt the contents of the storage for `other`
269*9356374aSAndroid Build Coastguard Worker     // and remove its own reference to them. It's as if we had individually
270*9356374aSAndroid Build Coastguard Worker     // move-constructed each value and then destroyed the original.
271*9356374aSAndroid Build Coastguard Worker     if (absl::is_trivially_relocatable<value_type>::value &&
272*9356374aSAndroid Build Coastguard Worker         std::is_same<A, std::allocator<value_type>>::value) {
273*9356374aSAndroid Build Coastguard Worker       storage_.MemcpyFrom(other.storage_);
274*9356374aSAndroid Build Coastguard Worker       other.storage_.SetInlinedSize(0);
275*9356374aSAndroid Build Coastguard Worker       return;
276*9356374aSAndroid Build Coastguard Worker     }
277*9356374aSAndroid Build Coastguard Worker 
278*9356374aSAndroid Build Coastguard Worker     // Fast path: if the other vector is on the heap and shared the same
279*9356374aSAndroid Build Coastguard Worker     // allocator, we can simply take over its allocation.
280*9356374aSAndroid Build Coastguard Worker     if ((storage_.GetAllocator() == other.storage_.GetAllocator()) &&
281*9356374aSAndroid Build Coastguard Worker         other.storage_.GetIsAllocated()) {
282*9356374aSAndroid Build Coastguard Worker       storage_.SetAllocation({other.storage_.GetAllocatedData(),
283*9356374aSAndroid Build Coastguard Worker                               other.storage_.GetAllocatedCapacity()});
284*9356374aSAndroid Build Coastguard Worker       storage_.SetAllocatedSize(other.storage_.GetSize());
285*9356374aSAndroid Build Coastguard Worker 
286*9356374aSAndroid Build Coastguard Worker       other.storage_.SetInlinedSize(0);
287*9356374aSAndroid Build Coastguard Worker       return;
288*9356374aSAndroid Build Coastguard Worker     }
289*9356374aSAndroid Build Coastguard Worker 
290*9356374aSAndroid Build Coastguard Worker     // Otherwise we must move each element individually.
291*9356374aSAndroid Build Coastguard Worker     storage_.Initialize(
292*9356374aSAndroid Build Coastguard Worker         IteratorValueAdapter<A, MoveIterator<A>>(MoveIterator<A>(other.data())),
293*9356374aSAndroid Build Coastguard Worker         other.size());
294*9356374aSAndroid Build Coastguard Worker   }
295*9356374aSAndroid Build Coastguard Worker 
~InlinedVector()296*9356374aSAndroid Build Coastguard Worker   ~InlinedVector() {}
297*9356374aSAndroid Build Coastguard Worker 
298*9356374aSAndroid Build Coastguard Worker   // ---------------------------------------------------------------------------
299*9356374aSAndroid Build Coastguard Worker   // InlinedVector Member Accessors
300*9356374aSAndroid Build Coastguard Worker   // ---------------------------------------------------------------------------
301*9356374aSAndroid Build Coastguard Worker 
302*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::empty()`
303*9356374aSAndroid Build Coastguard Worker   //
304*9356374aSAndroid Build Coastguard Worker   // Returns whether the inlined vector contains no elements.
empty()305*9356374aSAndroid Build Coastguard Worker   bool empty() const noexcept { return !size(); }
306*9356374aSAndroid Build Coastguard Worker 
307*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::size()`
308*9356374aSAndroid Build Coastguard Worker   //
309*9356374aSAndroid Build Coastguard Worker   // Returns the number of elements in the inlined vector.
size()310*9356374aSAndroid Build Coastguard Worker   size_type size() const noexcept { return storage_.GetSize(); }
311*9356374aSAndroid Build Coastguard Worker 
312*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::max_size()`
313*9356374aSAndroid Build Coastguard Worker   //
314*9356374aSAndroid Build Coastguard Worker   // Returns the maximum number of elements the inlined vector can hold.
max_size()315*9356374aSAndroid Build Coastguard Worker   size_type max_size() const noexcept {
316*9356374aSAndroid Build Coastguard Worker     // One bit of the size storage is used to indicate whether the inlined
317*9356374aSAndroid Build Coastguard Worker     // vector contains allocated memory. As a result, the maximum size that the
318*9356374aSAndroid Build Coastguard Worker     // inlined vector can express is the minimum of the limit of how many
319*9356374aSAndroid Build Coastguard Worker     // objects we can allocate and std::numeric_limits<size_type>::max() / 2.
320*9356374aSAndroid Build Coastguard Worker     return (std::min)(AllocatorTraits<A>::max_size(storage_.GetAllocator()),
321*9356374aSAndroid Build Coastguard Worker                       (std::numeric_limits<size_type>::max)() / 2);
322*9356374aSAndroid Build Coastguard Worker   }
323*9356374aSAndroid Build Coastguard Worker 
324*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::capacity()`
325*9356374aSAndroid Build Coastguard Worker   //
326*9356374aSAndroid Build Coastguard Worker   // Returns the number of elements that could be stored in the inlined vector
327*9356374aSAndroid Build Coastguard Worker   // without requiring a reallocation.
328*9356374aSAndroid Build Coastguard Worker   //
329*9356374aSAndroid Build Coastguard Worker   // NOTE: for most inlined vectors, `capacity()` should be equal to the
330*9356374aSAndroid Build Coastguard Worker   // template parameter `N`. For inlined vectors which exceed this capacity,
331*9356374aSAndroid Build Coastguard Worker   // they will no longer be inlined and `capacity()` will equal the capactity of
332*9356374aSAndroid Build Coastguard Worker   // the allocated memory.
capacity()333*9356374aSAndroid Build Coastguard Worker   size_type capacity() const noexcept {
334*9356374aSAndroid Build Coastguard Worker     return storage_.GetIsAllocated() ? storage_.GetAllocatedCapacity()
335*9356374aSAndroid Build Coastguard Worker                                      : storage_.GetInlinedCapacity();
336*9356374aSAndroid Build Coastguard Worker   }
337*9356374aSAndroid Build Coastguard Worker 
338*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::data()`
339*9356374aSAndroid Build Coastguard Worker   //
340*9356374aSAndroid Build Coastguard Worker   // Returns a `pointer` to the elements of the inlined vector. This pointer
341*9356374aSAndroid Build Coastguard Worker   // can be used to access and modify the contained elements.
342*9356374aSAndroid Build Coastguard Worker   //
343*9356374aSAndroid Build Coastguard Worker   // NOTE: only elements within [`data()`, `data() + size()`) are valid.
data()344*9356374aSAndroid Build Coastguard Worker   pointer data() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
345*9356374aSAndroid Build Coastguard Worker     return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
346*9356374aSAndroid Build Coastguard Worker                                      : storage_.GetInlinedData();
347*9356374aSAndroid Build Coastguard Worker   }
348*9356374aSAndroid Build Coastguard Worker 
349*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::data()` that returns a `const_pointer` to the
350*9356374aSAndroid Build Coastguard Worker   // elements of the inlined vector. This pointer can be used to access but not
351*9356374aSAndroid Build Coastguard Worker   // modify the contained elements.
352*9356374aSAndroid Build Coastguard Worker   //
353*9356374aSAndroid Build Coastguard Worker   // NOTE: only elements within [`data()`, `data() + size()`) are valid.
data()354*9356374aSAndroid Build Coastguard Worker   const_pointer data() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
355*9356374aSAndroid Build Coastguard Worker     return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
356*9356374aSAndroid Build Coastguard Worker                                      : storage_.GetInlinedData();
357*9356374aSAndroid Build Coastguard Worker   }
358*9356374aSAndroid Build Coastguard Worker 
359*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::operator[](...)`
360*9356374aSAndroid Build Coastguard Worker   //
361*9356374aSAndroid Build Coastguard Worker   // Returns a `reference` to the `i`th element of the inlined vector.
362*9356374aSAndroid Build Coastguard Worker   reference operator[](size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
363*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(i < size());
364*9356374aSAndroid Build Coastguard Worker     return data()[i];
365*9356374aSAndroid Build Coastguard Worker   }
366*9356374aSAndroid Build Coastguard Worker 
367*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::operator[](...)` that returns a
368*9356374aSAndroid Build Coastguard Worker   // `const_reference` to the `i`th element of the inlined vector.
369*9356374aSAndroid Build Coastguard Worker   const_reference operator[](size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
370*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(i < size());
371*9356374aSAndroid Build Coastguard Worker     return data()[i];
372*9356374aSAndroid Build Coastguard Worker   }
373*9356374aSAndroid Build Coastguard Worker 
374*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::at(...)`
375*9356374aSAndroid Build Coastguard Worker   //
376*9356374aSAndroid Build Coastguard Worker   // Returns a `reference` to the `i`th element of the inlined vector.
377*9356374aSAndroid Build Coastguard Worker   //
378*9356374aSAndroid Build Coastguard Worker   // NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,
379*9356374aSAndroid Build Coastguard Worker   // in both debug and non-debug builds, `std::out_of_range` will be thrown.
at(size_type i)380*9356374aSAndroid Build Coastguard Worker   reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
381*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_FALSE(i >= size())) {
382*9356374aSAndroid Build Coastguard Worker       base_internal::ThrowStdOutOfRange(
383*9356374aSAndroid Build Coastguard Worker           "`InlinedVector::at(size_type)` failed bounds check");
384*9356374aSAndroid Build Coastguard Worker     }
385*9356374aSAndroid Build Coastguard Worker     return data()[i];
386*9356374aSAndroid Build Coastguard Worker   }
387*9356374aSAndroid Build Coastguard Worker 
388*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::at(...)` that returns a `const_reference` to
389*9356374aSAndroid Build Coastguard Worker   // the `i`th element of the inlined vector.
390*9356374aSAndroid Build Coastguard Worker   //
391*9356374aSAndroid Build Coastguard Worker   // NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,
392*9356374aSAndroid Build Coastguard Worker   // in both debug and non-debug builds, `std::out_of_range` will be thrown.
at(size_type i)393*9356374aSAndroid Build Coastguard Worker   const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
394*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_FALSE(i >= size())) {
395*9356374aSAndroid Build Coastguard Worker       base_internal::ThrowStdOutOfRange(
396*9356374aSAndroid Build Coastguard Worker           "`InlinedVector::at(size_type) const` failed bounds check");
397*9356374aSAndroid Build Coastguard Worker     }
398*9356374aSAndroid Build Coastguard Worker     return data()[i];
399*9356374aSAndroid Build Coastguard Worker   }
400*9356374aSAndroid Build Coastguard Worker 
401*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::front()`
402*9356374aSAndroid Build Coastguard Worker   //
403*9356374aSAndroid Build Coastguard Worker   // Returns a `reference` to the first element of the inlined vector.
front()404*9356374aSAndroid Build Coastguard Worker   reference front() ABSL_ATTRIBUTE_LIFETIME_BOUND {
405*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(!empty());
406*9356374aSAndroid Build Coastguard Worker     return data()[0];
407*9356374aSAndroid Build Coastguard Worker   }
408*9356374aSAndroid Build Coastguard Worker 
409*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::front()` that returns a `const_reference` to
410*9356374aSAndroid Build Coastguard Worker   // the first element of the inlined vector.
front()411*9356374aSAndroid Build Coastguard Worker   const_reference front() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
412*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(!empty());
413*9356374aSAndroid Build Coastguard Worker     return data()[0];
414*9356374aSAndroid Build Coastguard Worker   }
415*9356374aSAndroid Build Coastguard Worker 
416*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::back()`
417*9356374aSAndroid Build Coastguard Worker   //
418*9356374aSAndroid Build Coastguard Worker   // Returns a `reference` to the last element of the inlined vector.
back()419*9356374aSAndroid Build Coastguard Worker   reference back() ABSL_ATTRIBUTE_LIFETIME_BOUND {
420*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(!empty());
421*9356374aSAndroid Build Coastguard Worker     return data()[size() - 1];
422*9356374aSAndroid Build Coastguard Worker   }
423*9356374aSAndroid Build Coastguard Worker 
424*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::back()` that returns a `const_reference` to the
425*9356374aSAndroid Build Coastguard Worker   // last element of the inlined vector.
back()426*9356374aSAndroid Build Coastguard Worker   const_reference back() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
427*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(!empty());
428*9356374aSAndroid Build Coastguard Worker     return data()[size() - 1];
429*9356374aSAndroid Build Coastguard Worker   }
430*9356374aSAndroid Build Coastguard Worker 
431*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::begin()`
432*9356374aSAndroid Build Coastguard Worker   //
433*9356374aSAndroid Build Coastguard Worker   // Returns an `iterator` to the beginning of the inlined vector.
begin()434*9356374aSAndroid Build Coastguard Worker   iterator begin() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }
435*9356374aSAndroid Build Coastguard Worker 
436*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::begin()` that returns a `const_iterator` to
437*9356374aSAndroid Build Coastguard Worker   // the beginning of the inlined vector.
begin()438*9356374aSAndroid Build Coastguard Worker   const_iterator begin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
439*9356374aSAndroid Build Coastguard Worker     return data();
440*9356374aSAndroid Build Coastguard Worker   }
441*9356374aSAndroid Build Coastguard Worker 
442*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::end()`
443*9356374aSAndroid Build Coastguard Worker   //
444*9356374aSAndroid Build Coastguard Worker   // Returns an `iterator` to the end of the inlined vector.
end()445*9356374aSAndroid Build Coastguard Worker   iterator end() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
446*9356374aSAndroid Build Coastguard Worker     return data() + size();
447*9356374aSAndroid Build Coastguard Worker   }
448*9356374aSAndroid Build Coastguard Worker 
449*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::end()` that returns a `const_iterator` to the
450*9356374aSAndroid Build Coastguard Worker   // end of the inlined vector.
end()451*9356374aSAndroid Build Coastguard Worker   const_iterator end() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
452*9356374aSAndroid Build Coastguard Worker     return data() + size();
453*9356374aSAndroid Build Coastguard Worker   }
454*9356374aSAndroid Build Coastguard Worker 
455*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::cbegin()`
456*9356374aSAndroid Build Coastguard Worker   //
457*9356374aSAndroid Build Coastguard Worker   // Returns a `const_iterator` to the beginning of the inlined vector.
cbegin()458*9356374aSAndroid Build Coastguard Worker   const_iterator cbegin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
459*9356374aSAndroid Build Coastguard Worker     return begin();
460*9356374aSAndroid Build Coastguard Worker   }
461*9356374aSAndroid Build Coastguard Worker 
462*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::cend()`
463*9356374aSAndroid Build Coastguard Worker   //
464*9356374aSAndroid Build Coastguard Worker   // Returns a `const_iterator` to the end of the inlined vector.
cend()465*9356374aSAndroid Build Coastguard Worker   const_iterator cend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
466*9356374aSAndroid Build Coastguard Worker     return end();
467*9356374aSAndroid Build Coastguard Worker   }
468*9356374aSAndroid Build Coastguard Worker 
469*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::rbegin()`
470*9356374aSAndroid Build Coastguard Worker   //
471*9356374aSAndroid Build Coastguard Worker   // Returns a `reverse_iterator` from the end of the inlined vector.
rbegin()472*9356374aSAndroid Build Coastguard Worker   reverse_iterator rbegin() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
473*9356374aSAndroid Build Coastguard Worker     return reverse_iterator(end());
474*9356374aSAndroid Build Coastguard Worker   }
475*9356374aSAndroid Build Coastguard Worker 
476*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::rbegin()` that returns a
477*9356374aSAndroid Build Coastguard Worker   // `const_reverse_iterator` from the end of the inlined vector.
rbegin()478*9356374aSAndroid Build Coastguard Worker   const_reverse_iterator rbegin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
479*9356374aSAndroid Build Coastguard Worker     return const_reverse_iterator(end());
480*9356374aSAndroid Build Coastguard Worker   }
481*9356374aSAndroid Build Coastguard Worker 
482*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::rend()`
483*9356374aSAndroid Build Coastguard Worker   //
484*9356374aSAndroid Build Coastguard Worker   // Returns a `reverse_iterator` from the beginning of the inlined vector.
rend()485*9356374aSAndroid Build Coastguard Worker   reverse_iterator rend() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
486*9356374aSAndroid Build Coastguard Worker     return reverse_iterator(begin());
487*9356374aSAndroid Build Coastguard Worker   }
488*9356374aSAndroid Build Coastguard Worker 
489*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::rend()` that returns a `const_reverse_iterator`
490*9356374aSAndroid Build Coastguard Worker   // from the beginning of the inlined vector.
rend()491*9356374aSAndroid Build Coastguard Worker   const_reverse_iterator rend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
492*9356374aSAndroid Build Coastguard Worker     return const_reverse_iterator(begin());
493*9356374aSAndroid Build Coastguard Worker   }
494*9356374aSAndroid Build Coastguard Worker 
495*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::crbegin()`
496*9356374aSAndroid Build Coastguard Worker   //
497*9356374aSAndroid Build Coastguard Worker   // Returns a `const_reverse_iterator` from the end of the inlined vector.
crbegin()498*9356374aSAndroid Build Coastguard Worker   const_reverse_iterator crbegin() const noexcept
499*9356374aSAndroid Build Coastguard Worker       ABSL_ATTRIBUTE_LIFETIME_BOUND {
500*9356374aSAndroid Build Coastguard Worker     return rbegin();
501*9356374aSAndroid Build Coastguard Worker   }
502*9356374aSAndroid Build Coastguard Worker 
503*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::crend()`
504*9356374aSAndroid Build Coastguard Worker   //
505*9356374aSAndroid Build Coastguard Worker   // Returns a `const_reverse_iterator` from the beginning of the inlined
506*9356374aSAndroid Build Coastguard Worker   // vector.
crend()507*9356374aSAndroid Build Coastguard Worker   const_reverse_iterator crend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
508*9356374aSAndroid Build Coastguard Worker     return rend();
509*9356374aSAndroid Build Coastguard Worker   }
510*9356374aSAndroid Build Coastguard Worker 
511*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::get_allocator()`
512*9356374aSAndroid Build Coastguard Worker   //
513*9356374aSAndroid Build Coastguard Worker   // Returns a copy of the inlined vector's allocator.
get_allocator()514*9356374aSAndroid Build Coastguard Worker   allocator_type get_allocator() const { return storage_.GetAllocator(); }
515*9356374aSAndroid Build Coastguard Worker 
516*9356374aSAndroid Build Coastguard Worker   // ---------------------------------------------------------------------------
517*9356374aSAndroid Build Coastguard Worker   // InlinedVector Member Mutators
518*9356374aSAndroid Build Coastguard Worker   // ---------------------------------------------------------------------------
519*9356374aSAndroid Build Coastguard Worker 
520*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::operator=(...)`
521*9356374aSAndroid Build Coastguard Worker   //
522*9356374aSAndroid Build Coastguard Worker   // Replaces the elements of the inlined vector with copies of the elements of
523*9356374aSAndroid Build Coastguard Worker   // `list`.
524*9356374aSAndroid Build Coastguard Worker   InlinedVector& operator=(std::initializer_list<value_type> list) {
525*9356374aSAndroid Build Coastguard Worker     assign(list.begin(), list.end());
526*9356374aSAndroid Build Coastguard Worker 
527*9356374aSAndroid Build Coastguard Worker     return *this;
528*9356374aSAndroid Build Coastguard Worker   }
529*9356374aSAndroid Build Coastguard Worker 
530*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::operator=(...)` that replaces the elements of
531*9356374aSAndroid Build Coastguard Worker   // the inlined vector with copies of the elements of `other`.
532*9356374aSAndroid Build Coastguard Worker   InlinedVector& operator=(const InlinedVector& other) {
533*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
534*9356374aSAndroid Build Coastguard Worker       const_pointer other_data = other.data();
535*9356374aSAndroid Build Coastguard Worker       assign(other_data, other_data + other.size());
536*9356374aSAndroid Build Coastguard Worker     }
537*9356374aSAndroid Build Coastguard Worker 
538*9356374aSAndroid Build Coastguard Worker     return *this;
539*9356374aSAndroid Build Coastguard Worker   }
540*9356374aSAndroid Build Coastguard Worker 
541*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::operator=(...)` that moves the elements of
542*9356374aSAndroid Build Coastguard Worker   // `other` into the inlined vector.
543*9356374aSAndroid Build Coastguard Worker   //
544*9356374aSAndroid Build Coastguard Worker   // NOTE: as a result of calling this overload, `other` is left in a valid but
545*9356374aSAndroid Build Coastguard Worker   // unspecified state.
546*9356374aSAndroid Build Coastguard Worker   InlinedVector& operator=(InlinedVector&& other) {
547*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
548*9356374aSAndroid Build Coastguard Worker       MoveAssignment(MoveAssignmentPolicy{}, std::move(other));
549*9356374aSAndroid Build Coastguard Worker     }
550*9356374aSAndroid Build Coastguard Worker 
551*9356374aSAndroid Build Coastguard Worker     return *this;
552*9356374aSAndroid Build Coastguard Worker   }
553*9356374aSAndroid Build Coastguard Worker 
554*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::assign(...)`
555*9356374aSAndroid Build Coastguard Worker   //
556*9356374aSAndroid Build Coastguard Worker   // Replaces the contents of the inlined vector with `n` copies of `v`.
assign(size_type n,const_reference v)557*9356374aSAndroid Build Coastguard Worker   void assign(size_type n, const_reference v) {
558*9356374aSAndroid Build Coastguard Worker     storage_.Assign(CopyValueAdapter<A>(std::addressof(v)), n);
559*9356374aSAndroid Build Coastguard Worker   }
560*9356374aSAndroid Build Coastguard Worker 
561*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::assign(...)` that replaces the contents of the
562*9356374aSAndroid Build Coastguard Worker   // inlined vector with copies of the elements of `list`.
assign(std::initializer_list<value_type> list)563*9356374aSAndroid Build Coastguard Worker   void assign(std::initializer_list<value_type> list) {
564*9356374aSAndroid Build Coastguard Worker     assign(list.begin(), list.end());
565*9356374aSAndroid Build Coastguard Worker   }
566*9356374aSAndroid Build Coastguard Worker 
567*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::assign(...)` to replace the contents of the
568*9356374aSAndroid Build Coastguard Worker   // inlined vector with the range [`first`, `last`).
569*9356374aSAndroid Build Coastguard Worker   //
570*9356374aSAndroid Build Coastguard Worker   // NOTE: this overload is for iterators that are "forward" category or better.
571*9356374aSAndroid Build Coastguard Worker   template <typename ForwardIterator,
572*9356374aSAndroid Build Coastguard Worker             EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
assign(ForwardIterator first,ForwardIterator last)573*9356374aSAndroid Build Coastguard Worker   void assign(ForwardIterator first, ForwardIterator last) {
574*9356374aSAndroid Build Coastguard Worker     storage_.Assign(IteratorValueAdapter<A, ForwardIterator>(first),
575*9356374aSAndroid Build Coastguard Worker                     static_cast<size_t>(std::distance(first, last)));
576*9356374aSAndroid Build Coastguard Worker   }
577*9356374aSAndroid Build Coastguard Worker 
578*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::assign(...)` to replace the contents of the
579*9356374aSAndroid Build Coastguard Worker   // inlined vector with the range [`first`, `last`).
580*9356374aSAndroid Build Coastguard Worker   //
581*9356374aSAndroid Build Coastguard Worker   // NOTE: this overload is for iterators that are "input" category.
582*9356374aSAndroid Build Coastguard Worker   template <typename InputIterator,
583*9356374aSAndroid Build Coastguard Worker             DisableIfAtLeastForwardIterator<InputIterator> = 0>
assign(InputIterator first,InputIterator last)584*9356374aSAndroid Build Coastguard Worker   void assign(InputIterator first, InputIterator last) {
585*9356374aSAndroid Build Coastguard Worker     size_type i = 0;
586*9356374aSAndroid Build Coastguard Worker     for (; i < size() && first != last; ++i, static_cast<void>(++first)) {
587*9356374aSAndroid Build Coastguard Worker       data()[i] = *first;
588*9356374aSAndroid Build Coastguard Worker     }
589*9356374aSAndroid Build Coastguard Worker 
590*9356374aSAndroid Build Coastguard Worker     erase(data() + i, data() + size());
591*9356374aSAndroid Build Coastguard Worker     std::copy(first, last, std::back_inserter(*this));
592*9356374aSAndroid Build Coastguard Worker   }
593*9356374aSAndroid Build Coastguard Worker 
594*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::resize(...)`
595*9356374aSAndroid Build Coastguard Worker   //
596*9356374aSAndroid Build Coastguard Worker   // Resizes the inlined vector to contain `n` elements.
597*9356374aSAndroid Build Coastguard Worker   //
598*9356374aSAndroid Build Coastguard Worker   // NOTE: If `n` is smaller than `size()`, extra elements are destroyed. If `n`
599*9356374aSAndroid Build Coastguard Worker   // is larger than `size()`, new elements are value-initialized.
resize(size_type n)600*9356374aSAndroid Build Coastguard Worker   void resize(size_type n) {
601*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(n <= max_size());
602*9356374aSAndroid Build Coastguard Worker     storage_.Resize(DefaultValueAdapter<A>(), n);
603*9356374aSAndroid Build Coastguard Worker   }
604*9356374aSAndroid Build Coastguard Worker 
605*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::resize(...)` that resizes the inlined vector to
606*9356374aSAndroid Build Coastguard Worker   // contain `n` elements.
607*9356374aSAndroid Build Coastguard Worker   //
608*9356374aSAndroid Build Coastguard Worker   // NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n`
609*9356374aSAndroid Build Coastguard Worker   // is larger than `size()`, new elements are copied-constructed from `v`.
resize(size_type n,const_reference v)610*9356374aSAndroid Build Coastguard Worker   void resize(size_type n, const_reference v) {
611*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(n <= max_size());
612*9356374aSAndroid Build Coastguard Worker     storage_.Resize(CopyValueAdapter<A>(std::addressof(v)), n);
613*9356374aSAndroid Build Coastguard Worker   }
614*9356374aSAndroid Build Coastguard Worker 
615*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::insert(...)`
616*9356374aSAndroid Build Coastguard Worker   //
617*9356374aSAndroid Build Coastguard Worker   // Inserts a copy of `v` at `pos`, returning an `iterator` to the newly
618*9356374aSAndroid Build Coastguard Worker   // inserted element.
insert(const_iterator pos,const_reference v)619*9356374aSAndroid Build Coastguard Worker   iterator insert(const_iterator pos,
620*9356374aSAndroid Build Coastguard Worker                   const_reference v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
621*9356374aSAndroid Build Coastguard Worker     return emplace(pos, v);
622*9356374aSAndroid Build Coastguard Worker   }
623*9356374aSAndroid Build Coastguard Worker 
624*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::insert(...)` that inserts `v` at `pos` using
625*9356374aSAndroid Build Coastguard Worker   // move semantics, returning an `iterator` to the newly inserted element.
insert(const_iterator pos,value_type && v)626*9356374aSAndroid Build Coastguard Worker   iterator insert(const_iterator pos,
627*9356374aSAndroid Build Coastguard Worker                   value_type&& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
628*9356374aSAndroid Build Coastguard Worker     return emplace(pos, std::move(v));
629*9356374aSAndroid Build Coastguard Worker   }
630*9356374aSAndroid Build Coastguard Worker 
631*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::insert(...)` that inserts `n` contiguous copies
632*9356374aSAndroid Build Coastguard Worker   // of `v` starting at `pos`, returning an `iterator` pointing to the first of
633*9356374aSAndroid Build Coastguard Worker   // the newly inserted elements.
insert(const_iterator pos,size_type n,const_reference v)634*9356374aSAndroid Build Coastguard Worker   iterator insert(const_iterator pos, size_type n,
635*9356374aSAndroid Build Coastguard Worker                   const_reference v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
636*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos >= begin());
637*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos <= end());
638*9356374aSAndroid Build Coastguard Worker 
639*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(n != 0)) {
640*9356374aSAndroid Build Coastguard Worker       value_type dealias = v;
641*9356374aSAndroid Build Coastguard Worker       // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2
642*9356374aSAndroid Build Coastguard Worker       // It appears that GCC thinks that since `pos` is a const pointer and may
643*9356374aSAndroid Build Coastguard Worker       // point to uninitialized memory at this point, a warning should be
644*9356374aSAndroid Build Coastguard Worker       // issued. But `pos` is actually only used to compute an array index to
645*9356374aSAndroid Build Coastguard Worker       // write to.
646*9356374aSAndroid Build Coastguard Worker #if !defined(__clang__) && defined(__GNUC__)
647*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic push
648*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
649*9356374aSAndroid Build Coastguard Worker #endif
650*9356374aSAndroid Build Coastguard Worker       return storage_.Insert(pos, CopyValueAdapter<A>(std::addressof(dealias)),
651*9356374aSAndroid Build Coastguard Worker                              n);
652*9356374aSAndroid Build Coastguard Worker #if !defined(__clang__) && defined(__GNUC__)
653*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
654*9356374aSAndroid Build Coastguard Worker #endif
655*9356374aSAndroid Build Coastguard Worker     } else {
656*9356374aSAndroid Build Coastguard Worker       return const_cast<iterator>(pos);
657*9356374aSAndroid Build Coastguard Worker     }
658*9356374aSAndroid Build Coastguard Worker   }
659*9356374aSAndroid Build Coastguard Worker 
660*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::insert(...)` that inserts copies of the
661*9356374aSAndroid Build Coastguard Worker   // elements of `list` starting at `pos`, returning an `iterator` pointing to
662*9356374aSAndroid Build Coastguard Worker   // the first of the newly inserted elements.
insert(const_iterator pos,std::initializer_list<value_type> list)663*9356374aSAndroid Build Coastguard Worker   iterator insert(const_iterator pos, std::initializer_list<value_type> list)
664*9356374aSAndroid Build Coastguard Worker       ABSL_ATTRIBUTE_LIFETIME_BOUND {
665*9356374aSAndroid Build Coastguard Worker     return insert(pos, list.begin(), list.end());
666*9356374aSAndroid Build Coastguard Worker   }
667*9356374aSAndroid Build Coastguard Worker 
668*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::insert(...)` that inserts the range [`first`,
669*9356374aSAndroid Build Coastguard Worker   // `last`) starting at `pos`, returning an `iterator` pointing to the first
670*9356374aSAndroid Build Coastguard Worker   // of the newly inserted elements.
671*9356374aSAndroid Build Coastguard Worker   //
672*9356374aSAndroid Build Coastguard Worker   // NOTE: this overload is for iterators that are "forward" category or better.
673*9356374aSAndroid Build Coastguard Worker   template <typename ForwardIterator,
674*9356374aSAndroid Build Coastguard Worker             EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
insert(const_iterator pos,ForwardIterator first,ForwardIterator last)675*9356374aSAndroid Build Coastguard Worker   iterator insert(const_iterator pos, ForwardIterator first,
676*9356374aSAndroid Build Coastguard Worker                   ForwardIterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
677*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos >= begin());
678*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos <= end());
679*9356374aSAndroid Build Coastguard Worker 
680*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(first != last)) {
681*9356374aSAndroid Build Coastguard Worker       return storage_.Insert(
682*9356374aSAndroid Build Coastguard Worker           pos, IteratorValueAdapter<A, ForwardIterator>(first),
683*9356374aSAndroid Build Coastguard Worker           static_cast<size_type>(std::distance(first, last)));
684*9356374aSAndroid Build Coastguard Worker     } else {
685*9356374aSAndroid Build Coastguard Worker       return const_cast<iterator>(pos);
686*9356374aSAndroid Build Coastguard Worker     }
687*9356374aSAndroid Build Coastguard Worker   }
688*9356374aSAndroid Build Coastguard Worker 
689*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::insert(...)` that inserts the range [`first`,
690*9356374aSAndroid Build Coastguard Worker   // `last`) starting at `pos`, returning an `iterator` pointing to the first
691*9356374aSAndroid Build Coastguard Worker   // of the newly inserted elements.
692*9356374aSAndroid Build Coastguard Worker   //
693*9356374aSAndroid Build Coastguard Worker   // NOTE: this overload is for iterators that are "input" category.
694*9356374aSAndroid Build Coastguard Worker   template <typename InputIterator,
695*9356374aSAndroid Build Coastguard Worker             DisableIfAtLeastForwardIterator<InputIterator> = 0>
insert(const_iterator pos,InputIterator first,InputIterator last)696*9356374aSAndroid Build Coastguard Worker   iterator insert(const_iterator pos, InputIterator first,
697*9356374aSAndroid Build Coastguard Worker                   InputIterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
698*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos >= begin());
699*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos <= end());
700*9356374aSAndroid Build Coastguard Worker 
701*9356374aSAndroid Build Coastguard Worker     size_type index = static_cast<size_type>(std::distance(cbegin(), pos));
702*9356374aSAndroid Build Coastguard Worker     for (size_type i = index; first != last; ++i, static_cast<void>(++first)) {
703*9356374aSAndroid Build Coastguard Worker       insert(data() + i, *first);
704*9356374aSAndroid Build Coastguard Worker     }
705*9356374aSAndroid Build Coastguard Worker 
706*9356374aSAndroid Build Coastguard Worker     return iterator(data() + index);
707*9356374aSAndroid Build Coastguard Worker   }
708*9356374aSAndroid Build Coastguard Worker 
709*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::emplace(...)`
710*9356374aSAndroid Build Coastguard Worker   //
711*9356374aSAndroid Build Coastguard Worker   // Constructs and inserts an element using `args...` in the inlined vector at
712*9356374aSAndroid Build Coastguard Worker   // `pos`, returning an `iterator` pointing to the newly emplaced element.
713*9356374aSAndroid Build Coastguard Worker   template <typename... Args>
emplace(const_iterator pos,Args &&...args)714*9356374aSAndroid Build Coastguard Worker   iterator emplace(const_iterator pos,
715*9356374aSAndroid Build Coastguard Worker                    Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
716*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos >= begin());
717*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos <= end());
718*9356374aSAndroid Build Coastguard Worker 
719*9356374aSAndroid Build Coastguard Worker     value_type dealias(std::forward<Args>(args)...);
720*9356374aSAndroid Build Coastguard Worker     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2
721*9356374aSAndroid Build Coastguard Worker     // It appears that GCC thinks that since `pos` is a const pointer and may
722*9356374aSAndroid Build Coastguard Worker     // point to uninitialized memory at this point, a warning should be
723*9356374aSAndroid Build Coastguard Worker     // issued. But `pos` is actually only used to compute an array index to
724*9356374aSAndroid Build Coastguard Worker     // write to.
725*9356374aSAndroid Build Coastguard Worker #if !defined(__clang__) && defined(__GNUC__)
726*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic push
727*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
728*9356374aSAndroid Build Coastguard Worker #endif
729*9356374aSAndroid Build Coastguard Worker     return storage_.Insert(pos,
730*9356374aSAndroid Build Coastguard Worker                            IteratorValueAdapter<A, MoveIterator<A>>(
731*9356374aSAndroid Build Coastguard Worker                                MoveIterator<A>(std::addressof(dealias))),
732*9356374aSAndroid Build Coastguard Worker                            1);
733*9356374aSAndroid Build Coastguard Worker #if !defined(__clang__) && defined(__GNUC__)
734*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
735*9356374aSAndroid Build Coastguard Worker #endif
736*9356374aSAndroid Build Coastguard Worker   }
737*9356374aSAndroid Build Coastguard Worker 
738*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::emplace_back(...)`
739*9356374aSAndroid Build Coastguard Worker   //
740*9356374aSAndroid Build Coastguard Worker   // Constructs and inserts an element using `args...` in the inlined vector at
741*9356374aSAndroid Build Coastguard Worker   // `end()`, returning a `reference` to the newly emplaced element.
742*9356374aSAndroid Build Coastguard Worker   template <typename... Args>
emplace_back(Args &&...args)743*9356374aSAndroid Build Coastguard Worker   reference emplace_back(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
744*9356374aSAndroid Build Coastguard Worker     return storage_.EmplaceBack(std::forward<Args>(args)...);
745*9356374aSAndroid Build Coastguard Worker   }
746*9356374aSAndroid Build Coastguard Worker 
747*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::push_back(...)`
748*9356374aSAndroid Build Coastguard Worker   //
749*9356374aSAndroid Build Coastguard Worker   // Inserts a copy of `v` in the inlined vector at `end()`.
push_back(const_reference v)750*9356374aSAndroid Build Coastguard Worker   void push_back(const_reference v) { static_cast<void>(emplace_back(v)); }
751*9356374aSAndroid Build Coastguard Worker 
752*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::push_back(...)` for inserting `v` at `end()`
753*9356374aSAndroid Build Coastguard Worker   // using move semantics.
push_back(value_type && v)754*9356374aSAndroid Build Coastguard Worker   void push_back(value_type&& v) {
755*9356374aSAndroid Build Coastguard Worker     static_cast<void>(emplace_back(std::move(v)));
756*9356374aSAndroid Build Coastguard Worker   }
757*9356374aSAndroid Build Coastguard Worker 
758*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::pop_back()`
759*9356374aSAndroid Build Coastguard Worker   //
760*9356374aSAndroid Build Coastguard Worker   // Destroys the element at `back()`, reducing the size by `1`.
pop_back()761*9356374aSAndroid Build Coastguard Worker   void pop_back() noexcept {
762*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(!empty());
763*9356374aSAndroid Build Coastguard Worker 
764*9356374aSAndroid Build Coastguard Worker     AllocatorTraits<A>::destroy(storage_.GetAllocator(), data() + (size() - 1));
765*9356374aSAndroid Build Coastguard Worker     storage_.SubtractSize(1);
766*9356374aSAndroid Build Coastguard Worker   }
767*9356374aSAndroid Build Coastguard Worker 
768*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::erase(...)`
769*9356374aSAndroid Build Coastguard Worker   //
770*9356374aSAndroid Build Coastguard Worker   // Erases the element at `pos`, returning an `iterator` pointing to where the
771*9356374aSAndroid Build Coastguard Worker   // erased element was located.
772*9356374aSAndroid Build Coastguard Worker   //
773*9356374aSAndroid Build Coastguard Worker   // NOTE: may return `end()`, which is not dereferenceable.
erase(const_iterator pos)774*9356374aSAndroid Build Coastguard Worker   iterator erase(const_iterator pos) ABSL_ATTRIBUTE_LIFETIME_BOUND {
775*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos >= begin());
776*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(pos < end());
777*9356374aSAndroid Build Coastguard Worker 
778*9356374aSAndroid Build Coastguard Worker     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2
779*9356374aSAndroid Build Coastguard Worker     // It appears that GCC thinks that since `pos` is a const pointer and may
780*9356374aSAndroid Build Coastguard Worker     // point to uninitialized memory at this point, a warning should be
781*9356374aSAndroid Build Coastguard Worker     // issued. But `pos` is actually only used to compute an array index to
782*9356374aSAndroid Build Coastguard Worker     // write to.
783*9356374aSAndroid Build Coastguard Worker #if !defined(__clang__) && defined(__GNUC__)
784*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic push
785*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
786*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wuninitialized"
787*9356374aSAndroid Build Coastguard Worker #endif
788*9356374aSAndroid Build Coastguard Worker     return storage_.Erase(pos, pos + 1);
789*9356374aSAndroid Build Coastguard Worker #if !defined(__clang__) && defined(__GNUC__)
790*9356374aSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
791*9356374aSAndroid Build Coastguard Worker #endif
792*9356374aSAndroid Build Coastguard Worker   }
793*9356374aSAndroid Build Coastguard Worker 
794*9356374aSAndroid Build Coastguard Worker   // Overload of `InlinedVector::erase(...)` that erases every element in the
795*9356374aSAndroid Build Coastguard Worker   // range [`from`, `to`), returning an `iterator` pointing to where the first
796*9356374aSAndroid Build Coastguard Worker   // erased element was located.
797*9356374aSAndroid Build Coastguard Worker   //
798*9356374aSAndroid Build Coastguard Worker   // NOTE: may return `end()`, which is not dereferenceable.
erase(const_iterator from,const_iterator to)799*9356374aSAndroid Build Coastguard Worker   iterator erase(const_iterator from,
800*9356374aSAndroid Build Coastguard Worker                  const_iterator to) ABSL_ATTRIBUTE_LIFETIME_BOUND {
801*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(from >= begin());
802*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(from <= to);
803*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(to <= end());
804*9356374aSAndroid Build Coastguard Worker 
805*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(from != to)) {
806*9356374aSAndroid Build Coastguard Worker       return storage_.Erase(from, to);
807*9356374aSAndroid Build Coastguard Worker     } else {
808*9356374aSAndroid Build Coastguard Worker       return const_cast<iterator>(from);
809*9356374aSAndroid Build Coastguard Worker     }
810*9356374aSAndroid Build Coastguard Worker   }
811*9356374aSAndroid Build Coastguard Worker 
812*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::clear()`
813*9356374aSAndroid Build Coastguard Worker   //
814*9356374aSAndroid Build Coastguard Worker   // Destroys all elements in the inlined vector, setting the size to `0` and
815*9356374aSAndroid Build Coastguard Worker   // deallocating any held memory.
clear()816*9356374aSAndroid Build Coastguard Worker   void clear() noexcept {
817*9356374aSAndroid Build Coastguard Worker     inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
818*9356374aSAndroid Build Coastguard Worker         storage_.GetAllocator(), data(), size());
819*9356374aSAndroid Build Coastguard Worker     storage_.DeallocateIfAllocated();
820*9356374aSAndroid Build Coastguard Worker 
821*9356374aSAndroid Build Coastguard Worker     storage_.SetInlinedSize(0);
822*9356374aSAndroid Build Coastguard Worker   }
823*9356374aSAndroid Build Coastguard Worker 
824*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::reserve(...)`
825*9356374aSAndroid Build Coastguard Worker   //
826*9356374aSAndroid Build Coastguard Worker   // Ensures that there is enough room for at least `n` elements.
reserve(size_type n)827*9356374aSAndroid Build Coastguard Worker   void reserve(size_type n) { storage_.Reserve(n); }
828*9356374aSAndroid Build Coastguard Worker 
829*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::shrink_to_fit()`
830*9356374aSAndroid Build Coastguard Worker   //
831*9356374aSAndroid Build Coastguard Worker   // Attempts to reduce memory usage by moving elements to (or keeping elements
832*9356374aSAndroid Build Coastguard Worker   // in) the smallest available buffer sufficient for containing `size()`
833*9356374aSAndroid Build Coastguard Worker   // elements.
834*9356374aSAndroid Build Coastguard Worker   //
835*9356374aSAndroid Build Coastguard Worker   // If `size()` is sufficiently small, the elements will be moved into (or kept
836*9356374aSAndroid Build Coastguard Worker   // in) the inlined space.
shrink_to_fit()837*9356374aSAndroid Build Coastguard Worker   void shrink_to_fit() {
838*9356374aSAndroid Build Coastguard Worker     if (storage_.GetIsAllocated()) {
839*9356374aSAndroid Build Coastguard Worker       storage_.ShrinkToFit();
840*9356374aSAndroid Build Coastguard Worker     }
841*9356374aSAndroid Build Coastguard Worker   }
842*9356374aSAndroid Build Coastguard Worker 
843*9356374aSAndroid Build Coastguard Worker   // `InlinedVector::swap(...)`
844*9356374aSAndroid Build Coastguard Worker   //
845*9356374aSAndroid Build Coastguard Worker   // Swaps the contents of the inlined vector with `other`.
swap(InlinedVector & other)846*9356374aSAndroid Build Coastguard Worker   void swap(InlinedVector& other) {
847*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
848*9356374aSAndroid Build Coastguard Worker       storage_.Swap(std::addressof(other.storage_));
849*9356374aSAndroid Build Coastguard Worker     }
850*9356374aSAndroid Build Coastguard Worker   }
851*9356374aSAndroid Build Coastguard Worker 
852*9356374aSAndroid Build Coastguard Worker  private:
853*9356374aSAndroid Build Coastguard Worker   template <typename H, typename TheT, size_t TheN, typename TheA>
854*9356374aSAndroid Build Coastguard Worker   friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a);
855*9356374aSAndroid Build Coastguard Worker 
MoveAssignment(MemcpyPolicy,InlinedVector && other)856*9356374aSAndroid Build Coastguard Worker   void MoveAssignment(MemcpyPolicy, InlinedVector&& other) {
857*9356374aSAndroid Build Coastguard Worker     // Assumption check: we shouldn't be told to use memcpy to implement move
858*9356374aSAndroid Build Coastguard Worker     // assignment unless we have trivially destructible elements and an
859*9356374aSAndroid Build Coastguard Worker     // allocator that does nothing fancy.
860*9356374aSAndroid Build Coastguard Worker     static_assert(absl::is_trivially_destructible<value_type>::value, "");
861*9356374aSAndroid Build Coastguard Worker     static_assert(std::is_same<A, std::allocator<value_type>>::value, "");
862*9356374aSAndroid Build Coastguard Worker 
863*9356374aSAndroid Build Coastguard Worker     // Throw away our existing heap allocation, if any. There is no need to
864*9356374aSAndroid Build Coastguard Worker     // destroy the existing elements one by one because we know they are
865*9356374aSAndroid Build Coastguard Worker     // trivially destructible.
866*9356374aSAndroid Build Coastguard Worker     storage_.DeallocateIfAllocated();
867*9356374aSAndroid Build Coastguard Worker 
868*9356374aSAndroid Build Coastguard Worker     // Adopt the other vector's inline elements or heap allocation.
869*9356374aSAndroid Build Coastguard Worker     storage_.MemcpyFrom(other.storage_);
870*9356374aSAndroid Build Coastguard Worker     other.storage_.SetInlinedSize(0);
871*9356374aSAndroid Build Coastguard Worker   }
872*9356374aSAndroid Build Coastguard Worker 
873*9356374aSAndroid Build Coastguard Worker   // Destroy our existing elements, if any, and adopt the heap-allocated
874*9356374aSAndroid Build Coastguard Worker   // elements of the other vector.
875*9356374aSAndroid Build Coastguard Worker   //
876*9356374aSAndroid Build Coastguard Worker   // REQUIRES: other.storage_.GetIsAllocated()
DestroyExistingAndAdopt(InlinedVector && other)877*9356374aSAndroid Build Coastguard Worker   void DestroyExistingAndAdopt(InlinedVector&& other) {
878*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(other.storage_.GetIsAllocated());
879*9356374aSAndroid Build Coastguard Worker 
880*9356374aSAndroid Build Coastguard Worker     inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
881*9356374aSAndroid Build Coastguard Worker         storage_.GetAllocator(), data(), size());
882*9356374aSAndroid Build Coastguard Worker     storage_.DeallocateIfAllocated();
883*9356374aSAndroid Build Coastguard Worker 
884*9356374aSAndroid Build Coastguard Worker     storage_.MemcpyFrom(other.storage_);
885*9356374aSAndroid Build Coastguard Worker     other.storage_.SetInlinedSize(0);
886*9356374aSAndroid Build Coastguard Worker   }
887*9356374aSAndroid Build Coastguard Worker 
MoveAssignment(ElementwiseAssignPolicy,InlinedVector && other)888*9356374aSAndroid Build Coastguard Worker   void MoveAssignment(ElementwiseAssignPolicy, InlinedVector&& other) {
889*9356374aSAndroid Build Coastguard Worker     // Fast path: if the other vector is on the heap then we don't worry about
890*9356374aSAndroid Build Coastguard Worker     // actually move-assigning each element. Instead we only throw away our own
891*9356374aSAndroid Build Coastguard Worker     // existing elements and adopt the heap allocation of the other vector.
892*9356374aSAndroid Build Coastguard Worker     if (other.storage_.GetIsAllocated()) {
893*9356374aSAndroid Build Coastguard Worker       DestroyExistingAndAdopt(std::move(other));
894*9356374aSAndroid Build Coastguard Worker       return;
895*9356374aSAndroid Build Coastguard Worker     }
896*9356374aSAndroid Build Coastguard Worker 
897*9356374aSAndroid Build Coastguard Worker     storage_.Assign(IteratorValueAdapter<A, MoveIterator<A>>(
898*9356374aSAndroid Build Coastguard Worker                         MoveIterator<A>(other.storage_.GetInlinedData())),
899*9356374aSAndroid Build Coastguard Worker                     other.size());
900*9356374aSAndroid Build Coastguard Worker   }
901*9356374aSAndroid Build Coastguard Worker 
MoveAssignment(ElementwiseConstructPolicy,InlinedVector && other)902*9356374aSAndroid Build Coastguard Worker   void MoveAssignment(ElementwiseConstructPolicy, InlinedVector&& other) {
903*9356374aSAndroid Build Coastguard Worker     // Fast path: if the other vector is on the heap then we don't worry about
904*9356374aSAndroid Build Coastguard Worker     // actually move-assigning each element. Instead we only throw away our own
905*9356374aSAndroid Build Coastguard Worker     // existing elements and adopt the heap allocation of the other vector.
906*9356374aSAndroid Build Coastguard Worker     if (other.storage_.GetIsAllocated()) {
907*9356374aSAndroid Build Coastguard Worker       DestroyExistingAndAdopt(std::move(other));
908*9356374aSAndroid Build Coastguard Worker       return;
909*9356374aSAndroid Build Coastguard Worker     }
910*9356374aSAndroid Build Coastguard Worker 
911*9356374aSAndroid Build Coastguard Worker     inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
912*9356374aSAndroid Build Coastguard Worker         storage_.GetAllocator(), data(), size());
913*9356374aSAndroid Build Coastguard Worker     storage_.DeallocateIfAllocated();
914*9356374aSAndroid Build Coastguard Worker 
915*9356374aSAndroid Build Coastguard Worker     IteratorValueAdapter<A, MoveIterator<A>> other_values(
916*9356374aSAndroid Build Coastguard Worker         MoveIterator<A>(other.storage_.GetInlinedData()));
917*9356374aSAndroid Build Coastguard Worker     inlined_vector_internal::ConstructElements<A>(
918*9356374aSAndroid Build Coastguard Worker         storage_.GetAllocator(), storage_.GetInlinedData(), other_values,
919*9356374aSAndroid Build Coastguard Worker         other.storage_.GetSize());
920*9356374aSAndroid Build Coastguard Worker     storage_.SetInlinedSize(other.storage_.GetSize());
921*9356374aSAndroid Build Coastguard Worker   }
922*9356374aSAndroid Build Coastguard Worker 
923*9356374aSAndroid Build Coastguard Worker   Storage storage_;
924*9356374aSAndroid Build Coastguard Worker };
925*9356374aSAndroid Build Coastguard Worker 
926*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
927*9356374aSAndroid Build Coastguard Worker // InlinedVector Non-Member Functions
928*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
929*9356374aSAndroid Build Coastguard Worker 
930*9356374aSAndroid Build Coastguard Worker // `swap(...)`
931*9356374aSAndroid Build Coastguard Worker //
932*9356374aSAndroid Build Coastguard Worker // Swaps the contents of two inlined vectors.
933*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
swap(absl::InlinedVector<T,N,A> & a,absl::InlinedVector<T,N,A> & b)934*9356374aSAndroid Build Coastguard Worker void swap(absl::InlinedVector<T, N, A>& a,
935*9356374aSAndroid Build Coastguard Worker           absl::InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) {
936*9356374aSAndroid Build Coastguard Worker   a.swap(b);
937*9356374aSAndroid Build Coastguard Worker }
938*9356374aSAndroid Build Coastguard Worker 
939*9356374aSAndroid Build Coastguard Worker // `operator==(...)`
940*9356374aSAndroid Build Coastguard Worker //
941*9356374aSAndroid Build Coastguard Worker // Tests for value-equality of two inlined vectors.
942*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
943*9356374aSAndroid Build Coastguard Worker bool operator==(const absl::InlinedVector<T, N, A>& a,
944*9356374aSAndroid Build Coastguard Worker                 const absl::InlinedVector<T, N, A>& b) {
945*9356374aSAndroid Build Coastguard Worker   auto a_data = a.data();
946*9356374aSAndroid Build Coastguard Worker   auto b_data = b.data();
947*9356374aSAndroid Build Coastguard Worker   return std::equal(a_data, a_data + a.size(), b_data, b_data + b.size());
948*9356374aSAndroid Build Coastguard Worker }
949*9356374aSAndroid Build Coastguard Worker 
950*9356374aSAndroid Build Coastguard Worker // `operator!=(...)`
951*9356374aSAndroid Build Coastguard Worker //
952*9356374aSAndroid Build Coastguard Worker // Tests for value-inequality of two inlined vectors.
953*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
954*9356374aSAndroid Build Coastguard Worker bool operator!=(const absl::InlinedVector<T, N, A>& a,
955*9356374aSAndroid Build Coastguard Worker                 const absl::InlinedVector<T, N, A>& b) {
956*9356374aSAndroid Build Coastguard Worker   return !(a == b);
957*9356374aSAndroid Build Coastguard Worker }
958*9356374aSAndroid Build Coastguard Worker 
959*9356374aSAndroid Build Coastguard Worker // `operator<(...)`
960*9356374aSAndroid Build Coastguard Worker //
961*9356374aSAndroid Build Coastguard Worker // Tests whether the value of an inlined vector is less than the value of
962*9356374aSAndroid Build Coastguard Worker // another inlined vector using a lexicographical comparison algorithm.
963*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
964*9356374aSAndroid Build Coastguard Worker bool operator<(const absl::InlinedVector<T, N, A>& a,
965*9356374aSAndroid Build Coastguard Worker                const absl::InlinedVector<T, N, A>& b) {
966*9356374aSAndroid Build Coastguard Worker   auto a_data = a.data();
967*9356374aSAndroid Build Coastguard Worker   auto b_data = b.data();
968*9356374aSAndroid Build Coastguard Worker   return std::lexicographical_compare(a_data, a_data + a.size(), b_data,
969*9356374aSAndroid Build Coastguard Worker                                       b_data + b.size());
970*9356374aSAndroid Build Coastguard Worker }
971*9356374aSAndroid Build Coastguard Worker 
972*9356374aSAndroid Build Coastguard Worker // `operator>(...)`
973*9356374aSAndroid Build Coastguard Worker //
974*9356374aSAndroid Build Coastguard Worker // Tests whether the value of an inlined vector is greater than the value of
975*9356374aSAndroid Build Coastguard Worker // another inlined vector using a lexicographical comparison algorithm.
976*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
977*9356374aSAndroid Build Coastguard Worker bool operator>(const absl::InlinedVector<T, N, A>& a,
978*9356374aSAndroid Build Coastguard Worker                const absl::InlinedVector<T, N, A>& b) {
979*9356374aSAndroid Build Coastguard Worker   return b < a;
980*9356374aSAndroid Build Coastguard Worker }
981*9356374aSAndroid Build Coastguard Worker 
982*9356374aSAndroid Build Coastguard Worker // `operator<=(...)`
983*9356374aSAndroid Build Coastguard Worker //
984*9356374aSAndroid Build Coastguard Worker // Tests whether the value of an inlined vector is less than or equal to the
985*9356374aSAndroid Build Coastguard Worker // value of another inlined vector using a lexicographical comparison algorithm.
986*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
987*9356374aSAndroid Build Coastguard Worker bool operator<=(const absl::InlinedVector<T, N, A>& a,
988*9356374aSAndroid Build Coastguard Worker                 const absl::InlinedVector<T, N, A>& b) {
989*9356374aSAndroid Build Coastguard Worker   return !(b < a);
990*9356374aSAndroid Build Coastguard Worker }
991*9356374aSAndroid Build Coastguard Worker 
992*9356374aSAndroid Build Coastguard Worker // `operator>=(...)`
993*9356374aSAndroid Build Coastguard Worker //
994*9356374aSAndroid Build Coastguard Worker // Tests whether the value of an inlined vector is greater than or equal to the
995*9356374aSAndroid Build Coastguard Worker // value of another inlined vector using a lexicographical comparison algorithm.
996*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
997*9356374aSAndroid Build Coastguard Worker bool operator>=(const absl::InlinedVector<T, N, A>& a,
998*9356374aSAndroid Build Coastguard Worker                 const absl::InlinedVector<T, N, A>& b) {
999*9356374aSAndroid Build Coastguard Worker   return !(a < b);
1000*9356374aSAndroid Build Coastguard Worker }
1001*9356374aSAndroid Build Coastguard Worker 
1002*9356374aSAndroid Build Coastguard Worker // `AbslHashValue(...)`
1003*9356374aSAndroid Build Coastguard Worker //
1004*9356374aSAndroid Build Coastguard Worker // Provides `absl::Hash` support for `absl::InlinedVector`. It is uncommon to
1005*9356374aSAndroid Build Coastguard Worker // call this directly.
1006*9356374aSAndroid Build Coastguard Worker template <typename H, typename T, size_t N, typename A>
AbslHashValue(H h,const absl::InlinedVector<T,N,A> & a)1007*9356374aSAndroid Build Coastguard Worker H AbslHashValue(H h, const absl::InlinedVector<T, N, A>& a) {
1008*9356374aSAndroid Build Coastguard Worker   auto size = a.size();
1009*9356374aSAndroid Build Coastguard Worker   return H::combine(H::combine_contiguous(std::move(h), a.data(), size), size);
1010*9356374aSAndroid Build Coastguard Worker }
1011*9356374aSAndroid Build Coastguard Worker 
1012*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
1013*9356374aSAndroid Build Coastguard Worker }  // namespace absl
1014*9356374aSAndroid Build Coastguard Worker 
1015*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_CONTAINER_INLINED_VECTOR_H_
1016