You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

inlined_vector.h 38 kB

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