FixedVector.h (9544B)
1 // 2 // Copyright 2018 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // FixedVector.h: 7 // A vector class with a maximum size and fixed storage. 8 // 9 10 #ifndef COMMON_FIXEDVECTOR_H_ 11 #define COMMON_FIXEDVECTOR_H_ 12 13 #include "common/debug.h" 14 15 #include <algorithm> 16 #include <array> 17 #include <initializer_list> 18 19 namespace angle 20 { 21 template <class T, size_t N, class Storage = std::array<T, N>> 22 class FixedVector final 23 { 24 public: 25 using value_type = typename Storage::value_type; 26 using size_type = typename Storage::size_type; 27 using reference = typename Storage::reference; 28 using const_reference = typename Storage::const_reference; 29 using pointer = typename Storage::pointer; 30 using const_pointer = typename Storage::const_pointer; 31 using iterator = typename Storage::iterator; 32 using const_iterator = typename Storage::const_iterator; 33 using reverse_iterator = typename Storage::reverse_iterator; 34 using const_reverse_iterator = typename Storage::const_reverse_iterator; 35 36 FixedVector(); 37 FixedVector(size_type count, const value_type &value); 38 FixedVector(size_type count); 39 40 FixedVector(const FixedVector<T, N, Storage> &other); 41 FixedVector(FixedVector<T, N, Storage> &&other); 42 FixedVector(std::initializer_list<value_type> init); 43 44 FixedVector<T, N, Storage> &operator=(const FixedVector<T, N, Storage> &other); 45 FixedVector<T, N, Storage> &operator=(FixedVector<T, N, Storage> &&other); 46 FixedVector<T, N, Storage> &operator=(std::initializer_list<value_type> init); 47 48 ~FixedVector(); 49 50 reference at(size_type pos); 51 const_reference at(size_type pos) const; 52 53 reference operator[](size_type pos); 54 const_reference operator[](size_type pos) const; 55 56 pointer data(); 57 const_pointer data() const; 58 59 iterator begin(); 60 const_iterator begin() const; 61 62 iterator end(); 63 const_iterator end() const; 64 65 bool empty() const; 66 size_type size() const; 67 static constexpr size_type max_size(); 68 69 void clear(); 70 71 void push_back(const value_type &value); 72 void push_back(value_type &&value); 73 74 template <class... Args> 75 void emplace_back(Args &&... args); 76 77 void pop_back(); 78 reference back(); 79 const_reference back() const; 80 81 void swap(FixedVector<T, N, Storage> &other); 82 83 void resize(size_type count); 84 void resize(size_type count, const value_type &value); 85 86 bool full() const; 87 88 private: 89 void assign_from_initializer_list(std::initializer_list<value_type> init); 90 91 Storage mStorage; 92 size_type mSize = 0; 93 }; 94 95 template <class T, size_t N, class Storage> 96 bool operator==(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b) 97 { 98 return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); 99 } 100 101 template <class T, size_t N, class Storage> 102 bool operator!=(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b) 103 { 104 return !(a == b); 105 } 106 107 template <class T, size_t N, class Storage> 108 FixedVector<T, N, Storage>::FixedVector() = default; 109 110 template <class T, size_t N, class Storage> 111 FixedVector<T, N, Storage>::FixedVector(size_type count, const value_type &value) : mSize(count) 112 { 113 ASSERT(count <= N); 114 std::fill(mStorage.begin(), mStorage.begin() + count, value); 115 } 116 117 template <class T, size_t N, class Storage> 118 FixedVector<T, N, Storage>::FixedVector(size_type count) : mSize(count) 119 { 120 ASSERT(count <= N); 121 } 122 123 template <class T, size_t N, class Storage> 124 FixedVector<T, N, Storage>::FixedVector(const FixedVector<T, N, Storage> &other) = default; 125 126 template <class T, size_t N, class Storage> 127 FixedVector<T, N, Storage>::FixedVector(FixedVector<T, N, Storage> &&other) = default; 128 129 template <class T, size_t N, class Storage> 130 FixedVector<T, N, Storage>::FixedVector(std::initializer_list<value_type> init) 131 { 132 ASSERT(init.size() <= N); 133 assign_from_initializer_list(init); 134 } 135 136 template <class T, size_t N, class Storage> 137 FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=( 138 const FixedVector<T, N, Storage> &other) = default; 139 140 template <class T, size_t N, class Storage> 141 FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=( 142 FixedVector<T, N, Storage> &&other) = default; 143 144 template <class T, size_t N, class Storage> 145 FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=( 146 std::initializer_list<value_type> init) 147 { 148 clear(); 149 ASSERT(init.size() <= N); 150 assign_from_initializer_list(init); 151 return this; 152 } 153 154 template <class T, size_t N, class Storage> 155 FixedVector<T, N, Storage>::~FixedVector() 156 { 157 clear(); 158 } 159 160 template <class T, size_t N, class Storage> 161 typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::at(size_type pos) 162 { 163 ASSERT(pos < N); 164 return mStorage.at(pos); 165 } 166 167 template <class T, size_t N, class Storage> 168 typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::at( 169 size_type pos) const 170 { 171 ASSERT(pos < N); 172 return mStorage.at(pos); 173 } 174 175 template <class T, size_t N, class Storage> 176 typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::operator[](size_type pos) 177 { 178 ASSERT(pos < N); 179 return mStorage[pos]; 180 } 181 182 template <class T, size_t N, class Storage> 183 typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::operator[]( 184 size_type pos) const 185 { 186 ASSERT(pos < N); 187 return mStorage[pos]; 188 } 189 190 template <class T, size_t N, class Storage> 191 typename FixedVector<T, N, Storage>::const_pointer angle::FixedVector<T, N, Storage>::data() const 192 { 193 return mStorage.data(); 194 } 195 196 template <class T, size_t N, class Storage> 197 typename FixedVector<T, N, Storage>::pointer angle::FixedVector<T, N, Storage>::data() 198 { 199 return mStorage.data(); 200 } 201 202 template <class T, size_t N, class Storage> 203 typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::begin() 204 { 205 return mStorage.begin(); 206 } 207 208 template <class T, size_t N, class Storage> 209 typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::begin() const 210 { 211 return mStorage.begin(); 212 } 213 214 template <class T, size_t N, class Storage> 215 typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::end() 216 { 217 return mStorage.begin() + mSize; 218 } 219 220 template <class T, size_t N, class Storage> 221 typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::end() const 222 { 223 return mStorage.begin() + mSize; 224 } 225 226 template <class T, size_t N, class Storage> 227 bool FixedVector<T, N, Storage>::empty() const 228 { 229 return mSize == 0; 230 } 231 232 template <class T, size_t N, class Storage> 233 typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::size() const 234 { 235 return mSize; 236 } 237 238 template <class T, size_t N, class Storage> 239 constexpr typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::max_size() 240 { 241 return N; 242 } 243 244 template <class T, size_t N, class Storage> 245 void FixedVector<T, N, Storage>::clear() 246 { 247 resize(0); 248 } 249 250 template <class T, size_t N, class Storage> 251 void FixedVector<T, N, Storage>::push_back(const value_type &value) 252 { 253 ASSERT(mSize < N); 254 mStorage[mSize] = value; 255 mSize++; 256 } 257 258 template <class T, size_t N, class Storage> 259 void FixedVector<T, N, Storage>::push_back(value_type &&value) 260 { 261 ASSERT(mSize < N); 262 mStorage[mSize] = std::move(value); 263 mSize++; 264 } 265 266 template <class T, size_t N, class Storage> 267 template <class... Args> 268 void FixedVector<T, N, Storage>::emplace_back(Args &&... args) 269 { 270 ASSERT(mSize < N); 271 new (&mStorage[mSize]) T{std::forward<Args>(args)...}; 272 mSize++; 273 } 274 275 template <class T, size_t N, class Storage> 276 void FixedVector<T, N, Storage>::pop_back() 277 { 278 ASSERT(mSize > 0); 279 mSize--; 280 } 281 282 template <class T, size_t N, class Storage> 283 typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::back() 284 { 285 ASSERT(mSize > 0); 286 return mStorage[mSize - 1]; 287 } 288 289 template <class T, size_t N, class Storage> 290 typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::back() const 291 { 292 ASSERT(mSize > 0); 293 return mStorage[mSize - 1]; 294 } 295 296 template <class T, size_t N, class Storage> 297 void FixedVector<T, N, Storage>::swap(FixedVector<T, N, Storage> &other) 298 { 299 std::swap(mSize, other.mSize); 300 std::swap(mStorage, other.mStorage); 301 } 302 303 template <class T, size_t N, class Storage> 304 void FixedVector<T, N, Storage>::resize(size_type count) 305 { 306 ASSERT(count <= N); 307 while (mSize > count) 308 { 309 mSize--; 310 mStorage[mSize] = value_type(); 311 } 312 while (mSize < count) 313 { 314 mStorage[mSize] = value_type(); 315 mSize++; 316 } 317 } 318 319 template <class T, size_t N, class Storage> 320 void FixedVector<T, N, Storage>::resize(size_type count, const value_type &value) 321 { 322 ASSERT(count <= N); 323 while (mSize > count) 324 { 325 mSize--; 326 mStorage[mSize] = value_type(); 327 } 328 while (mSize < count) 329 { 330 mStorage[mSize] = value; 331 mSize++; 332 } 333 } 334 335 template <class T, size_t N, class Storage> 336 void FixedVector<T, N, Storage>::assign_from_initializer_list( 337 std::initializer_list<value_type> init) 338 { 339 for (auto element : init) 340 { 341 mStorage[mSize] = std::move(element); 342 mSize++; 343 } 344 } 345 346 template <class T, size_t N, class Storage> 347 bool FixedVector<T, N, Storage>::full() const 348 { 349 return (mSize == N); 350 } 351 } // namespace angle 352 353 #endif // COMMON_FIXEDVECTOR_H_