Wayverb
recursive_vector.h
1 #pragma once
2 
3 #include <algorithm>
4 #include <memory>
5 
6 namespace wayverb {
7 namespace core {
8 namespace detail {
9 
16 template <typename T>
17 class recursive_vector_impl final {
18 public:
19  using value_type = T;
20  using allocator_type = std::allocator<T>;
21  using size_type = std::size_t;
22 
23  using allocator_traits = std::allocator_traits<std::allocator<T>>;
24 
25  using pointer = typename allocator_traits::pointer;
26  using const_pointer = typename allocator_traits::const_pointer;
27 
28  using iterator = pointer;
29  using const_iterator = const_pointer;
30 
31  using reverse_iterator = std::reverse_iterator<iterator>;
32  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
33 
34  explicit recursive_vector_impl(size_type size = 0)
35  : capacity_{size}
36  , ptr_{size ? allocator_traits::allocate(alloc_, size) : nullptr} {}
37 
38  void swap(recursive_vector_impl& other) noexcept {
39  using std::swap;
40  swap(size_, other.size_);
41  swap(capacity_, other.capacity_);
42  swap(alloc_, other.alloc_);
43  swap(ptr_, other.ptr_);
44  }
45 
47  : capacity_{other.size_}
48  , ptr_{other.ptr_ ? allocator_traits::allocate(alloc_, other.size_)
49  : nullptr} {
50  for (auto i = other.begin(), end = other.end(); i != end; ++i) {
51  construct(*i);
52  }
53  }
54 
56  swap(other);
57  }
58 
59  recursive_vector_impl& operator=(const recursive_vector_impl& other) {
60  auto copy = other;
61  swap(copy);
62  return *this;
63  }
64  recursive_vector_impl& operator=(recursive_vector_impl&& other) noexcept {
65  swap(other);
66  return *this;
67  }
68 
69  ~recursive_vector_impl() noexcept {
70  while (size_) {
71  destroy();
72  }
73  allocator_traits::deallocate(alloc_, ptr_, capacity_);
74  }
75 
76  template <typename... Ts>
77  void construct(Ts&&... ts) {
78  allocator_traits::construct(
79  alloc_, ptr_ + size_, std::forward<Ts>(ts)...);
80  size_ += 1;
81  }
82 
83  void destroy() noexcept {
84  size_ -= 1;
85  allocator_traits::destroy(alloc_, ptr_ + size_);
86  }
87 
88  size_type size() const { return size_; }
89  size_type capacity() const { return capacity_; }
90 
91  iterator begin() { return ptr_; }
92  const_iterator begin() const { return ptr_; }
93  const_iterator cbegin() const { return ptr_; }
94 
95  iterator end() { return ptr_ + size_; }
96  const_iterator end() const { return ptr_ + size_; }
97  const_iterator cend() const { return ptr_ + size_; }
98 
99 private:
100  size_type size_{0};
101  size_type capacity_{0};
102  allocator_type alloc_{};
103  T* ptr_{nullptr};
104 };
105 
106 template <typename T>
107 void swap(recursive_vector_impl<T>& a, recursive_vector_impl<T>& b) noexcept {
108  a.swap(b);
109 }
110 
111 } // namespace detail
112 
113 template <typename T>
114 class recursive_vector final {
115 public:
117  using value_type = typename impl_type::value_type;
118  using allocator_type = typename impl_type::allocator_type;
119  using size_type = typename impl_type::size_type;
120  using difference_type = std::ptrdiff_t;
121 
122  using reference = value_type&;
123  using const_reference = const value_type&;
124 
125  using pointer = typename impl_type::pointer;
126  using const_pointer = typename impl_type::const_pointer;
127 
128  using iterator = pointer;
129  using const_iterator = const_pointer;
130 
131  using reverse_iterator = std::reverse_iterator<iterator>;
132  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
133 
134  void swap(recursive_vector& other) noexcept {
135  using std::swap;
136  swap(impl_, other.impl_);
137  }
138 
139  template <typename It>
140  iterator insert(const_iterator pos, It first, It last) {
141  const auto n = std::distance(first, last);
142  const auto c = impl_.capacity();
143  const auto new_size = impl_.size() + n;
144  const auto old_pos = std::distance(impl_.cbegin(), pos);
145  // If there's already room for the new elements.
146  if (new_size <= c) {
147  // Default-construct some new elements at the end.
148  const auto old_end = impl_.end();
149  while (impl_.size() < new_size) {
150  impl_.construct();
151  }
152  // Move items back.
153  const auto r = impl_.begin() + old_pos;
154  std::move_backward(r, old_end, impl_.begin() + new_size);
155  std::copy(first, last, r);
156  return r;
157  }
158  // There wasn't room for the new elements, so we construct a new
159  // storage area, and move each element across.
160  // This line might throw, which is fine, because the object is still
161  // in a valid state.
162  impl_type v{std::max(impl_.size() + n, impl_.capacity() * 2 + 1)};
163  // Function is nothrow from here on.
164  for (auto i = impl_.begin(); i != pos; ++i) {
165  v.construct(std::move(*i));
166  }
167  for (auto i = first; i != last; ++i) {
168  v.construct(*i);
169  }
170  for (auto i = pos; i != impl_.end(); ++i) {
171  v.construct(std::move(*i));
172  }
173  // Take ownership of the copy;
174  impl_.swap(v);
175  return impl_.begin() + old_pos;
176  }
177 
178  iterator erase(const_iterator begin, const_iterator end) {
179  // Move elements down the range one-by-one.
180  const auto p = impl_.begin() + std::distance(impl_.cbegin(), begin);
181  std::move(impl_.begin() + std::distance(impl_.cbegin(), end),
182  impl_.end(),
183  p);
184  // Destroy the moved-from elements.
185  const auto num = std::distance(begin, end);
186  for (auto i = 0u; i != num; ++i) {
187  impl_.destroy();
188  }
189  return p;
190  }
191 
192  void reserve(size_type new_cap) {
193  if (new_cap > impl_.capacity()) {
194  // We have to reallocate.
195  // Create a new impl to store the data.
196  impl_type v{std::max(new_cap, impl_.capacity() * 2 + 1)};
197  // Copy/move elements across one-by-one.
198  for (auto i = impl_.begin(), end = impl_.end(); i != end; ++i) {
199  v.construct(std::move(*i));
200  }
201  // Swap internals.
202  impl_.swap(v);
203  }
204  }
205 
206  pointer data() { return impl_.begin(); }
207  const_pointer data() const { return impl_.cbegin(); }
208 
209  size_type size() const { return impl_.size(); }
210  size_type capacity() const { return impl_.capacity(); }
211 
212  iterator begin() { return impl_.begin(); }
213  const_iterator begin() const { return impl_.begin(); }
214  const_iterator cbegin() const { return impl_.begin(); }
215 
216  iterator end() { return impl_.end(); }
217  const_iterator end() const { return impl_.end(); }
218  const_iterator cend() const { return impl_.end(); }
219 
220 private:
221  impl_type impl_{};
222 };
223 
224 template <class T, class Comp = std::less<T>>
226 public:
227  recursive_vector_backed_set() = default;
228  explicit recursive_vector_backed_set(const Comp& comp)
229  : comp_{comp} {}
230  explicit recursive_vector_backed_set(Comp&& comp)
231  : comp_{std::move(comp)} {}
232 
233  auto begin() { return data_.begin(); }
234  const auto begin() const { return data_.begin(); }
235  const auto cbegin() const { return data_.cbegin(); }
236 
237  auto end() { return data_.end(); }
238  const auto end() const { return data_.end(); }
239  const auto cend() const { return data_.cend(); }
240 
241  auto find(const T& t) const {
242  const auto it = std::lower_bound(data_.begin(), data_.end(), t, comp_);
243  if (it != data_.end() && values_equal(t, *it)) {
244  return it;
245  }
246  return data_.end();
247  }
248 
249  auto insert(T t) {
250  const auto it = std::lower_bound(data_.begin(), data_.end(), t, comp_);
251  if (it != data_.end() && values_equal(t, *it)) {
252  return std::make_pair(it, false);
253  }
254  return std::make_pair(data_.insert(it, &t, &t + 1), true);
255  }
256 
257  constexpr auto key_comp() const { return comp_; }
258  constexpr auto value_comp() const { return comp_; }
259 
260  auto size() const { return data_.size(); }
261 
262 private:
263  constexpr bool values_not_equal(const T& a, const T& b) const {
264  return comp_(a, b) || comp_(b, a);
265  }
266  constexpr bool values_equal(const T& a, const T& b) const {
267  return !values_not_equal(a, b);
268  }
269 
270  Comp comp_;
271  recursive_vector<T> data_;
272 };
273 
274 } // namespace core
275 } // namespace wayverb
Definition: recursive_vector.h:114
Definition: traits.cpp:2
Definition: traits.h:46
Definition: capsule_base.h:9
Definition: recursive_vector.h:17
Definition: recursive_vector.h:225