Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
38template <typename ValueType,
39 typename SizeType,
40 size_t kCapacity = containers::internal::kGenericSized>
41using BasicInlineDeque = containers::internal::BasicInlineDequeImpl<
42 ValueType,
43 containers::internal::CountAndCapacity<SizeType>,
44 kCapacity>;
45
63template <typename T, size_t kCapacity = containers::internal::kGenericSized>
65
66namespace containers::internal {
67
68template <typename ValueType, typename CountAndCapacityType, size_t kCapacity>
70 : public RawStorage<
71 BasicInlineDequeImpl<ValueType, CountAndCapacityType, kGenericSized>,
72 ValueType,
73 kCapacity> {
74 private:
75 using Base =
77
78 public:
79 using typename Base::const_iterator;
80 using typename Base::const_pointer;
81 using typename Base::const_reference;
82 using typename Base::difference_type;
83 using typename Base::iterator;
84 using typename Base::pointer;
85 using typename Base::reference;
86 using typename Base::size_type;
87 using typename Base::value_type;
88
91
92 // Explicit zero element constexpr constructor. Using this constructor will
93 // place the entire object in .data, which will increase ROM size. Use with
94 // caution if working with large capacity sizes.
95 constexpr BasicInlineDequeImpl(ConstexprTag /*constexpr_tag*/) noexcept {}
96
98 BasicInlineDequeImpl(size_type count, const_reference value) {
99 Base::assign(count, value);
100 }
101
103 explicit BasicInlineDequeImpl(size_type count)
104 : BasicInlineDequeImpl(count, value_type()) {}
105
107 template <typename InputIterator,
108 typename = EnableIfInputIterator<InputIterator>>
109 BasicInlineDequeImpl(InputIterator start, InputIterator finish) {
110 Base::assign(start, finish);
111 }
112
114 BasicInlineDequeImpl(const BasicInlineDequeImpl& other) { *this = other; }
115
119 template <size_t kOtherCapacity>
121 CountAndCapacityType,
122 kOtherCapacity>& other) {
123 *this = other;
124 }
125
128 *this = std::move(other);
129 }
130
132 template <size_t kOtherCapacity>
135 other) noexcept {
136 *this = std::move(other);
137 }
138
140 BasicInlineDequeImpl(const std::initializer_list<value_type>& list) {
141 *this = list;
142 }
143
145 template <typename T, typename = EnableIfIterable<T>>
146 BasicInlineDequeImpl(const T& other) {
147 *this = other;
148 }
149
150 // Assignment operators
151 //
152 // These operators delegate to the base class implementations in order to
153 // maximize code reuse. The wrappers are required so that `operator=`
154 // returns the correct type of reference.
155 //
156 // The `static_cast`s below are unfortunately necessary: without them,
157 // overload resolution prefers to use the "iterable" operators rather than
158 // upcast the RHS.
159
162 const std::initializer_list<value_type>& list) {
163 Base::operator=(list);
164 return *this;
165 }
166
169 Base::operator=(static_cast<const Base&>(other));
170 return *this;
171 }
172
176 template <size_t kOtherCapacity>
178 const BasicInlineDequeImpl<ValueType,
179 CountAndCapacityType,
180 kOtherCapacity>& other) {
181 Base::operator=(static_cast<const Base&>(other));
182 return *this;
183 }
184
187 Base::operator=(static_cast<Base&&>(std::move(other)));
188 return *this;
189 }
190
192 template <size_t kOtherCapacity>
195 other) noexcept {
196 Base::operator=(static_cast<Base&&>(std::move(other)));
197 return *this;
198 }
199
200 template <typename T, typename = EnableIfIterable<T>>
201 BasicInlineDequeImpl& operator=(const T& other) {
202 Base::operator=(other);
203 return *this;
204 }
205
206 // Size
207
208 static constexpr size_type max_size() { return capacity(); }
209 static constexpr size_type capacity() { return kCapacity; }
210};
211
212// Defines the generic-sized BasicInlineDequeImpl<T> specialization, which
213// serves as the base class for BasicInlineDequeImpl<T> of any capacity.
214//
215// Except for constructors and destructors, all other methods should be
216// implemented on this generic-sized specialization.
217//
218// NOTE: this size-polymorphic base class must not be used inside of
219// ``std::unique_ptr`` or ``delete``.
220template <typename ValueType, typename CountAndCapacityType>
221class BasicInlineDequeImpl<ValueType, CountAndCapacityType, kGenericSized>
222 : public GenericDeque<
223 BasicInlineDequeImpl<ValueType, CountAndCapacityType, kGenericSized>,
224 ValueType,
225 CountAndCapacityType> {
226 private:
227 using Base = GenericDeque<
229 ValueType,
230 CountAndCapacityType>;
231
232 public:
233 using typename Base::const_iterator;
234 using typename Base::const_pointer;
235 using typename Base::const_reference;
236 using typename Base::difference_type;
237 using typename Base::iterator;
238 using typename Base::pointer;
239 using typename Base::reference;
240 using typename Base::size_type;
241 using typename Base::value_type;
242
243 // Polymorphic-sized `pw::InlineDeque<T>` may not be constructed directly.
244 BasicInlineDequeImpl() = delete;
245
247 Base::assign(other.begin(), other.end());
248 return *this;
249 }
250
252 Base::clear();
253 for (auto&& item : other) {
254 Base::emplace_back(std::move(item));
255 }
256 other.clear();
257 return *this;
258 }
259
260 using Base::operator=;
261
262 size_type max_size() const noexcept { return Base::capacity(); }
263
264 [[nodiscard]] bool full() const noexcept {
265 return Base::size() == Base::capacity();
266 }
267
268 protected:
269 constexpr BasicInlineDequeImpl(size_type capacity) noexcept
270 : Base(capacity) {}
271
272 // Polymorphic-sized `pw::InlineDeque<T>` may not be used with `unique_ptr`
273 // or `delete`. `delete` could be supported using C++20's destroying delete.
274 ~BasicInlineDequeImpl() = default;
275
276 template <size_t kCapacity>
277 using Derived = RawStorage<
279 ValueType,
280 kCapacity>;
281
282 // The underlying RawStorage is not part of the generic-sized class. It is
283 // provided in the derived class from which this instance was constructed. To
284 // access the data, down-cast this to a known max size specialization, and
285 // return the RawStorage's data, which is the same for all sizes.
286 pointer data() { return static_cast<Derived<0>*>(this)->data(); }
287 const_pointer data() const {
288 return static_cast<const Derived<0>*>(this)->data();
289 }
290
291 private:
292 friend Base;
293
294 static constexpr bool kFixedCapacity = true; // uses static allocation
295};
296
297} // namespace containers::internal
298} // namespace pw
BasicInlineDequeImpl(size_type count)
Constructs with count default-initialized elements.
Definition: inline_deque.h:103
BasicInlineDequeImpl & operator=(BasicInlineDequeImpl< ValueType, CountAndCapacityType, kOtherCapacity > &&other) noexcept
Move assigns for mismatched capacity.
Definition: inline_deque.h:193
BasicInlineDequeImpl(const BasicInlineDequeImpl< ValueType, CountAndCapacityType, kOtherCapacity > &other)
Definition: inline_deque.h:120
BasicInlineDequeImpl & operator=(BasicInlineDequeImpl &&other) noexcept
Move assigns for matching capacity.
Definition: inline_deque.h:186
BasicInlineDequeImpl & operator=(const BasicInlineDequeImpl< ValueType, CountAndCapacityType, kOtherCapacity > &other)
Definition: inline_deque.h:177
BasicInlineDequeImpl & operator=(const std::initializer_list< value_type > &list)
Copy assigns from list.
Definition: inline_deque.h:161
BasicInlineDequeImpl() noexcept
Constructs with zero elements.
Definition: inline_deque.h:90
BasicInlineDequeImpl(BasicInlineDequeImpl< ValueType, CountAndCapacityType, kOtherCapacity > &&other) noexcept
Move constructs for mismatched capacity.
Definition: inline_deque.h:133
BasicInlineDequeImpl(BasicInlineDequeImpl &&other) noexcept
Move constructs for matching capacity.
Definition: inline_deque.h:127
BasicInlineDequeImpl(const std::initializer_list< value_type > &list)
Copy constructs from an initializer list.
Definition: inline_deque.h:140
BasicInlineDequeImpl & operator=(const BasicInlineDequeImpl &other)
Copy assigns for matching capacity.
Definition: inline_deque.h:168
BasicInlineDequeImpl(const BasicInlineDequeImpl &other)
Copy constructs for matching capacity.
Definition: inline_deque.h:114
BasicInlineDequeImpl(size_type count, const_reference value)
Constructs with count copies of value.
Definition: inline_deque.h:98
BasicInlineDequeImpl(const T &other)
Copy constructor for arbitrary iterables.
Definition: inline_deque.h:146
BasicInlineDequeImpl(InputIterator start, InputIterator finish)
Copy constructs from an iterator.
Definition: inline_deque.h:109
constexpr size_type size() const noexcept
Returns the number of elements in the deque.
Definition: generic_deque.h:58
constexpr size_type capacity() const noexcept
Returns the maximum number of elements in the deque.
Definition: generic_deque.h:63
Definition: generic_deque.h:189
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:220
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
Definition: constexpr_tag.h:46