Embedded Template Library 1.0
Loading...
Searching...
No Matches
intrusive_avl_tree.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2026 Sergei Shirokov
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_INTRUSIVE_AVL_TREE_INCLUDED
32#define ETL_INTRUSIVE_AVL_TREE_INCLUDED
33
34#include "platform.h"
35#include "error_handler.h"
36#include "intrusive_links.h"
37#include "iterator.h"
38#include "memory.h"
39#include "type_traits.h"
40#include "utility.h"
41
42#include <stddef.h>
43
44namespace etl
45{
46 //***************************************************************************
49 //***************************************************************************
50 class intrusive_avl_tree_exception : public exception
51 {
52 public:
53
54 intrusive_avl_tree_exception(const string_type reason_, const string_type file_name_, const numeric_type line_number_)
55 : exception(reason_, file_name_, line_number_)
56 {
57 }
58 };
59
60 //***************************************************************************
63 //***************************************************************************
64 class intrusive_avl_tree_iterator_exception : public intrusive_avl_tree_exception
65 {
66 public:
67
68 intrusive_avl_tree_iterator_exception(const string_type file_name_, const numeric_type line_number_)
69 : intrusive_avl_tree_exception(ETL_ERROR_TEXT("intrusive_avl_tree:iterator", ETL_INTRUSIVE_AVL_TREE_FILE_ID "A"), file_name_, line_number_)
70 {
71 }
72 };
73
74 //***************************************************************************
77 //***************************************************************************
78 class intrusive_avl_tree_value_is_already_linked : public intrusive_avl_tree_exception
79 {
80 public:
81
82 intrusive_avl_tree_value_is_already_linked(const string_type file_name_, const numeric_type line_number_)
83 : intrusive_avl_tree_exception(ETL_ERROR_TEXT("intrusive_avl_tree:value is already linked", ETL_INTRUSIVE_AVL_TREE_FILE_ID"B"), file_name_,
84 line_number_)
85 {
86 }
87 };
88
89 //***************************************************************************
93 //***************************************************************************
94 template <size_t ID_>
96 {
97 public:
98
99 enum
100 {
101 ID = ID_,
102 };
103
104#if ETL_USING_CPP11
106 intrusive_avl_tree_base& operator=(const intrusive_avl_tree_base&) = delete;
107#endif
108
117 struct link_type : private etl::tree_link<ID_>
118 {
119 private:
120
121 typedef etl::tree_link<ID_> base;
122
123 public:
124
125 link_type() ETL_NOEXCEPT
126 : base()
127 , etl_size(0)
128 {
129 }
130
131#if ETL_USING_CPP11
132 //***************************************************************************
141 //***************************************************************************
142 link_type(link_type&& other) ETL_NOEXCEPT
143 : base()
144 , etl_size(0)
145 {
146 move_impl(other);
147 }
148
149 //***************************************************************************
162 //***************************************************************************
163 link_type& operator=(link_type&& other) ETL_NOEXCEPT
164 {
165 if (this != &other)
166 {
167 // Before move assigning `other` we have to
168 // make sure this item is not linked to any tree.
169 erase_impl(this);
170 move_impl(other);
171 }
172 return *this;
173 }
174#endif
175
176#if ETL_USING_CPP11
177 // Disable copy construction and assignment.
178 link_type(const link_type&) = delete;
179 link_type& operator=(const link_type&) = delete;
180#endif
181
182 //***************************************************************************
192 //***************************************************************************
194 {
195 // We can't just remove item (by simple rewiring of links at parent and children)
196 // b/c its former "owner" tree has to be rebalanced after the removal -
197 // hence the full-blown erasing which might rotate the tree as necessary.
198 erase_impl(this);
199 }
200
201 private:
202
203 friend class intrusive_avl_tree_base;
204
205 union
206 {
207 int_fast8_t etl_bf;
208 size_t etl_size;
209 };
210
211#if ETL_USING_CPP11
212#else
213 // Disable copy construction and assignment.
214 link_type(const link_type&);
215 link_type& operator=(const link_type&);
216#endif
217
218 ETL_NODISCARD
219 bool is_linked() const
220 {
221 return base::is_linked();
222 }
223
224 ETL_NODISCARD
225 bool is_origin() const
226 {
227 return ETL_NULLPTR == base::etl_parent;
228 }
229
231 ETL_NODISCARD
232 link_type* get_parent()
233 {
234 return static_cast<link_type*>(base::etl_parent);
235 }
237
238 ETL_NODISCARD
239 const link_type* get_parent() const
240 {
241 return static_cast<const link_type*>(base::etl_parent);
242 }
243
244 ETL_NODISCARD
245 bool is_child(const bool is_right) const
246 {
247 const link_type* parent = get_parent();
248 return (ETL_NULLPTR != parent) && (this == parent->get_child(is_right));
249 }
250
251 ETL_NODISCARD
252 bool is_left_child() const
253 {
254 return is_child(false);
255 }
256
257 ETL_NODISCARD
258 bool is_right_child() const
259 {
260 return is_child(true);
261 }
262
263 ETL_NODISCARD
264 link_type* get_child(const bool is_right)
265 {
266 return static_cast<link_type*>(is_right ? base::etl_right : base::etl_left);
267 }
268
269 ETL_NODISCARD
270 const link_type* get_child(const bool is_right) const
271 {
272 return static_cast<const link_type*>(is_right ? base::etl_right : base::etl_left);
273 }
274
275 void set_child(link_type* const child, const bool is_right)
276 {
277 base*& child_ref = is_right ? base::etl_right : base::etl_left;
278 child_ref = child;
279 }
280
281 ETL_NODISCARD
282 link_type* get_left()
283 {
284 return static_cast<link_type*>(base::etl_left);
285 }
286
287 ETL_NODISCARD
288 const link_type* get_left() const
289 {
290 return static_cast<const link_type*>(base::etl_left);
291 }
292
293 ETL_NODISCARD
294 link_type* get_right()
295 {
296 return static_cast<link_type*>(base::etl_right);
297 }
298
299 ETL_NODISCARD
300 const link_type* get_right() const
301 {
302 return static_cast<const link_type*>(base::etl_right);
303 }
304
305 void move_impl(link_type& other)
306 {
307 const bool is_right = other.is_right_child();
308 base::etl_parent = other.etl_parent;
309 base::etl_left = other.etl_left;
310 base::etl_right = other.etl_right;
311 etl_size = other.etl_size;
312
313 other.clear();
314 other.etl_size = 0;
315
316 if (ETL_NULLPTR != base::etl_parent)
317 {
318 get_parent()->link_child(this, is_right);
319 }
320 if (ETL_NULLPTR != base::etl_left)
321 {
322 get_left()->set_parent(this);
323 }
324 if (ETL_NULLPTR != base::etl_right)
325 {
326 get_right()->set_parent(this);
327 }
328 }
329
330 void rotate(const bool is_right)
331 {
332 const bool was_right = is_right_child();
333 link_type* const child = get_child(!is_right);
334 etl::link_rotate<base>(this, child);
335 if (link_type* const parent = child->get_parent())
336 {
337 parent->set_child(child, was_right);
338 }
339 }
340
341 ETL_NODISCARD
342 link_type* adjust_balance(const bool increase)
343 {
344 const int_fast8_t new_bf = etl_bf + (increase ? +1 : -1);
345 if ((-1 <= new_bf) && (new_bf <= +1))
346 {
347 etl_bf = new_bf;
348 return this;
349 }
350
351 const bool is_right_rotation = new_bf < 0;
352 const int_fast8_t sign = is_right_rotation ? +1 : -1;
353 link_type* const z_leaf = get_child(!is_right_rotation);
354 if (z_leaf->etl_bf * sign <= 0)
355 {
356 rotate(is_right_rotation);
357 if (z_leaf->etl_bf == 0)
358 {
359 etl_bf = -sign;
360 z_leaf->etl_bf = +sign;
361 }
362 else
363 {
364 etl_bf = 0;
365 z_leaf->etl_bf = 0;
366 }
367 return z_leaf;
368 }
369
370 link_type* const y_leaf = z_leaf->get_child(is_right_rotation);
371 z_leaf->rotate(!is_right_rotation);
372 rotate(is_right_rotation);
373 if (y_leaf->etl_bf == 0)
374 {
375 etl_bf = 0;
376 z_leaf->etl_bf = 0;
377 }
378 else if (y_leaf->etl_bf == sign)
379 {
380 etl_bf = 0;
381 y_leaf->etl_bf = 0;
382 z_leaf->etl_bf = -sign;
383 }
384 else
385 {
386 etl_bf = +sign;
387 y_leaf->etl_bf = 0;
388 z_leaf->etl_bf = 0;
389 }
390 return y_leaf;
391 }
392
393 void link_child(link_type* child, const bool is_right)
394 {
395 if (is_right)
396 {
397 etl::link_right<base>(this, child);
398 }
399 else
400 {
401 etl::link_left<base>(this, child);
402 }
403 }
404
405 }; // link_type
406
407 //*************************************************************************
410 //*************************************************************************
411 ETL_NODISCARD
412 bool empty() const ETL_NOEXCEPT
413 {
414 return ETL_NULLPTR == get_root();
415 }
416
417 //*************************************************************************
420 //*************************************************************************
421 ETL_NODISCARD
422 size_t size() const ETL_NOEXCEPT
423 {
424 return get_origin().etl_size;
425 }
426
427 //*************************************************************************
435 //*************************************************************************
436 void clear() ETL_NOEXCEPT
437 {
438#if ETL_USING_CPP11
439 auto unlinker = [](link_type& link)
440 {
441 link.clear();
442 link.etl_size = 0;
443 };
444#else
445 struct
446 {
447 void operator()(link_type& link) const
448 {
449 link.clear();
450 link.etl_size = 0;
451 }
452 } unlinker;
453#endif
454
455 // No need to balance b/c everything will be unlinked.
456 // Note that "post-order" visitation is important -
457 // it ensures that once a link is passed to the "visitor" functor,
458 // traversal won't use a pointer to this link anymore,
459 // so we could efficiently clear the link.
460 visit_post_order_impl(&origin, false, unlinker);
461 origin.set_left(ETL_NULLPTR);
462 origin.etl_size = 0;
463 }
464
465 //*******************************************
469 //*******************************************
470 void swap(intrusive_avl_tree_base& other) ETL_NOEXCEPT
471 {
472 if (this != &other)
473 {
474 ETL_OR_STD::swap(origin, other.origin);
475 }
476 }
477
478 //*************************************************************************
482 //*************************************************************************
483 friend void swap(intrusive_avl_tree_base& lhs, intrusive_avl_tree_base& rhs) ETL_NOEXCEPT
484 {
485 if (&lhs != &rhs)
486 {
487 lhs.swap(rhs);
488 }
489 }
490
491 protected:
492
493 //*************************************************************************
495 //*************************************************************************
496 intrusive_avl_tree_base() ETL_NOEXCEPT {}
497
498#if ETL_USING_CPP11
499 //*************************************************************************
504 //*************************************************************************
505 intrusive_avl_tree_base(intrusive_avl_tree_base&&) ETL_NOEXCEPT = default;
506
507 //*************************************************************************
512 //*************************************************************************
513 intrusive_avl_tree_base& operator=(intrusive_avl_tree_base&& other) ETL_NOEXCEPT
514 {
515 if (this != &other)
516 {
517 intrusive_avl_tree_base tmp(etl::move(other));
518 swap(tmp);
519 }
520 return *this;
521 }
522#endif
523
524 //*************************************************************************
533 //***************************************************************************
535 {
536 // It's important to clear, so that none of the former (but still alive) items
537 // stay linked to this tree (neither directly at the root item
538 // nor transitively via "parent" links from leaf items up to the origin).
539 clear();
540 }
541
542 ETL_NODISCARD
543 link_type* get_root() ETL_NOEXCEPT
544 {
545 return static_cast<link_type*>(origin.etl_left);
546 }
547
548 ETL_NODISCARD
549 const link_type* get_root() const ETL_NOEXCEPT
550 {
551 return static_cast<const link_type*>(origin.etl_left);
552 }
553
554 ETL_NODISCARD
555 link_type& get_origin() ETL_NOEXCEPT
556 {
557 return origin;
558 }
559
560 const link_type& get_origin() const ETL_NOEXCEPT
561 {
562 return origin;
563 }
564
565 template <typename TLink>
566 ETL_NODISCARD
567 static TLink* get_origin(TLink* link) ETL_NOEXCEPT
568 {
569 while ((ETL_NULLPTR != link) && !link->is_origin())
570 {
571 link = link->get_parent();
572 }
573 return link;
574 }
575
576 ETL_NODISCARD
577 static bool is_real_link(const link_type* link) ETL_NOEXCEPT
578 {
579 return (ETL_NULLPTR != link) && !link->is_origin();
580 }
581
582 template <typename TLink>
583 ETL_NODISCARD
584 static TLink* begin_impl(TLink& origin) ETL_NOEXCEPT
585 {
586 TLink* curr = &origin;
587 TLink* next = curr->get_child(false);
588 while (ETL_NULLPTR != next)
589 {
590 curr = next;
591 next = next->get_child(false);
592 }
593 return curr;
594 }
595
596 template <typename TLink>
597 ETL_NODISCARD
598 static TLink* end_impl(TLink& origin) ETL_NOEXCEPT
599 {
600 return &origin;
601 }
602
603 template <typename TLink>
604 ETL_NODISCARD
605 static TLink* find_extremum_impl(TLink* curr, const bool is_max) ETL_NOEXCEPT
606 {
607 if (ETL_NULLPTR != curr)
608 {
609 TLink* next = curr->get_child(is_max);
610 while (ETL_NULLPTR != next)
611 {
612 curr = next;
613 next = curr->get_child(is_max);
614 }
615 }
616 return curr;
617 }
618
619 template <typename TLink>
620 ETL_NODISCARD
621 static TLink* next_in_order_impl(TLink* curr) ETL_NOEXCEPT
622 {
623 if ((ETL_NULLPTR == curr) || curr->is_origin())
624 {
625 return curr;
626 }
627
628 if (TLink* const next = curr->get_child(true))
629 {
630 return find_extremum_impl(next, false);
631 }
632
633 while (curr->is_right_child())
634 {
635 curr = curr->get_parent();
636 }
637 return curr->get_parent();
638 }
639
640 template <typename TLink>
641 ETL_NODISCARD
642 static TLink* prev_in_order_impl(TLink* curr) ETL_NOEXCEPT
643 {
644 if (ETL_NULLPTR == curr)
645 {
646 return ETL_NULLPTR;
647 }
648
649 if (TLink* const next = curr->get_child(false))
650 {
651 return find_extremum_impl(next, true);
652 }
653
654 while (curr->is_left_child())
655 {
656 curr = curr->get_parent();
657 }
658 return curr->is_origin() ? curr : curr->get_parent();
659 }
660
661 template <typename TLink, typename Visitor>
662 static void visit_in_order_impl(TLink* curr, const bool is_reverse, Visitor visitor)
663 {
664 TLink* prev = ETL_NULLPTR;
665 while (ETL_NULLPTR != curr)
666 {
667 TLink* next = curr->get_parent();
668 if (prev == next)
669 {
670 if (TLink* const child1 = curr->get_child(is_reverse))
671 {
672 next = child1;
673 }
674 else
675 {
676 if (!curr->is_origin())
677 {
678 visitor(*curr);
679 }
680
681 if (TLink* const child2 = curr->get_child(!is_reverse))
682 {
683 next = child2;
684 }
685 }
686 }
687 else if (prev == curr->get_child(is_reverse))
688 {
689 if (!curr->is_origin())
690 {
691 visitor(*curr);
692 }
693
694 if (TLink* const child2 = curr->get_child(!is_reverse))
695 {
696 next = child2;
697 }
698 }
699
700 prev = etl::exchange(curr, next);
701 }
702 }
703
704 template <typename TLink, typename Visitor>
705 static void visit_post_order_impl(TLink* curr, const bool is_reverse, Visitor visitor)
706 {
707 TLink* prev = ETL_NULLPTR;
708 while (ETL_NULLPTR != curr)
709 {
710 TLink* next = curr->get_parent();
711 if (prev == next)
712 {
713 if (TLink* const child1 = curr->get_child(is_reverse))
714 {
715 next = child1;
716 }
717 else if (TLink* const child2 = curr->get_child(!is_reverse))
718 {
719 next = child2;
720 }
721 else if (!curr->is_origin())
722 {
723 visitor(*curr);
724 }
725 }
726 else if (prev == curr->get_child(is_reverse))
727 {
728 if (TLink* const child2 = curr->get_child(!is_reverse))
729 {
730 next = child2;
731 }
732 else if (!curr->is_origin())
733 {
734 visitor(*curr);
735 }
736 }
737 else if (!curr->is_origin())
738 {
739 visitor(*curr);
740 }
741
742 prev = etl::exchange(curr, next);
743 }
744 }
745
746 template <typename TLink, typename Visitor>
747 static void visit_pre_order_impl(TLink* curr, const bool is_reverse, Visitor visitor)
748 {
749 TLink* prev = ETL_NULLPTR;
750 while (ETL_NULLPTR != curr)
751 {
752 TLink* next = curr->get_parent();
753 if (prev == next)
754 {
755 if (!curr->is_origin())
756 {
757 visitor(*curr);
758 }
759
760 if (TLink* const child1 = curr->get_child(is_reverse))
761 {
762 next = child1;
763 }
764 else if (TLink* const child2 = curr->get_child(!is_reverse))
765 {
766 next = child2;
767 }
768 }
769 else if (prev == curr->get_child(is_reverse))
770 {
771 if (TLink* const child2 = curr->get_child(!is_reverse))
772 {
773 next = child2;
774 }
775 }
776
777 prev = etl::exchange(curr, next);
778 }
779 }
780
781 ETL_NODISCARD
782 static int_fast8_t get_balance_factor_impl(const link_type* const curr) ETL_NOEXCEPT
783 {
784 return (ETL_NULLPTR != curr) ? curr->etl_bf : 0;
785 }
786
787 template <typename TLink>
788 ETL_NODISCARD
789 static TLink* get_parent_impl(TLink* const curr) ETL_NOEXCEPT
790 {
791 if (ETL_NULLPTR == curr)
792 {
793 return ETL_NULLPTR;
794 }
795 TLink* const parent = curr->get_parent();
796 if ((ETL_NULLPTR == parent) || parent->is_origin())
797 {
798 return ETL_NULLPTR;
799 }
800 return parent;
801 }
802
803 template <typename TLink>
804 ETL_NODISCARD
805 static TLink* get_child_impl(TLink* const curr, const bool is_right) ETL_NOEXCEPT
806 {
807 if (ETL_NULLPTR == curr)
808 {
809 return ETL_NULLPTR;
810 }
811 return curr->get_child(is_right);
812 }
813
814 template <typename TValue, typename TIterator, typename TBinaryCompare>
815 void assign_impl(TIterator first, TIterator last, TBinaryCompare binary_comp)
816 {
817#if ETL_IS_DEBUG_BUILD
818 const intmax_t diff = etl::distance(first, last);
819 ETL_ASSERT(diff >= 0, ETL_ERROR(intrusive_avl_tree_iterator_exception));
820#endif
821
822 // Add all the elements.
823 while (first != last)
824 {
825 link_type& link = *first++;
826 TValue& value = static_cast<TValue&>(link);
827#if ETL_USING_CPP11
828 find_or_insert_impl<TValue>( //
829 [&value, &binary_comp](const TValue& other) { return binary_comp(value, other); }, //
830 [&value] { return &value; });
831#else
832 const CompareFactory<TValue, TBinaryCompare> compareFactory(value, binary_comp);
833 find_or_insert_impl<TValue>(compareFactory, compareFactory);
834#endif
835 }
836 }
837
838 template <typename TValue, typename TLink, typename TCompare>
839 static TValue* find_impl(TLink* const root, TCompare comp)
840 {
841 // Try to find existing node.
842 TLink* curr = root;
843 while (ETL_NULLPTR != curr)
844 {
845 TValue* const result = static_cast<TValue*>(curr);
846 const int cmp = comp(*result);
847 if (0 == cmp)
848 {
849 // Found!
850 return result;
851 }
852
853 curr = curr->get_child(cmp > 0);
854 }
855
856 // Not found.
857 return ETL_NULLPTR;
858 }
859
860 template <typename TValue, typename TCompare, typename TFactory>
861 etl::pair<TValue*, bool> find_or_insert_impl(TCompare comp, TFactory factory)
862 {
863 // Try to find existing node.
864 bool is_right = false;
865 link_type* curr = get_root();
866 link_type* parent = &origin;
867 while (ETL_NULLPTR != curr)
868 {
869 TValue* const result = static_cast<TValue*>(curr);
870 const int cmp = comp(*result);
871 if (0 == cmp)
872 {
873 // Found! Tree was not modified.
874 return etl::make_pair(result, false);
875 }
876
877 parent = curr;
878 is_right = cmp > 0;
879 curr = curr->get_child(is_right);
880 }
881
882 // Try to instantiate new node.
883 TValue* const result = factory();
884 if (ETL_NULLPTR == result)
885 {
886 // Failed (or rejected)! The tree was not modified.
887 return etl::make_pair(ETL_NULLPTR, false);
888 }
889
890 link_type& result_link = static_cast<link_type&>(*result);
891 ETL_ASSERT(!(result_link.is_linked()), ETL_ERROR(intrusive_avl_tree_value_is_already_linked));
892
893 // Link the new node.
894 parent->link_child(&result_link, is_right);
895 get_origin(parent)->etl_size += 1;
896
897 retrace_on_insert(&result_link);
898
899 // Successfully linked, so the tree was modified.
900 return etl::make_pair(result, true);
901 }
902
903 template <bool IsUpper, typename TValue, typename TLink, typename TCompare>
904 static TValue* find_bound_impl(TLink* const root, TCompare comp)
905 {
906 TValue* result = ETL_NULLPTR;
907 TLink* next = root;
908 while (ETL_NULLPTR != next)
909 {
910 TValue* const next_value = static_cast<TValue*>(next);
911 const int cmp = comp(*next_value);
912 if ((cmp > 0) || (IsUpper && (cmp == 0)))
913 {
914 next = next->get_right();
915 }
916 else
917 {
918 result = next_value;
919 next = next->get_left();
920 }
921 }
922 return result;
923 }
924
925 static void erase_impl(link_type* const z_link) ETL_NOEXCEPT
926 {
927 // Remove only real and still-linked items.
928 // Tree itself uses this `link_type` for its `origin` sentinel item,
929 // but you can't (and there is no need to) erase it.
930 if ((ETL_NULLPTR == z_link) || z_link->is_origin() || !z_link->is_linked())
931 {
932 return;
933 }
934
935 link_type* parent = z_link->get_parent();
936 bool is_right = z_link->is_right_child();
937
938 if (!z_link->has_left())
939 {
940 parent->link_child(z_link->get_right(), is_right);
941 }
942 else if (!z_link->has_right())
943 {
944 parent->link_child(z_link->get_left(), is_right);
945 }
946 else
947 {
948 link_type* const y_link = next_in_order_impl(z_link);
949 link_type* const y_link_parent = y_link->get_parent();
950 y_link->etl_bf = z_link->etl_bf;
951 if (z_link != y_link_parent)
952 {
953 y_link_parent->link_child(y_link->get_right(), y_link->is_right_child());
954 link_type* const z_right = z_link->get_right();
955 y_link->set_right(z_right);
956 z_right->set_parent(y_link);
957 parent->link_child(y_link, is_right);
958
959 is_right = false;
960 parent = y_link_parent;
961 }
962 else
963 {
964 parent->link_child(y_link, is_right);
965
966 is_right = true;
967 parent = y_link;
968 }
969 link_type* const z_left = z_link->get_left();
970 y_link->set_left(z_left);
971 z_left->set_parent(y_link);
972 }
973
974 z_link->clear();
975 z_link->etl_size = 0;
976 get_origin(parent)->etl_size -= 1;
977
978 retrace_on_erase(parent, is_right);
979 }
980
981 private:
982
987 link_type origin;
988
989#if ETL_USING_CPP11
990#else
991 // Disable copy construction and assignment.
994
995 template <typename TValue, typename TBinaryCompare>
996 struct CompareFactory
997 {
998 TValue& value_ref;
999 TBinaryCompare binary_comp;
1000
1001 CompareFactory(TValue& value, TBinaryCompare comp)
1002 : value_ref(value)
1003 , binary_comp(comp)
1004 {
1005 }
1006
1008 ETL_NODISCARD
1009 int operator()(const TValue& other) const
1010 {
1011 return binary_comp(value_ref, other);
1012 }
1013
1015 ETL_NODISCARD
1016 TValue* operator()() const
1017 {
1018 return &value_ref;
1019 }
1020
1021 }; // CompareFactory
1022#endif
1023
1024 static void retrace_on_insert(link_type* curr)
1025 {
1026 link_type* parent = curr->get_parent();
1027 while (!parent->is_origin())
1028 {
1029 const bool is_right = curr->is_right_child();
1030 curr = parent->adjust_balance(is_right);
1031 parent = curr->get_parent();
1032 if (curr->etl_bf == 0)
1033 {
1034 break;
1035 }
1036 }
1037
1038 if (parent->is_origin())
1039 {
1040 parent->set_left(curr);
1041 }
1042 }
1043
1044 static void retrace_on_erase(link_type* parent, bool is_right)
1045 {
1046 while (!parent->is_origin())
1047 {
1048 link_type* const curr = parent->adjust_balance(!is_right);
1049 parent = curr->get_parent();
1050 if ((curr->etl_bf != 0) || parent->is_origin())
1051 {
1052 if (parent->is_origin())
1053 {
1054 parent->set_left(curr);
1055 }
1056 break;
1057 }
1058 is_right = curr->is_right_child();
1059 }
1060 }
1061
1062 }; // intrusive_avl_tree_base
1063
1064 //***************************************************************************
1075 //***************************************************************************
1076 template <typename TValue, size_t ID_ = 0>
1078 {
1080
1081 public:
1082
1083 // Node typedef.
1084 typedef typename base::link_type link_type;
1085
1086 // STL style typedefs.
1087 typedef TValue value_type;
1088 typedef value_type* pointer;
1089 typedef const value_type* const_pointer;
1090 typedef value_type& reference;
1091 typedef const value_type& const_reference;
1092 typedef size_t size_type;
1093#if ETL_USING_CPP11
1094 typedef value_type&& rvalue_reference;
1095#endif
1096
1097 //*************************************************************************
1113 //*************************************************************************
1114 class iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, value_type>
1115 {
1116 public:
1117
1118 friend class intrusive_avl_tree;
1119 friend class const_iterator;
1120
1121 iterator() ETL_NOEXCEPT
1122 : p_value(ETL_NULLPTR)
1123 {
1124 }
1125
1126 //*************************************************************************
1129 //*************************************************************************
1130 iterator& operator++() ETL_NOEXCEPT
1131 {
1132 p_value = base::next_in_order_impl(p_value);
1133 return *this;
1134 }
1135
1136 //*************************************************************************
1140 //*************************************************************************
1141 iterator operator++(int) ETL_NOEXCEPT
1142 {
1143 iterator temp(*this);
1144 p_value = base::next_in_order_impl(p_value);
1145 return temp;
1146 }
1147
1148 //*************************************************************************
1151 //*************************************************************************
1152 iterator& operator--() ETL_NOEXCEPT
1153 {
1154 p_value = base::prev_in_order_impl(p_value);
1155 return *this;
1156 }
1157
1158 //*************************************************************************
1162 //*************************************************************************
1163 iterator operator--(int) ETL_NOEXCEPT
1164 {
1165 iterator temp(*this);
1166 p_value = base::prev_in_order_impl(p_value);
1167 return temp;
1168 }
1169
1170 //*************************************************************************
1175 //*************************************************************************
1176 reference operator*() const
1177 {
1178 ETL_ASSERT(has_value(), ETL_ERROR(intrusive_avl_tree_iterator_exception));
1179
1181
1182 return *static_cast<pointer>(p_value);
1183#include "private/diagnostic_pop.h"
1184 }
1185
1186 //*************************************************************************
1189 //*************************************************************************
1190 pointer get() const ETL_NOEXCEPT
1191 {
1192 return static_cast<pointer>(has_value() ? p_value : ETL_NULLPTR);
1193 }
1194
1195 //*************************************************************************
1200 //*************************************************************************
1201 pointer operator->() const
1202 {
1203 ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(intrusive_avl_tree_iterator_exception), ETL_NULLPTR);
1204
1205 return static_cast<pointer>(p_value);
1206 }
1207
1208 friend bool operator==(const iterator& lhs, const iterator& rhs) ETL_NOEXCEPT
1209 {
1210 return lhs.p_value == rhs.p_value;
1211 }
1212
1213 friend bool operator!=(const iterator& lhs, const iterator& rhs) ETL_NOEXCEPT
1214 {
1215 return !(lhs == rhs);
1216 }
1217
1218 ETL_EXPLICIT operator bool() const ETL_NOEXCEPT
1219 {
1220 return has_value();
1221 }
1222
1223 ETL_NODISCARD
1224 bool has_value() const ETL_NOEXCEPT
1225 {
1226 return base::is_real_link(p_value);
1227 }
1228
1229 //*************************************************************************
1234 //*************************************************************************
1235 ETL_NODISCARD
1236 int_fast8_t get_balance_factor() const ETL_NOEXCEPT
1237 {
1238 return base::get_balance_factor_impl(p_value);
1239 }
1240
1241 //*************************************************************************
1246 //*************************************************************************
1247 ETL_NODISCARD
1248 iterator get_parent() const ETL_NOEXCEPT
1249 {
1250 return iterator(base::get_parent_impl(p_value));
1251 }
1252
1253 //*************************************************************************
1258 //*************************************************************************
1259 ETL_NODISCARD
1260 iterator get_child(const bool is_right) const ETL_NOEXCEPT
1261 {
1262 return iterator(base::get_child_impl(p_value, is_right));
1263 }
1264
1265 private:
1266
1267 ETL_EXPLICIT iterator(link_type* value)
1268 : p_value(value)
1269 {
1270 }
1271
1272 link_type* p_value;
1273
1274 }; // iterator
1275
1276 //*************************************************************************
1289 //*************************************************************************
1290 class const_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, const value_type>
1291 {
1292 public:
1293
1294 friend class intrusive_avl_tree;
1295
1296 const_iterator() ETL_NOEXCEPT
1297 : p_value(ETL_NULLPTR)
1298 {
1299 }
1300
1301 // Implicit by design - it's always safe to make const iterator from ordinary one.
1302 const_iterator(const typename intrusive_avl_tree::iterator& other) ETL_NOEXCEPT // NOLINT
1303 : p_value(other.p_value)
1304 {
1305 }
1306
1307 //*************************************************************************
1310 //*************************************************************************
1311 const_iterator& operator++() ETL_NOEXCEPT
1312 {
1313 p_value = base::next_in_order_impl(p_value);
1314 return *this;
1315 }
1316
1317 //*************************************************************************
1321 const_iterator operator++(int) ETL_NOEXCEPT
1322 {
1323 const_iterator temp(*this);
1324 p_value = base::next_in_order_impl(p_value);
1325 return temp;
1326 }
1327
1328 //*************************************************************************
1331 //*************************************************************************
1332 const_iterator& operator--() ETL_NOEXCEPT
1333 {
1334 p_value = base::prev_in_order_impl(p_value);
1335 return *this;
1336 }
1337
1338 //*************************************************************************
1342 //*************************************************************************
1343 const_iterator operator--(int) ETL_NOEXCEPT
1344 {
1345 const_iterator temp(*this);
1346 p_value = base::prev_in_order_impl(p_value);
1347 return temp;
1348 }
1349
1350 //*************************************************************************
1355 //*************************************************************************
1356 const_reference operator*() const
1357 {
1358 ETL_ASSERT(has_value(), ETL_ERROR(intrusive_avl_tree_iterator_exception));
1359
1361
1362 return *static_cast<const_pointer>(p_value);
1363#include "private/diagnostic_pop.h"
1364 }
1365
1366 //*************************************************************************
1369 //*************************************************************************
1370 const_pointer get() const ETL_NOEXCEPT
1371 {
1372 return static_cast<const_pointer>(has_value() ? p_value : ETL_NULLPTR);
1373 }
1374
1375 //*************************************************************************
1380 //*************************************************************************
1381 const_pointer operator->() const
1382 {
1383 ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(intrusive_avl_tree_iterator_exception), ETL_NULLPTR);
1384
1385 return static_cast<const_pointer>(p_value);
1386 }
1387
1388 friend bool operator==(const const_iterator& lhs, const const_iterator& rhs) ETL_NOEXCEPT
1389 {
1390 return lhs.p_value == rhs.p_value;
1391 }
1392
1393 friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs) ETL_NOEXCEPT
1394 {
1395 return !(lhs == rhs);
1396 }
1397
1398 ETL_EXPLICIT operator bool() const ETL_NOEXCEPT
1399 {
1400 return has_value();
1401 }
1402
1403 ETL_NODISCARD
1404 bool has_value() const ETL_NOEXCEPT
1405 {
1406 return base::is_real_link(p_value);
1407 }
1408
1409 //*************************************************************************
1414 //*************************************************************************
1415 ETL_NODISCARD
1416 int_fast8_t get_balance_factor() const ETL_NOEXCEPT
1417 {
1418 return base::get_balance_factor_impl(p_value);
1419 }
1420
1421 //*************************************************************************
1426 //*************************************************************************
1427 ETL_NODISCARD
1428 const_iterator get_parent() const ETL_NOEXCEPT
1429 {
1430 return const_iterator(base::get_parent_impl(p_value));
1431 }
1432
1433 //*************************************************************************
1438 //*************************************************************************
1439 ETL_NODISCARD
1440 const_iterator get_child(const bool is_right) const ETL_NOEXCEPT
1441 {
1442 return const_iterator(base::get_child_impl(p_value, is_right));
1443 }
1444
1445 private:
1446
1447 ETL_EXPLICIT const_iterator(const link_type* value)
1448 : p_value(value)
1449 {
1450 }
1451
1452 const link_type* p_value;
1453
1454 }; // const_iterator
1455
1456 //*************************************************************************
1458 //*************************************************************************
1459 intrusive_avl_tree() ETL_NOEXCEPT
1461 {
1462 }
1463
1464 //*************************************************************************
1491 //*************************************************************************
1492 template <typename TIterator, typename TBinaryCompare>
1493 intrusive_avl_tree(TIterator first, TIterator last, TBinaryCompare binary_comp,
1494 typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
1495 {
1496 base::template assign_impl<value_type>(first, last, binary_comp);
1497 }
1498
1499 //*************************************************************************
1502 //*************************************************************************
1504
1505#if ETL_USING_CPP11
1506 //*************************************************************************
1509 //*************************************************************************
1510 intrusive_avl_tree(intrusive_avl_tree&&) ETL_NOEXCEPT = default;
1511
1512 //*************************************************************************
1517 //*************************************************************************
1518 intrusive_avl_tree& operator=(intrusive_avl_tree&&) ETL_NOEXCEPT = default;
1519
1520 intrusive_avl_tree(const intrusive_avl_tree&) = delete;
1521 intrusive_avl_tree& operator=(const intrusive_avl_tree&) = delete;
1522#endif
1523
1524 //*************************************************************************
1528 //*************************************************************************
1529 ETL_NODISCARD
1530 iterator begin() ETL_NOEXCEPT
1531 {
1532 return iterator(base::begin_impl(base::get_origin()));
1533 }
1534
1535 //*************************************************************************
1539 //*************************************************************************
1540 ETL_NODISCARD
1541 const_iterator begin() const ETL_NOEXCEPT
1542 {
1543 return const_iterator(base::begin_impl(base::get_origin()));
1544 }
1545
1546 //*************************************************************************
1550 //*************************************************************************
1551 ETL_NODISCARD
1552 const_iterator cbegin() const ETL_NOEXCEPT
1553 {
1554 return begin();
1555 }
1556
1557 //*************************************************************************
1560 //*************************************************************************
1561 ETL_NODISCARD
1562 iterator end() ETL_NOEXCEPT
1563 {
1564 return iterator(base::end_impl(base::get_origin()));
1565 }
1566
1567 //*************************************************************************
1570 //*************************************************************************
1571 ETL_NODISCARD
1572 const_iterator end() const ETL_NOEXCEPT
1573 {
1574 return const_iterator(base::end_impl(base::get_origin()));
1575 }
1576
1577 //*************************************************************************
1580 //*************************************************************************
1581 ETL_NODISCARD
1582 const_iterator cend() const ETL_NOEXCEPT
1583 {
1584 return end();
1585 }
1586
1587 //*************************************************************************
1591 //*************************************************************************
1592 ETL_NODISCARD
1593 iterator max() ETL_NOEXCEPT
1594 {
1595 return --end();
1596 }
1597
1598 //*************************************************************************
1602 //*************************************************************************
1603 ETL_NODISCARD
1604 const_iterator max() const ETL_NOEXCEPT
1605 {
1606 return --end();
1607 }
1608
1609 //*************************************************************************
1613 //*************************************************************************
1614 ETL_NODISCARD
1615 iterator min() ETL_NOEXCEPT
1616 {
1617 return begin();
1618 }
1619
1620 //*************************************************************************
1624 //*************************************************************************
1625 ETL_NODISCARD
1626 const_iterator min() const ETL_NOEXCEPT
1627 {
1628 return begin();
1629 }
1630
1631 //*************************************************************************
1642 //*************************************************************************
1643 template <typename TCompare>
1644 iterator lower_bound(TCompare comp)
1645 {
1646 pointer ptr = base::template find_bound_impl<false, value_type>(base::get_root(), comp);
1647 return make_iterator(ptr, end());
1648 }
1649 template <typename TCompare>
1650 const_iterator lower_bound(TCompare comp) const
1651 {
1652 const_pointer ptr = base::template find_bound_impl<false, const value_type>(base::get_root(), comp);
1653 return make_iterator(ptr, end());
1654 }
1655
1656 //*************************************************************************
1667 //*************************************************************************
1668 template <typename TCompare>
1669 iterator upper_bound(TCompare comp)
1670 {
1671 pointer ptr = base::template find_bound_impl<true, value_type>(base::get_root(), comp);
1672 return make_iterator(ptr, end());
1673 }
1674 template <typename TCompare>
1675 const_iterator upper_bound(TCompare comp) const
1676 {
1677 const_pointer ptr = base::template find_bound_impl<true, const value_type>(base::get_root(), comp);
1678 return make_iterator(ptr, end());
1679 }
1680
1681 //*************************************************************************
1686 //*************************************************************************
1687 ETL_NODISCARD
1688 iterator get_root() ETL_NOEXCEPT
1689 {
1690 return iterator(base::get_root());
1691 }
1692
1693 //*************************************************************************
1698 //*************************************************************************
1699 ETL_NODISCARD
1700 const_iterator get_root() const ETL_NOEXCEPT
1701 {
1702 return const_iterator(base::get_root());
1703 }
1704
1705 //*************************************************************************
1717 //*************************************************************************
1718 template <typename TCompare>
1719 iterator find(TCompare comp)
1720 {
1721 pointer ptr = base::template find_impl<value_type>(base::get_root(), comp);
1722 return make_iterator(ptr, end());
1723 }
1724
1725 //*************************************************************************
1737 //*************************************************************************
1738 template <typename TCompare>
1739 const_iterator find(TCompare comp) const
1740 {
1741 const_pointer ptr = base::template find_impl<const value_type>(base::get_root(), comp);
1742 return make_iterator(ptr, end());
1743 }
1744
1745 //*************************************************************************
1775 //*************************************************************************
1776 template <typename TCompare, typename TFactory>
1778 {
1779 const etl::pair<value_type*, bool> ptr_mod = base::template find_or_insert_impl<value_type>(comp, factory);
1780 return etl::make_pair(make_iterator(ptr_mod.first, iterator()), ptr_mod.second);
1781 }
1782
1783 //*************************************************************************
1793 //*************************************************************************
1795 {
1796 ETL_ASSERT(position.has_value(), ETL_ERROR(intrusive_avl_tree_iterator_exception));
1797#if ETL_IS_DEBUG_BUILD
1798 // Iterator must originate from the same tree instance.
1799 // The check is still of the same O(log(N)) complexity.
1800 ETL_ASSERT(base::get_origin(position.p_value) == &base::get_origin(), ETL_ERROR(intrusive_avl_tree_iterator_exception));
1801#endif
1802
1803 iterator next(position);
1804 ++next;
1805
1806 base::erase_impl(position.p_value);
1807
1808 return next;
1809 }
1810
1811 //*************************************************************************
1821 //*************************************************************************
1823 {
1824 // It's safe to `const_cast` b/c we just need iterator to locate corresponding link.
1825 // Tree itself is not `const` anyway - so it's a legitimate operation, and it also matches
1826 // with similar `std::list::erase` or `etl::intrusive_list::erase` methods.
1827 return erase(iterator(const_cast<link_type*>(position.p_value)));
1828 }
1829
1830 //*************************************************************************
1839 //*************************************************************************
1840 template <typename Visitor>
1841 void visit_in_order(const bool is_reverse, Visitor visitor)
1842 {
1843#if ETL_USING_CPP11
1844 base::visit_in_order_impl( //
1845 &base::get_origin(), is_reverse, //
1846 [&visitor](link_type& link) { visitor(static_cast<reference>(link)); });
1847#else
1848 const CastingVisitor<reference, Visitor> casting_visitor(visitor);
1849 base::visit_in_order_impl(&base::get_origin(), is_reverse, casting_visitor);
1850#endif
1851 }
1852
1853 //*************************************************************************
1861 //*************************************************************************
1862 template <typename Visitor>
1863 void visit_in_order(const bool is_reverse, Visitor visitor) const
1864 {
1865#if ETL_USING_CPP11
1866 base::visit_in_order_impl( //
1867 &base::get_origin(), is_reverse, //
1868 [&visitor](const link_type& link) { visitor(static_cast<const_reference>(link)); });
1869#else
1870 const CastingVisitor<const_reference, Visitor> casting_visitor(visitor);
1871 base::visit_in_order_impl(&base::get_origin(), is_reverse, casting_visitor);
1872#endif
1873 }
1874
1875 //*************************************************************************
1887 //*************************************************************************
1888 template <typename Visitor>
1889 void visit_post_order(const bool is_reverse, Visitor visitor)
1890 {
1891#if ETL_USING_CPP11
1892 base::visit_post_order_impl( //
1893 &base::get_origin(), is_reverse, //
1894 [&visitor](link_type& link) { visitor(static_cast<reference>(link)); });
1895#else
1896 const CastingVisitor<reference, Visitor> casting_visitor(visitor);
1897 base::visit_post_order_impl(&base::get_origin(), is_reverse, casting_visitor);
1898#endif
1899 }
1900
1901 //*************************************************************************
1912 //*************************************************************************
1913 template <typename Visitor>
1914 void visit_post_order(const bool is_reverse, Visitor visitor) const
1915 {
1916#if ETL_USING_CPP11
1917 base::visit_post_order_impl( //
1918 &base::get_origin(), is_reverse, //
1919 [&visitor](const link_type& link) { visitor(static_cast<const_reference>(link)); });
1920#else
1921 const CastingVisitor<const_reference, Visitor> casting_visitor(visitor);
1922 base::visit_post_order_impl(&base::get_origin(), is_reverse, casting_visitor);
1923#endif
1924 }
1925
1926 //*************************************************************************
1938 //*************************************************************************
1939 template <typename Visitor>
1940 void visit_pre_order(const bool is_reverse, Visitor visitor)
1941 {
1942#if ETL_USING_CPP11
1943 base::visit_pre_order_impl( //
1944 &base::get_origin(), is_reverse, //
1945 [&visitor](link_type& link) { visitor(static_cast<reference>(link)); });
1946#else
1947 const CastingVisitor<reference, Visitor> casting_visitor(visitor);
1948 base::visit_pre_order_impl(&base::get_origin(), is_reverse, casting_visitor);
1949#endif
1950 }
1951
1952 //*************************************************************************
1963 //*************************************************************************
1964 template <typename Visitor>
1965 void visit_pre_order(const bool is_reverse, Visitor visitor) const
1966 {
1967#if ETL_USING_CPP11
1968 base::visit_pre_order_impl( //
1969 &base::get_origin(), is_reverse, //
1970 [&visitor](const link_type& link) { visitor(static_cast<const_reference>(link)); });
1971#else
1972 const CastingVisitor<const_reference, Visitor> casting_visitor(visitor);
1973 base::visit_pre_order_impl(&base::get_origin(), is_reverse, casting_visitor);
1974#endif
1975 }
1976
1977 private:
1978
1979#if ETL_USING_CPP11
1980#else
1981 // Disable copy construction and assignment.
1983 intrusive_avl_tree& operator=(const intrusive_avl_tree& rhs);
1984
1985 template <typename T, typename Visitor>
1986 struct CastingVisitor
1987 {
1988 Visitor& visitor;
1989 ETL_EXPLICIT CastingVisitor(Visitor& visitor)
1990 : visitor(visitor)
1991 {
1992 }
1993
1994 template <typename TLink>
1995 void operator()(TLink& link) const
1996 {
1997 visitor(static_cast<T>(link));
1998 }
1999 };
2000#endif
2001
2002 template <typename TIterator, typename Pointer>
2003 ETL_NODISCARD
2004 static TIterator make_iterator(Pointer const ptr, const TIterator end)
2005 {
2006 return (ETL_NULLPTR != ptr) ? TIterator(ptr) : end;
2007 }
2008
2009 }; // intrusive_avl_tree
2010
2011} // namespace etl
2012
2013#endif
Definition factory.h:99
Definition intrusive_avl_tree.h:1291
const_iterator operator--(int) ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1343
const_iterator & operator--() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1332
ETL_NODISCARD const_iterator get_child(const bool is_right) const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1440
ETL_NODISCARD int_fast8_t get_balance_factor() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1416
ETL_NODISCARD const_iterator get_parent() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1428
const_iterator & operator++() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1311
const_pointer get() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1370
const_iterator operator++(int) ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1321
const_pointer operator->() const
Definition intrusive_avl_tree.h:1381
Definition intrusive_avl_tree.h:1115
iterator operator--(int) ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1163
ETL_NODISCARD int_fast8_t get_balance_factor() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1236
iterator & operator++() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1130
ETL_NODISCARD iterator get_parent() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1248
ETL_NODISCARD iterator get_child(const bool is_right) const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1260
iterator operator++(int) ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1141
iterator & operator--() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1152
pointer get() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1190
pointer operator->() const
Definition intrusive_avl_tree.h:1201
Definition intrusive_avl_tree.h:96
friend void swap(intrusive_avl_tree_base &lhs, intrusive_avl_tree_base &rhs) ETL_NOEXCEPT
Definition intrusive_avl_tree.h:483
ETL_NODISCARD size_t size() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:422
void swap(intrusive_avl_tree_base &other) ETL_NOEXCEPT
Definition intrusive_avl_tree.h:470
~intrusive_avl_tree_base()
Definition intrusive_avl_tree.h:534
void clear() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:436
intrusive_avl_tree_base() ETL_NOEXCEPT
Default constructor.
Definition intrusive_avl_tree.h:496
ETL_NODISCARD bool empty() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:412
Definition intrusive_avl_tree.h:65
Definition intrusive_avl_tree.h:1078
ETL_NODISCARD iterator max() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1593
ETL_NODISCARD iterator get_root() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1688
ETL_NODISCARD iterator min() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1615
iterator erase(iterator position)
Definition intrusive_avl_tree.h:1794
iterator lower_bound(TCompare comp)
Definition intrusive_avl_tree.h:1644
iterator upper_bound(TCompare comp)
Definition intrusive_avl_tree.h:1669
iterator erase(const_iterator position)
Definition intrusive_avl_tree.h:1822
~intrusive_avl_tree()
Definition intrusive_avl_tree.h:1503
ETL_NODISCARD const_iterator max() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1604
void visit_pre_order(const bool is_reverse, Visitor visitor)
Definition intrusive_avl_tree.h:1940
void visit_post_order(const bool is_reverse, Visitor visitor) const
Definition intrusive_avl_tree.h:1914
ETL_NODISCARD const_iterator begin() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1541
ETL_NODISCARD const_iterator cbegin() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1552
void visit_post_order(const bool is_reverse, Visitor visitor)
Definition intrusive_avl_tree.h:1889
ETL_NODISCARD iterator end() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1562
intrusive_avl_tree() ETL_NOEXCEPT
Default constructor.
Definition intrusive_avl_tree.h:1459
etl::pair< iterator, bool > find_or_insert(TCompare comp, TFactory factory)
Definition intrusive_avl_tree.h:1777
iterator find(TCompare comp)
Definition intrusive_avl_tree.h:1719
void visit_pre_order(const bool is_reverse, Visitor visitor) const
Definition intrusive_avl_tree.h:1965
ETL_NODISCARD const_iterator cend() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1582
ETL_NODISCARD const_iterator min() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1626
const_iterator find(TCompare comp) const
Definition intrusive_avl_tree.h:1739
ETL_NODISCARD iterator begin() ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1530
ETL_NODISCARD const_iterator get_root() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1700
intrusive_avl_tree(TIterator first, TIterator last, TBinaryCompare binary_comp, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition intrusive_avl_tree.h:1493
ETL_NODISCARD const_iterator end() const ETL_NOEXCEPT
Definition intrusive_avl_tree.h:1572
void visit_in_order(const bool is_reverse, Visitor visitor)
Definition intrusive_avl_tree.h:1841
void visit_in_order(const bool is_reverse, Visitor visitor) const
Definition intrusive_avl_tree.h:1863
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition visitor.h:237
Definition absolute.h:40
pair< T1, T2 > make_pair(T1 a, T2 b)
A convenience wrapper for creating a pair from two objects.
Definition utility.h:335
T exchange(T &object, const T &new_value)
exchange (const)
Definition utility.h:498
ETL_CONSTEXPR14 enable_if<!etl::is_specialization< TRep2, etl::chrono::duration >::value, etl::chrono::duration< typenameetl::common_type< TRep1, TRep2 >::type, TPeriod1 > >::type operator*(const etl::chrono::duration< TRep1, TPeriod1 > &lhs, const TRep2 &rhs) ETL_NOEXCEPT
Operator *.
Definition duration.h:541
etl::enable_if< etl::is_same< TLink, etl::tree_link< TLink::ID > >::value, void >::type link_rotate(TLink &parent, TLink &child)
Automatically detects whether a left or right rotate is expected.
Definition intrusive_links.h:1377
iterator
Definition iterator.h:482
pair holds two objects of arbitrary type
Definition utility.h:176
T1 first
first is a copy of the first object
Definition utility.h:180
T2 second
second is a copy of the second object
Definition utility.h:181
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937