Zth (libzth)
Loading...
Searching...
No Matches
list.h
Go to the documentation of this file.
1#ifndef ZTH_LIST_H
2#define ZTH_LIST_H
3/*
4 * SPDX-FileCopyrightText: 2019-2026 Jochem Rutgers
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 */
8
9#include <libzth/macros.h>
10
11#ifdef __cplusplus
12
13# include <libzth/allocator.h>
14# include <libzth/config.h>
15# include <libzth/util.h>
16
17# include <functional>
18
19namespace zth {
20
21class Listable;
22
23template <typename T>
24class List;
25
26template <typename T = Listable, typename Compare = std::less<T> >
27class SortedList;
28
29class Listable {
30public:
31 typedef void* user_type;
32
33 constexpr Listable() noexcept
34 : prev()
35 , next()
36 , user()
37 {}
38
39 constexpr Listable(Listable const& UNUSED_PAR(e)) noexcept
40 : prev()
41 , next()
42 , user()
43 {}
44
45 Listable& operator=(Listable const& UNUSED_PAR(rhs)) noexcept
46 {
48 prev = next = nullptr;
49 return *this;
50 }
51
52# if __cplusplus >= 201103L
53 Listable(Listable&& l) noexcept
54 {
55 *this = std::move(l);
56 }
57
59 {
60 // Cannot move while in a list.
62 zth_assert(!l.prev);
64 zth_assert(!l.next);
65 return *this;
66 }
67# endif // C++11
68
69private:
70 union {
71 Listable* prev; // for List
72 Listable* left; // for SortedList
73 };
74 union {
75 Listable* next; // for List
76 Listable* right; // for SortedList
77 };
78 union {
79 user_type user; // For List
80 uint_fast8_t level; // for SortedList
81 };
82
83 template <typename T>
84 friend class List;
85 template <typename T, typename Compare>
86 friend class SortedList;
87};
88
89template <typename T = Listable>
90class List {
93public:
94 typedef T type;
97
98 template <bool cyclic>
99 class Iterator {
100 public:
101 constexpr explicit Iterator(elem_type* start, elem_type* current = nullptr) noexcept
102 : m_start(start)
103 , m_current(current)
104 {}
105
106 bool atBegin() const noexcept
107 {
108 return !m_current && m_start;
109 }
110
111 bool atEnd() const noexcept
112 {
113 return m_current == m_start;
114 }
115
116 elem_type* get() const noexcept
117 {
118 zth_assert(cyclic || !atEnd());
119 return unlikely(atBegin()) ? m_start : m_current;
120 }
121
122 template <bool C>
123 bool operator==(Iterator<C> const& rhs) const noexcept
124 {
125 if(atEnd())
126 return rhs.atEnd();
127 if(rhs.atEnd())
128 return false;
129 return get() == rhs.get();
130 }
131
132 template <bool C>
133 bool operator!=(Iterator<C> const& rhs) const noexcept
134 {
135 return !(*this == rhs);
136 }
137
138 void next() noexcept
139 {
140 zth_assert((cyclic || !atEnd()) && m_start);
141 // NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
142 m_current = unlikely(atBegin()) ? m_start->next : m_current->next;
143 }
144
145 void prev() noexcept
146 {
147 zth_assert((cyclic || !atEnd()) && m_start);
148 m_current =
149 unlikely(m_current->prev == m_start) ? nullptr : m_current->prev;
150 }
151
153 {
154 next();
155 return *this;
156 }
157
158 Iterator operator++(int) noexcept
159 {
160 Iterator i = *this;
161 next();
162 return i;
163 }
164
166 {
167 prev();
168 return *this;
169 }
170
171 Iterator operator--(int) noexcept
172 {
173 Iterator i = *this;
174 prev();
175 return i;
176 }
177
178 type& operator*() const noexcept
179 {
180 elem_type* elem = get();
181 zth_assert(elem);
182 // cppcheck-suppress nullPointerRedundantCheck
183 return *static_cast<type*>(elem);
184 }
185
186 type* operator->() const noexcept
187 {
188 return &this->operator*();
189 }
190
191 user_type const& user() const noexcept
192 {
193 elem_type const* elem = get();
194 zth_assert(elem);
195 // cppcheck-suppress nullPointerRedundantCheck
196 return elem->user;
197 }
198
199 user_type& user() noexcept
200 {
201 elem_type* elem = get();
202 zth_assert(elem);
203 // cppcheck-suppress nullPointerRedundantCheck
204 return elem->user;
205 }
206
207 private:
208 elem_type* m_start;
209 elem_type* m_current;
210 };
211
214
215 constexpr List() noexcept
216 : m_head()
217 , m_tail()
218 {}
219
220 ~List() noexcept
221 {
223 clear();
224 }
225
226 type& back() const noexcept
227 {
228 zth_assert(!empty());
229 return *static_cast<type*>(m_tail);
230 }
231
232 user_type const& user_back() const noexcept
233 {
234 zth_assert(!empty());
235 return m_tail->user;
236 }
237
239 {
240 zth_assert(!empty());
241 return m_tail->user;
242 }
243
245 {
246 zth_assert(elem.prev == nullptr);
247 zth_assert(elem.next == nullptr);
248
249 elem.user = user_type();
250
251 if(m_tail == nullptr) {
252 zth_assert(m_head == nullptr);
253 m_tail = m_head = elem.prev = elem.next = &elem;
254 return begin();
255 } else {
256 elem.next = m_tail->next;
257 elem.prev = m_tail;
258 m_tail = elem.next->prev = elem.prev->next = &elem;
259 return iterator(m_head, &elem);
260 }
261 }
262
264 {
265 zth_assert(!empty());
266
267 elem_type* elem = m_tail;
268
269 if(m_tail == m_head) {
270 m_tail = m_head = nullptr;
271 zth_assert(elem->prev == elem->next);
272 zth_assert(elem->prev == elem);
273 } else {
274 m_tail = m_tail->prev;
275 elem->prev->next = elem->next;
276 elem->next->prev = elem->prev;
277 }
278
280 elem->prev = elem->next = nullptr;
281
282 return elem->user;
283 }
284
285 type& front() const noexcept
286 {
287 zth_assert(!empty());
288 return *static_cast<type*>(m_head);
289 }
290
291 user_type const& user_front() const noexcept
292 {
293 zth_assert(!empty());
294 return m_head->user;
295 }
296
298 {
299 zth_assert(!empty());
300 return m_head->user;
301 }
302
304 {
305 zth_assert(elem.prev == nullptr);
306 zth_assert(elem.next == nullptr);
307
308 if(m_head == nullptr) {
309 zth_assert(m_tail == nullptr);
310 m_tail = m_head = elem.prev = elem.next = &elem;
311 } else {
312 elem.next = m_head;
313 elem.prev = m_head->prev;
314 elem.prev->next = elem.next->prev = m_head = &elem;
315 }
316 elem.user = user_type();
317 return iterator(m_head, &elem);
318 }
319
321 {
322 zth_assert(!empty());
323
324 elem_type* elem = m_head;
325
326 if(m_tail == m_head) {
327 m_tail = m_head = nullptr;
328 zth_assert(elem->prev == elem->next);
329 zth_assert(elem->prev == elem);
330 } else {
331 m_head = m_head->next;
332 elem->prev->next = elem->next;
333 elem->next->prev = elem->prev;
334 }
335
337 elem->prev = elem->next = nullptr;
338
339 return elem->user;
340 }
341
342 bool empty() const noexcept
343 {
344 zth_assert(m_head != nullptr || m_tail == nullptr);
345 return m_head == nullptr;
346 }
347
348 void clear() noexcept
349 {
351 while(!empty())
352 pop_front();
353 else
354 m_head = m_tail = nullptr;
355 }
356
357 iterator begin() const noexcept
358 {
359 return iterator(m_head);
360 }
361
362 cyclic_iterator cyclic(elem_type& start) const noexcept
363 {
364 zth_assert(contains(start));
365 return cyclic_iterator(&start);
366 }
367
368 iterator end() const noexcept
369 {
370 return iterator(m_head, m_head);
371 }
372
373 bool contains(elem_type const& elem) const noexcept
374 {
375 for(iterator it = begin(); it != end(); ++it)
376 if(it.get() == &elem)
377 return true;
378 return false;
379 }
380
381 size_t size() const noexcept
382 {
383 size_t res = 0;
384 for(iterator it = begin(); it != end(); ++it)
385 res++;
386 return res;
387 }
388
389 iterator insert(iterator const& pos, elem_type& elem) noexcept
390 {
391 if(pos.atEnd()) {
392 push_back(elem);
393 return iterator(m_head, &elem);
394 } else if(pos.atBegin()) {
395 push_front(elem);
396 return begin();
397 } else {
398 elem_type* before = pos.get();
399 elem.next = before;
400 elem.prev = before->prev;
401 before->prev = elem.prev->next = &elem;
402 elem.user = user_type();
403 return iterator(m_head, &elem);
404 }
405 }
406
407 iterator erase(iterator const& pos) noexcept
408 {
409 zth_assert(!pos.atEnd());
410 if(pos.atBegin()) {
411 erase(*pos.get());
412 return begin();
413 } else if(pos.get() == m_tail) {
414 erase(*pos.get());
415 return end();
416 } else {
417 elem_type* next = pos.get()->next;
418 erase(*pos.get());
419 return iterator(m_head, next);
420 }
421 }
422
423 user_type erase(elem_type& elem) noexcept
424 {
425 zth_assert(contains(elem));
426 if(m_head == &elem) {
427 return pop_front();
428 } else if(m_tail == &elem) {
429 return pop_back();
430 } else {
431 elem.prev->next = elem.next;
432 elem.next->prev = elem.prev;
434 elem.next = elem.prev = nullptr;
435 return elem.user;
436 }
437 }
438
439 void rotate(elem_type& elem) noexcept
440 {
441 zth_assert(contains(elem));
442 m_head = &elem;
443 m_tail = elem.prev;
444 }
445
446private:
447 elem_type* m_head;
448 elem_type* m_tail;
449};
450
451template <typename T, typename Compare>
455public:
456 typedef T type;
458
459 constexpr SortedList() noexcept
460 : m_comp()
461 , m_t()
462 , m_head()
463 , m_size()
464 {}
465
466 ~SortedList() noexcept
467 {
468 clear();
469 }
470
471 void insert(elem_type& x) noexcept
472 {
473 zth_assert(!x.left);
474 zth_assert(!x.right);
475 zth_assert(x.level == 0);
476 zth_assert(!contains(x));
477 if(!m_t)
478 m_head = &x;
479 m_t = insert_(x, m_t);
480 m_size++;
481 check();
482 }
483
484 void erase(elem_type& x) noexcept
485 {
487 m_t = delete_(x, m_t);
488 if(m_head == &x)
489 m_head = lowest(m_t);
491 x.level = 0;
492 x.left = x.right = nullptr;
493 }
494 m_size--;
495 check();
496 }
497
498 void clear() noexcept
499 {
501 while(!empty())
502 erase(*m_t);
503 } else {
504 m_t = m_head = nullptr;
505 m_size = 0;
506 }
507 }
508
509 size_t size() const noexcept
510 {
511 zth_assert(m_size > 0 || !m_t);
512 return m_size;
513 }
514
515 bool empty() const noexcept
516 {
517 zth_assert(m_size > 0 || !m_t);
518 return !m_t;
519 }
520
521 bool contains(elem_type& x) const noexcept
522 {
523 elem_type* t = m_t;
524 while(t) {
525 if(t == &x)
526 return true;
527 else if(m_comp(static_cast<type&>(x), static_cast<type&>(*t)))
528 t = t->left;
529 else if(m_comp(static_cast<type&>(*t), static_cast<type&>(x)))
530 t = t->right;
531 else if((uintptr_t)&x < (uintptr_t)t)
532 t = t->left;
533 else
534 t = t->right;
535 }
536 return false;
537 }
538
539 type& front() const noexcept
540 {
541 zth_assert(m_head && m_t);
542 return static_cast<type&>(*m_head);
543 }
544
545protected:
546 static elem_type* skew(elem_type* t) noexcept
547 {
548 if(!t)
549 return nullptr;
550 else if(!t->left)
551 return t;
552 else if(t->left->level == t->level) {
553 elem_type* l = t->left;
554 t->left = l->right;
555 l->right = t;
556 return l;
557 } else
558 return t;
559 }
560
561 static elem_type* split(elem_type* t) noexcept
562 {
563 if(!t)
564 return nullptr;
565 else if(!t->right || !t->right->right)
566 return t;
567 else if(t->level == t->right->right->level) {
568 elem_type* r = t->right;
569 t->right = r->left;
570 r->left = t;
571 zth_assert(r->level < std::numeric_limits<decltype(r->level)>::max());
572 r->level++;
573 return r;
574 } else
575 return t;
576 }
577
579 {
580 if(!t) {
581 x.level = 1;
582 x.left = x.right = nullptr;
583 return &x;
584 } else if(m_comp(static_cast<type&>(x), static_cast<type&>(*t)))
585 t->left = insert_(x, t->left);
586 else if(m_comp(static_cast<type&>(*t), static_cast<type&>(x)))
587 t->right = insert_(x, t->right);
588 else if((uintptr_t)&x < (uintptr_t)t)
589 t->left = insert_(x, t->left);
590 else
591 t->right = insert_(x, t->right);
592
593 if(t == m_head && t->left)
594 m_head = t->left;
595
596 return split(skew(t));
597 }
598
600 {
601 if(!t)
602 return nullptr;
603 else if(&x == t) {
604 if(!t->left && !t->right) {
605 return nullptr;
606 } else if(!t->left) {
607 elem_type* l = successor(t);
608 l->right = delete_(*l, t->right);
609 l->left = t->left;
610 l->level = t->level;
611 t = l;
612 } else {
613 elem_type* l = predecessor(t);
614 l->left = delete_(*l, t->left);
615 l->right = t->right;
616 l->level = t->level;
617 t = l;
618 }
619 } else if(m_comp(static_cast<type&>(x), static_cast<type&>(*t)))
620 t->left = delete_(x, t->left);
621 else if(m_comp(static_cast<type&>(*t), static_cast<type&>(x)))
622 t->right = delete_(x, t->right);
623 else if((uintptr_t)&x < (uintptr_t)t)
624 t->left = delete_(x, t->left);
625 else
626 t->right = delete_(x, t->right);
627
629 t = skew(t);
630 t->right = skew(t->right);
631 if(t->right)
632 t->right->right = skew(t->right->right);
633 t = split(t);
634 t->right = split(t->right);
635 return t;
636 }
637
638 static elem_type* lowest(elem_type* t) noexcept
639 {
640 if(!t)
641 return nullptr;
642 else if(!t->left)
643 return t;
644 else
645 return lowest(t->left);
646 }
647
648 static elem_type* highest(elem_type* t) noexcept
649 {
650 if(!t)
651 return nullptr;
652 else if(!t->right)
653 return t;
654 else
655 return highest(t->right);
656 }
657
658 static elem_type* successor(elem_type* t) noexcept
659 {
660 return t ? lowest(t->right) : nullptr;
661 }
662
663 static elem_type* predecessor(elem_type* t) noexcept
664 {
665 return t ? highest(t->left) : nullptr;
666 }
667
668 // cppcheck-suppress constParameterPointer
669 static void decrease_level(elem_type* t) noexcept
670 {
671# ifndef CPPCHECK // Internal error, somehow.
672 decltype(t->level) ll = t->left ? t->left->level : 0;
673 decltype(t->level) lr = t->right ? t->right->level : 0;
674 decltype(t->level) should_be = (decltype(t->level))((ll < lr ? ll : lr) + 1U);
675 if(should_be < t->level) {
676 t->level = should_be;
677 if(t->right && should_be < t->right->level)
678 t->right->level = should_be;
679 }
680# endif
681 }
682
683 void check() const noexcept
684 {
685 zth_dbg(list, "SortedList %p (head %p):", this, m_head);
686 print(m_t, 2);
687 zth_assert(m_size == check(m_t));
688 zth_assert((!m_t && !m_head) || (m_t && m_head && lowest(m_t) == m_head));
689 }
690
691 size_t check(elem_type* t) const noexcept
692 {
694 return 0;
695 if(!t)
696 return 0;
697
699 !t->left || m_comp(static_cast<type&>(*t->left), static_cast<type&>(*t))
700 || (!m_comp(static_cast<type&>(*t), static_cast<type&>(*t->left))
701 && ((uintptr_t)t > (uintptr_t)t->left)));
703 !t->right || m_comp(static_cast<type&>(*t), static_cast<type&>(*t->right))
704 || (!m_comp(static_cast<type&>(*t->right), static_cast<type&>(*t))
705 || ((uintptr_t)t < (uintptr_t)t->right)));
706
707 zth_assert(t->left || t->right || t->level == 1);
708 zth_assert(!t->left || t->left->level == t->level - 1);
710 !t->right || t->right->level == t->level - 1
711 || t->right->level == t->level);
712 zth_assert(!t->right || !t->right->right || t->right->right->level < t->level);
713 zth_assert(t->level < 2 || (t->left && t->right));
714 return 1 + check(t->left) + check(t->right);
715 }
716
717 static void print(elem_type* t, int indent = 0) noexcept
718 {
720 return;
721
722 if(!t)
723 zth_dbg(list, "%*s (null)", indent, "");
724 else {
725 zth_dbg(list, "%*s node %p level=%d: %s", indent, "", static_cast<type*>(t),
726 t->level, static_cast<type*>(t)->str().c_str());
727 if(t->left || t->right) {
728 print(t->left, indent + 2);
729 print(t->right, indent + 2);
730 }
731 }
732 }
733
734private:
735 Compare m_comp;
736 elem_type* m_t;
737 elem_type* m_head;
738 size_t m_size;
739};
740
741template <typename T>
742class Hookable {
744public:
745 typedef T type;
746 typedef void* arg_type;
747 typedef void (*function_type)(type, arg_type)
748# if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510
749 noexcept
750# endif
751 ;
752
753 explicit Hookable(function_type f, arg_type a = arg_type(), Hookable* n = nullptr) noexcept
754 : func(f)
755 , arg(a)
756 , next(n)
757 {}
758
759 Hookable* operator()(type x) const noexcept
760 {
761 func(x, arg);
762 return next;
763 }
764
768};
769
770template <typename T>
771class Hook {
774public:
775 typedef T type;
779
780 Hook() noexcept
781 : m_head()
782 {}
783
784 ~Hook() noexcept
785 {
786 clear();
787 }
788
789 void add(function_type f, arg_type a = arg_type()) noexcept
790 {
791 m_head = new hookable_type(f, a, m_head);
792 }
793
794 void remove(arg_type a) noexcept
795 {
796 zth_assert(a);
797
798 if(!m_head) {
799 // Empty.
800 } else if(m_head->arg == a) {
801 // Drop head.
802 hookable_type* h = m_head;
803 m_head = h->next;
804 delete h;
805 } else {
806 // Drop from middle or end.
807 hookable_type* prev = m_head;
808 hookable_type* h = prev->next;
809 while(h) {
810 if(h->arg == a) {
811 // Got it.
812 prev->next = h->next;
813 delete h;
814 break;
815 }
816
817 prev = h;
818 h = h->next;
819 }
820 }
821 }
822
823 void operator()(type x) const noexcept
824 {
825 hookable_type const* h = m_head;
826 while(h)
827 h = (*h)(x);
828 }
829
830 void once(type x) noexcept
831 {
832 hookable_type* h = m_head;
833
834 while(h) {
835 hookable_type* next = (*h)(x);
836 delete h;
837 h = next;
838 }
839 m_head = nullptr;
840 }
841
842 void clear() noexcept
843 {
844 hookable_type* h = m_head;
845
846 while(h) {
847 hookable_type* next = h->next;
848 delete h;
849 h = next;
850 }
851 m_head = nullptr;
852 }
853
854private:
855 hookable_type* m_head;
856};
857
858} // namespace zth
859#endif // __cplusplus
860#endif // ZTH_LIST_H
void clear() noexcept
Definition list.h:842
void add(function_type f, arg_type a=arg_type()) noexcept
Definition list.h:789
Hookable< type > hookable_type
Definition list.h:776
void operator()(type x) const noexcept
Definition list.h:823
hookable_type::function_type function_type
Definition list.h:777
~Hook() noexcept
Definition list.h:784
Hook() noexcept
Definition list.h:780
hookable_type::arg_type arg_type
Definition list.h:778
void remove(arg_type a) noexcept
Definition list.h:794
T type
Definition list.h:775
void once(type x) noexcept
Definition list.h:830
void(* function_type)(type, arg_type)
Definition list.h:747
Hookable(function_type f, arg_type a=arg_type(), Hookable *n=nullptr) noexcept
Definition list.h:753
function_type func
Definition list.h:765
Hookable * next
Definition list.h:767
Hookable * operator()(type x) const noexcept
Definition list.h:759
arg_type arg
Definition list.h:766
void * arg_type
Definition list.h:746
Iterator operator--(int) noexcept
Definition list.h:171
bool operator==(Iterator< C > const &rhs) const noexcept
Definition list.h:123
bool operator!=(Iterator< C > const &rhs) const noexcept
Definition list.h:133
void next() noexcept
Definition list.h:138
void prev() noexcept
Definition list.h:145
user_type & user() noexcept
Definition list.h:199
bool atEnd() const noexcept
Definition list.h:111
constexpr Iterator(elem_type *start, elem_type *current=nullptr) noexcept
Definition list.h:101
Iterator & operator++() noexcept
Definition list.h:152
bool atBegin() const noexcept
Definition list.h:106
Iterator & operator--() noexcept
Definition list.h:165
user_type const & user() const noexcept
Definition list.h:191
Iterator operator++(int) noexcept
Definition list.h:158
elem_type * get() const noexcept
Definition list.h:116
type & operator*() const noexcept
Definition list.h:178
type * operator->() const noexcept
Definition list.h:186
T type
Definition list.h:94
user_type const & user_back() const noexcept
Definition list.h:232
Iterator< false > iterator
Definition list.h:212
iterator begin() const noexcept
Definition list.h:357
elem_type::user_type user_type
Definition list.h:96
size_t size() const noexcept
Definition list.h:381
bool empty() const noexcept
Definition list.h:342
user_type const & user_front() const noexcept
Definition list.h:291
iterator erase(iterator const &pos) noexcept
Definition list.h:407
iterator push_back(elem_type &elem) noexcept
Definition list.h:244
user_type erase(elem_type &elem) noexcept
Definition list.h:423
constexpr List() noexcept
Definition list.h:215
iterator insert(iterator const &pos, elem_type &elem) noexcept
Definition list.h:389
Listable elem_type
Definition list.h:95
user_type pop_front() noexcept
Definition list.h:320
iterator push_front(elem_type &elem) noexcept
Definition list.h:303
user_type pop_back() noexcept
Definition list.h:263
type & back() const noexcept
Definition list.h:226
iterator end() const noexcept
Definition list.h:368
void clear() noexcept
Definition list.h:348
~List() noexcept
Definition list.h:220
bool contains(elem_type const &elem) const noexcept
Definition list.h:373
cyclic_iterator cyclic(elem_type &start) const noexcept
Definition list.h:362
user_type & user_front() noexcept
Definition list.h:297
user_type & user_back() noexcept
Definition list.h:238
type & front() const noexcept
Definition list.h:285
Iterator< true > cyclic_iterator
Definition list.h:213
void rotate(elem_type &elem) noexcept
Definition list.h:439
Listable(Listable &&l) noexcept
Definition list.h:53
Listable & operator=(Listable &&l) noexcept
Definition list.h:58
constexpr Listable(Listable const &e) noexcept
Definition list.h:39
user_type user
Definition list.h:79
uint_fast8_t level
Definition list.h:80
void * user_type
Definition list.h:31
Listable * prev
Definition list.h:71
Listable * right
Definition list.h:76
Listable * next
Definition list.h:75
constexpr Listable() noexcept
Definition list.h:33
Listable * left
Definition list.h:72
Listable & operator=(Listable const &rhs) noexcept
Definition list.h:45
void erase(elem_type &x) noexcept
Definition list.h:484
void check() const noexcept
Definition list.h:683
void clear() noexcept
Definition list.h:498
void insert(elem_type &x) noexcept
Definition list.h:471
bool contains(elem_type &x) const noexcept
Definition list.h:521
elem_type * insert_(elem_type &x, elem_type *t) noexcept
Definition list.h:578
static void decrease_level(elem_type *t) noexcept
Definition list.h:669
static elem_type * lowest(elem_type *t) noexcept
Definition list.h:638
type & front() const noexcept
Definition list.h:539
static elem_type * successor(elem_type *t) noexcept
Definition list.h:658
static elem_type * skew(elem_type *t) noexcept
Definition list.h:546
size_t size() const noexcept
Definition list.h:509
static void print(elem_type *t, int indent=0) noexcept
Definition list.h:717
~SortedList() noexcept
Definition list.h:466
size_t check(elem_type *t) const noexcept
Definition list.h:691
elem_type * delete_(elem_type &x, elem_type *t) noexcept
Definition list.h:599
static elem_type * split(elem_type *t) noexcept
Definition list.h:561
constexpr SortedList() noexcept
Definition list.h:459
static elem_type * highest(elem_type *t) noexcept
Definition list.h:648
static elem_type * predecessor(elem_type *t) noexcept
Definition list.h:663
bool empty() const noexcept
Definition list.h:515
Listable elem_type
Definition list.h:457
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
Definition util.h:194
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
Definition allocator.h:159
#define UNUSED_PAR(name)
Definition macros.h:78
static bool const EnableAssert
When true, enable zth_assert().
Definition config.h:64
static int const Print_list
Definition config.h:133
static bool const SupportDebugPrint
Add support to enable debug output prints.
Definition config.h:109
#define zth_assert(expr)
assert(), but better integrated in Zth.
Definition util.h:217
#define ZTH_CLASS_NOCOPY(Class)
Definition util.h:234
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.
Definition util.h:60