bounded_inline_vector.h 5.6 KB

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