C/C++ API Reference
Loading...
Searching...
No Matches
inline_deque.h
1// Copyright 2023 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// 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, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <cstddef>
17#include <cstdint>
18#include <initializer_list>
19#include <limits>
20#include <type_traits>
21#include <utility>
22
23#include "pw_assert/assert.h"
24#include "pw_containers/internal/count_and_capacity.h"
25#include "pw_containers/internal/generic_deque.h"
26#include "pw_containers/internal/raw_storage.h"
27#include "pw_toolchain/constexpr_tag.h"
28
29namespace pw {
30namespace containers::internal {
31
32// Forward declarations.
33template <typename T, typename CountAndCapacityType, size_t kCapacity>
34class BasicInlineDequeImpl;
35
36} // namespace containers::internal
37
39
40template <typename ValueType,
41 typename SizeType,
42 size_t kCapacity = containers::internal::kGenericSized>
43using BasicInlineDeque = containers::internal::BasicInlineDequeImpl<
44 ValueType,
45 containers::internal::CountAndCapacity<SizeType>,
46 kCapacity>;
47
65template <typename T, size_t kCapacity = containers::internal::kGenericSized>
67
69
70namespace containers::internal {
71
72template <typename ValueType, typename CountAndCapacityType, size_t kCapacity>
74 : public RawStorage<
75 BasicInlineDequeImpl<ValueType, CountAndCapacityType, kGenericSized>,
76 ValueType,
77 kCapacity> {
78 private:
79 using Base =
81
82 public:
83 using typename Base::const_iterator;
84 using typename Base::const_pointer;
85 using typename Base::const_reference;
86 using typename Base::difference_type;
87 using typename Base::iterator;
88 using typename Base::pointer;
89 using typename Base::reference;
90 using typename Base::size_type;
91 using typename Base::value_type;
92
95
96 // Explicit zero element constexpr constructor. Using this constructor will
97 // place the entire object in .data, which will increase ROM size. Use with
98 // caution if working with large capacity sizes.
99 constexpr BasicInlineDequeImpl(ConstexprTag /*constexpr_tag*/) noexcept {}
100
102 BasicInlineDequeImpl(size_type count, const_reference value) {
103 Base::assign(count, value);
104 }
105
107 explicit BasicInlineDequeImpl(size_type count)
108 : BasicInlineDequeImpl(count, value_type()) {}
109
111 template <typename InputIterator,
112 typename = EnableIfInputIterator<InputIterator>>
113 BasicInlineDequeImpl(InputIterator start, InputIterator finish) {
114 Base::assign(start, finish);
115 }
116
118 BasicInlineDequeImpl(const BasicInlineDequeImpl& other) { *this = other; }
119
123 template <size_t kOtherCapacity>
125 CountAndCapacityType,
126 kOtherCapacity>& other) {
127 *this = other;
128 }
129
132 *this = std::move(other);
133 }
134
136 template <size_t kOtherCapacity>
139 other) noexcept {
140 *this = std::move(other);
141 }
142
144 BasicInlineDequeImpl(const std::initializer_list<value_type>& list) {
145 *this = list;
146 }
147
149 template <typename T, typename = EnableIfIterable<T>>
150 BasicInlineDequeImpl(const T& other) {
151 *this = other;
152 }
153
154 // Assignment operators
155 //
156 // These operators delegate to the base class implementations in order to
157 // maximize code reuse. The wrappers are required so that `operator=`
158 // returns the correct type of reference.
159 //
160 // The `static_cast`s below are unfortunately necessary: without them,
161 // overload resolution prefers to use the "iterable" operators rather than
162 // upcast the RHS.
163
166 const std::initializer_list<value_type>& list) {
167 Base::operator=(list);
168 return *this;
169 }
170
173 Base::operator=(static_cast<const Base&>(other));
174 return *this;
175 }
176
180 template <size_t kOtherCapacity>
182 const BasicInlineDequeImpl<ValueType,
183 CountAndCapacityType,
184 kOtherCapacity>& other) {
185 Base::operator=(static_cast<const Base&>(other));
186 return *this;
187 }
188
191 Base::operator=(static_cast<Base&&>(std::move(other)));
192 return *this;
193 }
194
196 template <size_t kOtherCapacity>
199 other) noexcept {
200 Base::operator=(static_cast<Base&&>(std::move(other)));
201 return *this;
202 }
203
204 template <typename T, typename = EnableIfIterable<T>>
205 BasicInlineDequeImpl& operator=(const T& other) {
206 Base::operator=(other);
207 return *this;
208 }
209
210 // Size
211
212 static constexpr size_type max_size() { return capacity(); }
213 static constexpr size_type capacity() { return kCapacity; }
214};
215
216// Defines the generic-sized BasicInlineDequeImpl<T> specialization, which
217// serves as the base class for BasicInlineDequeImpl<T> of any capacity.
218//
219// Except for constructors and destructors, all other methods should be
220// implemented on this generic-sized specialization.
221//
222// NOTE: this size-polymorphic base class must not be used inside of
223// ``std::unique_ptr`` or ``delete``.
224template <typename ValueType, typename CountAndCapacityType>
225class BasicInlineDequeImpl<ValueType, CountAndCapacityType, kGenericSized>
226 : public GenericDeque<
227 BasicInlineDequeImpl<ValueType, CountAndCapacityType, kGenericSized>,
228 ValueType,
229 CountAndCapacityType> {
230 private:
231 using Base = GenericDeque<
233 ValueType,
234 CountAndCapacityType>;
235
236 public:
237 using typename Base::const_iterator;
238 using typename Base::const_pointer;
239 using typename Base::const_reference;
240 using typename Base::difference_type;
241 using typename Base::iterator;
242 using typename Base::pointer;
243 using typename Base::reference;
244 using typename Base::size_type;
245 using typename Base::value_type;
246
247 // Polymorphic-sized `pw::InlineDeque<T>` may not be constructed directly.
248 BasicInlineDequeImpl() = delete;
249
251 Base::assign(other.begin(), other.end());
252 return *this;
253 }
254
256 Base::clear();
257 for (auto&& item : other) {
258 Base::emplace_back(std::move(item));
259 }
260 other.clear();
261 return *this;
262 }
263
264 using Base::operator=;
265
266 size_type max_size() const noexcept { return Base::capacity(); }
267
268 [[nodiscard]] bool full() const noexcept {
269 return Base::size() == Base::capacity();
270 }
271
272 protected:
273 constexpr BasicInlineDequeImpl(size_type capacity) noexcept
274 : Base(capacity) {}
275
276 // Polymorphic-sized `pw::InlineDeque<T>` may not be used with `unique_ptr`
277 // or `delete`. `delete` could be supported using C++20's destroying delete.
278 ~BasicInlineDequeImpl() = default;
279
280 template <size_t kCapacity>
281 using Derived = RawStorage<
283 ValueType,
284 kCapacity>;
285
286 // The underlying RawStorage is not part of the generic-sized class. It is
287 // provided in the derived class from which this instance was constructed. To
288 // access the data, down-cast this to a known max size specialization, and
289 // return the RawStorage's data, which is the same for all sizes.
290 pointer data() { return static_cast<Derived<0>*>(this)->data(); }
291 const_pointer data() const {
292 return static_cast<const Derived<0>*>(this)->data();
293 }
294
295 private:
296 friend Base;
297
298 static constexpr bool kFixedCapacity = true; // uses static allocation
299};
300
301} // namespace containers::internal
302} // namespace pw
BasicInlineDequeImpl(size_type count)
Constructs with count default-initialized elements.
Definition: inline_deque.h:107
BasicInlineDequeImpl & operator=(BasicInlineDequeImpl< ValueType, CountAndCapacityType, kOtherCapacity > &&other) noexcept
Move assigns for mismatched capacity.
Definition: inline_deque.h:197
BasicInlineDequeImpl(const BasicInlineDequeImpl< ValueType, CountAndCapacityType, kOtherCapacity > &other)
Definition: inline_deque.h:124
BasicInlineDequeImpl & operator=(BasicInlineDequeImpl &&other) noexcept
Move assigns for matching capacity.
Definition: inline_deque.h:190
BasicInlineDequeImpl & operator=(const BasicInlineDequeImpl< ValueType, CountAndCapacityType, kOtherCapacity > &other)
Definition: inline_deque.h:181
BasicInlineDequeImpl & operator=(const std::initializer_list< value_type > &list)
Copy assigns from list.
Definition: inline_deque.h:165
BasicInlineDequeImpl() noexcept
Constructs with zero elements.
Definition: inline_deque.h:94
BasicInlineDequeImpl(BasicInlineDequeImpl< ValueType, CountAndCapacityType, kOtherCapacity > &&other) noexcept
Move constructs for mismatched capacity.
Definition: inline_deque.h:137
BasicInlineDequeImpl(BasicInlineDequeImpl &&other) noexcept
Move constructs for matching capacity.
Definition: inline_deque.h:131
BasicInlineDequeImpl(const std::initializer_list< value_type > &list)
Copy constructs from an initializer list.
Definition: inline_deque.h:144
BasicInlineDequeImpl & operator=(const BasicInlineDequeImpl &other)
Copy assigns for matching capacity.
Definition: inline_deque.h:172
BasicInlineDequeImpl(const BasicInlineDequeImpl &other)
Copy constructs for matching capacity.
Definition: inline_deque.h:118
BasicInlineDequeImpl(size_type count, const_reference value)
Constructs with count copies of value.
Definition: inline_deque.h:102
BasicInlineDequeImpl(const T &other)
Copy constructor for arbitrary iterables.
Definition: inline_deque.h:150
BasicInlineDequeImpl(InputIterator start, InputIterator finish)
Copy constructs from an iterator.
Definition: inline_deque.h:113
Definition: generic_deque.h:180
constexpr size_type size() const noexcept
Returns the number of elements in the deque.
Definition: generic_deque.h:64
constexpr size_type capacity() const noexcept
Returns the maximum number of elements in the deque.
Definition: generic_deque.h:69
void assign(size_type count, const value_type &value)
Sets the contents to count copies of value. Crashes if cannot fit.
Definition: generic_deque.h:211
The Pigweed namespace.
Definition: alignment.h:27
Definition: constexpr_tag.h:48