1 /* 2 * Copyright 2020 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef RTC_BASE_BOUNDED_INLINE_VECTOR_H_ 12 #define RTC_BASE_BOUNDED_INLINE_VECTOR_H_ 13 14 #include <stdint.h> 15 16 #include <memory> 17 #include <type_traits> 18 #include <utility> 19 20 #include "rtc_base/bounded_inline_vector_impl.h" 21 #include "rtc_base/checks.h" 22 23 namespace webrtc { 24 25 // A small std::vector-like type whose capacity is a compile-time constant. It 26 // stores all data inline and never heap allocates (beyond what its element type 27 // requires). Trying to grow it beyond its constant capacity is an error. 28 // 29 // TODO(bugs.webrtc.org/11391): Comparison operators. 30 // TODO(bugs.webrtc.org/11391): Methods for adding and deleting elements. 31 template <typename T, int fixed_capacity> 32 class BoundedInlineVector { 33 static_assert(!std::is_const<T>::value, "T may not be const"); 34 static_assert(fixed_capacity > 0, "Capacity must be strictly positive"); 35 36 public: 37 using size_type = int; 38 using value_type = T; 39 using const_iterator = const T*; 40 41 BoundedInlineVector() = default; 42 BoundedInlineVector(const BoundedInlineVector&) = default; 43 BoundedInlineVector(BoundedInlineVector&&) = default; 44 BoundedInlineVector& operator=(const BoundedInlineVector&) = default; 45 BoundedInlineVector& operator=(BoundedInlineVector&&) = default; 46 ~BoundedInlineVector() = default; 47 48 // This constructor is implicit, to make it possible to write e.g. 49 // 50 // BoundedInlineVector<double, 7> x = {2.72, 3.14}; 51 // 52 // and 53 // 54 // BoundedInlineVector<double, 7> GetConstants() { 55 // return {2.72, 3.14}; 56 // } 57 template <typename... Ts, 58 typename std::enable_if_t< 59 bounded_inline_vector_impl::AllConvertible<T, Ts...>::value>* = 60 nullptr> BoundedInlineVector(Ts &&...elements)61 BoundedInlineVector(Ts&&... elements) // NOLINT(runtime/explicit) 62 : storage_(std::forward<Ts>(elements)...) { 63 static_assert(sizeof...(Ts) <= fixed_capacity, ""); 64 } 65 66 template < 67 int other_capacity, 68 typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr> BoundedInlineVector(const BoundedInlineVector<T,other_capacity> & other)69 BoundedInlineVector(const BoundedInlineVector<T, other_capacity>& other) { 70 RTC_DCHECK_LE(other.size(), fixed_capacity); 71 bounded_inline_vector_impl::CopyElements(other.data(), other.size(), 72 storage_.data, &storage_.size); 73 } 74 75 template < 76 int other_capacity, 77 typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr> BoundedInlineVector(BoundedInlineVector<T,other_capacity> && other)78 BoundedInlineVector(BoundedInlineVector<T, other_capacity>&& other) { 79 RTC_DCHECK_LE(other.size(), fixed_capacity); 80 bounded_inline_vector_impl::MoveElements(other.data(), other.size(), 81 storage_.data, &storage_.size); 82 } 83 84 template < 85 int other_capacity, 86 typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr> 87 BoundedInlineVector& operator=( 88 const BoundedInlineVector<T, other_capacity>& other) { 89 bounded_inline_vector_impl::DestroyElements(storage_.data, storage_.size); 90 RTC_DCHECK_LE(other.size(), fixed_capacity); 91 bounded_inline_vector_impl::CopyElements(other.data(), other.size(), 92 storage_.data, &storage_.size); 93 return *this; 94 } 95 96 template < 97 int other_capacity, 98 typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr> 99 BoundedInlineVector& operator=( 100 BoundedInlineVector<T, other_capacity>&& other) { 101 bounded_inline_vector_impl::DestroyElements(storage_.data, storage_.size); 102 RTC_DCHECK_LE(other.size(), fixed_capacity); 103 bounded_inline_vector_impl::MoveElements(other.data(), other.size(), 104 storage_.data, &storage_.size); 105 return *this; 106 } 107 empty()108 bool empty() const { return storage_.size == 0; } size()109 int size() const { return storage_.size; } capacity()110 constexpr int capacity() const { return fixed_capacity; } 111 112 // Resizes the BoundedInlineVector to the given size, which must not exceed 113 // its constant capacity. If the size is increased, the added elements are 114 // default constructed. resize(int new_size)115 void resize(int new_size) { 116 RTC_DCHECK_GE(new_size, 0); 117 RTC_DCHECK_LE(new_size, fixed_capacity); 118 if (new_size > storage_.size) { 119 bounded_inline_vector_impl::DefaultInitializeElements( 120 storage_.data + storage_.size, new_size - storage_.size); 121 } else if (new_size < storage_.size) { 122 bounded_inline_vector_impl::DestroyElements(storage_.data + new_size, 123 storage_.size - new_size); 124 } 125 storage_.size = new_size; 126 } 127 data()128 const T* data() const { return storage_.data; } data()129 T* data() { return storage_.data; } 130 131 const T& operator[](int index) const { 132 RTC_DCHECK_GE(index, 0); 133 RTC_DCHECK_LT(index, storage_.size); 134 return storage_.data[index]; 135 } 136 T& operator[](int index) { 137 RTC_DCHECK_GE(index, 0); 138 RTC_DCHECK_LT(index, storage_.size); 139 return storage_.data[index]; 140 } 141 begin()142 T* begin() { return storage_.data; } end()143 T* end() { return storage_.data + storage_.size; } begin()144 const T* begin() const { return storage_.data; } end()145 const T* end() const { return storage_.data + storage_.size; } cbegin()146 const T* cbegin() const { return storage_.data; } cend()147 const T* cend() const { return storage_.data + storage_.size; } 148 149 private: 150 bounded_inline_vector_impl::Storage<T, fixed_capacity> storage_; 151 }; 152 153 } // namespace webrtc 154 155 #endif // RTC_BASE_BOUNDED_INLINE_VECTOR_H_ 156