Slick OrderBook 1.1.0
High-Performance C++23 OrderBook Library
Loading...
Searching...
No Matches
intrusive_list.hpp
Go to the documentation of this file.
1// Copyright 2026 Slick Quant
2// SPDX-License-Identifier: MIT
3
4#pragma once
5
7#include <cstddef>
8#include <iterator>
9#include <type_traits>
10
12
36template<typename T,
37 T* T::*NextPtr = &T::next,
38 T* T::*PrevPtr = &T::prev>
40public:
41 using value_type = T;
42 using pointer = T*;
43 using const_pointer = const T*;
44 using reference = T&;
45 using const_reference = const T&;
46 using size_type = std::size_t;
47
50 class Iterator {
51 public:
52 using iterator_category = std::bidirectional_iterator_tag;
53 using value_type = T;
54 using difference_type = std::ptrdiff_t;
55 using pointer = T*;
56 using reference = T&;
57
58 constexpr Iterator() noexcept : current_(nullptr), tail_(nullptr) {}
59 constexpr Iterator(T* node, T* tail) noexcept : current_(node), tail_(tail) {}
60
61 [[nodiscard]] constexpr reference operator*() const noexcept {
62 return *current_;
63 }
64
65 [[nodiscard]] constexpr pointer operator->() const noexcept {
66 return current_;
67 }
68
69 constexpr Iterator& operator++() noexcept {
70 current_ = current_->*NextPtr;
71 return *this;
72 }
73
74 constexpr Iterator operator++(int) noexcept {
75 Iterator tmp = *this;
76 ++(*this);
77 return tmp;
78 }
79
80 constexpr Iterator& operator--() noexcept {
81 // Handle decrement from end() (nullptr)
82 if (current_ == nullptr) {
83 current_ = tail_;
84 } else {
85 current_ = current_->*PrevPtr;
86 }
87 return *this;
88 }
89
90 constexpr Iterator operator--(int) noexcept {
91 Iterator tmp = *this;
92 --(*this);
93 return tmp;
94 }
95
96 [[nodiscard]] constexpr bool operator==(const Iterator& other) const noexcept {
97 return current_ == other.current_;
98 }
99
100 [[nodiscard]] constexpr bool operator!=(const Iterator& other) const noexcept {
101 return !(*this == other);
102 }
103
104 // Allow ConstIterator to access private members
105 friend class ConstIterator;
106
107 private:
108 T* current_;
109 T* tail_; // Needed to handle decrement from end() (nullptr)
110 };
111
114 public:
115 using iterator_category = std::bidirectional_iterator_tag;
116 using value_type = T;
117 using difference_type = std::ptrdiff_t;
118 using pointer = const T*;
119 using reference = const T&;
120
121 constexpr ConstIterator() noexcept : current_(nullptr), tail_(nullptr) {}
122 constexpr ConstIterator(const T* node, const T* tail) noexcept : current_(node), tail_(tail) {}
123 constexpr ConstIterator(Iterator it) noexcept : current_(it.current_), tail_(it.tail_) {}
124
125 [[nodiscard]] constexpr reference operator*() const noexcept {
126 return *current_;
127 }
128
129 [[nodiscard]] constexpr pointer operator->() const noexcept {
130 return current_;
131 }
132
133 constexpr ConstIterator& operator++() noexcept {
134 current_ = current_->*NextPtr;
135 return *this;
136 }
137
138 constexpr ConstIterator operator++(int) noexcept {
139 ConstIterator tmp = *this;
140 ++(*this);
141 return tmp;
142 }
143
144 constexpr ConstIterator& operator--() noexcept {
145 // Handle decrement from end() (nullptr)
146 if (current_ == nullptr) {
147 current_ = tail_;
148 } else {
149 current_ = current_->*PrevPtr;
150 }
151 return *this;
152 }
153
154 constexpr ConstIterator operator--(int) noexcept {
155 ConstIterator tmp = *this;
156 --(*this);
157 return tmp;
158 }
159
160 [[nodiscard]] constexpr bool operator==(const ConstIterator& other) const noexcept {
161 return current_ == other.current_;
162 }
163
164 [[nodiscard]] constexpr bool operator!=(const ConstIterator& other) const noexcept {
165 return !(*this == other);
166 }
167
168 private:
169 const T* current_;
170 const T* tail_; // Needed to handle decrement from end() (nullptr)
171 };
172
177 public:
178 using iterator_category = std::bidirectional_iterator_tag;
179 using value_type = T;
180 using difference_type = std::ptrdiff_t;
181 using pointer = T*;
182 using reference = T&;
183
184 constexpr ReverseIterator() noexcept : current_(nullptr), head_(nullptr) {}
185 constexpr ReverseIterator(T* node, T* head) noexcept : current_(node), head_(head) {}
186
187 [[nodiscard]] constexpr reference operator*() const noexcept {
188 return *current_;
189 }
190
191 [[nodiscard]] constexpr pointer operator->() const noexcept {
192 return current_;
193 }
194
195 constexpr ReverseIterator& operator++() noexcept {
196 current_ = current_->*PrevPtr; // Move backward through list
197 return *this;
198 }
199
200 constexpr ReverseIterator operator++(int) noexcept {
201 ReverseIterator tmp = *this;
202 ++(*this);
203 return tmp;
204 }
205
206 constexpr ReverseIterator& operator--() noexcept {
207 // Handle decrement from rend() (nullptr)
208 if (current_ == nullptr) {
209 current_ = head_;
210 } else {
211 current_ = current_->*NextPtr; // Move forward through list
212 }
213 return *this;
214 }
215
216 constexpr ReverseIterator operator--(int) noexcept {
217 ReverseIterator tmp = *this;
218 --(*this);
219 return tmp;
220 }
221
222 [[nodiscard]] constexpr bool operator==(const ReverseIterator& other) const noexcept {
223 return current_ == other.current_;
224 }
225
226 [[nodiscard]] constexpr bool operator!=(const ReverseIterator& other) const noexcept {
227 return !(*this == other);
228 }
229
230 // Allow ConstReverseIterator to access private members
232
233 private:
234 T* current_;
235 T* head_; // Needed to handle decrement from rend() (nullptr)
236 };
237
240 public:
241 using iterator_category = std::bidirectional_iterator_tag;
242 using value_type = T;
243 using difference_type = std::ptrdiff_t;
244 using pointer = const T*;
245 using reference = const T&;
246
247 constexpr ConstReverseIterator() noexcept : current_(nullptr), head_(nullptr) {}
248 constexpr ConstReverseIterator(const T* node, const T* head) noexcept : current_(node), head_(head) {}
249 constexpr ConstReverseIterator(ReverseIterator it) noexcept : current_(it.current_), head_(it.head_) {}
250
251 [[nodiscard]] constexpr reference operator*() const noexcept {
252 return *current_;
253 }
254
255 [[nodiscard]] constexpr pointer operator->() const noexcept {
256 return current_;
257 }
258
259 constexpr ConstReverseIterator& operator++() noexcept {
260 current_ = current_->*PrevPtr;
261 return *this;
262 }
263
264 constexpr ConstReverseIterator operator++(int) noexcept {
265 ConstReverseIterator tmp = *this;
266 ++(*this);
267 return tmp;
268 }
269
270 constexpr ConstReverseIterator& operator--() noexcept {
271 // Handle decrement from rend() (nullptr)
272 if (current_ == nullptr) {
273 current_ = head_;
274 } else {
275 current_ = current_->*NextPtr;
276 }
277 return *this;
278 }
279
280 constexpr ConstReverseIterator operator--(int) noexcept {
281 ConstReverseIterator tmp = *this;
282 --(*this);
283 return tmp;
284 }
285
286 [[nodiscard]] constexpr bool operator==(const ConstReverseIterator& other) const noexcept {
287 return current_ == other.current_;
288 }
289
290 [[nodiscard]] constexpr bool operator!=(const ConstReverseIterator& other) const noexcept {
291 return !(*this == other);
292 }
293
294 private:
295 const T* current_;
296 const T* head_; // Needed to handle decrement from rend() (nullptr)
297 };
298
303
305 constexpr IntrusiveList() noexcept : head_(nullptr), tail_(nullptr), size_(0) {}
306
308 ~IntrusiveList() noexcept = default;
309
310 // Non-copyable (elements can only be in one list)
311 IntrusiveList(const IntrusiveList&) = delete;
312 IntrusiveList& operator=(const IntrusiveList&) = delete;
313
314 // Movable
315 constexpr IntrusiveList(IntrusiveList&& other) noexcept
316 : head_(other.head_), tail_(other.tail_), size_(other.size_) {
317 other.head_ = nullptr;
318 other.tail_ = nullptr;
319 other.size_ = 0;
320 }
321
322 constexpr IntrusiveList& operator=(IntrusiveList&& other) noexcept {
323 if (this != &other) {
324 head_ = other.head_;
325 tail_ = other.tail_;
326 size_ = other.size_;
327 other.head_ = nullptr;
328 other.tail_ = nullptr;
329 other.size_ = 0;
330 }
331 return *this;
332 }
333
335 [[nodiscard]] constexpr bool empty() const noexcept {
336 return size_ == 0;
337 }
338
340 [[nodiscard]] constexpr size_type size() const noexcept {
341 return size_;
342 }
343
345 [[nodiscard]] constexpr pointer front() noexcept {
346 return head_;
347 }
348
349 [[nodiscard]] constexpr const_pointer front() const noexcept {
350 return head_;
351 }
352
354 [[nodiscard]] constexpr pointer back() noexcept {
355 return tail_;
356 }
357
358 [[nodiscard]] constexpr const_pointer back() const noexcept {
359 return tail_;
360 }
361
363 constexpr void push_front(T* node) noexcept {
364 node->*PrevPtr = nullptr;
365 node->*NextPtr = head_;
366
367 if (head_ != nullptr) {
368 head_->*PrevPtr = node;
369 } else {
370 tail_ = node;
371 }
372
373 head_ = node;
374 ++size_;
375 }
376
378 constexpr void push_back(T* node) noexcept {
379 node->*NextPtr = nullptr;
380 node->*PrevPtr = tail_;
381
382 if (tail_ != nullptr) {
383 tail_->*NextPtr = node;
384 } else {
385 head_ = node;
386 }
387
388 tail_ = node;
389 ++size_;
390 }
391
393 constexpr pointer pop_front() noexcept {
394 if (empty()) {
395 return nullptr;
396 }
397
398 T* node = head_;
399 head_ = head_->*NextPtr;
400
401 if (head_ != nullptr) {
402 head_->*PrevPtr = nullptr;
403 } else {
404 tail_ = nullptr;
405 }
406
407 node->*NextPtr = nullptr;
408 node->*PrevPtr = nullptr;
409 --size_;
410
411 return node;
412 }
413
415 constexpr pointer pop_back() noexcept {
416 if (empty()) {
417 return nullptr;
418 }
419
420 T* node = tail_;
421 tail_ = tail_->*PrevPtr;
422
423 if (tail_ != nullptr) {
424 tail_->*NextPtr = nullptr;
425 } else {
426 head_ = nullptr;
427 }
428
429 node->*NextPtr = nullptr;
430 node->*PrevPtr = nullptr;
431 --size_;
432
433 return node;
434 }
435
438 constexpr void erase(T* node) noexcept {
439 if (node == nullptr) {
440 return;
441 }
442
443 T* prev = node->*PrevPtr;
444 T* next = node->*NextPtr;
445
446 if (prev != nullptr) {
447 prev->*NextPtr = next;
448 } else {
449 head_ = next;
450 }
451
452 if (next != nullptr) {
453 next->*PrevPtr = prev;
454 } else {
455 tail_ = prev;
456 }
457
458 node->*NextPtr = nullptr;
459 node->*PrevPtr = nullptr;
460 --size_;
461 }
462
465 constexpr void insert_before(T* pos, T* node) noexcept {
466 if (pos == nullptr) {
467 push_back(node);
468 return;
469 }
470
471 if (pos == head_) {
472 push_front(node);
473 return;
474 }
475
476 T* prev = pos->*PrevPtr;
477
478 node->*PrevPtr = prev;
479 node->*NextPtr = pos;
480
481 if (prev != nullptr) {
482 prev->*NextPtr = node;
483 }
484
485 pos->*PrevPtr = node;
486 ++size_;
487 }
488
491 constexpr void insert_after(T* pos, T* node) noexcept {
492 if (pos == nullptr) {
493 push_front(node);
494 return;
495 }
496
497 if (pos == tail_) {
498 push_back(node);
499 return;
500 }
501
502 T* next = pos->*NextPtr;
503
504 node->*PrevPtr = pos;
505 node->*NextPtr = next;
506
507 if (next != nullptr) {
508 next->*PrevPtr = node;
509 }
510
511 pos->*NextPtr = node;
512 ++size_;
513 }
514
516 constexpr void clear() noexcept {
517 // Unlink all elements
518 T* current = head_;
519 while (current != nullptr) {
520 T* next = current->*NextPtr;
521 current->*NextPtr = nullptr;
522 current->*PrevPtr = nullptr;
523 current = next;
524 }
525
526 head_ = nullptr;
527 tail_ = nullptr;
528 size_ = 0;
529 }
530
532 [[nodiscard]] constexpr iterator begin() noexcept {
533 return iterator(head_, tail_);
534 }
535
536 [[nodiscard]] constexpr const_iterator begin() const noexcept {
537 return const_iterator(head_, tail_);
538 }
539
540 [[nodiscard]] constexpr const_iterator cbegin() const noexcept {
541 return const_iterator(head_, tail_);
542 }
543
544 [[nodiscard]] constexpr iterator end() noexcept {
545 return iterator(nullptr, tail_);
546 }
547
548 [[nodiscard]] constexpr const_iterator end() const noexcept {
549 return const_iterator(nullptr, tail_);
550 }
551
552 [[nodiscard]] constexpr const_iterator cend() const noexcept {
553 return const_iterator(nullptr, tail_);
554 }
555
557 [[nodiscard]] constexpr reverse_iterator rbegin() noexcept {
558 return reverse_iterator(tail_, head_);
559 }
560
561 [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept {
562 return const_reverse_iterator(tail_, head_);
563 }
564
565 [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept {
566 return const_reverse_iterator(tail_, head_);
567 }
568
569 [[nodiscard]] constexpr reverse_iterator rend() noexcept {
570 return reverse_iterator(nullptr, head_);
571 }
572
573 [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept {
574 return const_reverse_iterator(nullptr, head_);
575 }
576
577 [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept {
578 return const_reverse_iterator(nullptr, head_);
579 }
580
581private:
582 T* head_;
583 T* tail_;
584 size_type size_;
585};
586
constexpr bool operator!=(const ConstIterator &other) const noexcept
constexpr bool operator==(const ConstIterator &other) const noexcept
constexpr ConstIterator operator++(int) noexcept
constexpr ConstIterator operator--(int) noexcept
constexpr ConstIterator(const T *node, const T *tail) noexcept
constexpr ConstReverseIterator & operator++() noexcept
constexpr ConstReverseIterator & operator--() noexcept
constexpr ConstReverseIterator(ReverseIterator it) noexcept
constexpr ConstReverseIterator operator++(int) noexcept
constexpr ConstReverseIterator operator--(int) noexcept
constexpr bool operator!=(const ConstReverseIterator &other) const noexcept
constexpr bool operator==(const ConstReverseIterator &other) const noexcept
constexpr ConstReverseIterator(const T *node, const T *head) noexcept
Forward iterator for intrusive list We store a pointer to the list's tail to handle decrement from en...
constexpr bool operator!=(const Iterator &other) const noexcept
std::bidirectional_iterator_tag iterator_category
constexpr pointer operator->() const noexcept
constexpr Iterator(T *node, T *tail) noexcept
constexpr bool operator==(const Iterator &other) const noexcept
constexpr reference operator*() const noexcept
Reverse iterator for intrusive list Cannot use std::reverse_iterator because end() (nullptr) cannot b...
constexpr ReverseIterator operator--(int) noexcept
constexpr ReverseIterator operator++(int) noexcept
constexpr bool operator!=(const ReverseIterator &other) const noexcept
constexpr ReverseIterator & operator++() noexcept
constexpr bool operator==(const ReverseIterator &other) const noexcept
constexpr ReverseIterator & operator--() noexcept
Intrusive doubly-linked list for zero-allocation order management.
constexpr const_reverse_iterator rend() const noexcept
constexpr const_reverse_iterator crend() const noexcept
constexpr void insert_after(T *pos, T *node) noexcept
Insert element after given position O(1) operation.
constexpr pointer front() noexcept
Get front element.
constexpr void clear() noexcept
Clear list (does not delete elements)
constexpr pointer pop_back() noexcept
Remove back element.
constexpr IntrusiveList & operator=(IntrusiveList &&other) noexcept
constexpr const_pointer front() const noexcept
constexpr void push_front(T *node) noexcept
Add element to front (newest order, used for LIFO if needed)
constexpr iterator end() noexcept
constexpr void erase(T *node) noexcept
Remove specific element from list O(1) operation - no search required.
~IntrusiveList() noexcept=default
Destructor - does not delete elements (intrusive design)
constexpr const_iterator cbegin() const noexcept
constexpr const_iterator end() const noexcept
constexpr reverse_iterator rbegin() noexcept
Reverse iterators.
constexpr const_reverse_iterator rbegin() const noexcept
constexpr const_iterator begin() const noexcept
constexpr size_type size() const noexcept
Get number of elements.
constexpr const_reverse_iterator crbegin() const noexcept
constexpr pointer pop_front() noexcept
Remove front element.
constexpr bool empty() const noexcept
Check if list is empty.
constexpr iterator begin() noexcept
Iterators.
constexpr reverse_iterator rend() noexcept
constexpr void push_back(T *node) noexcept
Add element to back (oldest order, FIFO time priority)
constexpr void insert_before(T *pos, T *node) noexcept
Insert element before given position O(1) operation.
constexpr const_iterator cend() const noexcept
constexpr pointer back() noexcept
Get back element.
constexpr const_pointer back() const noexcept
constexpr IntrusiveList() noexcept
Constructor.
#define SLICK_DETAIL_NAMESPACE_BEGIN
Definition config.hpp:129
#define SLICK_DETAIL_NAMESPACE_END
Definition config.hpp:130