fennec
Loading...
Searching...
No Matches
deque.h
Go to the documentation of this file.
1// =====================================================================================================================
2// fennec, a free and open source game engine
3// Copyright © 2025 Medusa Slockbower
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17// =====================================================================================================================
18
30
31#ifndef FENNEC_CONTAINERS_DEQUE_H
32#define FENNEC_CONTAINERS_DEQUE_H
33
35
36// TODO: Document
37
38namespace fennec
39{
40
64template<typename TypeT, typename AllocT = allocator<TypeT>>
65struct deque {
66
67// Definitions =========================================================================================================
68public:
69 using value_t = TypeT;
70 class iterator;
71
72private:
73 struct node {
74 value_t value;
75 node *prev, *next;
76
77 template<typename...ArgsT>
78 node(node* prev, node* next, ArgsT&&...args)
79 : value(fennec::forward<ArgsT>(args)...)
80 , prev(prev), next(next) {
81 }
82
83 ~node() = default;
84 };
85
86public:
87 using alloc_t = allocator_traits<AllocT>::template rebind<node>;
88 using elem_t = node*;
89
90
91// Constructors ========================================================================================================
92
95
99 : _alloc()
100 , _first(nullptr)
101 , _last(nullptr)
102 , _size(0) {
103 }
104
108 deque(const alloc_t& alloc)
109 : _alloc(alloc)
110 , _first(nullptr)
111 , _last(nullptr)
112 , _size(0) {
113 }
114
119 : _alloc(deque._alloc)
120 , _first(nullptr)
121 , _last(nullptr)
122 , _size(0) {
123 const elem_t node = deque._first;
124 while (node) {
125 this->push_back(node->value);
126 node = node->next;
127 }
128 }
129
133 deque(deque&& deque) noexcept
134 : _alloc(deque._alloc)
135 , _first(deque._first)
136 , _last(deque._last)
137 , _size(deque._size) {
138 deque._first = nullptr;
139 deque._last = nullptr;
140 }
141
145 clear();
146 }
147
149
150// Properties ==========================================================================================================
151
154
157 constexpr bool empty() const {
158 return _size == 0;
159 }
160
163 constexpr size_t size() const {
164 return _size;
165 }
166
168
169
170// Access ==============================================================================================================
171
174
178 assert(not empty(), "Attempted to access an empty deque.");
179 return _first->value;
180 }
181
184 const value_t& front() const {
185 assert(not empty(), "Attempted to access an empty deque.");
186 return _first->value;
187 }
188
192 assert(not empty(), "Attempted to access an empty deque.");
193 return _last->value;
194 }
195
198 const value_t& back() const {
199 assert(not empty(), "Attempted to access an empty deque.");
200 return _last->value;
201 }
202
204
205
206// Modifiers ===========================================================================================================
207
210
214 void push_front(value_t&& elem) {
215 this->_push_front(elem);
216 }
217
221 void push_front(const value_t& elem) {
222 this->_push_front(elem);
223 }
224
229 template<typename...ArgsT>
230 void emplace_front(ArgsT&&...args) {
231 this->_push_front(fennec::forward<ArgsT>(args)...);
232 }
233
234
238 void push_back(value_t&& elem) {
239 this->_push_back(elem);
240 }
241
245 void push_back(const value_t& elem) {
246 this->_push_back(elem);
247 }
248
253 template<typename...ArgsT>
254 void emplace_back(ArgsT&&...args) {
255 this->_push_back(fennec::forward<ArgsT>(args)...);
256 }
257
260 void clear() {
261 elem_t it = _first;
262 while (it) {
263 elem_t next = it->next;
264 fennec::destruct(it);
265 _alloc.deallocate(it);
266 it = next;
267 }
268 _first = nullptr;
269 _last = nullptr;
270 _size = 0;
271 }
272
275 void pop_front() {
276 if (_first == nullptr) {
277 return;
278 }
279 elem_t next = _first->next;
280 fennec::destruct(_first);
281 _alloc.deallocate(_first);
282 _first = next;
283 _last = next ? _last : nullptr;
284 --_size;
285 }
286
289 void pop_back() {
290 if (_last == nullptr) {
291 return;
292 }
293 elem_t prev = _last->prev;
294 fennec::destruct(_last);
295 _alloc.deallocate(_last);
296 _last = prev;
297 _first = prev ? _first : nullptr;
298 --_size;
299 }
300
302
303
304// Iteration ===========================================================================================================
305
306 /*
307 * TODO: Decide whether you should be able to iterate over a deque
308 */
309
310private:
311 alloc_t _alloc;
312 node *_first, *_last;
313 size_t _size;
314
315 template<typename...ArgsT>
316 void _push_front(ArgsT&&...args) {
317 elem_t next = _first;
318 _first = _alloc.allocate(1);
319 fennec::construct(_first, nullptr, next, fennec::forward<ArgsT>(args)...);
320 if (next) {
321 next->prev = _first;
322 } else {
323 _last = _first;
324 }
325 ++_size;
326 }
327
328 template<typename...ArgsT>
329 void _push_back(ArgsT&&...args) {
330 elem_t prev = _last;
331 _last = _alloc.allocate(1);
332 fennec::construct(_last, prev, nullptr, fennec::forward<ArgsT>(args)...);
333 if (prev) {
334 prev->next = _last;
335 } else {
336 _first = _last;
337 }
338 ++_size;
339 }
340};
341
342
343}
344
345#endif // FENNEC_CONTAINERS_DEQUE_H
This header contains structures and classes related to allocating blocks of memory.
Data structure defining a double-ended queue.
Definition deque.h:65
void push_back(value_t &&elem)
Push Back Move, moves a value to the back of the deque.
Definition deque.h:238
constexpr bool empty() const
Definition deque.h:157
const value_t & front() const
Definition deque.h:184
void emplace_back(ArgsT &&...args)
Emplace Back, constructs a new value at the back of the deque.
Definition deque.h:254
TypeT value_t
Alias for the value type.
Definition deque.h:69
void push_front(value_t &&elem)
Push Front Move, moves a value to the front of the deque.
Definition deque.h:214
void emplace_front(ArgsT &&...args)
Emplace Front, constructs a new value at the front of the deque.
Definition deque.h:230
void pop_front()
Erase the First Element.
Definition deque.h:275
value_t & back()
Definition deque.h:191
deque()
Default Constructor, initializes an empty deque.
Definition deque.h:98
deque(const deque &deque)
Copy Constructor.
Definition deque.h:118
value_t & front()
Definition deque.h:177
const value_t & back() const
Definition deque.h:198
deque(const alloc_t &alloc)
Alloc Constructor, initializes an empty deque with the specified allocator.
Definition deque.h:108
void pop_back()
Erase the Last Element.
Definition deque.h:289
constexpr size_t size() const
Definition deque.h:163
~deque()
Destructor, calls deque::clear.
Definition deque.h:144
void push_back(const value_t &elem)
Push Back Copy, copies a value to the back of the deque.
Definition deque.h:245
deque(deque &&deque) noexcept
Deque Move Constructor.
Definition deque.h:133
void clear()
Clears the contents of the deque.
Definition deque.h:260
void push_front(const value_t &elem)
Push Front Copy, copies a value to the front of the deque.
Definition deque.h:221
constexpr T && forward(remove_reference_t< T > &x) noexcept
forwards reference types to extend their lifetime
Definition utility.h:75