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/generic_deque.h"
25#include "pw_containers/internal/raw_storage.h"
26#include "pw_toolchain/constexpr_tag.h"
27
28namespace pw {
29namespace containers::internal {
30
31// Forward declarations.
32template <typename T, typename SizeType, size_t kCapacity>
33class BasicInlineDequeImpl;
34
35} // namespace containers::internal
36
38
39template <typename ValueType,
40 typename SizeType,
41 size_t kCapacity = containers::internal::kGenericSized>
42using BasicInlineDeque =
43 containers::internal::BasicInlineDequeImpl<ValueType, SizeType, kCapacity>;
44
62template <typename T, size_t kCapacity = containers::internal::kGenericSized>
64
66
67namespace containers::internal {
68
69template <typename ValueType, typename SizeType, size_t kCapacity>
71 : public RawStorage<
72 BasicInlineDequeImpl<ValueType, SizeType, kGenericSized>,
73 ValueType,
74 kCapacity> {
75 private:
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
90 BasicInlineDequeImpl() noexcept = default;
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>
122 *this = other;
123 }
124
127 *this = std::move(other);
128 }
129
131 template <size_t kOtherCapacity>
134 other) noexcept {
135 *this = std::move(other);
136 }
137
139 BasicInlineDequeImpl(const std::initializer_list<value_type>& list) {
140 *this = list;
141 }
142
144 template <typename T, typename = EnableIfIterable<T>>
145 BasicInlineDequeImpl(const T& other) {
146 *this = other;
147 }
148
149 // Assignment operators
150 //
151 // These operators delegate to the base class implementations in order to
152 // maximize code reuse. The wrappers are required so that `operator=`
153 // returns the correct type of reference.
154 //
155 // The `static_cast`s below are unfortunately necessary: without them,
156 // overload resolution prefers to use the "iterable" operators rather than
157 // upcast the RHS.
158
161 const std::initializer_list<value_type>& list) {
162 Base::operator=(list);
163 return *this;
164 }
165
168 Base::operator=(static_cast<const Base&>(other));
169 return *this;
170 }
171
175 template <size_t kOtherCapacity>
178 Base::operator=(static_cast<const Base&>(other));
179 return *this;
180 }
181
184 Base::operator=(static_cast<Base&&>(std::move(other)));
185 return *this;
186 }
187
189 template <size_t kOtherCapacity>
192 other) noexcept {
193 Base::operator=(static_cast<Base&&>(std::move(other)));
194 return *this;
195 }
196
197 template <typename T, typename = EnableIfIterable<T>>
198 BasicInlineDequeImpl& operator=(const T& other) {
199 Base::operator=(other);
200 return *this;
201 }
202
203 // Size
204
205 static constexpr size_type max_size() { return capacity(); }
206 static constexpr size_type capacity() { return kCapacity; }
207};
208
209// Defines the generic-sized BasicInlineDequeImpl<T> specialization, which
210// serves as the base class for BasicInlineDequeImpl<T> of any capacity.
211//
212// Except for constructors and destructors, all other methods should be
213// implemented on this generic-sized specialization.
214//
215// NOTE: this size-polymorphic base class must not be used inside of
216// ``std::unique_ptr`` or ``delete``.
217template <typename ValueType, typename SizeType>
218class BasicInlineDequeImpl<ValueType, SizeType, kGenericSized>
219 : public GenericDeque<
220 BasicInlineDequeImpl<ValueType, SizeType, kGenericSized>,
221 ValueType,
222 SizeType> {
223 private:
224 using Base =
226 ValueType,
227 SizeType>;
228
229 public:
230 using typename Base::const_iterator;
231 using typename Base::const_pointer;
232 using typename Base::const_reference;
233 using typename Base::difference_type;
234 using typename Base::iterator;
235 using typename Base::pointer;
236 using typename Base::reference;
237 using typename Base::size_type;
238 using typename Base::value_type;
239
240 // Polymorphic-sized `pw::InlineDeque<T>` may not be constructed directly.
241 BasicInlineDequeImpl() = delete;
242
244 Base::assign(other.begin(), other.end());
245 return *this;
246 }
247
249 Base::clear();
250 for (auto&& item : other) {
251 Base::emplace_back(std::move(item));
252 }
253 other.clear();
254 return *this;
255 }
256
257 using Base::operator=;
258
259 size_type max_size() const noexcept { return Base::capacity(); }
260
261 protected:
262 constexpr BasicInlineDequeImpl(size_type capacity) noexcept
263 : Base(capacity) {}
264
265 // Polymorphic-sized `pw::InlineDeque<T>` may not be used with `unique_ptr`
266 // or `delete`. `delete` could be supported using C++20's destroying delete.
267 ~BasicInlineDequeImpl() = default;
268
269 template <size_t kCapacity>
270 using Derived =
271 RawStorage<BasicInlineDequeImpl<ValueType, SizeType, kGenericSized>,
272 ValueType,
273 kCapacity>;
274
275 // The underlying RawStorage is not part of the generic-sized class. It is
276 // provided in the derived class from which this instance was constructed. To
277 // access the data, down-cast this to a known max size specialization, and
278 // return the RawStorage's data, which is the same for all sizes.
279 pointer data() { return static_cast<Derived<0>*>(this)->data(); }
280 const_pointer data() const {
281 return static_cast<const Derived<0>*>(this)->data();
282 }
283
284 private:
285 friend Base;
286
287 static constexpr bool kFixedCapacity = true; // uses static allocation
288};
289
290} // namespace containers::internal
291} // namespace pw
BasicInlineDequeImpl(const BasicInlineDequeImpl &other)
Copy constructs for matching capacity.
Definition: inline_deque.h:114
BasicInlineDequeImpl(size_type count)
Constructs with count default-initialized elements.
Definition: inline_deque.h:103
BasicInlineDequeImpl & operator=(BasicInlineDequeImpl< ValueType, SizeType, kOtherCapacity > &&other) noexcept
Move assigns for mismatched capacity.
Definition: inline_deque.h:190
BasicInlineDequeImpl() noexcept=default
Constructs with zero elements.
BasicInlineDequeImpl & operator=(const std::initializer_list< value_type > &list)
Copy assigns from list.
Definition: inline_deque.h:160
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:145
BasicInlineDequeImpl(const BasicInlineDequeImpl< ValueType, SizeType, kOtherCapacity > &other)
Definition: inline_deque.h:120
BasicInlineDequeImpl(BasicInlineDequeImpl &&other) noexcept
Move constructs for matching capacity.
Definition: inline_deque.h:126
BasicInlineDequeImpl & operator=(const BasicInlineDequeImpl &other)
Copy assigns for matching capacity.
Definition: inline_deque.h:167
BasicInlineDequeImpl(InputIterator start, InputIterator finish)
Copy constructs from an iterator.
Definition: inline_deque.h:109
BasicInlineDequeImpl & operator=(BasicInlineDequeImpl &&other) noexcept
Move assigns for matching capacity.
Definition: inline_deque.h:183
BasicInlineDequeImpl(const std::initializer_list< value_type > &list)
Copy constructs from an initializer list.
Definition: inline_deque.h:139
BasicInlineDequeImpl(BasicInlineDequeImpl< ValueType, SizeType, kOtherCapacity > &&other) noexcept
Move constructs for mismatched capacity.
Definition: inline_deque.h:132
BasicInlineDequeImpl & operator=(const BasicInlineDequeImpl< ValueType, SizeType, kOtherCapacity > &other)
Definition: inline_deque.h:176
Definition: generic_deque.h:178
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:209
constexpr size_type capacity() const noexcept
Returns the maximum number of elements in the deque.
Definition: generic_deque.h:72
The Pigweed namespace.
Definition: alignment.h:27
Definition: constexpr_tag.h:48