C/C++ API Reference
Loading...
Searching...
No Matches
inline_queue.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 <initializer_list>
17#include <utility>
18
19#include "pw_containers/inline_deque.h"
20#include "pw_containers/internal/generic_queue.h"
21
22namespace pw {
23namespace containers::internal {
24
25template <typename Derived, typename Deque>
26class BasicInlineQueueImpl;
27
28} // namespace containers::internal
29
31
34
35template <typename T, typename SizeType, size_t kCapacity>
36class BasicInlineQueue;
37
46template <typename T, size_t kCapacity = containers::internal::kGenericSized>
48
49template <typename ValueType,
50 typename SizeType,
51 size_t kCapacity = containers::internal::kGenericSized>
53 : public BasicInlineQueue<ValueType,
54 SizeType,
55 containers::internal::kGenericSized> {
56 private:
57 using Base = BasicInlineQueue<ValueType,
58 SizeType,
59 containers::internal::kGenericSized>;
60
61 public:
62 using typename Base::const_iterator;
63 using typename Base::const_pointer;
64 using typename Base::const_reference;
65 using typename Base::difference_type;
66 using typename Base::iterator;
67 using typename Base::pointer;
68 using typename Base::reference;
69 using typename Base::size_type;
70 using typename Base::value_type;
71
72 // Constructors
73
74 BasicInlineQueue() noexcept {}
75
76 // Explicit zero element constexpr constructor. Using this constructor will
77 // place the entire object in .data, which will increase ROM size. Use with
78 // caution if working with large capacity sizes.
79 constexpr BasicInlineQueue(ConstexprTag constexpr_tag) noexcept
80 : deque_(constexpr_tag) {}
81
82 BasicInlineQueue(size_type count, const_reference value)
83 : deque_(count, value) {}
84
85 explicit BasicInlineQueue(size_type count) : deque_(count) {}
86
87 template <
88 typename InputIterator,
89 typename = containers::internal::EnableIfInputIterator<InputIterator>>
90 BasicInlineQueue(InputIterator start, InputIterator finish)
91 : deque_(start, finish) {}
92
93 BasicInlineQueue(const std::initializer_list<value_type>& list)
94 : deque_(list) {}
95
97 BasicInlineQueue(const BasicInlineQueue& other) : deque_(other) {}
98
102 template <size_t kOtherCapacity>
105 *this = other;
106 }
107
110 : deque_(std::move(other.deque_)) {}
111
115 template <size_t kOtherCapacity>
118 *this = std::move(other);
119 }
120
121 template <typename T, typename = containers::internal::EnableIfIterable<T>>
122 BasicInlineQueue(const T& other) : deque_(other.begin(), other.end()) {}
123
124 BasicInlineQueue& operator=(const std::initializer_list<value_type>& list) {
125 deque_ = std::move(list);
126 return *this;
127 }
128
131 deque_ = other.deque_;
132 return *this;
133 }
134
138 template <size_t kOtherCapacity>
141 deque_ = other.deque_;
142 return *this;
143 }
144
147 deque_ = std::move(other.deque_);
148 return *this;
149 }
150
154 template <size_t kOtherCapacity>
157 deque_ = std::move(other.deque_);
158 return *this;
159 }
160
161 template <typename T, typename = containers::internal::EnableIfIterable<T>>
162 BasicInlineQueue& operator=(const T& other) {
164 other.end());
165 return *this;
166 }
167
168 // Size
169
170 static constexpr size_type max_size() { return capacity(); }
171 static constexpr size_type capacity() { return kCapacity; }
172
173 private:
174 template <typename OtherValueType, typename OtherSizeType, size_t kOtherSized>
175 friend class BasicInlineQueue;
176
177 template <typename, typename>
178 friend class containers::internal::BasicInlineQueueImpl;
179
180 // The deque() function is defined differently for the generic-sized and
181 // known-sized specializations. This deque() implementation simply returns the
182 // generic-sized deque_. The generic-sized deque() function casts *this to a
183 // known zero-sized specialzation to access this exact function.
184 BasicInlineDeque<ValueType, SizeType>& deque() { return deque_; }
185 const BasicInlineDeque<ValueType, SizeType>& deque() const { return deque_; }
186
187 BasicInlineDeque<ValueType, SizeType, kCapacity> deque_;
188};
189
190// Defines the generic-sized BasicInlineDeque<T> specialization, which
191// serves as the base class for BasicInlineDeque<T> of any capacity.
192//
193// Except for constructors, all other methods should be implemented on this
194// generic-sized specialization.
195template <typename ValueType, typename SizeType>
196class BasicInlineQueue<ValueType, SizeType, containers::internal::kGenericSized>
198 BasicInlineQueue<ValueType,
199 SizeType,
200 containers::internal::kGenericSized>,
201 BasicInlineDeque<ValueType, SizeType>> {
202 private:
205 BasicInlineQueue<ValueType,
206 SizeType,
207 containers::internal::kGenericSized>,
208 Deque>;
209
210 public:
211 using typename Base::const_iterator;
212 using typename Base::const_pointer;
213 using typename Base::const_reference;
214 using typename Base::difference_type;
215 using typename Base::iterator;
216 using typename Base::pointer;
217 using typename Base::reference;
218 using typename Base::size_type;
219 using typename Base::value_type;
220
221 protected:
222 constexpr BasicInlineQueue() noexcept = default;
223
224 // Polymorphic-sized `pw::InlineQueue<T>` may not be used with `unique_ptr`
225 // or `delete`. `delete` could be supported using C++20's destroying delete.
226 ~BasicInlineQueue() = default;
227
228 protected:
229 template <typename, typename>
230 friend class containers::internal::GenericQueue;
231
232 template <size_t kCapacity>
234
235 // The underlying BasicInlineDeque is not part of the generic-sized class. It
236 // is provided in the derived class from which this instance was constructed.
237 // To access the data, down-cast this to a known max size specialization, and
238 // return a reference to a generic-sized BasicInlineDeque, which is the same
239 // reference for all sizes.
240 Deque& deque() { return static_cast<Derived<0>*>(this)->deque(); }
241 const Deque& deque() const {
242 return static_cast<const Derived<0>*>(this)->deque();
243 }
244};
245
247
248namespace containers::internal {
249
250template <typename Derived, typename Deque>
251class BasicInlineQueueImpl : public GenericQueue<Derived, Deque> {
252 private:
253 using Base = GenericQueue<Derived, Deque>;
254
255 public:
256 using typename Base::const_iterator;
257 using typename Base::const_pointer;
258 using typename Base::const_reference;
259 using typename Base::difference_type;
260 using typename Base::iterator;
261 using typename Base::pointer;
262 using typename Base::reference;
263 using typename Base::size_type;
264 using typename Base::value_type;
265
266 // Access
267
268 reference at(size_type index) { return deque().at(index); }
269 const_reference at(size_type index) const { return deque().at(index); }
270
271 reference operator[](size_type index) { return deque()[index]; }
272 const_reference operator[](size_type index) const { return deque()[index]; }
273
274 std::pair<span<const value_type>, span<const value_type>> contiguous_data()
275 const {
276 return deque().contiguous_data();
277 }
278 std::pair<span<value_type>, span<value_type>> contiguous_data() {
279 return deque().contiguous_data();
280 }
281
282 // Iterate
283
284 iterator begin() noexcept { return deque().begin(); }
285 const_iterator begin() const noexcept { return cbegin(); }
286 const_iterator cbegin() const noexcept { return deque().cbegin(); }
287
288 iterator end() noexcept { return deque().end(); }
289 const_iterator end() const noexcept { return cend(); }
290 const_iterator cend() const noexcept { return deque().cend(); }
291
292 // Size
293
294 [[nodiscard]] bool full() const noexcept { return deque().full(); }
295
296 // Modify
297
298 void clear() noexcept { deque().clear(); }
299
300 void push_overwrite(const value_type& value) { emplace_overwrite(value); }
301
302 void push_overwrite(value_type&& value) {
303 emplace_overwrite(std::move(value));
304 }
305
306 template <typename... Args>
307 void emplace_overwrite(Args&&... args) {
308 if (full()) {
309 Base::pop();
310 }
311 Base::emplace(std::forward<Args>(args)...);
312 }
313
314 private:
315 using Base::deque;
316};
317
318} // namespace containers::internal
319} // namespace pw
Definition: inline_queue.h:55
Definition: span_impl.h:235
BasicInlineQueue & operator=(BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &&other)
Definition: inline_queue.h:155
BasicInlineQueue & operator=(const BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &other)
Definition: inline_queue.h:139
BasicInlineQueue & operator=(BasicInlineQueue &&other)
Move assigns from matching capacity.
Definition: inline_queue.h:146
BasicInlineQueue & operator=(const BasicInlineQueue &other)
Copy assigns from matching capacity.
Definition: inline_queue.h:130
BasicInlineQueue(BasicInlineQueue &&other)
Move constructs for matching capacity.
Definition: inline_queue.h:109
BasicInlineQueue(BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &&other)
Definition: inline_queue.h:116
BasicInlineQueue(const BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &other)
Definition: inline_queue.h:103
BasicInlineQueue(const BasicInlineQueue &other)
Copy constructs for matching capacity.
Definition: inline_queue.h:97
The Pigweed namespace.
Definition: alignment.h:27
Definition: constexpr_tag.h:48