xref: /aosp_15_r20/external/libgav1/src/utils/vector.h (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop /*
2*09537850SAkhilesh Sanikop  * Copyright 2019 The libgav1 Authors
3*09537850SAkhilesh Sanikop  *
4*09537850SAkhilesh Sanikop  * Licensed under the Apache License, Version 2.0 (the "License");
5*09537850SAkhilesh Sanikop  * you may not use this file except in compliance with the License.
6*09537850SAkhilesh Sanikop  * You may obtain a copy of the License at
7*09537850SAkhilesh Sanikop  *
8*09537850SAkhilesh Sanikop  *      http://www.apache.org/licenses/LICENSE-2.0
9*09537850SAkhilesh Sanikop  *
10*09537850SAkhilesh Sanikop  * Unless required by applicable law or agreed to in writing, software
11*09537850SAkhilesh Sanikop  * distributed under the License is distributed on an "AS IS" BASIS,
12*09537850SAkhilesh Sanikop  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*09537850SAkhilesh Sanikop  * See the License for the specific language governing permissions and
14*09537850SAkhilesh Sanikop  * limitations under the License.
15*09537850SAkhilesh Sanikop  */
16*09537850SAkhilesh Sanikop 
17*09537850SAkhilesh Sanikop // libgav1::Vector implementation
18*09537850SAkhilesh Sanikop 
19*09537850SAkhilesh Sanikop #ifndef LIBGAV1_SRC_UTILS_VECTOR_H_
20*09537850SAkhilesh Sanikop #define LIBGAV1_SRC_UTILS_VECTOR_H_
21*09537850SAkhilesh Sanikop 
22*09537850SAkhilesh Sanikop #include <cassert>
23*09537850SAkhilesh Sanikop #include <cstddef>
24*09537850SAkhilesh Sanikop #include <cstdlib>
25*09537850SAkhilesh Sanikop #include <cstring>
26*09537850SAkhilesh Sanikop #include <iterator>
27*09537850SAkhilesh Sanikop #include <new>
28*09537850SAkhilesh Sanikop #include <type_traits>
29*09537850SAkhilesh Sanikop #include <utility>
30*09537850SAkhilesh Sanikop 
31*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h"
32*09537850SAkhilesh Sanikop 
33*09537850SAkhilesh Sanikop namespace libgav1 {
34*09537850SAkhilesh Sanikop namespace internal {
35*09537850SAkhilesh Sanikop 
36*09537850SAkhilesh Sanikop static constexpr size_t kMinVectorAllocation = 16;
37*09537850SAkhilesh Sanikop 
38*09537850SAkhilesh Sanikop // Returns the smallest power of two greater or equal to 'value'.
NextPow2(size_t value)39*09537850SAkhilesh Sanikop inline size_t NextPow2(size_t value) {
40*09537850SAkhilesh Sanikop   if (value == 0) return 0;
41*09537850SAkhilesh Sanikop   --value;
42*09537850SAkhilesh Sanikop   for (size_t i = 1; i < sizeof(size_t) * 8; i *= 2) value |= value >> i;
43*09537850SAkhilesh Sanikop   return value + 1;
44*09537850SAkhilesh Sanikop }
45*09537850SAkhilesh Sanikop 
46*09537850SAkhilesh Sanikop // Returns the smallest capacity greater or equal to 'value'.
NextCapacity(size_t value)47*09537850SAkhilesh Sanikop inline size_t NextCapacity(size_t value) {
48*09537850SAkhilesh Sanikop   if (value == 0) return 0;
49*09537850SAkhilesh Sanikop   if (value <= kMinVectorAllocation) return kMinVectorAllocation;
50*09537850SAkhilesh Sanikop   return NextPow2(value);
51*09537850SAkhilesh Sanikop }
52*09537850SAkhilesh Sanikop 
53*09537850SAkhilesh Sanikop //------------------------------------------------------------------------------
54*09537850SAkhilesh Sanikop // Data structure equivalent to std::vector but returning false and to its last
55*09537850SAkhilesh Sanikop // valid state on memory allocation failure.
56*09537850SAkhilesh Sanikop // std::vector with a custom allocator does not fill this need without
57*09537850SAkhilesh Sanikop // exceptions.
58*09537850SAkhilesh Sanikop 
59*09537850SAkhilesh Sanikop template <typename T>
60*09537850SAkhilesh Sanikop class VectorBase {
61*09537850SAkhilesh Sanikop  public:
62*09537850SAkhilesh Sanikop   using iterator = T*;
63*09537850SAkhilesh Sanikop   using const_iterator = const T*;
64*09537850SAkhilesh Sanikop 
65*09537850SAkhilesh Sanikop   VectorBase() noexcept = default;
66*09537850SAkhilesh Sanikop   // Move only.
67*09537850SAkhilesh Sanikop   VectorBase(const VectorBase&) = delete;
68*09537850SAkhilesh Sanikop   VectorBase& operator=(const VectorBase&) = delete;
VectorBase(VectorBase && other)69*09537850SAkhilesh Sanikop   VectorBase(VectorBase&& other) noexcept
70*09537850SAkhilesh Sanikop       : items_(other.items_),
71*09537850SAkhilesh Sanikop         capacity_(other.capacity_),
72*09537850SAkhilesh Sanikop         num_items_(other.num_items_) {
73*09537850SAkhilesh Sanikop     other.items_ = nullptr;
74*09537850SAkhilesh Sanikop     other.capacity_ = 0;
75*09537850SAkhilesh Sanikop     other.num_items_ = 0;
76*09537850SAkhilesh Sanikop   }
77*09537850SAkhilesh Sanikop   VectorBase& operator=(VectorBase&& other) noexcept {
78*09537850SAkhilesh Sanikop     if (this != &other) {
79*09537850SAkhilesh Sanikop       clear();
80*09537850SAkhilesh Sanikop       free(items_);
81*09537850SAkhilesh Sanikop       items_ = other.items_;
82*09537850SAkhilesh Sanikop       capacity_ = other.capacity_;
83*09537850SAkhilesh Sanikop       num_items_ = other.num_items_;
84*09537850SAkhilesh Sanikop       other.items_ = nullptr;
85*09537850SAkhilesh Sanikop       other.capacity_ = 0;
86*09537850SAkhilesh Sanikop       other.num_items_ = 0;
87*09537850SAkhilesh Sanikop     }
88*09537850SAkhilesh Sanikop     return *this;
89*09537850SAkhilesh Sanikop   }
~VectorBase()90*09537850SAkhilesh Sanikop   ~VectorBase() {
91*09537850SAkhilesh Sanikop     clear();
92*09537850SAkhilesh Sanikop     free(items_);
93*09537850SAkhilesh Sanikop   }
94*09537850SAkhilesh Sanikop 
95*09537850SAkhilesh Sanikop   // Reallocates just enough memory if needed so that 'new_cap' items can fit.
reserve(size_t new_cap)96*09537850SAkhilesh Sanikop   LIBGAV1_MUST_USE_RESULT bool reserve(size_t new_cap) {
97*09537850SAkhilesh Sanikop     if (capacity_ < new_cap) {
98*09537850SAkhilesh Sanikop       T* const new_items = static_cast<T*>(malloc(new_cap * sizeof(T)));
99*09537850SAkhilesh Sanikop       if (new_items == nullptr) return false;
100*09537850SAkhilesh Sanikop       if (num_items_ > 0) {
101*09537850SAkhilesh Sanikop         if (std::is_trivial<T>::value) {
102*09537850SAkhilesh Sanikop           // Cast |new_items| and |items_| to void* to avoid the GCC
103*09537850SAkhilesh Sanikop           // -Wclass-memaccess warning and additionally the
104*09537850SAkhilesh Sanikop           // bugprone-undefined-memory-manipulation clang-tidy warning. The
105*09537850SAkhilesh Sanikop           // memcpy is safe because T is a trivial type.
106*09537850SAkhilesh Sanikop           memcpy(static_cast<void*>(new_items),
107*09537850SAkhilesh Sanikop                  static_cast<const void*>(items_), num_items_ * sizeof(T));
108*09537850SAkhilesh Sanikop         } else {
109*09537850SAkhilesh Sanikop           for (size_t i = 0; i < num_items_; ++i) {
110*09537850SAkhilesh Sanikop             new (&new_items[i]) T(std::move(items_[i]));
111*09537850SAkhilesh Sanikop             items_[i].~T();
112*09537850SAkhilesh Sanikop           }
113*09537850SAkhilesh Sanikop         }
114*09537850SAkhilesh Sanikop       }
115*09537850SAkhilesh Sanikop       free(items_);
116*09537850SAkhilesh Sanikop       items_ = new_items;
117*09537850SAkhilesh Sanikop       capacity_ = new_cap;
118*09537850SAkhilesh Sanikop     }
119*09537850SAkhilesh Sanikop     return true;
120*09537850SAkhilesh Sanikop   }
121*09537850SAkhilesh Sanikop 
122*09537850SAkhilesh Sanikop   // Reallocates less memory so that only the existing items can fit.
shrink_to_fit()123*09537850SAkhilesh Sanikop   bool shrink_to_fit() {
124*09537850SAkhilesh Sanikop     if (capacity_ == num_items_) return true;
125*09537850SAkhilesh Sanikop     if (num_items_ == 0) {
126*09537850SAkhilesh Sanikop       free(items_);
127*09537850SAkhilesh Sanikop       items_ = nullptr;
128*09537850SAkhilesh Sanikop       capacity_ = 0;
129*09537850SAkhilesh Sanikop       return true;
130*09537850SAkhilesh Sanikop     }
131*09537850SAkhilesh Sanikop     const size_t previous_capacity = capacity_;
132*09537850SAkhilesh Sanikop     capacity_ = 0;  // Force reserve() to allocate and copy.
133*09537850SAkhilesh Sanikop     if (reserve(num_items_)) return true;
134*09537850SAkhilesh Sanikop     capacity_ = previous_capacity;
135*09537850SAkhilesh Sanikop     return false;
136*09537850SAkhilesh Sanikop   }
137*09537850SAkhilesh Sanikop 
138*09537850SAkhilesh Sanikop   // Constructs a new item by copy constructor. May reallocate if
139*09537850SAkhilesh Sanikop   // 'resize_if_needed'.
140*09537850SAkhilesh Sanikop   LIBGAV1_MUST_USE_RESULT bool push_back(const T& value,
141*09537850SAkhilesh Sanikop                                          bool resize_if_needed = true) {
142*09537850SAkhilesh Sanikop     if (num_items_ >= capacity_ &&
143*09537850SAkhilesh Sanikop         (!resize_if_needed ||
144*09537850SAkhilesh Sanikop          !reserve(internal::NextCapacity(num_items_ + 1)))) {
145*09537850SAkhilesh Sanikop       return false;
146*09537850SAkhilesh Sanikop     }
147*09537850SAkhilesh Sanikop     new (&items_[num_items_]) T(value);
148*09537850SAkhilesh Sanikop     ++num_items_;
149*09537850SAkhilesh Sanikop     return true;
150*09537850SAkhilesh Sanikop   }
151*09537850SAkhilesh Sanikop 
152*09537850SAkhilesh Sanikop   // Constructs a new item by copy constructor. reserve() must have been called
153*09537850SAkhilesh Sanikop   // with a sufficient capacity.
154*09537850SAkhilesh Sanikop   //
155*09537850SAkhilesh Sanikop   // WARNING: No error checking is performed.
push_back_unchecked(const T & value)156*09537850SAkhilesh Sanikop   void push_back_unchecked(const T& value) {
157*09537850SAkhilesh Sanikop     assert(num_items_ < capacity_);
158*09537850SAkhilesh Sanikop     new (&items_[num_items_]) T(value);
159*09537850SAkhilesh Sanikop     ++num_items_;
160*09537850SAkhilesh Sanikop   }
161*09537850SAkhilesh Sanikop 
162*09537850SAkhilesh Sanikop   // Constructs a new item by move constructor. May reallocate if
163*09537850SAkhilesh Sanikop   // 'resize_if_needed'.
164*09537850SAkhilesh Sanikop   LIBGAV1_MUST_USE_RESULT bool push_back(T&& value,
165*09537850SAkhilesh Sanikop                                          bool resize_if_needed = true) {
166*09537850SAkhilesh Sanikop     if (num_items_ >= capacity_ &&
167*09537850SAkhilesh Sanikop         (!resize_if_needed ||
168*09537850SAkhilesh Sanikop          !reserve(internal::NextCapacity(num_items_ + 1)))) {
169*09537850SAkhilesh Sanikop       return false;
170*09537850SAkhilesh Sanikop     }
171*09537850SAkhilesh Sanikop     new (&items_[num_items_]) T(std::move(value));
172*09537850SAkhilesh Sanikop     ++num_items_;
173*09537850SAkhilesh Sanikop     return true;
174*09537850SAkhilesh Sanikop   }
175*09537850SAkhilesh Sanikop 
176*09537850SAkhilesh Sanikop   // Constructs a new item by move constructor. reserve() must have been called
177*09537850SAkhilesh Sanikop   // with a sufficient capacity.
178*09537850SAkhilesh Sanikop   //
179*09537850SAkhilesh Sanikop   // WARNING: No error checking is performed.
push_back_unchecked(T && value)180*09537850SAkhilesh Sanikop   void push_back_unchecked(T&& value) {
181*09537850SAkhilesh Sanikop     assert(num_items_ < capacity_);
182*09537850SAkhilesh Sanikop     new (&items_[num_items_]) T(std::move(value));
183*09537850SAkhilesh Sanikop     ++num_items_;
184*09537850SAkhilesh Sanikop   }
185*09537850SAkhilesh Sanikop 
186*09537850SAkhilesh Sanikop   // Constructs a new item in place by forwarding the arguments args... to the
187*09537850SAkhilesh Sanikop   // constructor. May reallocate.
188*09537850SAkhilesh Sanikop   template <typename... Args>
emplace_back(Args &&...args)189*09537850SAkhilesh Sanikop   LIBGAV1_MUST_USE_RESULT bool emplace_back(Args&&... args) {
190*09537850SAkhilesh Sanikop     if (num_items_ >= capacity_ &&
191*09537850SAkhilesh Sanikop         !reserve(internal::NextCapacity(num_items_ + 1))) {
192*09537850SAkhilesh Sanikop       return false;
193*09537850SAkhilesh Sanikop     }
194*09537850SAkhilesh Sanikop     new (&items_[num_items_]) T(std::forward<Args>(args)...);
195*09537850SAkhilesh Sanikop     ++num_items_;
196*09537850SAkhilesh Sanikop     return true;
197*09537850SAkhilesh Sanikop   }
198*09537850SAkhilesh Sanikop 
199*09537850SAkhilesh Sanikop   // Destructs the last item.
pop_back()200*09537850SAkhilesh Sanikop   void pop_back() {
201*09537850SAkhilesh Sanikop     --num_items_;
202*09537850SAkhilesh Sanikop     items_[num_items_].~T();
203*09537850SAkhilesh Sanikop   }
204*09537850SAkhilesh Sanikop 
205*09537850SAkhilesh Sanikop   // Destructs the item at 'pos'.
erase(iterator pos)206*09537850SAkhilesh Sanikop   void erase(iterator pos) { erase(pos, pos + 1); }
207*09537850SAkhilesh Sanikop 
208*09537850SAkhilesh Sanikop   // Destructs the items in [first,last).
erase(iterator first,iterator last)209*09537850SAkhilesh Sanikop   void erase(iterator first, iterator last) {
210*09537850SAkhilesh Sanikop     for (iterator it = first; it != last; ++it) it->~T();
211*09537850SAkhilesh Sanikop     if (last != end()) {
212*09537850SAkhilesh Sanikop       if (std::is_trivial<T>::value) {
213*09537850SAkhilesh Sanikop         // Cast |first| and |last| to void* to avoid the GCC
214*09537850SAkhilesh Sanikop         // -Wclass-memaccess warning and additionally the
215*09537850SAkhilesh Sanikop         // bugprone-undefined-memory-manipulation clang-tidy warning. The
216*09537850SAkhilesh Sanikop         // memmove is safe because T is a trivial type.
217*09537850SAkhilesh Sanikop         memmove(static_cast<void*>(first), static_cast<const void*>(last),
218*09537850SAkhilesh Sanikop                 (end() - last) * sizeof(T));
219*09537850SAkhilesh Sanikop       } else {
220*09537850SAkhilesh Sanikop         for (iterator it_src = last, it_dst = first; it_src != end();
221*09537850SAkhilesh Sanikop              ++it_src, ++it_dst) {
222*09537850SAkhilesh Sanikop           new (it_dst) T(std::move(*it_src));
223*09537850SAkhilesh Sanikop           it_src->~T();
224*09537850SAkhilesh Sanikop         }
225*09537850SAkhilesh Sanikop       }
226*09537850SAkhilesh Sanikop     }
227*09537850SAkhilesh Sanikop     num_items_ -= std::distance(first, last);
228*09537850SAkhilesh Sanikop   }
229*09537850SAkhilesh Sanikop 
230*09537850SAkhilesh Sanikop   // Destructs all the items.
clear()231*09537850SAkhilesh Sanikop   void clear() { erase(begin(), end()); }
232*09537850SAkhilesh Sanikop 
233*09537850SAkhilesh Sanikop   // Destroys (including deallocating) all the items.
reset()234*09537850SAkhilesh Sanikop   void reset() {
235*09537850SAkhilesh Sanikop     clear();
236*09537850SAkhilesh Sanikop     if (!shrink_to_fit()) assert(false);
237*09537850SAkhilesh Sanikop   }
238*09537850SAkhilesh Sanikop 
239*09537850SAkhilesh Sanikop   // Accessors
empty()240*09537850SAkhilesh Sanikop   bool empty() const { return (num_items_ == 0); }
size()241*09537850SAkhilesh Sanikop   size_t size() const { return num_items_; }
capacity()242*09537850SAkhilesh Sanikop   size_t capacity() const { return capacity_; }
243*09537850SAkhilesh Sanikop 
data()244*09537850SAkhilesh Sanikop   T* data() { return items_; }
front()245*09537850SAkhilesh Sanikop   T& front() { return items_[0]; }
back()246*09537850SAkhilesh Sanikop   T& back() { return items_[num_items_ - 1]; }
247*09537850SAkhilesh Sanikop   T& operator[](size_t i) { return items_[i]; }
at(size_t i)248*09537850SAkhilesh Sanikop   T& at(size_t i) { return items_[i]; }
data()249*09537850SAkhilesh Sanikop   const T* data() const { return items_; }
front()250*09537850SAkhilesh Sanikop   const T& front() const { return items_[0]; }
back()251*09537850SAkhilesh Sanikop   const T& back() const { return items_[num_items_ - 1]; }
252*09537850SAkhilesh Sanikop   const T& operator[](size_t i) const { return items_[i]; }
at(size_t i)253*09537850SAkhilesh Sanikop   const T& at(size_t i) const { return items_[i]; }
254*09537850SAkhilesh Sanikop 
begin()255*09537850SAkhilesh Sanikop   iterator begin() { return &items_[0]; }
begin()256*09537850SAkhilesh Sanikop   const_iterator begin() const { return &items_[0]; }
end()257*09537850SAkhilesh Sanikop   iterator end() { return &items_[num_items_]; }
end()258*09537850SAkhilesh Sanikop   const_iterator end() const { return &items_[num_items_]; }
259*09537850SAkhilesh Sanikop 
swap(VectorBase & b)260*09537850SAkhilesh Sanikop   void swap(VectorBase& b) {
261*09537850SAkhilesh Sanikop     // Although not necessary here, adding "using std::swap;" and then calling
262*09537850SAkhilesh Sanikop     // swap() without namespace qualification is recommended. See Effective
263*09537850SAkhilesh Sanikop     // C++, Item 25.
264*09537850SAkhilesh Sanikop     using std::swap;
265*09537850SAkhilesh Sanikop     swap(items_, b.items_);
266*09537850SAkhilesh Sanikop     swap(capacity_, b.capacity_);
267*09537850SAkhilesh Sanikop     swap(num_items_, b.num_items_);
268*09537850SAkhilesh Sanikop   }
269*09537850SAkhilesh Sanikop 
270*09537850SAkhilesh Sanikop  protected:
271*09537850SAkhilesh Sanikop   T* items_ = nullptr;
272*09537850SAkhilesh Sanikop   size_t capacity_ = 0;
273*09537850SAkhilesh Sanikop   size_t num_items_ = 0;
274*09537850SAkhilesh Sanikop };
275*09537850SAkhilesh Sanikop 
276*09537850SAkhilesh Sanikop }  // namespace internal
277*09537850SAkhilesh Sanikop 
278*09537850SAkhilesh Sanikop //------------------------------------------------------------------------------
279*09537850SAkhilesh Sanikop 
280*09537850SAkhilesh Sanikop // Vector class that does *NOT* construct the content on resize().
281*09537850SAkhilesh Sanikop // Should be reserved to plain old data.
282*09537850SAkhilesh Sanikop template <typename T>
283*09537850SAkhilesh Sanikop class VectorNoCtor : public internal::VectorBase<T> {
284*09537850SAkhilesh Sanikop  public:
285*09537850SAkhilesh Sanikop   // Creates or destructs items so that 'new_num_items' exist.
286*09537850SAkhilesh Sanikop   // Allocated memory grows every power-of-two items.
resize(size_t new_num_items)287*09537850SAkhilesh Sanikop   LIBGAV1_MUST_USE_RESULT bool resize(size_t new_num_items) {
288*09537850SAkhilesh Sanikop     using super = internal::VectorBase<T>;
289*09537850SAkhilesh Sanikop     if (super::num_items_ < new_num_items) {
290*09537850SAkhilesh Sanikop       if (super::capacity_ < new_num_items) {
291*09537850SAkhilesh Sanikop         if (!super::reserve(internal::NextCapacity(new_num_items))) {
292*09537850SAkhilesh Sanikop           return false;
293*09537850SAkhilesh Sanikop         }
294*09537850SAkhilesh Sanikop       }
295*09537850SAkhilesh Sanikop       super::num_items_ = new_num_items;
296*09537850SAkhilesh Sanikop     } else {
297*09537850SAkhilesh Sanikop       while (super::num_items_ > new_num_items) {
298*09537850SAkhilesh Sanikop         --super::num_items_;
299*09537850SAkhilesh Sanikop         super::items_[super::num_items_].~T();
300*09537850SAkhilesh Sanikop       }
301*09537850SAkhilesh Sanikop     }
302*09537850SAkhilesh Sanikop     return true;
303*09537850SAkhilesh Sanikop   }
304*09537850SAkhilesh Sanikop };
305*09537850SAkhilesh Sanikop 
306*09537850SAkhilesh Sanikop // This generic vector class will call the constructors.
307*09537850SAkhilesh Sanikop template <typename T>
308*09537850SAkhilesh Sanikop class Vector : public internal::VectorBase<T> {
309*09537850SAkhilesh Sanikop  public:
310*09537850SAkhilesh Sanikop   // Constructs or destructs items so that 'new_num_items' exist.
311*09537850SAkhilesh Sanikop   // Allocated memory grows every power-of-two items.
resize(size_t new_num_items)312*09537850SAkhilesh Sanikop   LIBGAV1_MUST_USE_RESULT bool resize(size_t new_num_items) {
313*09537850SAkhilesh Sanikop     using super = internal::VectorBase<T>;
314*09537850SAkhilesh Sanikop     if (super::num_items_ < new_num_items) {
315*09537850SAkhilesh Sanikop       if (super::capacity_ < new_num_items) {
316*09537850SAkhilesh Sanikop         if (!super::reserve(internal::NextCapacity(new_num_items))) {
317*09537850SAkhilesh Sanikop           return false;
318*09537850SAkhilesh Sanikop         }
319*09537850SAkhilesh Sanikop       }
320*09537850SAkhilesh Sanikop       while (super::num_items_ < new_num_items) {
321*09537850SAkhilesh Sanikop         new (&super::items_[super::num_items_]) T();
322*09537850SAkhilesh Sanikop         ++super::num_items_;
323*09537850SAkhilesh Sanikop       }
324*09537850SAkhilesh Sanikop     } else {
325*09537850SAkhilesh Sanikop       while (super::num_items_ > new_num_items) {
326*09537850SAkhilesh Sanikop         --super::num_items_;
327*09537850SAkhilesh Sanikop         super::items_[super::num_items_].~T();
328*09537850SAkhilesh Sanikop       }
329*09537850SAkhilesh Sanikop     }
330*09537850SAkhilesh Sanikop     return true;
331*09537850SAkhilesh Sanikop   }
332*09537850SAkhilesh Sanikop };
333*09537850SAkhilesh Sanikop 
334*09537850SAkhilesh Sanikop //------------------------------------------------------------------------------
335*09537850SAkhilesh Sanikop 
336*09537850SAkhilesh Sanikop // Define non-member swap() functions in the namespace in which VectorNoCtor
337*09537850SAkhilesh Sanikop // and Vector are implemented. See Effective C++, Item 25.
338*09537850SAkhilesh Sanikop 
339*09537850SAkhilesh Sanikop template <typename T>
swap(VectorNoCtor<T> & a,VectorNoCtor<T> & b)340*09537850SAkhilesh Sanikop void swap(VectorNoCtor<T>& a, VectorNoCtor<T>& b) {
341*09537850SAkhilesh Sanikop   a.swap(b);
342*09537850SAkhilesh Sanikop }
343*09537850SAkhilesh Sanikop 
344*09537850SAkhilesh Sanikop template <typename T>
swap(Vector<T> & a,Vector<T> & b)345*09537850SAkhilesh Sanikop void swap(Vector<T>& a, Vector<T>& b) {
346*09537850SAkhilesh Sanikop   a.swap(b);
347*09537850SAkhilesh Sanikop }
348*09537850SAkhilesh Sanikop 
349*09537850SAkhilesh Sanikop //------------------------------------------------------------------------------
350*09537850SAkhilesh Sanikop 
351*09537850SAkhilesh Sanikop }  // namespace libgav1
352*09537850SAkhilesh Sanikop 
353*09537850SAkhilesh Sanikop #endif  // LIBGAV1_SRC_UTILS_VECTOR_H_
354