libstdc++: stl_tree.h Source File

libstdc++

stl_tree.h
Go to the documentation of this file.
1// RB tree implementation -*- C++ -*-
2
3// Copyright (C) 2001-2026 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 *
27 * Copyright (c) 1996,1997
28 * Silicon Graphics Computer Systems, Inc.
29 *
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation. Silicon Graphics makes no
35 * representations about the suitability of this software for any
36 * purpose. It is provided "as is" without express or implied warranty.
37 *
38 *
39 * Copyright (c) 1994
40 * Hewlett-Packard Company
41 *
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation. Hewlett-Packard Company makes no
47 * representations about the suitability of this software for any
48 * purpose. It is provided "as is" without express or implied warranty.
49 *
50 *
51 */
52
53/** @file bits/stl_tree.h
54 * This is an internal header file, included by other library headers.
55 * Do not attempt to use it directly. @headername{map,set}
56 */
57
58#ifndef _STL_TREE_H
59#define _STL_TREE_H 1
60
61#ifdef _GLIBCXX_SYSHDR
62#pragma GCC system_header
63#endif
64
65#include <bits/stl_algobase.h>
66#include <bits/allocator.h>
67#include <bits/stl_function.h>
68#include <bits/cpp_type_traits.h>
69#include <bits/ptr_traits.h>
70#include <ext/alloc_traits.h>
71#if __cplusplus >= 201103L
72# include <ext/aligned_buffer.h>
73#endif
74#ifdef __glibcxx_node_extract // >= C++17
75# include <bits/node_handle.h>
76#endif
77
78#if __cplusplus < 201103L
79# undef _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
80# define _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE 0
81#elif ! defined _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
82# define _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE 1
83#endif
84
85namespace std _GLIBCXX_VISIBILITY(default)
86{
87_GLIBCXX_BEGIN_NAMESPACE_VERSION
88
89 // Red-black tree class, designed for use in implementing STL
90 // associative containers (set, multiset, map, and multimap). The
91 // insertion and deletion algorithms are based on those in Cormen,
92 // Leiserson, and Rivest, Introduction to Algorithms (MIT Press,
93 // 1990), except that
94 //
95 // (1) the header cell is maintained with links not only to the root
96 // but also to the leftmost node of the tree, to enable constant
97 // time begin(), and to the rightmost node of the tree, to enable
98 // linear time performance when used with the generic set algorithms
99 // (set_union, etc.)
100 //
101 // (2) when a node being deleted has two children its successor node
102 // is relinked into its place, rather than copied, so that the only
103 // iterators invalidated are those referring to the deleted node.
104
105 enum _Rb_tree_color { _S_red = false, _S_black = true };
106
107 struct _Rb_tree_node_base
108 {
109 typedef _Rb_tree_node_base* _Base_ptr;
110
111 _Rb_tree_color _M_color;
112 _Base_ptr _M_parent;
113 _Base_ptr _M_left;
114 _Base_ptr _M_right;
115
116 static _Base_ptr
117 _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
118 {
119 while (__x->_M_left != 0) __x = __x->_M_left;
120 return __x;
121 }
122
123 static _Base_ptr
124 _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
125 {
126 while (__x->_M_right != 0) __x = __x->_M_right;
127 return __x;
128 }
129
130 // This is not const-correct, but it's only used in a const access path
131 // by std::_Rb_tree::_M_end() where the pointer is used to initialize a
132 // const_iterator and so constness is restored.
133 _Base_ptr
134 _M_base_ptr() const _GLIBCXX_NOEXCEPT
135 { return const_cast<_Rb_tree_node_base*>(this); }
136 };
137
138 // Helper type offering value initialization guarantee on the compare functor.
139 template<typename _Key_compare>
140 struct _Rb_tree_key_compare
141 {
142 _Key_compare _M_key_compare;
143
144 _Rb_tree_key_compare()
145 _GLIBCXX_NOEXCEPT_IF(
146 is_nothrow_default_constructible<_Key_compare>::value)
147 : _M_key_compare()
148 { }
149
150 _Rb_tree_key_compare(const _Key_compare& __comp)
151 : _M_key_compare(__comp)
152 { }
153
154#if __cplusplus >= 201103L
155 // Copy constructor added for consistency with C++98 mode.
156 _Rb_tree_key_compare(const _Rb_tree_key_compare&) = default;
157
158 _Rb_tree_key_compare(_Rb_tree_key_compare&& __x)
159 noexcept(is_nothrow_copy_constructible<_Key_compare>::value)
160 : _M_key_compare(__x._M_key_compare)
161 { }
162#endif
163 };
164
165 // Helper type to manage default initialization of node count and header.
166 struct _Rb_tree_header
167 {
168 _Rb_tree_node_base _M_header;
169 size_t _M_node_count; // Keeps track of size of tree.
170
171 _Rb_tree_header() _GLIBCXX_NOEXCEPT
172 {
173 _M_header._M_color = _S_red;
174 _M_reset();
175 }
176
177#if __cplusplus >= 201103L
178 _Rb_tree_header(_Rb_tree_header&& __x) noexcept
179 {
180 if (__x._M_header._M_parent != nullptr)
181 _M_move_data(__x);
182 else
183 {
184 _M_header._M_color = _S_red;
185 _M_reset();
186 }
187 }
188#endif
189
190 void
191 _M_move_data(_Rb_tree_header& __from)
192 {
193 _M_header._M_color = __from._M_header._M_color;
194 _M_header._M_parent = __from._M_header._M_parent;
195 _M_header._M_left = __from._M_header._M_left;
196 _M_header._M_right = __from._M_header._M_right;
197 _M_header._M_parent->_M_parent = &_M_header;
198 _M_node_count = __from._M_node_count;
199
200 __from._M_reset();
201 }
202
203 void
204 _M_reset()
205 {
206 _M_header._M_parent = 0;
207 _M_header._M_left = &_M_header;
208 _M_header._M_right = &_M_header;
209 _M_node_count = 0;
210 }
211 };
212
213 template<typename _Val>
214 struct _Rb_tree_node : public _Rb_tree_node_base
215 {
216#if __cplusplus < 201103L
217 _Val _M_value_field;
218
219 _Val*
220 _M_valptr()
221 { return std::__addressof(_M_value_field); }
222
223 const _Val*
224 _M_valptr() const
225 { return std::__addressof(_M_value_field); }
226#else
227 __gnu_cxx::__aligned_membuf<_Val> _M_storage;
228
229 _Val*
230 _M_valptr()
231 { return _M_storage._M_ptr(); }
232
233 const _Val*
234 _M_valptr() const
235 { return _M_storage._M_ptr(); }
236#endif
237
238 _Rb_tree_node*
239 _M_node_ptr() _GLIBCXX_NOEXCEPT
240 { return this; }
241 };
242
243#if _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
244namespace __rb_tree
245{
246 template<typename _VoidPtr>
247 struct _Node_base
248 {
249 using _Base_ptr = __ptr_rebind<_VoidPtr, _Node_base>;
250
251 _Rb_tree_color _M_color;
252 _Base_ptr _M_parent;
253 _Base_ptr _M_left;
254 _Base_ptr _M_right;
255
256 static _Base_ptr
257 _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
258 {
259 while (__x->_M_left) __x = __x->_M_left;
260 return __x;
261 }
262
263 static _Base_ptr
264 _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
265 {
266 while (__x->_M_right) __x = __x->_M_right;
267 return __x;
268 }
269
270 // This is not const-correct, but it's only used in a const access path
271 // by std::_Rb_tree::_M_end() where the pointer is used to initialize a
272 // const_iterator and so constness is restored.
273 _Base_ptr
274 _M_base_ptr() const noexcept
275 {
276 return pointer_traits<_Base_ptr>::pointer_to
277 (*const_cast<_Node_base*>(this));
278 }
279 };
280
281 // Helper type to manage default initialization of node count and header.
282 template<typename _NodeBase>
283 struct _Header
284 {
285 private:
286 using _Base_ptr = typename _NodeBase::_Base_ptr;
287
288 public:
289 _NodeBase _M_header;
290 size_t _M_node_count; // Keeps track of size of tree.
291
292 _Header() noexcept
293 {
294 _M_header._M_color = _S_red;
295 _M_reset();
296 }
297
298 _Header(_Header&& __x) noexcept
299 {
300 if (__x._M_header._M_parent)
301 _M_move_data(__x);
302 else
303 {
304 _M_header._M_color = _S_red;
305 _M_reset();
306 }
307 }
308
309 void
310 _M_move_data(_Header& __from)
311 {
312 _M_header._M_color = __from._M_header._M_color;
313 _M_header._M_parent = __from._M_header._M_parent;
314 _M_header._M_left = __from._M_header._M_left;
315 _M_header._M_right = __from._M_header._M_right;
316 _M_header._M_parent->_M_parent = _M_header._M_base_ptr();
317 _M_node_count = __from._M_node_count;
318
319 __from._M_reset();
320 }
321
322 void
323 _M_reset()
324 {
325 _M_header._M_parent = nullptr;
326 _M_header._M_left = _M_header._M_right = _M_header._M_base_ptr();
327 _M_node_count = 0;
328 }
329 };
330
331 template<typename _ValPtr>
332 struct _Node : public __rb_tree::_Node_base<__ptr_rebind<_ValPtr, void>>
333 {
334 using value_type = typename pointer_traits<_ValPtr>::element_type;
335 using _Node_ptr = __ptr_rebind<_ValPtr, _Node>;
336
337 _Node() noexcept { }
338 ~_Node() { }
339 _Node(_Node&&) = delete;
340
341 union _Uninit_storage
342 {
343 _Uninit_storage() noexcept { }
344 ~_Uninit_storage() { }
345
346 value_type _M_data;
347 };
348 _Uninit_storage _M_u;
349
350 value_type*
351 _M_valptr()
352 { return std::addressof(_M_u._M_data); }
353
354 value_type const*
355 _M_valptr() const
356 { return std::addressof(_M_u._M_data); }
357
358 _Node_ptr
359 _M_node_ptr() noexcept
360 { return pointer_traits<_Node_ptr>::pointer_to(*this); }
361 };
362} // namespace __rb_tree
363#endif // _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
364
365 _GLIBCXX_PURE _Rb_tree_node_base*
366 _Rb_tree_increment(_Rb_tree_node_base* __x) throw ();
367
368 _GLIBCXX_PURE _Rb_tree_node_base*
369 _Rb_tree_decrement(_Rb_tree_node_base* __x) throw ();
370
371 template<typename _Tp>
372 struct _Rb_tree_iterator
373 {
374 typedef _Tp value_type;
375 typedef _Tp& reference;
376 typedef _Tp* pointer;
377
378 typedef bidirectional_iterator_tag iterator_category;
379 typedef ptrdiff_t difference_type;
380
381 typedef _Rb_tree_node_base::_Base_ptr _Base_ptr;
382 typedef _Rb_tree_node<_Tp>* _Node_ptr;
383
384 _Rb_tree_iterator() _GLIBCXX_NOEXCEPT
385 : _M_node() { }
386
387 explicit
388 _Rb_tree_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT
389 : _M_node(__x) { }
390
391 reference
392 operator*() const _GLIBCXX_NOEXCEPT
393 { return *static_cast<_Node_ptr>(_M_node)->_M_valptr(); }
394
395 pointer
396 operator->() const _GLIBCXX_NOEXCEPT
397 { return static_cast<_Node_ptr>(_M_node)->_M_valptr(); }
398
399 _Rb_tree_iterator&
400 operator++() _GLIBCXX_NOEXCEPT
401 {
402 _M_node = _Rb_tree_increment(_M_node);
403 return *this;
404 }
405
406 _Rb_tree_iterator
407 operator++(int) _GLIBCXX_NOEXCEPT
408 {
409 _Rb_tree_iterator __tmp = *this;
410 _M_node = _Rb_tree_increment(_M_node);
411 return __tmp;
412 }
413
414 _Rb_tree_iterator&
415 operator--() _GLIBCXX_NOEXCEPT
416 {
417 _M_node = _Rb_tree_decrement(_M_node);
418 return *this;
419 }
420
421 _Rb_tree_iterator
422 operator--(int) _GLIBCXX_NOEXCEPT
423 {
424 _Rb_tree_iterator __tmp = *this;
425 _M_node = _Rb_tree_decrement(_M_node);
426 return __tmp;
427 }
428
429 friend bool
430 operator==(const _Rb_tree_iterator& __x,
431 const _Rb_tree_iterator& __y) _GLIBCXX_NOEXCEPT
432 { return __x._M_node == __y._M_node; }
433
434#if ! __cpp_lib_three_way_comparison
435 friend bool
436 operator!=(const _Rb_tree_iterator& __x,
437 const _Rb_tree_iterator& __y) _GLIBCXX_NOEXCEPT
438 { return __x._M_node != __y._M_node; }
439#endif
440
441 _Base_ptr _M_node;
442 };
443
444 template<typename _Tp>
445 struct _Rb_tree_const_iterator
446 {
447 typedef _Tp value_type;
448 typedef const _Tp& reference;
449 typedef const _Tp* pointer;
450
451 typedef _Rb_tree_iterator<_Tp> iterator;
452
453 typedef bidirectional_iterator_tag iterator_category;
454 typedef ptrdiff_t difference_type;
455
456 typedef _Rb_tree_node_base::_Base_ptr _Base_ptr;
457 typedef const _Rb_tree_node<_Tp>* _Node_ptr;
458
459 _Rb_tree_const_iterator() _GLIBCXX_NOEXCEPT
460 : _M_node() { }
461
462 explicit
463 _Rb_tree_const_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT
464 : _M_node(__x) { }
465
466 _Rb_tree_const_iterator(const iterator& __it) _GLIBCXX_NOEXCEPT
467 : _M_node(__it._M_node) { }
468
469 reference
470 operator*() const _GLIBCXX_NOEXCEPT
471 { return *static_cast<_Node_ptr>(_M_node)->_M_valptr(); }
472
473 pointer
474 operator->() const _GLIBCXX_NOEXCEPT
475 { return static_cast<_Node_ptr>(_M_node)->_M_valptr(); }
476
477 _Rb_tree_const_iterator&
478 operator++() _GLIBCXX_NOEXCEPT
479 {
480 _M_node = _Rb_tree_increment(_M_node);
481 return *this;
482 }
483
484 _Rb_tree_const_iterator
485 operator++(int) _GLIBCXX_NOEXCEPT
486 {
487 _Rb_tree_const_iterator __tmp = *this;
488 _M_node = _Rb_tree_increment(_M_node);
489 return __tmp;
490 }
491
492 _Rb_tree_const_iterator&
493 operator--() _GLIBCXX_NOEXCEPT
494 {
495 _M_node = _Rb_tree_decrement(_M_node);
496 return *this;
497 }
498
499 _Rb_tree_const_iterator
500 operator--(int) _GLIBCXX_NOEXCEPT
501 {
502 _Rb_tree_const_iterator __tmp = *this;
503 _M_node = _Rb_tree_decrement(_M_node);
504 return __tmp;
505 }
506
507 friend bool
508 operator==(const _Rb_tree_const_iterator& __x,
509 const _Rb_tree_const_iterator& __y) _GLIBCXX_NOEXCEPT
510 { return __x._M_node == __y._M_node; }
511
512#if ! __cpp_lib_three_way_comparison
513 friend bool
514 operator!=(const _Rb_tree_const_iterator& __x,
515 const _Rb_tree_const_iterator& __y) _GLIBCXX_NOEXCEPT
516 { return __x._M_node != __y._M_node; }
517#endif
518
519 _Base_ptr _M_node;
520 };
521
522 __attribute__((__nonnull__))
523 void
524 _Rb_tree_insert_and_rebalance(const bool __insert_left,
525 _Rb_tree_node_base* __x,
526 _Rb_tree_node_base* __p,
527 _Rb_tree_node_base& __header) throw ();
528
529 __attribute__((__nonnull__,__returns_nonnull__))
530 _Rb_tree_node_base*
531 _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z,
532 _Rb_tree_node_base& __header) throw ();
533
534namespace __rb_tree
535{
536#if _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
537 template<bool _Const, typename _ValPtr>
538 struct _Iterator
539 {
540 template<typename _Tp>
541 using __maybe_const = __conditional_t<_Const, const _Tp, _Tp>;
542
543 using __ptr_traits = pointer_traits<_ValPtr>;
544 using value_type = typename __ptr_traits::element_type;
545 using reference = __maybe_const<value_type>&;
546 using pointer = __maybe_const<value_type>*;
547
548 using iterator_category = bidirectional_iterator_tag;
549 using difference_type = ptrdiff_t;
550
551 using _Node = __rb_tree::_Node<_ValPtr>;
552 using _Node_base = __rb_tree::_Node_base<__ptr_rebind<_ValPtr, void>>;
553 using _Base_ptr = typename _Node_base::_Base_ptr;
554
555 _Iterator() noexcept
556 : _M_node() { }
557
558 constexpr explicit
559 _Iterator(_Base_ptr __x) noexcept
560 : _M_node(__x) { }
561
562 _Iterator(const _Iterator&) = default;
563 _Iterator& operator=(const _Iterator&) = default;
564
565#ifdef __glibcxx_concepts
566 constexpr
567 _Iterator(const _Iterator<false, _ValPtr>& __it) requires _Const
568#else
569 template<bool _OtherConst,
570 typename = __enable_if_t<_Const && !_OtherConst>>
571 constexpr
572 _Iterator(const _Iterator<_OtherConst, _ValPtr>& __it)
573#endif
574 : _M_node(__it._M_node) { }
575
576 [[__nodiscard__]]
577 reference
578 operator*() const noexcept
579 { return *static_cast<_Node&>(*_M_node)._M_valptr(); }
580
581 [[__nodiscard__]]
582 pointer
583 operator->() const noexcept
584 { return static_cast<_Node&>(*_M_node)._M_valptr(); }
585
586 _GLIBCXX14_CONSTEXPR _Iterator&
587 operator++() noexcept
588 {
589 if (_M_node->_M_right)
590 {
591 _M_node = _M_node->_M_right;
592 while (_M_node->_M_left)
593 _M_node = _M_node->_M_left;
594 }
595 else
596 {
597 _Base_ptr __y = _M_node->_M_parent;
598 while (_M_node == __y->_M_right)
599 {
600 _M_node = __y;
601 __y = __y->_M_parent;
602 }
603 if (_M_node->_M_right != __y)
604 _M_node = __y;
605 }
606
607 return *this;
608 }
609
610 _GLIBCXX14_CONSTEXPR _Iterator
611 operator++(int) noexcept
612 {
613 _Iterator __tmp(this->_M_node);
614 ++*this;
615 return __tmp;
616 }
617
618 _GLIBCXX14_CONSTEXPR _Iterator&
619 operator--() noexcept
620 {
621 if (_M_node->_M_color == _S_red
622 && _M_node->_M_parent->_M_parent == _M_node)
623 _M_node = _M_node->_M_right;
624 else if (_M_node->_M_left)
625 {
626 _Base_ptr __y = _M_node->_M_left;
627 while (__y->_M_right)
628 __y = __y->_M_right;
629 _M_node = __y;
630 }
631 else
632 {
633 _Base_ptr __y = _M_node->_M_parent;
634 while (_M_node == __y->_M_left)
635 {
636 _M_node = __y;
637 __y = __y->_M_parent;
638 }
639 _M_node = __y;
640 }
641 return *this;
642 }
643
644 _GLIBCXX14_CONSTEXPR _Iterator
645 operator--(int) noexcept
646 {
647 _Iterator __tmp(this->_M_node);
648 --*this;
649 return __tmp;
650 }
651
652 [[__nodiscard__]]
653 friend bool
654 operator==(const _Iterator& __x, const _Iterator& __y) _GLIBCXX_NOEXCEPT
655 { return __x._M_node == __y._M_node; }
656
657#if ! __cpp_lib_three_way_comparison
658 [[__nodiscard__]]
659 friend bool
660 operator!=(const _Iterator& __x, const _Iterator& __y) _GLIBCXX_NOEXCEPT
661 { return __x._M_node != __y._M_node; }
662#endif
663
664 _Base_ptr _M_node;
665 };
666#endif // USE_ALLOC_PTR_FOR_RB_TREE
667
668 // Determine the node and iterator types used by std::_Rb_tree.
669 template<typename _Val, typename _Ptr>
670 struct _Node_traits;
671
672#if _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE <= 9000
673 // Specialization for the simple case where the allocator's pointer type
674 // is the same type as value_type*.
675 // For ABI compatibility we can't change the types used for this case.
676 template<typename _Val>
677 struct _Node_traits<_Val, _Val*>
678 {
679 typedef _Rb_tree_node<_Val> _Node;
680 typedef _Node* _Node_ptr;
681 typedef _Rb_tree_node_base _Node_base;
682 typedef _Node_base* _Base_ptr;
683 typedef _Rb_tree_header _Header_t;
684 typedef _Rb_tree_iterator<_Val> _Iterator;
685 typedef _Rb_tree_const_iterator<_Val> _Const_iterator;
686
687 __attribute__((__nonnull__))
688 static void
689 _S_insert_and_rebalance(const bool __insert_left,
690 _Node_base* __x, _Node_base* __p,
691 _Node_base& __header) _GLIBCXX_USE_NOEXCEPT
692 {
693 return _Rb_tree_insert_and_rebalance(__insert_left, __x, __p, __header);
694 }
695
696 __attribute__((__nonnull__,__returns_nonnull__))
697 static _Node_base*
698 _S_rebalance_for_erase(_Node_base* const __z,
699 _Node_base& __header) _GLIBCXX_USE_NOEXCEPT
700 { return _Rb_tree_rebalance_for_erase(__z, __header); }
701 };
702#endif
703
704#if ! _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
705 // Always use the T* specialization.
706 template<typename _Val, typename _Ptr>
707 struct _Node_traits
708 : _Node_traits<_Val, _Val*>
709 { };
710#else
711 // Primary template used when the allocator uses fancy pointers.
712 template<typename _Val, typename _ValPtr>
713 struct _Node_traits
714 {
715 using _Node = __rb_tree::_Node<_ValPtr>;
716 using _Node_ptr = __ptr_rebind<_ValPtr, _Node>;
717 using _Node_base = __rb_tree::_Node_base<__ptr_rebind<_ValPtr, void>>;
718 using _Base_ptr = __ptr_rebind<_ValPtr, _Node_base>;
719 using _Header_t = __rb_tree::_Header<_Node_base>;
720 using _Iterator = __rb_tree::_Iterator<false, _ValPtr>;
721 using _Const_iterator = __rb_tree::_Iterator<true, _ValPtr>;
722
723 static void
724 _Rotate_left(_Base_ptr __x, _Base_ptr& __root)
725 {
726 const _Base_ptr __y = __x->_M_right;
727
728 __x->_M_right = __y->_M_left;
729 if (__y->_M_left)
730 __y->_M_left->_M_parent = __x;
731 __y->_M_parent = __x->_M_parent;
732
733 if (__x == __root)
734 __root = __y;
735 else if (__x == __x->_M_parent->_M_left)
736 __x->_M_parent->_M_left = __y;
737 else
738 __x->_M_parent->_M_right = __y;
739 __y->_M_left = __x;
740 __x->_M_parent = __y;
741 }
742
743 static void
744 _Rotate_right(_Base_ptr __x, _Base_ptr& __root)
745 {
746 const _Base_ptr __y = __x->_M_left;
747
748 __x->_M_left = __y->_M_right;
749 if (__y->_M_right)
750 __y->_M_right->_M_parent = __x;
751 __y->_M_parent = __x->_M_parent;
752
753 if (__x == __root)
754 __root = __y;
755 else if (__x == __x->_M_parent->_M_right)
756 __x->_M_parent->_M_right = __y;
757 else
758 __x->_M_parent->_M_left = __y;
759 __y->_M_right = __x;
760 __x->_M_parent = __y;
761 }
762
763 static void
764 _S_insert_and_rebalance(const bool __insert_left,
765 _Base_ptr __x, _Base_ptr __p,
766 _Node_base& __header)
767 {
768 _Base_ptr& __root = __header._M_parent;
769
770 // Initialize fields in new node to insert.
771 __x->_M_parent = __p;
772 __x->_M_left = __x->_M_right = nullptr;
773 __x->_M_color = _S_red;
774
775 // Insert.
776 // Make new node child of parent and maintain root, leftmost and
777 // rightmost nodes.
778 // N.B. First node is always inserted left.
779 if (__insert_left)
780 {
781 __p->_M_left = __x; // also makes leftmost = __x when __p == &__header
782
783 if (std::__to_address(__p) == std::addressof(__header))
784 {
785 __header._M_parent = __x;
786 __header._M_right = __x;
787 }
788 else if (__p == __header._M_left)
789 __header._M_left = __x; // maintain leftmost pointing to min node
790 }
791 else
792 {
793 __p->_M_right = __x;
794
795 if (__p == __header._M_right)
796 __header._M_right = __x; // maintain rightmost pointing to max node
797 }
798 // Rebalance.
799 while (__x != __root
800 && __x->_M_parent->_M_color == _S_red)
801 {
802 const _Base_ptr __xpp = __x->_M_parent->_M_parent;
803
804 if (__x->_M_parent == __xpp->_M_left)
805 {
806 const _Base_ptr __y = __xpp->_M_right;
807 if (__y && __y->_M_color == _S_red)
808 {
809 __x->_M_parent->_M_color = _S_black;
810 __y->_M_color = _S_black;
811 __xpp->_M_color = _S_red;
812 __x = __xpp;
813 }
814 else
815 {
816 if (__x == __x->_M_parent->_M_right)
817 {
818 __x = __x->_M_parent;
819 _Rotate_left(__x, __root);
820 }
821 __x->_M_parent->_M_color = _S_black;
822 __xpp->_M_color = _S_red;
823 _Rotate_right(__xpp, __root);
824 }
825 }
826 else
827 {
828 const _Base_ptr __y = __xpp->_M_left;
829 if (__y && __y->_M_color == _S_red)
830 {
831 __x->_M_parent->_M_color = _S_black;
832 __y->_M_color = _S_black;
833 __xpp->_M_color = _S_red;
834 __x = __xpp;
835 }
836 else
837 {
838 if (__x == __x->_M_parent->_M_left)
839 {
840 __x = __x->_M_parent;
841 _Rotate_right(__x, __root);
842 }
843 __x->_M_parent->_M_color = _S_black;
844 __xpp->_M_color = _S_red;
845 _Rotate_left(__xpp, __root);
846 }
847 }
848 }
849 __root->_M_color = _S_black;
850 }
851
852 static _Base_ptr
853 _S_rebalance_for_erase(_Base_ptr __z, _Node_base& __header)
854 {
855 _Base_ptr& __root = __header._M_parent;
856 _Base_ptr& __leftmost = __header._M_left;
857 _Base_ptr& __rightmost = __header._M_right;
858 _Base_ptr __y = __z;
859 _Base_ptr __x{};
860 _Base_ptr __x_parent{};
861
862 if (!__y->_M_left) // __z has at most one non-null child. y == z.
863 __x = __y->_M_right; // __x might be null.
864 else
865 if (!__y->_M_right) // __z has exactly one non-null child. y == z.
866 __x = __y->_M_left; // __x is not null.
867 else
868 {
869 // __z has two non-null children. Set __y to
870 __y = __y->_M_right; // __z's successor. __x might be null.
871 while (__y->_M_left)
872 __y = __y->_M_left;
873 __x = __y->_M_right;
874 }
875 if (__y != __z)
876 {
877 // relink y in place of z. y is z's successor
878 __z->_M_left->_M_parent = __y;
879 __y->_M_left = __z->_M_left;
880 if (__y != __z->_M_right)
881 {
882 __x_parent = __y->_M_parent;
883 if (__x)
884 __x->_M_parent = __y->_M_parent;
885 __y->_M_parent->_M_left = __x; // __y must be a child of _M_left
886 __y->_M_right = __z->_M_right;
887 __z->_M_right->_M_parent = __y;
888 }
889 else
890 __x_parent = __y;
891 if (__root == __z)
892 __root = __y;
893 else if (__z->_M_parent->_M_left == __z)
894 __z->_M_parent->_M_left = __y;
895 else
896 __z->_M_parent->_M_right = __y;
897 __y->_M_parent = __z->_M_parent;
898 std::swap(__y->_M_color, __z->_M_color);
899 __y = __z;
900 // __y now points to node to be actually deleted
901 }
902 else
903 { // __y == __z
904 __x_parent = __y->_M_parent;
905 if (__x)
906 __x->_M_parent = __y->_M_parent;
907 if (__root == __z)
908 __root = __x;
909 else
910 if (__z->_M_parent->_M_left == __z)
911 __z->_M_parent->_M_left = __x;
912 else
913 __z->_M_parent->_M_right = __x;
914 if (__leftmost == __z)
915 {
916 if (!__z->_M_right) // __z->_M_left must be null also
917 __leftmost = __z->_M_parent;
918 // makes __leftmost == _M_header if __z == __root
919 else
920 __leftmost = _Node_base::_S_minimum(__x);
921 }
922 if (__rightmost == __z)
923 {
924 if (__z->_M_left == 0) // __z->_M_right must be null also
925 __rightmost = __z->_M_parent;
926 // makes __rightmost == _M_header if __z == __root
927 else // __x == __z->_M_left
928 __rightmost = _Node_base::_S_maximum(__x);
929 }
930 }
931 if (__y->_M_color != _S_red)
932 {
933 while (__x != __root && (__x == 0 || __x->_M_color == _S_black))
934 if (__x == __x_parent->_M_left)
935 {
936 _Base_ptr __w = __x_parent->_M_right;
937 if (__w->_M_color == _S_red)
938 {
939 __w->_M_color = _S_black;
940 __x_parent->_M_color = _S_red;
941 _Rotate_left(__x_parent, __root);
942 __w = __x_parent->_M_right;
943 }
944 if ((!__w->_M_left || __w->_M_left->_M_color == _S_black) &&
945 (!__w->_M_right || __w->_M_right->_M_color == _S_black))
946 {
947 __w->_M_color = _S_red;
948 __x = __x_parent;
949 __x_parent = __x_parent->_M_parent;
950 }
951 else
952 {
953 if (!__w->_M_right || __w->_M_right->_M_color == _S_black)
954 {
955 __w->_M_left->_M_color = _S_black;
956 __w->_M_color = _S_red;
957 _Rotate_right(__w, __root);
958 __w = __x_parent->_M_right;
959 }
960 __w->_M_color = __x_parent->_M_color;
961 __x_parent->_M_color = _S_black;
962 if (__w->_M_right)
963 __w->_M_right->_M_color = _S_black;
964 _Rotate_left(__x_parent, __root);
965 break;
966 }
967 }
968 else
969 {
970 // same as above, with _M_right <-> _M_left.
971 _Base_ptr __w = __x_parent->_M_left;
972 if (__w->_M_color == _S_red)
973 {
974 __w->_M_color = _S_black;
975 __x_parent->_M_color = _S_red;
976 _Rotate_right(__x_parent, __root);
977 __w = __x_parent->_M_left;
978 }
979 if ((!__w->_M_right || __w->_M_right->_M_color == _S_black) &&
980 (!__w->_M_left || __w->_M_left->_M_color == _S_black))
981 {
982 __w->_M_color = _S_red;
983 __x = __x_parent;
984 __x_parent = __x_parent->_M_parent;
985 }
986 else
987 {
988 if (!__w->_M_left || __w->_M_left->_M_color == _S_black)
989 {
990 __w->_M_right->_M_color = _S_black;
991 __w->_M_color = _S_red;
992 _Rotate_left(__w, __root);
993 __w = __x_parent->_M_left;
994 }
995 __w->_M_color = __x_parent->_M_color;
996 __x_parent->_M_color = _S_black;
997 if (__w->_M_left)
998 __w->_M_left->_M_color = _S_black;
999 _Rotate_right(__x_parent, __root);
1000 break;
1001 }
1002 }
1003 if (__x)
1004 __x->_M_color = _S_black;
1005 }
1006
1007 return __y;
1008 }
1009 };
1010#endif
1011} // namespace __rb_tree
1012
1013#ifdef __glibcxx_node_extract // >= C++17
1014 template<typename _Tree1, typename _Cmp2>
1015 struct _Rb_tree_merge_helper { };
1016#endif
1017
1018 template<typename _Key, typename _Val, typename _KeyOfValue,
1019 typename _Compare, typename _Alloc = allocator<_Val> >
1020 class _Rb_tree
1021 {
1022 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
1023 rebind<_Val>::other _Val_alloc_type;
1024
1025 typedef __gnu_cxx::__alloc_traits<_Val_alloc_type> _Val_alloc_traits;
1026 typedef typename _Val_alloc_traits::pointer _ValPtr;
1027 typedef __rb_tree::_Node_traits<_Val, _ValPtr> _Node_traits;
1028
1029 typedef typename _Node_traits::_Node_base _Node_base;
1030 typedef typename _Node_traits::_Node _Node;
1031
1032 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
1033 rebind<_Node>::other _Node_allocator;
1034
1035 typedef __gnu_cxx::__alloc_traits<_Node_allocator> _Node_alloc_traits;
1036
1037 protected:
1038 typedef typename _Node_traits::_Base_ptr _Base_ptr;
1039 typedef typename _Node_traits::_Node_ptr _Node_ptr;
1040
1041 private:
1042 // Functor recycling a pool of nodes and using allocation once the pool
1043 // is empty.
1044 struct _Reuse_or_alloc_node
1045 {
1046 _Reuse_or_alloc_node(_Rb_tree& __t)
1047 : _M_root(__t._M_root()), _M_nodes(__t._M_rightmost()), _M_t(__t)
1048 {
1049 if (_M_root)
1050 {
1051 _M_root->_M_parent = _Base_ptr();
1052
1053 if (_M_nodes->_M_left)
1054 _M_nodes = _M_nodes->_M_left;
1055 }
1056 else
1057 _M_nodes = _Base_ptr();
1058 }
1059
1060#if __cplusplus >= 201103L
1061 _Reuse_or_alloc_node(const _Reuse_or_alloc_node&) = delete;
1062#endif
1063
1064 ~_Reuse_or_alloc_node()
1065 {
1066 if (_M_root)
1067 _M_t._M_erase(static_cast<_Node&>(*_M_root)._M_node_ptr());
1068 }
1069
1070 template<typename _Arg>
1071 _Node_ptr
1072 operator()(_GLIBCXX_FWDREF(_Arg) __arg)
1073 {
1074 _Base_ptr __base = _M_extract();
1075 if (__base)
1076 {
1077 _Node_ptr __node = static_cast<_Node&>(*__base)._M_node_ptr();
1078 _M_t._M_destroy_node(__node);
1079 _M_t._M_construct_node(__node, _GLIBCXX_FORWARD(_Arg, __arg));
1080 return __node;
1081 }
1082
1083 return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg));
1084 }
1085
1086 private:
1087 _Base_ptr
1088 _M_extract()
1089 {
1090 if (!_M_nodes)
1091 return _M_nodes;
1092
1093 _Base_ptr __node = _M_nodes;
1094 _M_nodes = _M_nodes->_M_parent;
1095 if (_M_nodes)
1096 {
1097 if (_M_nodes->_M_right == __node)
1098 {
1099 _M_nodes->_M_right = _Base_ptr();
1100
1101 if (_M_nodes->_M_left)
1102 {
1103 _M_nodes = _M_nodes->_M_left;
1104
1105 while (_M_nodes->_M_right)
1106 _M_nodes = _M_nodes->_M_right;
1107
1108 if (_M_nodes->_M_left)
1109 _M_nodes = _M_nodes->_M_left;
1110 }
1111 }
1112 else // __node is on the left.
1113 _M_nodes->_M_left = _Base_ptr();
1114 }
1115 else
1116 _M_root = _Base_ptr();
1117
1118 return __node;
1119 }
1120
1121 _Base_ptr _M_root;
1122 _Base_ptr _M_nodes;
1123 _Rb_tree& _M_t;
1124 };
1125
1126 // Functor similar to the previous one but without any pool of nodes to
1127 // recycle.
1128 struct _Alloc_node
1129 {
1130 _Alloc_node(_Rb_tree& __t)
1131 : _M_t(__t) { }
1132
1133 template<typename _Arg>
1134 _Node_ptr
1135 operator()(_GLIBCXX_FWDREF(_Arg) __arg) const
1136 { return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); }
1137
1138 private:
1139 _Rb_tree& _M_t;
1140 };
1141
1142 public:
1143 typedef _Key key_type;
1144 typedef _Val value_type;
1145 typedef value_type* pointer;
1146 typedef const value_type* const_pointer;
1147 typedef value_type& reference;
1148 typedef const value_type& const_reference;
1149 typedef size_t size_type;
1150 typedef ptrdiff_t difference_type;
1151 typedef _Alloc allocator_type;
1152
1153 _Node_allocator&
1154 _M_get_Node_allocator() _GLIBCXX_NOEXCEPT
1155 { return this->_M_impl; }
1156
1157 const _Node_allocator&
1158 _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT
1159 { return this->_M_impl; }
1160
1161 allocator_type
1162 get_allocator() const _GLIBCXX_NOEXCEPT
1163 { return allocator_type(_M_get_Node_allocator()); }
1164
1165 protected:
1166 _Node_ptr
1167 _M_get_node()
1168 {
1169#if __cplusplus < 201102L || _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
1170 return _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1);
1171#else
1172#pragma GCC diagnostic push
1173#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
1174 using __alloc_pointer = typename _Node_alloc_traits::pointer;
1175 if constexpr (is_same<_Node_ptr, __alloc_pointer>::value)
1176 return _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1);
1177 else
1178 {
1179 auto __ptr =
1180 _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1);
1181 return std::__to_address(__ptr);
1182 }
1183#pragma GCC diagnostic pop
1184#endif
1185 }
1186
1187 void
1188 _M_put_node(_Node_ptr __p) _GLIBCXX_NOEXCEPT
1189 {
1190#if __cplusplus < 201102L || _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
1191 _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1);
1192#else
1193#pragma GCC diagnostic push
1194#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
1195 using __alloc_pointer = typename _Node_alloc_traits::pointer;
1196 if constexpr (is_same<_Node_ptr, __alloc_pointer>::value)
1197 _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1);
1198 else
1199 {
1200 // When not using the allocator's pointer type internally we must
1201 // convert __p to __alloc_pointer so it can be deallocated.
1202 auto __ap = pointer_traits<__alloc_pointer>::pointer_to(*__p);
1203 _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __ap, 1);
1204 }
1205#pragma GCC diagnostic pop
1206#endif
1207 }
1208
1209#if __cplusplus < 201103L
1210 void
1211 _M_construct_node(_Node_ptr __node, const value_type& __x)
1212 {
1213 __try
1214 { get_allocator().construct(__node->_M_valptr(), __x); }
1215 __catch(...)
1216 {
1217 _M_put_node(__node);
1218 __throw_exception_again;
1219 }
1220 }
1221
1222 _Node_ptr
1223 _M_create_node(const value_type& __x)
1224 {
1225 _Node_ptr __tmp = _M_get_node();
1226 _M_construct_node(__tmp, __x);
1227 return __tmp;
1228 }
1229#else
1230 template<typename... _Args>
1231 void
1232 _M_construct_node(_Node_ptr __node, _Args&&... __args)
1233 {
1234 __try
1235 {
1236 ::new(std::addressof(*__node)) _Node;
1237 _Node_alloc_traits::construct(_M_get_Node_allocator(),
1238 __node->_M_valptr(),
1239 std::forward<_Args>(__args)...);
1240 }
1241 __catch(...)
1242 {
1243 __node->~_Node();
1244 _M_put_node(__node);
1245 __throw_exception_again;
1246 }
1247 }
1248
1249 template<typename... _Args>
1250 _Node_ptr
1251 _M_create_node(_Args&&... __args)
1252 {
1253 _Node_ptr __tmp = _M_get_node();
1254 _M_construct_node(__tmp, std::forward<_Args>(__args)...);
1255 return __tmp;
1256 }
1257#endif
1258
1259 void
1260 _M_destroy_node(_Node_ptr __p) _GLIBCXX_NOEXCEPT
1261 {
1262#if __cplusplus < 201103L
1263 get_allocator().destroy(__p->_M_valptr());
1264#else
1265 _Node_alloc_traits::destroy(_M_get_Node_allocator(), __p->_M_valptr());
1266 __p->~_Node();
1267#endif
1268 }
1269
1270 void
1271 _M_drop_node(_Node_ptr __p) _GLIBCXX_NOEXCEPT
1272 {
1273 _M_destroy_node(__p);
1274 _M_put_node(__p);
1275 }
1276
1277 template<bool _MoveValue, typename _NodeGen>
1278 _Node_ptr
1279 _M_clone_node(_Node_ptr __x, _NodeGen& __node_gen)
1280 {
1281#if __cplusplus >= 201103L
1282 using _Vp = __conditional_t<_MoveValue,
1283 value_type&&,
1284 const value_type&>;
1285#endif
1286 _Node_ptr __tmp
1287 = __node_gen(_GLIBCXX_FORWARD(_Vp, *__x->_M_valptr()));
1288 __tmp->_M_color = __x->_M_color;
1289 __tmp->_M_left = __tmp->_M_right = _Base_ptr();
1290 return __tmp;
1291 }
1292
1293 protected:
1294 typedef typename _Node_traits::_Header_t _Header_t;
1295
1296#if _GLIBCXX_INLINE_VERSION
1297 template<typename _Key_compare>
1298#else
1299 // Unused _Is_pod_comparator is kept as it is part of mangled name.
1300 template<typename _Key_compare,
1301 bool /* _Is_pod_comparator */ = __is_pod(_Key_compare)>
1302#endif
1303 struct _Rb_tree_impl
1304 : public _Node_allocator
1305 , public _Rb_tree_key_compare<_Key_compare>
1306 , public _Header_t
1307 {
1308 typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare;
1309
1310 _Rb_tree_impl()
1311 _GLIBCXX_NOEXCEPT_IF(
1312 is_nothrow_default_constructible<_Node_allocator>::value
1313 && is_nothrow_default_constructible<_Base_key_compare>::value )
1314 : _Node_allocator()
1315 { }
1316
1317 _Rb_tree_impl(const _Rb_tree_impl& __x)
1318 : _Node_allocator(_Node_alloc_traits::_S_select_on_copy(__x))
1319 , _Base_key_compare(__x._M_key_compare)
1320 , _Header_t()
1321 { }
1322
1323#if __cplusplus < 201103L
1324 _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a)
1325 : _Node_allocator(__a), _Base_key_compare(__comp)
1326 { }
1327#else
1328 _Rb_tree_impl(_Rb_tree_impl&&)
1329 noexcept( is_nothrow_move_constructible<_Base_key_compare>::value )
1330 = default;
1331
1332 explicit
1333 _Rb_tree_impl(_Node_allocator&& __a)
1334 : _Node_allocator(std::move(__a))
1335 { }
1336
1337 _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a)
1338 : _Node_allocator(std::move(__a)),
1339 _Base_key_compare(std::move(__x)),
1340 _Header_t(std::move(__x))
1341 { }
1342
1343 _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a)
1344 : _Node_allocator(std::move(__a)), _Base_key_compare(__comp)
1345 { }
1346#endif
1347 };
1348
1349 _Rb_tree_impl<_Compare> _M_impl;
1350
1351 protected:
1352 _Base_ptr&
1353 _M_root() _GLIBCXX_NOEXCEPT
1354 { return this->_M_impl._M_header._M_parent; }
1355
1356 _Base_ptr
1357 _M_root() const _GLIBCXX_NOEXCEPT
1358 { return this->_M_impl._M_header._M_parent; }
1359
1360 _Base_ptr&
1361 _M_leftmost() _GLIBCXX_NOEXCEPT
1362 { return this->_M_impl._M_header._M_left; }
1363
1364 _Base_ptr
1365 _M_leftmost() const _GLIBCXX_NOEXCEPT
1366 { return this->_M_impl._M_header._M_left; }
1367
1368 _Base_ptr&
1369 _M_rightmost() _GLIBCXX_NOEXCEPT
1370 { return this->_M_impl._M_header._M_right; }
1371
1372 _Base_ptr
1373 _M_rightmost() const _GLIBCXX_NOEXCEPT
1374 { return this->_M_impl._M_header._M_right; }
1375
1376 _Base_ptr
1377 _M_begin() const _GLIBCXX_NOEXCEPT
1378 { return this->_M_impl._M_header._M_parent; }
1379
1380 _Node_ptr
1381 _M_begin_node() const _GLIBCXX_NOEXCEPT
1382 {
1383 _Base_ptr __begin = this->_M_impl._M_header._M_parent;
1384 return __begin
1385 ? static_cast<_Node&>(*__begin)._M_node_ptr()
1386 : _Node_ptr();
1387 }
1388
1389 _Base_ptr
1390 _M_end() const _GLIBCXX_NOEXCEPT
1391 { return this->_M_impl._M_header._M_base_ptr(); }
1392
1393 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1394 // 2542. Missing const requirements for associative containers
1395 template<typename _Key1, typename _Key2>
1396 bool
1397 _M_key_compare(const _Key1& __k1, const _Key2& __k2) const
1398 {
1399#if __cplusplus >= 201103L
1400 // Enforce this here with a user-friendly message.
1401 static_assert(
1402 __is_invocable<const _Compare&, const _Key&, const _Key&>::value,
1403 "comparison object must be invocable with arguments of key_type"
1404 );
1405#endif
1406 return _M_impl._M_key_compare(__k1, __k2);
1407 }
1408
1409 static const _Key&
1410 _S_key(const _Node& __node)
1411 { return _KeyOfValue()(*__node._M_valptr()); }
1412
1413 static const _Key&
1414 _S_key(_Base_ptr __x)
1415 { return _S_key(static_cast<const _Node&>(*__x)); }
1416
1417 static const _Key&
1418 _S_key(_Node_ptr __x)
1419 { return _S_key(*__x); }
1420
1421 static _Base_ptr
1422 _S_left(_Base_ptr __x) _GLIBCXX_NOEXCEPT
1423 { return __x->_M_left; }
1424
1425 static _Node_ptr
1426 _S_left(_Node_ptr __x)
1427 {
1428 return __x->_M_left
1429 ? static_cast<_Node&>(*__x->_M_left)._M_node_ptr()
1430 : _Node_ptr();
1431 }
1432
1433 static _Base_ptr
1434 _S_right(_Base_ptr __x) _GLIBCXX_NOEXCEPT
1435 { return __x->_M_right; }
1436
1437 static _Node_ptr
1438 _S_right(_Node_ptr __x) _GLIBCXX_NOEXCEPT
1439 {
1440 return __x->_M_right
1441 ? static_cast<_Node&>(*__x->_M_right)._M_node_ptr()
1442 : _Node_ptr();
1443 }
1444
1445 public:
1446 typedef typename _Node_traits::_Iterator iterator;
1447 typedef typename _Node_traits::_Const_iterator const_iterator;
1448
1449 typedef std::reverse_iterator<iterator> reverse_iterator;
1450 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1451
1452#ifdef __glibcxx_node_extract // >= C++17
1453 using node_type = _Node_handle<_Key, _Val, _Node_allocator>;
1454 using insert_return_type = _Node_insert_return<
1455 __conditional_t<is_same_v<_Key, _Val>, const_iterator, iterator>,
1456 node_type>;
1457#endif
1458
1459 pair<_Base_ptr, _Base_ptr>
1460 _M_get_insert_unique_pos(const key_type& __k);
1461
1462 pair<_Base_ptr, _Base_ptr>
1463 _M_get_insert_equal_pos(const key_type& __k);
1464
1465 pair<_Base_ptr, _Base_ptr>
1466 _M_get_insert_hint_unique_pos(const_iterator __pos,
1467 const key_type& __k);
1468
1469 pair<_Base_ptr, _Base_ptr>
1470 _M_get_insert_hint_equal_pos(const_iterator __pos,
1471 const key_type& __k);
1472
1473#ifdef __glibcxx_associative_heterogeneous_insertion // C++26
1474 template <typename... _Args>
1475 iterator
1476 _M_emplace_here(bool __place_left, _Base_ptr __node, _Args&&... __args);
1477
1478 template <typename _Kt>
1479 pair<_Base_ptr, _Base_ptr>
1480 _M_get_insert_unique_pos_tr(const _Kt& __k);
1481
1482 template <typename _Kt>
1483 pair<_Base_ptr, _Base_ptr>
1484 _M_get_insert_hint_unique_pos_tr(const_iterator, const _Kt& __k);
1485#endif
1486
1487 private:
1488#if __cplusplus >= 201103L
1489 template<typename _Arg, typename _NodeGen>
1490 iterator
1491 _M_insert_(_Base_ptr __x, _Base_ptr __y, _Arg&& __v, _NodeGen&);
1492
1493 iterator
1494 _M_insert_node(_Base_ptr __x, _Base_ptr __y, _Node_ptr __z);
1495
1496 template<typename _Arg>
1497 iterator
1498 _M_insert_lower(_Base_ptr __y, _Arg&& __v);
1499
1500 template<typename _Arg>
1501 iterator
1502 _M_insert_equal_lower(_Arg&& __x);
1503
1504 iterator
1505 _M_insert_lower_node(_Base_ptr __p, _Node_ptr __z);
1506
1507 iterator
1508 _M_insert_equal_lower_node(_Node_ptr __z);
1509#else
1510 template<typename _NodeGen>
1511 iterator
1512 _M_insert_(_Base_ptr __x, _Base_ptr __y,
1513 const value_type& __v, _NodeGen&);
1514
1515 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1516 // 233. Insertion hints in associative containers.
1517 iterator
1518 _M_insert_lower(_Base_ptr __y, const value_type& __v);
1519
1520 iterator
1521 _M_insert_equal_lower(const value_type& __x);
1522#endif
1523
1524 enum { __as_lvalue, __as_rvalue };
1525
1526 template<bool _MoveValues, typename _NodeGen>
1527 _Base_ptr
1528 _M_copy(_Node_ptr, _Base_ptr, _NodeGen&);
1529
1530 template<bool _MoveValues, typename _NodeGen>
1531 _Base_ptr
1532 _M_copy(const _Rb_tree& __x, _NodeGen& __gen)
1533 {
1534 _Base_ptr __root =
1535 _M_copy<_MoveValues>(__x._M_begin_node(), _M_end(), __gen);
1536 _M_leftmost() = _Node_base::_S_minimum(__root);
1537 _M_rightmost() = _Node_base::_S_maximum(__root);
1538 _M_impl._M_node_count = __x._M_impl._M_node_count;
1539 return __root;
1540 }
1541
1542 _Base_ptr
1543 _M_copy(const _Rb_tree& __x)
1544 {
1545 _Alloc_node __an(*this);
1546 return _M_copy<__as_lvalue>(__x, __an);
1547 }
1548
1549 void
1550 _M_erase(_Node_ptr __x);
1551
1552 _Base_ptr
1553 _M_lower_bound(_Base_ptr __x, _Base_ptr __y,
1554 const _Key& __k) const;
1555
1556 template <typename _Kt>
1557 _Base_ptr
1558 _M_lower_bound_tr(_Base_ptr __x, _Base_ptr __y, const _Kt& __k) const;
1559
1560 _Base_ptr
1561 _M_upper_bound(_Base_ptr __x, _Base_ptr __y,
1562 const _Key& __k) const;
1563
1564 template <typename _Kt>
1565 _Base_ptr
1566 _M_upper_bound_tr(_Base_ptr __x, _Base_ptr __y, const _Kt& __k) const;
1567
1568 public:
1569 // allocation/deallocation
1570#if __cplusplus < 201103L
1571 _Rb_tree() { }
1572#else
1573 _Rb_tree() = default;
1574#endif
1575
1576 _Rb_tree(const _Compare& __comp,
1577 const allocator_type& __a = allocator_type())
1578 : _M_impl(__comp, _Node_allocator(__a)) { }
1579
1580 _Rb_tree(const _Rb_tree& __x)
1581 : _M_impl(__x._M_impl)
1582 {
1583 if (__x._M_root())
1584 _M_root() = _M_copy(__x);
1585 }
1586
1587#if __cplusplus >= 201103L
1588 _Rb_tree(const allocator_type& __a)
1589 : _M_impl(_Node_allocator(__a))
1590 { }
1591
1592 _Rb_tree(const _Rb_tree& __x, const allocator_type& __a)
1593 : _M_impl(__x._M_impl._M_key_compare, _Node_allocator(__a))
1594 {
1595 if (__x._M_root())
1596 _M_root() = _M_copy(__x);
1597 }
1598
1599 _Rb_tree(_Rb_tree&&) = default;
1600
1601 _Rb_tree(_Rb_tree&& __x, const allocator_type& __a)
1602 : _Rb_tree(std::move(__x), _Node_allocator(__a))
1603 { }
1604
1605 private:
1606 _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type)
1607 noexcept(is_nothrow_default_constructible<_Compare>::value)
1608 : _M_impl(std::move(__x._M_impl), std::move(__a))
1609 { }
1610
1611 _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type)
1612 : _M_impl(__x._M_impl._M_key_compare, std::move(__a))
1613 {
1614 if (__x._M_root())
1615 _M_move_data(__x, false_type{});
1616 }
1617
1618 public:
1619 _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)
1620 noexcept( noexcept(
1621 _Rb_tree(std::declval<_Rb_tree&&>(), std::declval<_Node_allocator&&>(),
1622 std::declval<typename _Node_alloc_traits::is_always_equal>())) )
1623 : _Rb_tree(std::move(__x), std::move(__a),
1624 typename _Node_alloc_traits::is_always_equal{})
1625 { }
1626#endif
1627
1628 ~_Rb_tree() _GLIBCXX_NOEXCEPT
1629 { _M_erase(_M_begin_node()); }
1630
1631 _Rb_tree&
1632 operator=(const _Rb_tree& __x);
1633
1634 // Accessors.
1635 _Compare
1636 key_comp() const
1637 { return _M_impl._M_key_compare; }
1638
1639 iterator
1640 begin() _GLIBCXX_NOEXCEPT
1641 { return iterator(this->_M_impl._M_header._M_left); }
1642
1643 const_iterator
1644 begin() const _GLIBCXX_NOEXCEPT
1645 { return const_iterator(this->_M_impl._M_header._M_left); }
1646
1647 iterator
1648 end() _GLIBCXX_NOEXCEPT
1649 { return iterator(_M_end()); }
1650
1651 const_iterator
1652 end() const _GLIBCXX_NOEXCEPT
1653 { return const_iterator(_M_end()); }
1654
1655 reverse_iterator
1656 rbegin() _GLIBCXX_NOEXCEPT
1657 { return reverse_iterator(end()); }
1658
1659 const_reverse_iterator
1660 rbegin() const _GLIBCXX_NOEXCEPT
1661 { return const_reverse_iterator(end()); }
1662
1663 reverse_iterator
1664 rend() _GLIBCXX_NOEXCEPT
1665 { return reverse_iterator(begin()); }
1666
1667 const_reverse_iterator
1668 rend() const _GLIBCXX_NOEXCEPT
1669 { return const_reverse_iterator(begin()); }
1670
1671 _GLIBCXX_NODISCARD bool
1672 empty() const _GLIBCXX_NOEXCEPT
1673 { return _M_impl._M_node_count == 0; }
1674
1675 size_type
1676 size() const _GLIBCXX_NOEXCEPT
1677 { return _M_impl._M_node_count; }
1678
1679 size_type
1680 max_size() const _GLIBCXX_NOEXCEPT
1681 { return _Node_alloc_traits::max_size(_M_get_Node_allocator()); }
1682
1683 void
1684 swap(_Rb_tree& __t)
1685 _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value);
1686
1687 // Insert/erase.
1688#if __cplusplus >= 201103L
1689 template<typename _Arg>
1690 pair<iterator, bool>
1691 _M_insert_unique(_Arg&& __x);
1692
1693 template<typename _Arg>
1694 iterator
1695 _M_insert_equal(_Arg&& __x);
1696
1697 template<typename _Arg, typename _NodeGen>
1698 iterator
1699 _M_insert_unique_(const_iterator __pos, _Arg&& __x, _NodeGen&);
1700
1701 template<typename _Arg>
1702 iterator
1703 _M_insert_unique_(const_iterator __pos, _Arg&& __x)
1704 {
1705 _Alloc_node __an(*this);
1706 return _M_insert_unique_(__pos, std::forward<_Arg>(__x), __an);
1707 }
1708
1709 template<typename _Arg, typename _NodeGen>
1710 iterator
1711 _M_insert_equal_(const_iterator __pos, _Arg&& __x, _NodeGen&);
1712
1713 template<typename _Arg>
1714 iterator
1715 _M_insert_equal_(const_iterator __pos, _Arg&& __x)
1716 {
1717 _Alloc_node __an(*this);
1718 return _M_insert_equal_(__pos, std::forward<_Arg>(__x), __an);
1719 }
1720
1721 template<typename... _Args>
1722 pair<iterator, bool>
1723 _M_emplace_unique(_Args&&... __args);
1724
1725 template<typename... _Args>
1726 iterator
1727 _M_emplace_equal(_Args&&... __args);
1728
1729 template<typename... _Args>
1730 iterator
1731 _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args);
1732
1733 template<typename... _Args>
1734 iterator
1735 _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args);
1736
1737 template<typename _Iter>
1738 using __same_value_type
1739 = is_same<value_type, typename iterator_traits<_Iter>::value_type>;
1740
1741 template<typename _InputIterator>
1742 __enable_if_t<__same_value_type<_InputIterator>::value>
1743 _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
1744 {
1745 _Alloc_node __an(*this);
1746 for (; __first != __last; ++__first)
1747 _M_insert_unique_(end(), *__first, __an);
1748 }
1749
1750 template<typename _InputIterator>
1751 __enable_if_t<!__same_value_type<_InputIterator>::value>
1752 _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
1753 {
1754 for (; __first != __last; ++__first)
1755 _M_emplace_unique(*__first);
1756 }
1757
1758 template<typename _InputIterator>
1759 __enable_if_t<__same_value_type<_InputIterator>::value>
1760 _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
1761 {
1762 _Alloc_node __an(*this);
1763 for (; __first != __last; ++__first)
1764 _M_insert_equal_(end(), *__first, __an);
1765 }
1766
1767 template<typename _InputIterator>
1768 __enable_if_t<!__same_value_type<_InputIterator>::value>
1769 _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
1770 {
1771 for (; __first != __last; ++__first)
1772 _M_emplace_equal(*__first);
1773 }
1774#else
1775 pair<iterator, bool>
1776 _M_insert_unique(const value_type& __x);
1777
1778 iterator
1779 _M_insert_equal(const value_type& __x);
1780
1781 template<typename _NodeGen>
1782 iterator
1783 _M_insert_unique_(const_iterator __pos, const value_type& __x,
1784 _NodeGen&);
1785
1786 iterator
1787 _M_insert_unique_(const_iterator __pos, const value_type& __x)
1788 {
1789 _Alloc_node __an(*this);
1790 return _M_insert_unique_(__pos, __x, __an);
1791 }
1792
1793 template<typename _NodeGen>
1794 iterator
1795 _M_insert_equal_(const_iterator __pos, const value_type& __x,
1796 _NodeGen&);
1797 iterator
1798 _M_insert_equal_(const_iterator __pos, const value_type& __x)
1799 {
1800 _Alloc_node __an(*this);
1801 return _M_insert_equal_(__pos, __x, __an);
1802 }
1803
1804 template<typename _InputIterator>
1805 void
1806 _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
1807 {
1808 _Alloc_node __an(*this);
1809 for (; __first != __last; ++__first)
1810 _M_insert_unique_(end(), *__first, __an);
1811 }
1812
1813 template<typename _InputIterator>
1814 void
1815 _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
1816 {
1817 _Alloc_node __an(*this);
1818 for (; __first != __last; ++__first)
1819 _M_insert_equal_(end(), *__first, __an);
1820 }
1821#endif
1822
1823 private:
1824 void
1825 _M_erase_aux(const_iterator __position);
1826
1827 void
1828 _M_erase_aux(const_iterator __first, const_iterator __last);
1829
1830 public:
1831#if __cplusplus >= 201103L
1832 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1833 // DR 130. Associative erase should return an iterator.
1834 _GLIBCXX_ABI_TAG_CXX11
1835 iterator
1836 erase(const_iterator __position)
1837 {
1838 __glibcxx_assert(__position != end());
1839 const_iterator __result = __position;
1840 ++__result;
1841 _M_erase_aux(__position);
1842 return iterator(__result._M_node);
1843 }
1844
1845 // LWG 2059.
1846 _GLIBCXX_ABI_TAG_CXX11
1847 iterator
1848 erase(iterator __position)
1849 {
1850 __glibcxx_assert(__position != end());
1851 iterator __result = __position;
1852 ++__result;
1853 _M_erase_aux(__position);
1854 return __result;
1855 }
1856#else
1857 void
1858 erase(iterator __position)
1859 {
1860 __glibcxx_assert(__position != end());
1861 _M_erase_aux(__position);
1862 }
1863
1864 void
1865 erase(const_iterator __position)
1866 {
1867 __glibcxx_assert(__position != end());
1868 _M_erase_aux(__position);
1869 }
1870#endif
1871
1872 size_type
1873 erase(const key_type& __x);
1874
1875 template <typename _Kt>
1876 size_type
1877 _M_erase_tr(const _Kt& __x);
1878
1879 size_type
1880 _M_erase_unique(const key_type& __x);
1881
1882#if __cplusplus >= 201103L
1883 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1884 // DR 130. Associative erase should return an iterator.
1885 _GLIBCXX_ABI_TAG_CXX11
1886 iterator
1887 erase(const_iterator __first, const_iterator __last)
1888 {
1889 _M_erase_aux(__first, __last);
1890 return iterator(__last._M_node);
1891 }
1892#else
1893 void
1894 erase(iterator __first, iterator __last)
1895 { _M_erase_aux(__first, __last); }
1896
1897 void
1898 erase(const_iterator __first, const_iterator __last)
1899 { _M_erase_aux(__first, __last); }
1900#endif
1901
1902 void
1903 clear() _GLIBCXX_NOEXCEPT
1904 {
1905 _M_erase(_M_begin_node());
1906 _M_impl._M_reset();
1907 }
1908
1909 // Set operations.
1910 iterator
1911 find(const key_type& __k);
1912
1913 const_iterator
1914 find(const key_type& __k) const;
1915
1916 size_type
1917 count(const key_type& __k) const;
1918
1919 iterator
1920 lower_bound(const key_type& __k)
1921 { return iterator(_M_lower_bound(_M_begin(), _M_end(), __k)); }
1922
1923 const_iterator
1924 lower_bound(const key_type& __k) const
1925 {
1926 return const_iterator
1927 (_M_lower_bound(_M_begin(), _M_end(), __k));
1928 }
1929
1930 iterator
1931 upper_bound(const key_type& __k)
1932 { return iterator(_M_upper_bound(_M_begin(), _M_end(), __k)); }
1933
1934 const_iterator
1935 upper_bound(const key_type& __k) const
1936 {
1937 return const_iterator
1938 (_M_upper_bound(_M_begin(), _M_end(), __k));
1939 }
1940
1941 pair<iterator, iterator>
1942 equal_range(const key_type& __k);
1943
1944 pair<const_iterator, const_iterator>
1945 equal_range(const key_type& __k) const;
1946
1947#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
1948 template<typename _Kt,
1949 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1950 iterator
1951 _M_find_tr(const _Kt& __k)
1952 {
1953 const _Rb_tree* __const_this = this;
1954 return iterator(__const_this->_M_find_tr(__k)._M_node);
1955 }
1956
1957 template<typename _Kt,
1958 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1959 const_iterator
1960 _M_find_tr(const _Kt& __k) const
1961 {
1962 const_iterator __j(_M_lower_bound_tr(__k));
1963 if (__j != end() && _M_key_compare(__k, _S_key(__j._M_node)))
1964 __j = end();
1965 return __j;
1966 }
1967
1968 template<typename _Kt,
1969 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1970 size_type
1971 _M_count_tr(const _Kt& __k) const
1972 {
1973 auto __p = _M_equal_range_tr(__k);
1974 return std::distance(__p.first, __p.second);
1975 }
1976
1977 template<typename _Kt,
1978 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1979 _Base_ptr
1980 _M_lower_bound_tr(const _Kt& __k) const
1981 {
1982 auto __x = _M_begin();
1983 auto __y = _M_end();
1984 while (__x)
1985 if (!_M_key_compare(_S_key(__x), __k))
1986 {
1987 __y = __x;
1988 __x = _S_left(__x);
1989 }
1990 else
1991 __x = _S_right(__x);
1992 return __y;
1993 }
1994
1995 template<typename _Kt,
1996 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1997 _Base_ptr
1998 _M_upper_bound_tr(const _Kt& __k) const
1999 {
2000 auto __x = _M_begin();
2001 auto __y = _M_end();
2002 while (__x)
2003 if (_M_key_compare(__k, _S_key(__x)))
2004 {
2005 __y = __x;
2006 __x = _S_left(__x);
2007 }
2008 else
2009 __x = _S_right(__x);
2010 return __y;
2011 }
2012
2013 template<typename _Kt,
2014 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
2015 pair<iterator, iterator>
2016 _M_equal_range_tr(const _Kt& __k)
2017 {
2018 const _Rb_tree* __const_this = this;
2019 auto __ret = __const_this->_M_equal_range_tr(__k);
2020 return
2021 { iterator(__ret.first._M_node), iterator(__ret.second._M_node) };
2022 }
2023
2024 template<typename _Kt,
2025 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
2026 pair<const_iterator, const_iterator>
2027 _M_equal_range_tr(const _Kt& __k) const
2028 {
2029 const_iterator __low(_M_lower_bound_tr(__k));
2030 auto __high = __low;
2031 auto& __cmp = _M_impl._M_key_compare;
2032 while (__high != end() && !__cmp(__k, _S_key(__high._M_node)))
2033 ++__high;
2034 return { __low, __high };
2035 }
2036#endif // __glibcxx_generic_associative_lookup
2037
2038 // Debugging.
2039 bool
2040 __rb_verify() const;
2041
2042#if __cplusplus >= 201103L
2043 _Rb_tree&
2044 operator=(_Rb_tree&&)
2045 noexcept(_Node_alloc_traits::_S_nothrow_move()
2046 && is_nothrow_move_assignable<_Compare>::value);
2047
2048 template<typename _Iterator>
2049 void
2050 _M_assign_unique(_Iterator, _Iterator);
2051
2052 template<typename _Iterator>
2053 void
2054 _M_assign_equal(_Iterator, _Iterator);
2055
2056 private:
2057 // Move elements from container with equal allocator.
2058 void
2059 _M_move_data(_Rb_tree& __x, true_type)
2060 { _M_impl._M_move_data(__x._M_impl); }
2061
2062 // Move elements from container with possibly non-equal allocator,
2063 // which might result in a copy not a move.
2064 void
2065 _M_move_data(_Rb_tree&, false_type);
2066
2067 // Move assignment from container with equal allocator.
2068 void
2069 _M_move_assign(_Rb_tree&, true_type);
2070
2071 // Move assignment from container with possibly non-equal allocator,
2072 // which might result in a copy not a move.
2073 void
2074 _M_move_assign(_Rb_tree&, false_type);
2075#endif
2076
2077#ifdef __glibcxx_node_extract // >= C++17
2078 static _Node_ptr
2079 _S_adapt(typename _Node_alloc_traits::pointer __ptr)
2080 {
2081#if _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
2082 return __ptr;
2083#else
2084#pragma GCC diagnostic push
2085#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
2086 using __alloc_ptr = typename _Node_alloc_traits::pointer;
2087 if constexpr (is_same<_Node_ptr, __alloc_ptr>::value)
2088 return __ptr;
2089 else
2090 return std::__to_address(__ptr);
2091#pragma GCC diagnostic pop
2092#endif
2093 }
2094
2095 public:
2096 /// Re-insert an extracted node.
2097 insert_return_type
2098 _M_reinsert_node_unique(node_type&& __nh)
2099 {
2100 insert_return_type __ret;
2101 if (__nh.empty())
2102 __ret.position = end();
2103 else
2104 {
2105 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
2106
2107 auto __res = _M_get_insert_unique_pos(__nh._M_key());
2108 if (__res.second)
2109 {
2110 __ret.position
2111 = _M_insert_node(__res.first, __res.second,
2112 _S_adapt(__nh._M_ptr));
2113 __nh.release();
2114 __ret.inserted = true;
2115 }
2116 else
2117 {
2118 __ret.node = std::move(__nh);
2119 __ret.position = iterator(__res.first);
2120 __ret.inserted = false;
2121 }
2122 }
2123 return __ret;
2124 }
2125
2126 /// Re-insert an extracted node.
2127 iterator
2128 _M_reinsert_node_equal(node_type&& __nh)
2129 {
2130 iterator __ret;
2131 if (__nh.empty())
2132 __ret = end();
2133 else
2134 {
2135 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
2136 auto __res = _M_get_insert_equal_pos(__nh._M_key());
2137 if (__res.second)
2138 __ret = _M_insert_node(__res.first, __res.second,
2139 _S_adapt(__nh._M_ptr));
2140 else
2141 __ret = _M_insert_equal_lower_node(_S_adapt(__nh._M_ptr));
2142 __nh.release();
2143 }
2144 return __ret;
2145 }
2146
2147 /// Re-insert an extracted node.
2148 iterator
2149 _M_reinsert_node_hint_unique(const_iterator __hint, node_type&& __nh)
2150 {
2151 iterator __ret;
2152 if (__nh.empty())
2153 __ret = end();
2154 else
2155 {
2156 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
2157 auto __res = _M_get_insert_hint_unique_pos(__hint, __nh._M_key());
2158 if (__res.second)
2159 {
2160 __ret = _M_insert_node(__res.first, __res.second,
2161 _S_adapt(__nh._M_ptr));
2162 __nh.release();
2163 }
2164 else
2165 __ret = iterator(__res.first);
2166 }
2167 return __ret;
2168 }
2169
2170 /// Re-insert an extracted node.
2171 iterator
2172 _M_reinsert_node_hint_equal(const_iterator __hint, node_type&& __nh)
2173 {
2174 iterator __ret;
2175 if (__nh.empty())
2176 __ret = end();
2177 else
2178 {
2179 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
2180 auto __res = _M_get_insert_hint_equal_pos(__hint, __nh._M_key());
2181 if (__res.second)
2182 __ret = _M_insert_node(__res.first, __res.second,
2183 _S_adapt(__nh._M_ptr));
2184 else
2185 __ret = _M_insert_equal_lower_node(_S_adapt(__nh._M_ptr));
2186 __nh.release();
2187 }
2188 return __ret;
2189 }
2190
2191 /// Extract a node.
2192 node_type
2193 extract(const_iterator __pos)
2194 {
2195 auto __ptr = _Node_traits::_S_rebalance_for_erase
2196 (__pos._M_node, _M_impl._M_header);
2197 --_M_impl._M_node_count;
2198 auto __node_ptr = static_cast<_Node&>(*__ptr)._M_node_ptr();
2199#if _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
2200 return { __node_ptr, _M_get_Node_allocator() };
2201#else
2202#pragma GCC diagnostic push
2203#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
2204 using __alloc_ptr = typename _Node_alloc_traits::pointer;
2205 if constexpr (is_same<_Node_ptr, __alloc_ptr>::value)
2206 return { __node_ptr, _M_get_Node_allocator() };
2207 else
2208 {
2209 auto __ap = pointer_traits<__alloc_ptr>::pointer_to(*__node_ptr);
2210 return { __ap, _M_get_Node_allocator() };
2211 }
2212#pragma GCC diagnostic pop
2213#endif
2214 }
2215
2216 /// Extract a node.
2217 node_type
2218 extract(const key_type& __k)
2219 {
2220 node_type __nh;
2221 auto __pos = find(__k);
2222 if (__pos != end())
2223 __nh = extract(const_iterator(__pos));
2224 return __nh;
2225 }
2226
2227 template <typename _Kt>
2228 node_type
2229 _M_extract_tr(const _Kt& __k)
2230 {
2231 node_type __nh;
2232 auto __pos = _M_find_tr(__k);
2233 if (__pos != end())
2234 __nh = extract(const_iterator(__pos));
2235 return __nh;
2236 }
2237
2238 template<typename _Compare2>
2239 using _Compatible_tree
2240 = _Rb_tree<_Key, _Val, _KeyOfValue, _Compare2, _Alloc>;
2241
2242 template<typename, typename>
2243 friend struct _Rb_tree_merge_helper;
2244
2245 /// Merge from a compatible container into one with unique keys.
2246 template<typename _Compare2>
2247 void
2248 _M_merge_unique(_Compatible_tree<_Compare2>& __src) noexcept
2249 {
2250 using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>;
2251 for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
2252 {
2253 auto __pos = __i++;
2254 auto __res = _M_get_insert_unique_pos(_KeyOfValue()(*__pos));
2255 if (__res.second)
2256 {
2257 auto& __src_impl = _Merge_helper::_S_get_impl(__src);
2258 auto __ptr = _Node_traits::_S_rebalance_for_erase
2259 (__pos._M_node, __src_impl._M_header);
2260 --__src_impl._M_node_count;
2261 auto __node_ptr = static_cast<_Node&>(*__ptr)._M_node_ptr();
2262 _M_insert_node(__res.first, __res.second, __node_ptr);
2263 }
2264 }
2265 }
2266
2267 /// Merge from a compatible container into one with equivalent keys.
2268 template<typename _Compare2>
2269 void
2270 _M_merge_equal(_Compatible_tree<_Compare2>& __src) noexcept
2271 {
2272 using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>;
2273 for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
2274 {
2275 auto __pos = __i++;
2276 auto __res = _M_get_insert_equal_pos(_KeyOfValue()(*__pos));
2277 if (__res.second)
2278 {
2279 auto& __src_impl = _Merge_helper::_S_get_impl(__src);
2280 auto __ptr = _Node_traits::_S_rebalance_for_erase
2281 (__pos._M_node, __src_impl._M_header);
2282 --__src_impl._M_node_count;
2283 auto __node_ptr = static_cast<_Node&>(*__ptr)._M_node_ptr();
2284 _M_insert_node(__res.first, __res.second, __node_ptr);
2285 }
2286 }
2287 }
2288#endif // C++17 node_extract
2289
2290 friend bool
2291 operator==(const _Rb_tree& __x, const _Rb_tree& __y)
2292 {
2293 return __x.size() == __y.size()
2294 && std::equal(__x.begin(), __x.end(), __y.begin());
2295 }
2296
2297#if __cpp_lib_three_way_comparison
2298 friend auto
2299 operator<=>(const _Rb_tree& __x, const _Rb_tree& __y)
2300 {
2301 if constexpr (requires { typename __detail::__synth3way_t<_Val>; })
2302 return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
2303 __y.begin(), __y.end(),
2304 __detail::__synth3way);
2305 }
2306#else
2307 friend bool
2308 operator<(const _Rb_tree& __x, const _Rb_tree& __y)
2309 {
2310 return std::lexicographical_compare(__x.begin(), __x.end(),
2311 __y.begin(), __y.end());
2312 }
2313#endif
2314
2315 private:
2316#if __cplusplus >= 201103L
2317 // An RAII _Node handle
2318 struct _Auto_node
2319 {
2320 template<typename... _Args>
2321 _Auto_node(_Rb_tree& __t, _Args&&... __args)
2322 : _M_t(__t),
2323 _M_node(__t._M_create_node(std::forward<_Args>(__args)...))
2324 { }
2325
2326 ~_Auto_node()
2327 {
2328 if (_M_node)
2329 _M_t._M_drop_node(_M_node);
2330 }
2331
2332 _Auto_node(_Auto_node&& __n)
2333 : _M_t(__n._M_t), _M_node(__n._M_node)
2334 { __n._M_node = nullptr; }
2335
2336 const _Key&
2337 _M_key() const
2338 { return _S_key(_M_node); }
2339
2340 iterator
2341 _M_insert(pair<_Base_ptr, _Base_ptr> __p)
2342 {
2343 auto __it = _M_t._M_insert_node(__p.first, __p.second, _M_node);
2344 _M_node = nullptr;
2345 return __it;
2346 }
2347
2348 iterator
2349 _M_insert_equal_lower()
2350 {
2351 auto __it = _M_t._M_insert_equal_lower_node(_M_node);
2352 _M_node = nullptr;
2353 return __it;
2354 }
2355
2356 _Rb_tree& _M_t;
2357 _Node_ptr _M_node;
2358 };
2359#endif // C++11
2360 };
2361
2362 template<typename _Key, typename _Val, typename _KeyOfValue,
2363 typename _Compare, typename _Alloc>
2364 inline void
2365 swap(_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
2366 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
2367 { __x.swap(__y); }
2368
2369#if __cplusplus >= 201103L
2370 template<typename _Key, typename _Val, typename _KeyOfValue,
2371 typename _Compare, typename _Alloc>
2372 void
2373 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2374 _M_move_data(_Rb_tree& __x, false_type)
2375 {
2376 if (_M_get_Node_allocator() == __x._M_get_Node_allocator())
2377 _M_move_data(__x, true_type());
2378 else
2379 {
2380 constexpr bool __move = !__move_if_noexcept_cond<value_type>::value;
2381 _Alloc_node __an(*this);
2382 _M_root() = _M_copy<__move>(__x, __an);
2383#pragma GCC diagnostic push
2384#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
2385 if constexpr (__move)
2386 __x.clear();
2387#pragma GCC diagnostic pop
2388 }
2389 }
2390
2391 template<typename _Key, typename _Val, typename _KeyOfValue,
2392 typename _Compare, typename _Alloc>
2393 inline void
2394 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2395 _M_move_assign(_Rb_tree& __x, true_type)
2396 {
2397 clear();
2398 if (__x._M_root())
2399 _M_move_data(__x, true_type());
2400 std::__alloc_on_move(_M_get_Node_allocator(),
2401 __x._M_get_Node_allocator());
2402 }
2403
2404 template<typename _Key, typename _Val, typename _KeyOfValue,
2405 typename _Compare, typename _Alloc>
2406 void
2407 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2408 _M_move_assign(_Rb_tree& __x, false_type)
2409 {
2410 if (_M_get_Node_allocator() == __x._M_get_Node_allocator())
2411 return _M_move_assign(__x, true_type{});
2412
2413 // Try to move each node reusing existing nodes and copying __x nodes
2414 // structure.
2415 _Reuse_or_alloc_node __roan(*this);
2416 _M_impl._M_reset();
2417 if (__x._M_root())
2418 {
2419 _M_root() = _M_copy<__as_rvalue>(__x, __roan);
2420 __x.clear();
2421 }
2422 }
2423
2424 template<typename _Key, typename _Val, typename _KeyOfValue,
2425 typename _Compare, typename _Alloc>
2426 inline _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&
2427 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2428 operator=(_Rb_tree&& __x)
2429 noexcept(_Node_alloc_traits::_S_nothrow_move()
2430 && is_nothrow_move_assignable<_Compare>::value)
2431 {
2432 _M_impl._M_key_compare = std::move(__x._M_impl._M_key_compare);
2433 _M_move_assign(__x,
2434 __bool_constant<_Node_alloc_traits::_S_nothrow_move()>());
2435 return *this;
2436 }
2437
2438 template<typename _Key, typename _Val, typename _KeyOfValue,
2439 typename _Compare, typename _Alloc>
2440 template<typename _Iterator>
2441 void
2442 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2443 _M_assign_unique(_Iterator __first, _Iterator __last)
2444 {
2445 _Reuse_or_alloc_node __roan(*this);
2446 _M_impl._M_reset();
2447 for (; __first != __last; ++__first)
2448 _M_insert_unique_(end(), *__first, __roan);
2449 }
2450
2451 template<typename _Key, typename _Val, typename _KeyOfValue,
2452 typename _Compare, typename _Alloc>
2453 template<typename _Iterator>
2454 void
2455 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2456 _M_assign_equal(_Iterator __first, _Iterator __last)
2457 {
2458 _Reuse_or_alloc_node __roan(*this);
2459 _M_impl._M_reset();
2460 for (; __first != __last; ++__first)
2461 _M_insert_equal_(end(), *__first, __roan);
2462 }
2463#endif // C++11
2464
2465 template<typename _Key, typename _Val, typename _KeyOfValue,
2466 typename _Compare, typename _Alloc>
2467 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&
2468 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2469 operator=(const _Rb_tree& __x)
2470 {
2471 if (this != std::__addressof(__x))
2472 {
2473 // Note that _Key may be a constant type.
2474#if __cplusplus >= 201103L
2475 if (_Node_alloc_traits::_S_propagate_on_copy_assign())
2476 {
2477 auto& __this_alloc = this->_M_get_Node_allocator();
2478 auto& __that_alloc = __x._M_get_Node_allocator();
2479 if (!_Node_alloc_traits::_S_always_equal()
2480 && __this_alloc != __that_alloc)
2481 {
2482 // Replacement allocator cannot free existing storage, we need
2483 // to erase nodes first.
2484 clear();
2485 std::__alloc_on_copy(__this_alloc, __that_alloc);
2486 }
2487 }
2488#endif
2489
2490 _Reuse_or_alloc_node __roan(*this);
2491 _M_impl._M_reset();
2492 _M_impl._M_key_compare = __x._M_impl._M_key_compare;
2493 if (__x._M_root())
2494 _M_root() = _M_copy<__as_lvalue>(__x, __roan);
2495 }
2496
2497 return *this;
2498 }
2499
2500 template<typename _Key, typename _Val, typename _KeyOfValue,
2501 typename _Compare, typename _Alloc>
2502#if __cplusplus >= 201103L
2503 template<typename _Arg, typename _NodeGen>
2504#else
2505 template<typename _NodeGen>
2506#endif
2507 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2508 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2509 _M_insert_(_Base_ptr __x, _Base_ptr __p,
2510#if __cplusplus >= 201103L
2511 _Arg&& __v,
2512#else
2513 const _Val& __v,
2514#endif
2515 _NodeGen& __node_gen)
2516 {
2517 bool __insert_left = (__x || __p == _M_end()
2518 || _M_key_compare(_KeyOfValue()(__v),
2519 _S_key(__p)));
2520
2521 _Base_ptr __z =
2522 __node_gen(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr();
2523
2524 _Node_traits::_S_insert_and_rebalance
2525 (__insert_left, __z, __p, this->_M_impl._M_header);
2526 ++_M_impl._M_node_count;
2527 return iterator(__z);
2528 }
2529
2530 template<typename _Key, typename _Val, typename _KeyOfValue,
2531 typename _Compare, typename _Alloc>
2532#if __cplusplus >= 201103L
2533 template<typename _Arg>
2534#endif
2535 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2536 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2537#if __cplusplus >= 201103L
2538 _M_insert_lower(_Base_ptr __p, _Arg&& __v)
2539#else
2540 _M_insert_lower(_Base_ptr __p, const _Val& __v)
2541#endif
2542 {
2543 bool __insert_left = (__p == _M_end()
2544 || !_M_key_compare(_S_key(__p),
2545 _KeyOfValue()(__v)));
2546
2547 _Base_ptr __z =
2548 _M_create_node(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr();
2549 _Node_traits::_S_insert_and_rebalance
2550 (__insert_left, __z, __p, this->_M_impl._M_header);
2551 ++_M_impl._M_node_count;
2552 return iterator(__z);
2553 }
2554
2555 template<typename _Key, typename _Val, typename _KeyOfValue,
2556 typename _Compare, typename _Alloc>
2557#if __cplusplus >= 201103L
2558 template<typename _Arg>
2559#endif
2560 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2561 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2562#if __cplusplus >= 201103L
2563 _M_insert_equal_lower(_Arg&& __v)
2564#else
2565 _M_insert_equal_lower(const _Val& __v)
2566#endif
2567 {
2568 _Base_ptr __x = _M_begin();
2569 _Base_ptr __y = _M_end();
2570 while (__x)
2571 {
2572 __y = __x;
2573 __x = !_M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ?
2574 _S_left(__x) : _S_right(__x);
2575 }
2576 return _M_insert_lower(__y, _GLIBCXX_FORWARD(_Arg, __v));
2577 }
2578
2579 template<typename _Key, typename _Val, typename _KoV,
2580 typename _Compare, typename _Alloc>
2581 template<bool _MoveValues, typename _NodeGen>
2582 typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Base_ptr
2583 _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::
2584 _M_copy(_Node_ptr __x, _Base_ptr __p, _NodeGen& __node_gen)
2585 {
2586 // Structural copy. __x and __p must be non-null.
2587 _Node_ptr __top = _M_clone_node<_MoveValues>(__x, __node_gen);
2588 _Base_ptr __top_base = __top->_M_base_ptr();
2589 __top->_M_parent = __p;
2590
2591 __try
2592 {
2593 if (__x->_M_right)
2594 __top->_M_right =
2595 _M_copy<_MoveValues>(_S_right(__x), __top_base, __node_gen);
2596 __p = __top_base;
2597 __x = _S_left(__x);
2598
2599 while (__x)
2600 {
2601 _Base_ptr __y =
2602 _M_clone_node<_MoveValues>(__x, __node_gen)->_M_base_ptr();
2603 __p->_M_left = __y;
2604 __y->_M_parent = __p;
2605 if (__x->_M_right)
2606 __y->_M_right = _M_copy<_MoveValues>(_S_right(__x),
2607 __y, __node_gen);
2608 __p = __y;
2609 __x = _S_left(__x);
2610 }
2611 }
2612 __catch(...)
2613 {
2614 _M_erase(__top);
2615 __throw_exception_again;
2616 }
2617 return __top_base;
2618 }
2619
2620 template<typename _Key, typename _Val, typename _KeyOfValue,
2621 typename _Compare, typename _Alloc>
2622 void
2623 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2624 _M_erase(_Node_ptr __x)
2625 {
2626 // Erase without rebalancing.
2627 while (__x)
2628 {
2629 _M_erase(_S_right(__x));
2630 _Node_ptr __y = _S_left(__x);
2631 _M_drop_node(__x);
2632 __x = __y;
2633 }
2634 }
2635
2636 template<typename _Key, typename _Val, typename _KeyOfValue,
2637 typename _Compare, typename _Alloc>
2638 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2639 _Compare, _Alloc>::_Base_ptr
2640 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2641 _M_lower_bound(_Base_ptr __x, _Base_ptr __y,
2642 const _Key& __k) const
2643 {
2644 while (__x)
2645 if (!_M_key_compare(_S_key(__x), __k))
2646 __y = __x, __x = _S_left(__x);
2647 else
2648 __x = _S_right(__x);
2649 return __y;
2650 }
2651
2652 template<typename _Key, typename _Val, typename _KeyOfValue,
2653 typename _Compare, typename _Alloc>
2654 template <typename _Kt>
2655 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr
2656 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2657 _M_lower_bound_tr(_Base_ptr __x, _Base_ptr __y, const _Kt& __k) const
2658 {
2659 while (__x)
2660 if (!_M_key_compare(_S_key(__x), __k))
2661 __y = __x, __x = _S_left(__x);
2662 else
2663 __x = _S_right(__x);
2664 return __y;
2665 }
2666
2667 template<typename _Key, typename _Val, typename _KeyOfValue,
2668 typename _Compare, typename _Alloc>
2669 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2670 _Compare, _Alloc>::_Base_ptr
2671 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2672 _M_upper_bound(_Base_ptr __x, _Base_ptr __y,
2673 const _Key& __k) const
2674 {
2675 while (__x)
2676 if (_M_key_compare(__k, _S_key(__x)))
2677 __y = __x, __x = _S_left(__x);
2678 else
2679 __x = _S_right(__x);
2680 return __y;
2681 }
2682
2683 template<typename _Key, typename _Val, typename _KeyOfValue,
2684 typename _Compare, typename _Alloc>
2685 template <typename _Kt>
2686 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr
2687 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2688 _M_upper_bound_tr(_Base_ptr __x, _Base_ptr __y, const _Kt& __k) const
2689 {
2690 while (__x)
2691 if (_M_key_compare(__k, _S_key(__x)))
2692 __y = __x, __x = _S_left(__x);
2693 else
2694 __x = _S_right(__x);
2695 return __y;
2696 }
2697
2698 template<typename _Key, typename _Val, typename _KeyOfValue,
2699 typename _Compare, typename _Alloc>
2700 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2701 _Compare, _Alloc>::iterator,
2702 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2703 _Compare, _Alloc>::iterator>
2704 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2705 equal_range(const _Key& __k)
2706 {
2707 typedef pair<iterator, iterator> _Ret;
2708
2709 _Base_ptr __x = _M_begin();
2710 _Base_ptr __y = _M_end();
2711 while (__x)
2712 {
2713 if (_M_key_compare(_S_key(__x), __k))
2714 __x = _S_right(__x);
2715 else if (_M_key_compare(__k, _S_key(__x)))
2716 __y = __x, __x = _S_left(__x);
2717 else
2718 {
2719 _Base_ptr __xu(__x);
2720 _Base_ptr __yu(__y);
2721 __y = __x, __x = _S_left(__x);
2722 __xu = _S_right(__xu);
2723 return _Ret(iterator(_M_lower_bound(__x, __y, __k)),
2724 iterator(_M_upper_bound(__xu, __yu, __k)));
2725 }
2726 }
2727 return _Ret(iterator(__y), iterator(__y));
2728 }
2729
2730 template<typename _Key, typename _Val, typename _KeyOfValue,
2731 typename _Compare, typename _Alloc>
2732 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2733 _Compare, _Alloc>::const_iterator,
2734 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2735 _Compare, _Alloc>::const_iterator>
2736 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2737 equal_range(const _Key& __k) const
2738 {
2739 typedef pair<const_iterator, const_iterator> _Ret;
2740
2741 _Base_ptr __x = _M_begin();
2742 _Base_ptr __y = _M_end();
2743 while (__x)
2744 {
2745 if (_M_key_compare(_S_key(__x), __k))
2746 __x = _S_right(__x);
2747 else if (_M_key_compare(__k, _S_key(__x)))
2748 __y = __x, __x = _S_left(__x);
2749 else
2750 {
2751 _Base_ptr __xu(__x);
2752 _Base_ptr __yu(__y);
2753 __y = __x, __x = _S_left(__x);
2754 __xu = _S_right(__xu);
2755 return _Ret(const_iterator(_M_lower_bound(__x, __y, __k)),
2756 const_iterator(_M_upper_bound(__xu, __yu, __k)));
2757 }
2758 }
2759 return _Ret(const_iterator(__y), const_iterator(__y));
2760 }
2761
2762 template<typename _Key, typename _Val, typename _KeyOfValue,
2763 typename _Compare, typename _Alloc>
2764 void
2765 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2766 swap(_Rb_tree& __t)
2767 _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value)
2768 {
2769 if (!_M_root())
2770 {
2771 if (__t._M_root())
2772 _M_impl._M_move_data(__t._M_impl);
2773 }
2774 else if (!__t._M_root())
2775 __t._M_impl._M_move_data(_M_impl);
2776 else
2777 {
2778 std::swap(_M_root(),__t._M_root());
2779 std::swap(_M_leftmost(),__t._M_leftmost());
2780 std::swap(_M_rightmost(),__t._M_rightmost());
2781
2782 _M_root()->_M_parent = _M_end();
2783 __t._M_root()->_M_parent = __t._M_end();
2784 std::swap(this->_M_impl._M_node_count, __t._M_impl._M_node_count);
2785 }
2786 // No need to swap header's color as it does not change.
2787
2788 using std::swap;
2789 swap(this->_M_impl._M_key_compare, __t._M_impl._M_key_compare);
2790
2791 _Node_alloc_traits::_S_on_swap(_M_get_Node_allocator(),
2792 __t._M_get_Node_allocator());
2793 }
2794
2795 template<typename _Key, typename _Val, typename _KeyOfValue,
2796 typename _Compare, typename _Alloc>
2797 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2798 _Compare, _Alloc>::_Base_ptr,
2799 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2800 _Compare, _Alloc>::_Base_ptr>
2801 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2802 _M_get_insert_unique_pos(const key_type& __k)
2803 {
2804 typedef pair<_Base_ptr, _Base_ptr> _Res;
2805 _Base_ptr __x = _M_begin();
2806 _Base_ptr __y = _M_end();
2807 bool __comp = true;
2808 while (__x)
2809 {
2810 __y = __x;
2811 __comp = _M_key_compare(__k, _S_key(__x));
2812 __x = __comp ? _S_left(__x) : _S_right(__x);
2813 }
2814 iterator __j = iterator(__y);
2815 if (__comp)
2816 {
2817 if (__j == begin())
2818 return _Res(__x, __y);
2819 else
2820 --__j;
2821 }
2822 if (_M_key_compare(_S_key(__j._M_node), __k))
2823 return _Res(__x, __y);
2824 return _Res(__j._M_node, _Base_ptr());
2825 }
2826
2827 template<typename _Key, typename _Val, typename _KeyOfValue,
2828 typename _Compare, typename _Alloc>
2829 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2830 _Compare, _Alloc>::_Base_ptr,
2831 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2832 _Compare, _Alloc>::_Base_ptr>
2833 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2834 _M_get_insert_equal_pos(const key_type& __k)
2835 {
2836 typedef pair<_Base_ptr, _Base_ptr> _Res;
2837 _Base_ptr __x = _M_begin();
2838 _Base_ptr __y = _M_end();
2839 while (__x)
2840 {
2841 __y = __x;
2842 __x = _M_key_compare(__k, _S_key(__x)) ? _S_left(__x) : _S_right(__x);
2843 }
2844 return _Res(__x, __y);
2845 }
2846
2847#ifdef __glibcxx_associative_heterogeneous_insertion // C++26
2848
2849 // Multiple elements may compare equal to __k. Identify the first
2850 // of any such elements, or insert normally.
2851
2852 template <typename _Key, typename _Val, typename _KeyOfValue,
2853 typename _Compare, typename _Alloc>
2854 template <typename _Kt>
2855 auto
2856 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2857 _M_get_insert_unique_pos_tr(const _Kt& __k)
2858 -> pair<_Base_ptr, _Base_ptr>
2859 {
2860 if (size() == 0)
2861 return { _M_end(), _M_end() }; // Insert as root.
2862
2863 _Base_ptr __x = _M_begin(), __y = __x;
2864 bool __k_le_y = false;
2865 do
2866 {
2867 __y = __x;
2868 __k_le_y = ! _M_key_compare(_S_key(__x), __k);
2869 __x = __k_le_y ? _S_left(__x) : _S_right(__x);
2870 }
2871 while (__x);
2872 // If !__k_le_y, __k > *__y;
2873 // If __y is rightmost, put at _M_right under *__y.
2874 // else if __k < *(__y+1), put at _M_right under *__y.
2875 // else __k == *(__y+1), do not insert, report (__y+1).
2876 // else, __k_le_y, __k <= *__y;
2877 // If __k < *__Y, put at _M_left under *__y.
2878 // else __k == *__y, do not insert, report __y.
2879 auto __j = iterator(__y);
2880 if (! __k_le_y) // k > *__y
2881 {
2882 if (__y == _M_rightmost())
2883 return { {}, __y }; // Place to right under __y.
2884 ++__j;
2885 }
2886 if (_M_key_compare(__k, _S_key(__j._M_node)))
2887 {
2888 if (__k_le_y)
2889 return { __y, __y }; // Place to left under __y.
2890 else
2891 return { {}, __y }; // Place to right under __y.
2892 }
2893 return { __j._M_node, {} }; // No insert.
2894 }
2895#endif
2896
2897 template<typename _Key, typename _Val, typename _KeyOfValue,
2898 typename _Compare, typename _Alloc>
2899#if __cplusplus >= 201103L
2900 template<typename _Arg>
2901#endif
2902 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2903 _Compare, _Alloc>::iterator, bool>
2904 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2905#if __cplusplus >= 201103L
2906 _M_insert_unique(_Arg&& __v)
2907#else
2908 _M_insert_unique(const _Val& __v)
2909#endif
2910 {
2911 typedef pair<iterator, bool> _Res;
2912 pair<_Base_ptr, _Base_ptr> __res
2913 = _M_get_insert_unique_pos(_KeyOfValue()(__v));
2914
2915 if (__res.second)
2916 {
2917 _Alloc_node __an(*this);
2918 return _Res(_M_insert_(__res.first, __res.second,
2919 _GLIBCXX_FORWARD(_Arg, __v), __an),
2920 true);
2921 }
2922
2923 return _Res(iterator(__res.first), false);
2924 }
2925
2926 template<typename _Key, typename _Val, typename _KeyOfValue,
2927 typename _Compare, typename _Alloc>
2928#if __cplusplus >= 201103L
2929 template<typename _Arg>
2930#endif
2931 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2932 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2933#if __cplusplus >= 201103L
2934 _M_insert_equal(_Arg&& __v)
2935#else
2936 _M_insert_equal(const _Val& __v)
2937#endif
2938 {
2939 pair<_Base_ptr, _Base_ptr> __res
2940 = _M_get_insert_equal_pos(_KeyOfValue()(__v));
2941 _Alloc_node __an(*this);
2942 return _M_insert_(__res.first, __res.second,
2943 _GLIBCXX_FORWARD(_Arg, __v), __an);
2944 }
2945
2946 template<typename _Key, typename _Val, typename _KeyOfValue,
2947 typename _Compare, typename _Alloc>
2948 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2949 _Compare, _Alloc>::_Base_ptr,
2950 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2951 _Compare, _Alloc>::_Base_ptr>
2952 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2953 _M_get_insert_hint_unique_pos(const_iterator __position,
2954 const key_type& __k)
2955 {
2956 typedef pair<_Base_ptr, _Base_ptr> _Res;
2957
2958 // end()
2959 if (__position._M_node == _M_end())
2960 {
2961 if (size() > 0 && _M_key_compare(_S_key(_M_rightmost()), __k))
2962 return _Res(_Base_ptr(), _M_rightmost());
2963 else
2964 return _M_get_insert_unique_pos(__k);
2965 }
2966 else if (_M_key_compare(__k, _S_key(__position._M_node)))
2967 {
2968 // First, try before...
2969 iterator __before(__position._M_node);
2970 if (__position._M_node == _M_leftmost()) // begin()
2971 return _Res(_M_leftmost(), _M_leftmost());
2972 else if (_M_key_compare(_S_key((--__before)._M_node), __k))
2973 {
2974 if (!_S_right(__before._M_node))
2975 return _Res(_Base_ptr(), __before._M_node);
2976 else
2977 return _Res(__position._M_node, __position._M_node);
2978 }
2979 else
2980 return _M_get_insert_unique_pos(__k);
2981 }
2982 else if (_M_key_compare(_S_key(__position._M_node), __k))
2983 {
2984 // ... then try after.
2985 iterator __after(__position._M_node);
2986 if (__position._M_node == _M_rightmost())
2987 return _Res(_Base_ptr(), _M_rightmost());
2988 else if (_M_key_compare(__k, _S_key((++__after)._M_node)))
2989 {
2990 if (!_S_right(__position._M_node))
2991 return _Res(_Base_ptr(), __position._M_node);
2992 else
2993 return _Res(__after._M_node, __after._M_node);
2994 }
2995 else
2996 return _M_get_insert_unique_pos(__k);
2997 }
2998 else
2999 // Equivalent keys.
3000 return _Res(__position._M_node, _Base_ptr());
3001 }
3002
3003#ifdef __glibcxx_associative_heterogeneous_insertion // C++26
3004 template <typename _Key, typename _Val, typename _KeyOfValue,
3005 typename _Compare, typename _Alloc>
3006 template <typename _Kt>
3007 auto
3008 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3009 _M_get_insert_hint_unique_pos_tr(const_iterator __hint, const _Kt& __k)
3010 -> pair<_Base_ptr, _Base_ptr>
3011 {
3012 auto __node =__hint._M_node;
3013 if (__node == _M_end())
3014 {
3015 if (size() > 0 && _M_key_compare(_S_key(_M_rightmost()), __k))
3016 return { {}, _M_rightmost() };
3017 return _M_get_insert_unique_pos_tr(__k);
3018 }
3019 if (_M_key_compare(__k, _S_key(__node)))
3020 { // First, try before...
3021 if (__node == _M_leftmost()) // begin()
3022 return { _M_leftmost(), _M_leftmost() };
3023 iterator __before(__node);
3024 --__before;
3025 if (_M_key_compare(_S_key(__before._M_node), __k))
3026 {
3027 if (!_S_right(__before._M_node))
3028 return { {}, __before._M_node }; // put right
3029 return { __node, __node }; // put left;
3030 }
3031 return _M_get_insert_unique_pos_tr(__k);
3032 }
3033 if (_M_key_compare(_S_key(__node), __k))
3034 { // ... then try after.
3035 if (__node == _M_rightmost())
3036 return { {}, _M_rightmost() };
3037 iterator __after(__node);
3038 ++__after;
3039 if (_M_key_compare(__k, _S_key(__after._M_node)))
3040 {
3041 if (!_S_right(__node))
3042 return { {}, __node };
3043 return { __after._M_node, __after._M_node };
3044 }
3045 return _M_get_insert_unique_pos_tr(__k);
3046 }
3047 // Equal to __k; check if any more to the left.
3048 iterator __before(__node);
3049 if (__node == _M_leftmost() ||
3050 _M_key_compare(_S_key((--__before)._M_node), __k))
3051 { return { __node, {} }; }
3052 return _M_get_insert_unique_pos_tr(__k);
3053 }
3054#endif
3055
3056 template<typename _Key, typename _Val, typename _KeyOfValue,
3057 typename _Compare, typename _Alloc>
3058#if __cplusplus >= 201103L
3059 template<typename _Arg, typename _NodeGen>
3060#else
3061 template<typename _NodeGen>
3062#endif
3063 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
3064 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3065 _M_insert_unique_(const_iterator __position,
3066#if __cplusplus >= 201103L
3067 _Arg&& __v,
3068#else
3069 const _Val& __v,
3070#endif
3071 _NodeGen& __node_gen)
3072 {
3073 pair<_Base_ptr, _Base_ptr> __res
3074 = _M_get_insert_hint_unique_pos(__position, _KeyOfValue()(__v));
3075
3076 if (__res.second)
3077 return _M_insert_(__res.first, __res.second,
3078 _GLIBCXX_FORWARD(_Arg, __v),
3079 __node_gen);
3080 return iterator(__res.first);
3081 }
3082
3083 template<typename _Key, typename _Val, typename _KeyOfValue,
3084 typename _Compare, typename _Alloc>
3085 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
3086 _Compare, _Alloc>::_Base_ptr,
3087 typename _Rb_tree<_Key, _Val, _KeyOfValue,
3088 _Compare, _Alloc>::_Base_ptr>
3089 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3090 _M_get_insert_hint_equal_pos(const_iterator __position, const key_type& __k)
3091 {
3092 typedef pair<_Base_ptr, _Base_ptr> _Res;
3093
3094 // end()
3095 if (__position._M_node == _M_end())
3096 {
3097 if (size() > 0
3098 && !_M_key_compare(__k, _S_key(_M_rightmost())))
3099 return _Res(_Base_ptr(), _M_rightmost());
3100 else
3101 return _M_get_insert_equal_pos(__k);
3102 }
3103 else if (!_M_key_compare(_S_key(__position._M_node), __k))
3104 {
3105 // First, try before...
3106 iterator __before(__position._M_node);
3107 if (__position._M_node == _M_leftmost()) // begin()
3108 return _Res(_M_leftmost(), _M_leftmost());
3109 else if (!_M_key_compare(__k, _S_key((--__before)._M_node)))
3110 {
3111 if (!_S_right(__before._M_node))
3112 return _Res(_Base_ptr(), __before._M_node);
3113 else
3114 return _Res(__position._M_node, __position._M_node);
3115 }
3116 else
3117 return _M_get_insert_equal_pos(__k);
3118 }
3119 else
3120 {
3121 // ... then try after.
3122 iterator __after(__position._M_node);
3123 if (__position._M_node == _M_rightmost())
3124 return _Res(_Base_ptr(), _M_rightmost());
3125 else if (!_M_key_compare(_S_key((++__after)._M_node), __k))
3126 {
3127 if (!_S_right(__position._M_node))
3128 return _Res(_Base_ptr(), __position._M_node);
3129 else
3130 return _Res(__after._M_node, __after._M_node);
3131 }
3132 else
3133 return _Res(_Base_ptr(), _Base_ptr());
3134 }
3135 }
3136
3137 template<typename _Key, typename _Val, typename _KeyOfValue,
3138 typename _Compare, typename _Alloc>
3139#if __cplusplus >= 201103L
3140 template<typename _Arg, typename _NodeGen>
3141#else
3142 template<typename _NodeGen>
3143#endif
3144 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
3145 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3146 _M_insert_equal_(const_iterator __position,
3147#if __cplusplus >= 201103L
3148 _Arg&& __v,
3149#else
3150 const _Val& __v,
3151#endif
3152 _NodeGen& __node_gen)
3153 {
3154 pair<_Base_ptr, _Base_ptr> __res
3155 = _M_get_insert_hint_equal_pos(__position, _KeyOfValue()(__v));
3156
3157 if (__res.second)
3158 return _M_insert_(__res.first, __res.second,
3159 _GLIBCXX_FORWARD(_Arg, __v),
3160 __node_gen);
3161
3162 return _M_insert_equal_lower(_GLIBCXX_FORWARD(_Arg, __v));
3163 }
3164
3165#if __cplusplus >= 201103L
3166 template<typename _Key, typename _Val, typename _KeyOfValue,
3167 typename _Compare, typename _Alloc>
3168 auto
3169 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3170 _M_insert_node(_Base_ptr __x, _Base_ptr __p, _Node_ptr __z)
3171 -> iterator
3172 {
3173 bool __insert_left = (__x || __p == _M_end()
3174 || _M_key_compare(_S_key(__z), _S_key(__p)));
3175
3176 _Base_ptr __base_z = __z->_M_base_ptr();
3177 _Node_traits::_S_insert_and_rebalance
3178 (__insert_left, __base_z, __p, this->_M_impl._M_header);
3179 ++_M_impl._M_node_count;
3180 return iterator(__base_z);
3181 }
3182
3183 template<typename _Key, typename _Val, typename _KeyOfValue,
3184 typename _Compare, typename _Alloc>
3185 auto
3186 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3187 _M_insert_lower_node(_Base_ptr __p, _Node_ptr __z)
3188 -> iterator
3189 {
3190 bool __insert_left = (__p == _M_end()
3191 || !_M_key_compare(_S_key(__p), _S_key(__z)));
3192
3193 _Base_ptr __base_z = __z->_M_base_ptr();
3194 _Node_traits::_S_insert_and_rebalance
3195 (__insert_left, __base_z, __p, this->_M_impl._M_header);
3196 ++_M_impl._M_node_count;
3197 return iterator(__base_z);
3198 }
3199
3200 template<typename _Key, typename _Val, typename _KeyOfValue,
3201 typename _Compare, typename _Alloc>
3202 auto
3203 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3204 _M_insert_equal_lower_node(_Node_ptr __z)
3205 -> iterator
3206 {
3207 _Base_ptr __x = _M_begin();
3208 _Base_ptr __y = _M_end();
3209 while (__x)
3210 {
3211 __y = __x;
3212 __x = !_M_key_compare(_S_key(__x), _S_key(__z)) ?
3213 _S_left(__x) : _S_right(__x);
3214 }
3215 return _M_insert_lower_node(__y, __z);
3216 }
3217
3218 template<typename _Key, typename _Val, typename _KeyOfValue,
3219 typename _Compare, typename _Alloc>
3220 template<typename... _Args>
3221 auto
3222 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3223 _M_emplace_unique(_Args&&... __args)
3224 -> pair<iterator, bool>
3225 {
3226 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3227 auto __res = _M_get_insert_unique_pos(__z._M_key());
3228 if (__res.second)
3229 return {__z._M_insert(__res), true};
3230 return {iterator(__res.first), false};
3231 }
3232
3233 template<typename _Key, typename _Val, typename _KeyOfValue,
3234 typename _Compare, typename _Alloc>
3235 template<typename... _Args>
3236 auto
3237 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3238 _M_emplace_equal(_Args&&... __args)
3239 -> iterator
3240 {
3241 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3242 auto __res = _M_get_insert_equal_pos(__z._M_key());
3243 return __z._M_insert(__res);
3244 }
3245
3246 template<typename _Key, typename _Val, typename _KeyOfValue,
3247 typename _Compare, typename _Alloc>
3248 template<typename... _Args>
3249 auto
3250 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3251 _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args)
3252 -> iterator
3253 {
3254 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3255 auto __res = _M_get_insert_hint_unique_pos(__pos, __z._M_key());
3256 if (__res.second)
3257 return __z._M_insert(__res);
3258 return iterator(__res.first);
3259 }
3260
3261 template<typename _Key, typename _Val, typename _KeyOfValue,
3262 typename _Compare, typename _Alloc>
3263 template<typename... _Args>
3264 auto
3265 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3266 _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args)
3267 -> iterator
3268 {
3269 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3270 auto __res = _M_get_insert_hint_equal_pos(__pos, __z._M_key());
3271 if (__res.second)
3272 return __z._M_insert(__res);
3273 return __z._M_insert_equal_lower();
3274 }
3275
3276#ifdef __glibcxx_associative_heterogeneous_insertion // C++26
3277 template <typename _Key, typename _Val, typename _KeyOfValue,
3278 typename _Compare, typename _Alloc>
3279 template <typename... _Args>
3280 auto
3281 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3282 _M_emplace_here(bool __place_left, _Base_ptr __node, _Args&&... __args)
3283 -> iterator
3284 {
3285 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3286 _Base_ptr __base_z = __z._M_node->_M_base_ptr();
3287 _Node_traits::_S_insert_and_rebalance(
3288 __place_left, __base_z, __node, _M_impl._M_header);
3289 __z._M_node = nullptr;
3290 ++_M_impl._M_node_count;
3291 return iterator(__base_z);
3292 }
3293#endif
3294
3295#endif // >= C++11
3296
3297
3298 template<typename _Key, typename _Val, typename _KeyOfValue,
3299 typename _Compare, typename _Alloc>
3300 void
3301 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3302 _M_erase_aux(const_iterator __position)
3303 {
3304 _Base_ptr __y = _Node_traits::_S_rebalance_for_erase
3305 (__position._M_node, this->_M_impl._M_header);
3306 _M_drop_node(static_cast<_Node&>(*__y)._M_node_ptr());
3307 --_M_impl._M_node_count;
3308 }
3309
3310 template<typename _Key, typename _Val, typename _KeyOfValue,
3311 typename _Compare, typename _Alloc>
3312 void
3313 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3314 _M_erase_aux(const_iterator __first, const_iterator __last)
3315 {
3316 if (__first == begin() && __last == end())
3317 clear();
3318 else
3319 while (__first != __last)
3320 _M_erase_aux(__first++);
3321 }
3322
3323 template<typename _Key, typename _Val, typename _KeyOfValue,
3324 typename _Compare, typename _Alloc>
3325 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
3326 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3327 erase(const _Key& __x)
3328 {
3329 pair<iterator, iterator> __p = equal_range(__x);
3330 const size_type __old_size = size();
3331 _M_erase_aux(__p.first, __p.second);
3332 return __old_size - size();
3333 }
3334
3335 template<typename _Key, typename _Val, typename _KeyOfValue,
3336 typename _Compare, typename _Alloc>
3337 template <typename _Kt>
3338 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
3339 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3340 _M_erase_tr(const _Kt& __x)
3341 {
3342 pair<iterator, iterator> __p = _M_equal_range_tr(__x);
3343 const size_type __old_size = size();
3344 _M_erase_aux(__p.first, __p.second);
3345 return __old_size - size();
3346 }
3347
3348 template<typename _Key, typename _Val, typename _KeyOfValue,
3349 typename _Compare, typename _Alloc>
3350 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
3351 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3352 _M_erase_unique(const _Key& __x)
3353 {
3354 iterator __it = find(__x);
3355 if (__it == end())
3356 return 0;
3357
3358 _M_erase_aux(__it);
3359 return 1;
3360 }
3361
3362 template<typename _Key, typename _Val, typename _KeyOfValue,
3363 typename _Compare, typename _Alloc>
3364 typename _Rb_tree<_Key, _Val, _KeyOfValue,
3365 _Compare, _Alloc>::iterator
3366 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3367 find(const _Key& __k)
3368 {
3369 iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k));
3370 return (__j == end()
3371 || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j;
3372 }
3373
3374 template<typename _Key, typename _Val, typename _KeyOfValue,
3375 typename _Compare, typename _Alloc>
3376 typename _Rb_tree<_Key, _Val, _KeyOfValue,
3377 _Compare, _Alloc>::const_iterator
3378 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3379 find(const _Key& __k) const
3380 {
3381 const_iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k));
3382 return (__j == end()
3383 || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j;
3384 }
3385
3386 template<typename _Key, typename _Val, typename _KeyOfValue,
3387 typename _Compare, typename _Alloc>
3388 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
3389 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3390 count(const _Key& __k) const
3391 {
3392 pair<const_iterator, const_iterator> __p = equal_range(__k);
3393 const size_type __n = std::distance(__p.first, __p.second);
3394 return __n;
3395 }
3396
3397 _GLIBCXX_PURE unsigned int
3398 _Rb_tree_black_count(const _Rb_tree_node_base* __node,
3399 const _Rb_tree_node_base* __root) throw ();
3400
3401 template<typename _Key, typename _Val, typename _KeyOfValue,
3402 typename _Compare, typename _Alloc>
3403 bool
3404 _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::__rb_verify() const
3405 {
3406 if (_M_impl._M_node_count == 0 || begin() == end())
3407 return _M_impl._M_node_count == 0 && begin() == end()
3408 && this->_M_impl._M_header._M_left == _M_end()
3409 && this->_M_impl._M_header._M_right == _M_end();
3410
3411 unsigned int __len = _Rb_tree_black_count(_M_leftmost(), _M_root());
3412 for (const_iterator __it = begin(); __it != end(); ++__it)
3413 {
3414 _Base_ptr __x = __it._M_node;
3415 _Base_ptr __L = _S_left(__x);
3416 _Base_ptr __R = _S_right(__x);
3417
3418 if (__x->_M_color == _S_red)
3419 if ((__L && __L->_M_color == _S_red)
3420 || (__R && __R->_M_color == _S_red))
3421 return false;
3422
3423 if (__L && _M_key_compare(_S_key(__x), _S_key(__L)))
3424 return false;
3425 if (__R && _M_key_compare(_S_key(__R), _S_key(__x)))
3426 return false;
3427
3428 if (!__L && !__R && _Rb_tree_black_count(__x, _M_root()) != __len)
3429 return false;
3430 }
3431
3432 if (_M_leftmost() != _Node_base::_S_minimum(_M_root()))
3433 return false;
3434 if (_M_rightmost() != _Node_base::_S_maximum(_M_root()))
3435 return false;
3436 return true;
3437 }
3438
3439#ifdef __glibcxx_node_extract // >= C++17
3440 // Allow access to internals of compatible _Rb_tree specializations.
3441 template<typename _Key, typename _Val, typename _Sel, typename _Cmp1,
3442 typename _Alloc, typename _Cmp2>
3443 struct _Rb_tree_merge_helper<_Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>,
3444 _Cmp2>
3445 {
3446 private:
3447 friend class _Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>;
3448
3449 static auto&
3450 _S_get_impl(_Rb_tree<_Key, _Val, _Sel, _Cmp2, _Alloc>& __tree)
3451 { return __tree._M_impl; }
3452 };
3453#endif // C++17
3454
3455#ifdef __glibcxx_associative_heterogeneous_erasure // C++ >= 23
3456template <typename _Kt, typename _Container>
3457 concept __heterogeneous_tree_key =
3458 __transparent_comparator<typename _Container::key_compare> &&
3459 __heterogeneous_key<_Kt, _Container>;
3460#endif
3461
3462_GLIBCXX_END_NAMESPACE_VERSION
3463} // namespace
3464
3465#endif
allocator.h
cpp_type_traits.h
ptr_traits.h
stl_algobase.h
stl_function.h
node_handle.h
aligned_buffer.h
std::chrono::operator<
constexpr bool operator<(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:830
std::true_type
__bool_constant< true > true_type
The type used as a compile-time boolean with true value.
Definition type_traits:119
std::false_type
__bool_constant< false > false_type
The type used as a compile-time boolean with false value.
Definition type_traits:122
std::pair::pair
pair(_T1, _T2) -> pair< _T1, _T2 >
Two pairs are equal iff their members are equal.
std::declval
auto declval() noexcept -> decltype(__declval< _Tp >(0))
Definition type_traits:2741
std::addressof
constexpr _Tp * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
Definition move.h:176
std::move
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
std::__addressof
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition move.h:52
std::forward
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
std::lexicographical_compare_three_way
constexpr auto lexicographical_compare_three_way(_InputIter1 __first1, _InputIter1 __last1, _InputIter2 __first2, _InputIter2 __last2, _Comp __comp) -> decltype(__comp(*__first1, *__first2))
Performs dictionary comparison on ranges.
Definition stl_algobase.h:1867
std
ISO C++ entities toplevel namespace is std.
std::distance
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
Definition stl_iterator_base_funcs.h:177
std::__ptr_rebind
typename pointer_traits< _Ptr >::template rebind< _Tp > __ptr_rebind
Convenience alias for rebinding pointers.
Definition ptr_traits.h:203
std::end
constexpr auto end(_Container &__cont) noexcept(noexcept(__cont.end())) -> decltype(__cont.end())
Return an iterator pointing to one past the last element of the container.
Definition range_access.h:80
std::size
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
Definition range_access.h:294
std::begin
constexpr auto begin(_Container &__cont) noexcept(noexcept(__cont.begin())) -> decltype(__cont.begin())
Return an iterator pointing to the first element of the container.
Definition range_access.h:55
__gnu_debug::__base
constexpr _Iterator __base(_Iterator __it)
Definition helper_functions.h:339
std::is_nothrow_move_assignable
is_nothrow_move_assignable
Definition type_traits:1438
std::size_type
std::allocator
The standard allocator, as per C++03 [20.4.1].
Definition allocator.h:134
std::pair
Struct holding two objects (or references) of arbitrary type.
Definition stl_pair.h:307
std::iterator
Common iterator class.
Definition stl_iterator_base_types.h:133
__gnu_cxx::__alloc_traits< _Node_allocator >::allocate
static constexpr pointer allocate(_Node_allocator &__a, size_type __n)
__gnu_cxx::__alloc_traits< _Node_allocator >::deallocate
static constexpr void deallocate(_Node_allocator &__a, pointer __p, size_type __n)
__gnu_cxx::__alloc_traits< _Node_allocator >::max_size
static constexpr size_type max_size(const _Node_allocator &__a) noexcept
alloc_traits.h