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>
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#pragma GCC diagnostic push
1061#pragma GCC diagnostic ignored "-Wc++11-extensions"
1062 _Reuse_or_alloc_node(const _Reuse_or_alloc_node&) = delete;
1063#pragma GCC diagnostic pop
1064
1065 ~_Reuse_or_alloc_node()
1066 {
1067 if (_M_root)
1068 _M_t._M_erase(static_cast<_Node&>(*_M_root)._M_node_ptr());
1069 }
1070
1071 template<typename _Arg>
1072 _Node_ptr
1073 operator()(_GLIBCXX_FWDREF(_Arg) __arg)
1074 {
1075 _Base_ptr __base = _M_extract();
1076 if (__base)
1077 {
1078 _Node_ptr __node = static_cast<_Node&>(*__base)._M_node_ptr();
1079 _M_t._M_destroy_node(__node);
1080 _M_t._M_construct_node(__node, _GLIBCXX_FORWARD(_Arg, __arg));
1081 return __node;
1082 }
1083
1084 return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg));
1085 }
1086
1087 private:
1088 _Base_ptr
1089 _M_extract()
1090 {
1091 if (!_M_nodes)
1092 return _M_nodes;
1093
1094 _Base_ptr __node = _M_nodes;
1095 _M_nodes = _M_nodes->_M_parent;
1096 if (_M_nodes)
1097 {
1098 if (_M_nodes->_M_right == __node)
1099 {
1100 _M_nodes->_M_right = _Base_ptr();
1101
1102 if (_M_nodes->_M_left)
1103 {
1104 _M_nodes = _M_nodes->_M_left;
1105
1106 while (_M_nodes->_M_right)
1107 _M_nodes = _M_nodes->_M_right;
1108
1109 if (_M_nodes->_M_left)
1110 _M_nodes = _M_nodes->_M_left;
1111 }
1112 }
1113 else // __node is on the left.
1114 _M_nodes->_M_left = _Base_ptr();
1115 }
1116 else
1117 _M_root = _Base_ptr();
1118
1119 return __node;
1120 }
1121
1122 _Base_ptr _M_root;
1123 _Base_ptr _M_nodes;
1124 _Rb_tree& _M_t;
1125 };
1126
1127 // Functor similar to the previous one but without any pool of nodes to
1128 // recycle.
1129 struct _Alloc_node
1130 {
1131 _Alloc_node(_Rb_tree& __t)
1132 : _M_t(__t) { }
1133
1134 template<typename _Arg>
1135 _Node_ptr
1136 operator()(_GLIBCXX_FWDREF(_Arg) __arg) const
1137 { return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); }
1138
1139 private:
1140 _Rb_tree& _M_t;
1141 };
1142
1143 public:
1144 typedef _Key key_type;
1145 typedef _Val value_type;
1146 typedef value_type* pointer;
1147 typedef const value_type* const_pointer;
1148 typedef value_type& reference;
1149 typedef const value_type& const_reference;
1150 typedef size_t size_type;
1151 typedef ptrdiff_t difference_type;
1152 typedef _Alloc allocator_type;
1153
1154 _Node_allocator&
1155 _M_get_Node_allocator() _GLIBCXX_NOEXCEPT
1156 { return this->_M_impl; }
1157
1158 const _Node_allocator&
1159 _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT
1160 { return this->_M_impl; }
1161
1162 allocator_type
1163 get_allocator() const _GLIBCXX_NOEXCEPT
1164 { return allocator_type(_M_get_Node_allocator()); }
1165
1166 protected:
1167 _Node_ptr
1168 _M_get_node()
1169 {
1170#if __cplusplus < 201102L || _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
1171 return _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1);
1172#else
1173#pragma GCC diagnostic push
1174#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
1175 using __alloc_pointer = typename _Node_alloc_traits::pointer;
1176 if constexpr (is_same<_Node_ptr, __alloc_pointer>::value)
1177 return _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1);
1178 else
1179 {
1180 auto __ptr =
1181 _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1);
1182 return std::__to_address(__ptr);
1183 }
1184#pragma GCC diagnostic pop
1185#endif
1186 }
1187
1188 void
1189 _M_put_node(_Node_ptr __p) _GLIBCXX_NOEXCEPT
1190 {
1191#if __cplusplus < 201102L || _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
1192 _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1);
1193#else
1194#pragma GCC diagnostic push
1195#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
1196 using __alloc_pointer = typename _Node_alloc_traits::pointer;
1197 if constexpr (is_same<_Node_ptr, __alloc_pointer>::value)
1198 _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1);
1199 else
1200 {
1201 // When not using the allocator's pointer type internally we must
1202 // convert __p to __alloc_pointer so it can be deallocated.
1203 auto __ap = pointer_traits<__alloc_pointer>::pointer_to(*__p);
1204 _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __ap, 1);
1205 }
1206#pragma GCC diagnostic pop
1207#endif
1208 }
1209
1210#if __cplusplus < 201103L
1211 void
1212 _M_construct_node(_Node_ptr __node, const value_type& __x)
1213 {
1214 __try
1215 { get_allocator().construct(__node->_M_valptr(), __x); }
1216 __catch(...)
1217 {
1218 _M_put_node(__node);
1219 __throw_exception_again;
1220 }
1221 }
1222
1223 _Node_ptr
1224 _M_create_node(const value_type& __x)
1225 {
1226 _Node_ptr __tmp = _M_get_node();
1227 _M_construct_node(__tmp, __x);
1228 return __tmp;
1229 }
1230#else
1231 template<typename... _Args>
1232 void
1233 _M_construct_node(_Node_ptr __node, _Args&&... __args)
1234 {
1235 __try
1236 {
1237 ::new(std::addressof(*__node)) _Node;
1238 _Node_alloc_traits::construct(_M_get_Node_allocator(),
1239 __node->_M_valptr(),
1240 std::forward<_Args>(__args)...);
1241 }
1242 __catch(...)
1243 {
1244 __node->~_Node();
1245 _M_put_node(__node);
1246 __throw_exception_again;
1247 }
1248 }
1249
1250 template<typename... _Args>
1251 _Node_ptr
1252 _M_create_node(_Args&&... __args)
1253 {
1254 _Node_ptr __tmp = _M_get_node();
1255 _M_construct_node(__tmp, std::forward<_Args>(__args)...);
1256 return __tmp;
1257 }
1258#endif
1259
1260 void
1261 _M_destroy_node(_Node_ptr __p) _GLIBCXX_NOEXCEPT
1262 {
1263#if __cplusplus < 201103L
1264 get_allocator().destroy(__p->_M_valptr());
1265#else
1266 _Node_alloc_traits::destroy(_M_get_Node_allocator(), __p->_M_valptr());
1267 __p->~_Node();
1268#endif
1269 }
1270
1271 void
1272 _M_drop_node(_Node_ptr __p) _GLIBCXX_NOEXCEPT
1273 {
1274 _M_destroy_node(__p);
1275 _M_put_node(__p);
1276 }
1277
1278 template<bool _MoveValue, typename _NodeGen>
1279 _Node_ptr
1280 _M_clone_node(_Node_ptr __x, _NodeGen& __node_gen)
1281 {
1282#if __cplusplus >= 201103L
1283 using _Vp = __conditional_t<_MoveValue,
1284 value_type&&,
1285 const value_type&>;
1286#endif
1287 _Node_ptr __tmp
1288 = __node_gen(_GLIBCXX_FORWARD(_Vp, *__x->_M_valptr()));
1289 __tmp->_M_color = __x->_M_color;
1290 __tmp->_M_left = __tmp->_M_right = _Base_ptr();
1291 return __tmp;
1292 }
1293
1294 protected:
1295 typedef typename _Node_traits::_Header_t _Header_t;
1296
1297#if _GLIBCXX_INLINE_VERSION
1298 template<typename _Key_compare>
1299#else
1300 // Unused _Is_pod_comparator is kept as it is part of mangled name.
1301 template<typename _Key_compare,
1302 bool /* _Is_pod_comparator */ = __is_pod(_Key_compare)>
1303#endif
1304 struct _Rb_tree_impl
1305 : public _Node_allocator
1306 , public _Rb_tree_key_compare<_Key_compare>
1307 , public _Header_t
1308 {
1309 typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare;
1310
1311 _Rb_tree_impl()
1312 _GLIBCXX_NOEXCEPT_IF(
1313 is_nothrow_default_constructible<_Node_allocator>::value
1314 && is_nothrow_default_constructible<_Base_key_compare>::value )
1315 : _Node_allocator()
1316 { }
1317
1318 _Rb_tree_impl(const _Rb_tree_impl& __x)
1319 : _Node_allocator(_Node_alloc_traits::_S_select_on_copy(__x))
1320 , _Base_key_compare(__x._M_key_compare)
1321 , _Header_t()
1322 { }
1323
1324#if __cplusplus < 201103L
1325 _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a)
1326 : _Node_allocator(__a), _Base_key_compare(__comp)
1327 { }
1328#else
1329 _Rb_tree_impl(_Rb_tree_impl&&)
1330 noexcept( is_nothrow_move_constructible<_Base_key_compare>::value )
1331 = default;
1332
1333 explicit
1334 _Rb_tree_impl(_Node_allocator&& __a)
1335 : _Node_allocator(std::move(__a))
1336 { }
1337
1338 _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a)
1339 : _Node_allocator(std::move(__a)),
1340 _Base_key_compare(std::move(__x)),
1341 _Header_t(std::move(__x))
1342 { }
1343
1344 _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a)
1345 : _Node_allocator(std::move(__a)), _Base_key_compare(__comp)
1346 { }
1347#endif
1348 };
1349
1350 _Rb_tree_impl<_Compare> _M_impl;
1351
1352 protected:
1353 _Base_ptr&
1354 _M_root() _GLIBCXX_NOEXCEPT
1355 { return this->_M_impl._M_header._M_parent; }
1356
1357 _Base_ptr
1358 _M_root() const _GLIBCXX_NOEXCEPT
1359 { return this->_M_impl._M_header._M_parent; }
1360
1361 _Base_ptr&
1362 _M_leftmost() _GLIBCXX_NOEXCEPT
1363 { return this->_M_impl._M_header._M_left; }
1364
1365 _Base_ptr
1366 _M_leftmost() const _GLIBCXX_NOEXCEPT
1367 { return this->_M_impl._M_header._M_left; }
1368
1369 _Base_ptr&
1370 _M_rightmost() _GLIBCXX_NOEXCEPT
1371 { return this->_M_impl._M_header._M_right; }
1372
1373 _Base_ptr
1374 _M_rightmost() const _GLIBCXX_NOEXCEPT
1375 { return this->_M_impl._M_header._M_right; }
1376
1377 _Base_ptr
1378 _M_begin() const _GLIBCXX_NOEXCEPT
1379 { return this->_M_impl._M_header._M_parent; }
1380
1381 _Node_ptr
1382 _M_begin_node() const _GLIBCXX_NOEXCEPT
1383 {
1384 _Base_ptr __begin = this->_M_impl._M_header._M_parent;
1385 return __begin
1386 ? static_cast<_Node&>(*__begin)._M_node_ptr()
1387 : _Node_ptr();
1388 }
1389
1390 _Base_ptr
1391 _M_end() const _GLIBCXX_NOEXCEPT
1392 { return this->_M_impl._M_header._M_base_ptr(); }
1393
1394 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1395 // 2542. Missing const requirements for associative containers
1396 template<typename _Key1, typename _Key2>
1397 bool
1398 _M_key_compare(const _Key1& __k1, const _Key2& __k2) const
1399 {
1400#if __cplusplus >= 201103L
1401 // Enforce this here with a user-friendly message.
1402 static_assert(
1403 __is_invocable<const _Compare&, const _Key&, const _Key&>::value,
1404 "comparison object must be invocable with arguments of key_type"
1405 );
1406#endif
1407 return _M_impl._M_key_compare(__k1, __k2);
1408 }
1409
1410 static const _Key&
1411 _S_key(const _Node& __node)
1412 { return _KeyOfValue()(*__node._M_valptr()); }
1413
1414 static const _Key&
1415 _S_key(_Base_ptr __x)
1416 { return _S_key(static_cast<const _Node&>(*__x)); }
1417
1418 static const _Key&
1419 _S_key(_Node_ptr __x)
1420 { return _S_key(*__x); }
1421
1422 static _Base_ptr
1423 _S_left(_Base_ptr __x) _GLIBCXX_NOEXCEPT
1424 { return __x->_M_left; }
1425
1426 static _Node_ptr
1427 _S_left(_Node_ptr __x)
1428 {
1429 return __x->_M_left
1430 ? static_cast<_Node&>(*__x->_M_left)._M_node_ptr()
1431 : _Node_ptr();
1432 }
1433
1434 static _Base_ptr
1435 _S_right(_Base_ptr __x) _GLIBCXX_NOEXCEPT
1436 { return __x->_M_right; }
1437
1438 static _Node_ptr
1439 _S_right(_Node_ptr __x) _GLIBCXX_NOEXCEPT
1440 {
1441 return __x->_M_right
1442 ? static_cast<_Node&>(*__x->_M_right)._M_node_ptr()
1443 : _Node_ptr();
1444 }
1445
1446 public:
1447 typedef typename _Node_traits::_Iterator iterator;
1448 typedef typename _Node_traits::_Const_iterator const_iterator;
1449
1450 typedef std::reverse_iterator<iterator> reverse_iterator;
1451 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1452
1453#ifdef __glibcxx_node_extract // >= C++17
1454 using node_type = _Node_handle<_Key, _Val, _Node_allocator>;
1455 using insert_return_type = _Node_insert_return<
1456 __conditional_t<is_same_v<_Key, _Val>, const_iterator, iterator>,
1457 node_type>;
1458#endif
1459
1461 _M_get_insert_unique_pos(const key_type& __k);
1462
1464 _M_get_insert_equal_pos(const key_type& __k);
1465
1467 _M_get_insert_hint_unique_pos(const_iterator __pos,
1468 const key_type& __k);
1469
1471 _M_get_insert_hint_equal_pos(const_iterator __pos,
1472 const key_type& __k);
1473
1474#ifdef __glibcxx_associative_heterogeneous_insertion // C++26
1475 template <typename... _Args>
1476 iterator
1477 _M_emplace_here(bool __place_left, _Base_ptr __node, _Args&&... __args);
1478
1479 template <typename _Kt>
1481 _M_get_insert_unique_pos_tr(const _Kt& __k);
1482
1483 template <typename _Kt>
1485 _M_get_insert_hint_unique_pos_tr(const_iterator, const _Kt& __k);
1486#endif
1487
1488 private:
1489#if __cplusplus >= 201103L
1490 template<typename _Arg, typename _NodeGen>
1491 iterator
1492 _M_insert_(_Base_ptr __x, _Base_ptr __y, _Arg&& __v, _NodeGen&);
1493
1494 iterator
1495 _M_insert_node(_Base_ptr __x, _Base_ptr __y, _Node_ptr __z);
1496
1497 template<typename _Arg>
1498 iterator
1499 _M_insert_lower(_Base_ptr __y, _Arg&& __v);
1500
1501 template<typename _Arg>
1502 iterator
1503 _M_insert_equal_lower(_Arg&& __x);
1504
1505 iterator
1506 _M_insert_lower_node(_Base_ptr __p, _Node_ptr __z);
1507
1508 iterator
1509 _M_insert_equal_lower_node(_Node_ptr __z);
1510#else
1511 template<typename _NodeGen>
1512 iterator
1513 _M_insert_(_Base_ptr __x, _Base_ptr __y,
1514 const value_type& __v, _NodeGen&);
1515
1516 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1517 // 233. Insertion hints in associative containers.
1518 iterator
1519 _M_insert_lower(_Base_ptr __y, const value_type& __v);
1520
1521 iterator
1522 _M_insert_equal_lower(const value_type& __x);
1523#endif
1524
1525 enum { __as_lvalue, __as_rvalue };
1526
1527 template<bool _MoveValues, typename _NodeGen>
1528 _Base_ptr
1529 _M_copy(_Node_ptr, _Base_ptr, _NodeGen&);
1530
1531 template<bool _MoveValues, typename _NodeGen>
1532 _Base_ptr
1533 _M_copy(const _Rb_tree& __x, _NodeGen& __gen)
1534 {
1535 _Base_ptr __root =
1536 _M_copy<_MoveValues>(__x._M_begin_node(), _M_end(), __gen);
1537 _M_leftmost() = _Node_base::_S_minimum(__root);
1538 _M_rightmost() = _Node_base::_S_maximum(__root);
1539 _M_impl._M_node_count = __x._M_impl._M_node_count;
1540 return __root;
1541 }
1542
1543 _Base_ptr
1544 _M_copy(const _Rb_tree& __x)
1545 {
1546 _Alloc_node __an(*this);
1547 return _M_copy<__as_lvalue>(__x, __an);
1548 }
1549
1550 void
1551 _M_erase(_Node_ptr __x);
1552
1553 _Base_ptr
1554 _M_lower_bound(_Base_ptr __x, _Base_ptr __y,
1555 const _Key& __k) const;
1556
1557 template <typename _Kt>
1558 _Base_ptr
1559 _M_lower_bound_tr(_Base_ptr __x, _Base_ptr __y, const _Kt& __k) const;
1560
1561 _Base_ptr
1562 _M_upper_bound(_Base_ptr __x, _Base_ptr __y,
1563 const _Key& __k) const;
1564
1565 template <typename _Kt>
1566 _Base_ptr
1567 _M_upper_bound_tr(_Base_ptr __x, _Base_ptr __y, const _Kt& __k) const;
1568
1569 public:
1570 // allocation/deallocation
1571#if __cplusplus < 201103L
1572 _Rb_tree() { }
1573#else
1574 _Rb_tree() = default;
1575#endif
1576
1577 _Rb_tree(const _Compare& __comp,
1578 const allocator_type& __a = allocator_type())
1579 : _M_impl(__comp, _Node_allocator(__a)) { }
1580
1581 _Rb_tree(const _Rb_tree& __x)
1582 : _M_impl(__x._M_impl)
1583 {
1584 if (__x._M_root())
1585 _M_root() = _M_copy(__x);
1586 }
1587
1588#if __cplusplus >= 201103L
1589 _Rb_tree(const allocator_type& __a)
1590 : _M_impl(_Node_allocator(__a))
1591 { }
1592
1593 _Rb_tree(const _Rb_tree& __x, const allocator_type& __a)
1594 : _M_impl(__x._M_impl._M_key_compare, _Node_allocator(__a))
1595 {
1596 if (__x._M_root())
1597 _M_root() = _M_copy(__x);
1598 }
1599
1600 _Rb_tree(_Rb_tree&&) = default;
1601
1602 _Rb_tree(_Rb_tree&& __x, const allocator_type& __a)
1603 : _Rb_tree(std::move(__x), _Node_allocator(__a))
1604 { }
1605
1606 private:
1607 _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type)
1608 noexcept(is_nothrow_default_constructible<_Compare>::value)
1609 : _M_impl(std::move(__x._M_impl), std::move(__a))
1610 { }
1611
1612 _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type)
1613 : _M_impl(__x._M_impl._M_key_compare, std::move(__a))
1614 {
1615 if (__x._M_root())
1616 _M_move_data(__x, false_type{});
1617 }
1618
1619 public:
1620 _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)
1621 noexcept( noexcept(
1624 : _Rb_tree(std::move(__x), std::move(__a),
1625 typename _Node_alloc_traits::is_always_equal{})
1626 { }
1627#endif
1628
1629 ~_Rb_tree() _GLIBCXX_NOEXCEPT
1630 { _M_erase(_M_begin_node()); }
1631
1632 _Rb_tree&
1633 operator=(const _Rb_tree& __x);
1634
1635 // Accessors.
1636 _Compare
1637 key_comp() const
1638 { return _M_impl._M_key_compare; }
1639
1640 iterator
1641 begin() _GLIBCXX_NOEXCEPT
1642 { return iterator(this->_M_impl._M_header._M_left); }
1643
1644 const_iterator
1645 begin() const _GLIBCXX_NOEXCEPT
1646 { return const_iterator(this->_M_impl._M_header._M_left); }
1647
1648 iterator
1649 end() _GLIBCXX_NOEXCEPT
1650 { return iterator(_M_end()); }
1651
1652 const_iterator
1653 end() const _GLIBCXX_NOEXCEPT
1654 { return const_iterator(_M_end()); }
1655
1656 reverse_iterator
1657 rbegin() _GLIBCXX_NOEXCEPT
1658 { return reverse_iterator(end()); }
1659
1660 const_reverse_iterator
1661 rbegin() const _GLIBCXX_NOEXCEPT
1662 { return const_reverse_iterator(end()); }
1663
1664 reverse_iterator
1665 rend() _GLIBCXX_NOEXCEPT
1666 { return reverse_iterator(begin()); }
1667
1668 const_reverse_iterator
1669 rend() const _GLIBCXX_NOEXCEPT
1670 { return const_reverse_iterator(begin()); }
1671
1672 _GLIBCXX_NODISCARD bool
1673 empty() const _GLIBCXX_NOEXCEPT
1674 { return _M_impl._M_node_count == 0; }
1675
1676 size_type
1677 size() const _GLIBCXX_NOEXCEPT
1678 { return _M_impl._M_node_count; }
1679
1680 size_type
1681 max_size() const _GLIBCXX_NOEXCEPT
1682 { return _Node_alloc_traits::max_size(_M_get_Node_allocator()); }
1683
1684 void
1685 swap(_Rb_tree& __t)
1686 _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value);
1687
1688 // Insert/erase.
1689#if __cplusplus >= 201103L
1690 template<typename _Arg>
1692 _M_insert_unique(_Arg&& __x);
1693
1694 template<typename _Arg>
1695 iterator
1696 _M_insert_equal(_Arg&& __x);
1697
1698 template<typename _Arg, typename _NodeGen>
1699 iterator
1700 _M_insert_unique_(const_iterator __pos, _Arg&& __x, _NodeGen&);
1701
1702 template<typename _Arg>
1703 iterator
1704 _M_insert_unique_(const_iterator __pos, _Arg&& __x)
1705 {
1706 _Alloc_node __an(*this);
1707 return _M_insert_unique_(__pos, std::forward<_Arg>(__x), __an);
1708 }
1709
1710 template<typename _Arg, typename _NodeGen>
1711 iterator
1712 _M_insert_equal_(const_iterator __pos, _Arg&& __x, _NodeGen&);
1713
1714 template<typename _Arg>
1715 iterator
1716 _M_insert_equal_(const_iterator __pos, _Arg&& __x)
1717 {
1718 _Alloc_node __an(*this);
1719 return _M_insert_equal_(__pos, std::forward<_Arg>(__x), __an);
1720 }
1721
1722 template<typename... _Args>
1724 _M_emplace_unique(_Args&&... __args);
1725
1726 template<typename... _Args>
1727 iterator
1728 _M_emplace_equal(_Args&&... __args);
1729
1730 template<typename... _Args>
1731 iterator
1732 _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args);
1733
1734 template<typename... _Args>
1735 iterator
1736 _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args);
1737
1738 template<typename _Iter>
1739 using __same_value_type
1740 = is_same<value_type, typename iterator_traits<_Iter>::value_type>;
1741
1742 template<typename _InputIterator>
1743 __enable_if_t<__same_value_type<_InputIterator>::value>
1744 _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
1745 {
1746 _Alloc_node __an(*this);
1747 for (; __first != __last; ++__first)
1748 _M_insert_unique_(end(), *__first, __an);
1749 }
1750
1751 template<typename _InputIterator>
1752 __enable_if_t<!__same_value_type<_InputIterator>::value>
1753 _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
1754 {
1755 for (; __first != __last; ++__first)
1756 _M_emplace_unique(*__first);
1757 }
1758
1759 template<typename _InputIterator>
1760 __enable_if_t<__same_value_type<_InputIterator>::value>
1761 _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
1762 {
1763 _Alloc_node __an(*this);
1764 for (; __first != __last; ++__first)
1765 _M_insert_equal_(end(), *__first, __an);
1766 }
1767
1768 template<typename _InputIterator>
1769 __enable_if_t<!__same_value_type<_InputIterator>::value>
1770 _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
1771 {
1772 for (; __first != __last; ++__first)
1773 _M_emplace_equal(*__first);
1774 }
1775#else
1777 _M_insert_unique(const value_type& __x);
1778
1779 iterator
1780 _M_insert_equal(const value_type& __x);
1781
1782 template<typename _NodeGen>
1783 iterator
1784 _M_insert_unique_(const_iterator __pos, const value_type& __x,
1785 _NodeGen&);
1786
1787 iterator
1788 _M_insert_unique_(const_iterator __pos, const value_type& __x)
1789 {
1790 _Alloc_node __an(*this);
1791 return _M_insert_unique_(__pos, __x, __an);
1792 }
1793
1794 template<typename _NodeGen>
1795 iterator
1796 _M_insert_equal_(const_iterator __pos, const value_type& __x,
1797 _NodeGen&);
1798 iterator
1799 _M_insert_equal_(const_iterator __pos, const value_type& __x)
1800 {
1801 _Alloc_node __an(*this);
1802 return _M_insert_equal_(__pos, __x, __an);
1803 }
1804
1805 template<typename _InputIterator>
1806 void
1807 _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
1808 {
1809 _Alloc_node __an(*this);
1810 for (; __first != __last; ++__first)
1811 _M_insert_unique_(end(), *__first, __an);
1812 }
1813
1814 template<typename _InputIterator>
1815 void
1816 _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
1817 {
1818 _Alloc_node __an(*this);
1819 for (; __first != __last; ++__first)
1820 _M_insert_equal_(end(), *__first, __an);
1821 }
1822#endif
1823
1824 private:
1825 void
1826 _M_erase_aux(const_iterator __position);
1827
1828 void
1829 _M_erase_aux(const_iterator __first, const_iterator __last);
1830
1831 public:
1832#if __cplusplus >= 201103L
1833 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1834 // DR 130. Associative erase should return an iterator.
1835 _GLIBCXX_ABI_TAG_CXX11
1836 iterator
1837 erase(const_iterator __position)
1838 {
1839 __glibcxx_assert(__position != end());
1840 const_iterator __result = __position;
1841 ++__result;
1842 _M_erase_aux(__position);
1843 return iterator(__result._M_node);
1844 }
1845
1846 // LWG 2059.
1847 _GLIBCXX_ABI_TAG_CXX11
1848 iterator
1849 erase(iterator __position)
1850 {
1851 __glibcxx_assert(__position != end());
1852 iterator __result = __position;
1853 ++__result;
1854 _M_erase_aux(__position);
1855 return __result;
1856 }
1857#else
1858 void
1859 erase(iterator __position)
1860 {
1861 __glibcxx_assert(__position != end());
1862 _M_erase_aux(__position);
1863 }
1864
1865 void
1866 erase(const_iterator __position)
1867 {
1868 __glibcxx_assert(__position != end());
1869 _M_erase_aux(__position);
1870 }
1871#endif
1872
1873 size_type
1874 erase(const key_type& __x);
1875
1876 template <typename _Kt>
1877 size_type
1878 _M_erase_tr(const _Kt& __x);
1879
1880 size_type
1881 _M_erase_unique(const key_type& __x);
1882
1883#if __cplusplus >= 201103L
1884 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1885 // DR 130. Associative erase should return an iterator.
1886 _GLIBCXX_ABI_TAG_CXX11
1887 iterator
1888 erase(const_iterator __first, const_iterator __last)
1889 {
1890 _M_erase_aux(__first, __last);
1891 return iterator(__last._M_node);
1892 }
1893#else
1894 void
1895 erase(iterator __first, iterator __last)
1896 { _M_erase_aux(__first, __last); }
1897
1898 void
1899 erase(const_iterator __first, const_iterator __last)
1900 { _M_erase_aux(__first, __last); }
1901#endif
1902
1903 void
1904 clear() _GLIBCXX_NOEXCEPT
1905 {
1906 _M_erase(_M_begin_node());
1907 _M_impl._M_reset();
1908 }
1909
1910 // Set operations.
1911 iterator
1912 find(const key_type& __k);
1913
1914 const_iterator
1915 find(const key_type& __k) const;
1916
1917 size_type
1918 count(const key_type& __k) const;
1919
1920 iterator
1921 lower_bound(const key_type& __k)
1922 { return iterator(_M_lower_bound(_M_begin(), _M_end(), __k)); }
1923
1924 const_iterator
1925 lower_bound(const key_type& __k) const
1926 {
1927 return const_iterator
1928 (_M_lower_bound(_M_begin(), _M_end(), __k));
1929 }
1930
1931 iterator
1932 upper_bound(const key_type& __k)
1933 { return iterator(_M_upper_bound(_M_begin(), _M_end(), __k)); }
1934
1935 const_iterator
1936 upper_bound(const key_type& __k) const
1937 {
1938 return const_iterator
1939 (_M_upper_bound(_M_begin(), _M_end(), __k));
1940 }
1941
1943 equal_range(const key_type& __k);
1944
1946 equal_range(const key_type& __k) const;
1947
1948#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
1949 template<typename _Kt,
1950 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1951 iterator
1952 _M_find_tr(const _Kt& __k)
1953 {
1954 const _Rb_tree* __const_this = this;
1955 return iterator(__const_this->_M_find_tr(__k)._M_node);
1956 }
1957
1958 template<typename _Kt,
1959 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1960 const_iterator
1961 _M_find_tr(const _Kt& __k) const
1962 {
1963 const_iterator __j(_M_lower_bound_tr(__k));
1964 if (__j != end() && _M_key_compare(__k, _S_key(__j._M_node)))
1965 __j = end();
1966 return __j;
1967 }
1968
1969 template<typename _Kt,
1970 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1971 size_type
1972 _M_count_tr(const _Kt& __k) const
1973 {
1974 auto __p = _M_equal_range_tr(__k);
1975 return std::distance(__p.first, __p.second);
1976 }
1977
1978 template<typename _Kt,
1979 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1980 _Base_ptr
1981 _M_lower_bound_tr(const _Kt& __k) const
1982 {
1983 auto __x = _M_begin();
1984 auto __y = _M_end();
1985 while (__x)
1986 if (!_M_key_compare(_S_key(__x), __k))
1987 {
1988 __y = __x;
1989 __x = _S_left(__x);
1990 }
1991 else
1992 __x = _S_right(__x);
1993 return __y;
1994 }
1995
1996 template<typename _Kt,
1997 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1998 _Base_ptr
1999 _M_upper_bound_tr(const _Kt& __k) const
2000 {
2001 auto __x = _M_begin();
2002 auto __y = _M_end();
2003 while (__x)
2004 if (_M_key_compare(__k, _S_key(__x)))
2005 {
2006 __y = __x;
2007 __x = _S_left(__x);
2008 }
2009 else
2010 __x = _S_right(__x);
2011 return __y;
2012 }
2013
2014 template<typename _Kt,
2015 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
2017 _M_equal_range_tr(const _Kt& __k)
2018 {
2019 const _Rb_tree* __const_this = this;
2020 auto __ret = __const_this->_M_equal_range_tr(__k);
2021 return
2022 { iterator(__ret.first._M_node), iterator(__ret.second._M_node) };
2023 }
2024
2025 template<typename _Kt,
2026 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
2028 _M_equal_range_tr(const _Kt& __k) const
2029 {
2030 auto __x = _M_begin();
2031 auto __y = _M_end();
2032 while (__x)
2033 {
2034 if (_M_key_compare(_S_key(__x), __k))
2035 __x = _S_right(__x);
2036 else if (_M_key_compare(__k, _S_key(__x)))
2037 {
2038 __y = __x;
2039 __x = _S_left(__x);
2040 }
2041 else
2042 {
2043 auto __xu(__x);
2044 auto __yu(__y);
2045 __y = __x;
2046 __x = _S_left(__x);
2047 __xu = _S_right(__xu);
2048 return { const_iterator(_M_lower_bound_tr(__x, __y, __k)),
2049 const_iterator(_M_upper_bound_tr(__xu, __yu, __k)) };
2050 }
2051 }
2052 return { const_iterator(__y), const_iterator(__y) };
2053 }
2054#endif // __glibcxx_generic_associative_lookup
2055
2056 // Debugging.
2057 bool
2058 __rb_verify() const;
2059
2060#if __cplusplus >= 201103L
2061 _Rb_tree&
2062 operator=(_Rb_tree&&)
2063 noexcept(_Node_alloc_traits::_S_nothrow_move()
2064 && is_nothrow_move_assignable<_Compare>::value);
2065
2066 template<typename _Iterator>
2067 void
2068 _M_assign_unique(_Iterator, _Iterator);
2069
2070 template<typename _Iterator>
2071 void
2072 _M_assign_equal(_Iterator, _Iterator);
2073
2074 private:
2075 // Move elements from container with equal allocator.
2076 void
2077 _M_move_data(_Rb_tree& __x, true_type)
2078 { _M_impl._M_move_data(__x._M_impl); }
2079
2080 // Move elements from container with possibly non-equal allocator,
2081 // which might result in a copy not a move.
2082 void
2083 _M_move_data(_Rb_tree&, false_type);
2084
2085 // Move assignment from container with equal allocator.
2086 void
2087 _M_move_assign(_Rb_tree&, true_type);
2088
2089 // Move assignment from container with possibly non-equal allocator,
2090 // which might result in a copy not a move.
2091 void
2092 _M_move_assign(_Rb_tree&, false_type);
2093#endif
2094
2095#ifdef __glibcxx_node_extract // >= C++17
2096 static _Node_ptr
2097 _S_adapt(typename _Node_alloc_traits::pointer __ptr)
2098 {
2099#if _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
2100 return __ptr;
2101#else
2102#pragma GCC diagnostic push
2103#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
2104 using __alloc_ptr = typename _Node_alloc_traits::pointer;
2105 if constexpr (is_same<_Node_ptr, __alloc_ptr>::value)
2106 return __ptr;
2107 else
2108 return std::__to_address(__ptr);
2109#pragma GCC diagnostic pop
2110#endif
2111 }
2112
2113 public:
2114 /// Re-insert an extracted node.
2115 insert_return_type
2116 _M_reinsert_node_unique(node_type&& __nh)
2117 {
2118 insert_return_type __ret;
2119 if (__nh.empty())
2120 __ret.position = end();
2121 else
2122 {
2123 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
2124
2125 auto __res = _M_get_insert_unique_pos(__nh._M_key());
2126 if (__res.second)
2127 {
2128 __ret.position
2129 = _M_insert_node(__res.first, __res.second,
2130 _S_adapt(__nh._M_ptr));
2131 __nh.release();
2132 __ret.inserted = true;
2133 }
2134 else
2135 {
2136 __ret.node = std::move(__nh);
2137 __ret.position = iterator(__res.first);
2138 __ret.inserted = false;
2139 }
2140 }
2141 return __ret;
2142 }
2143
2144 /// Re-insert an extracted node.
2145 iterator
2146 _M_reinsert_node_equal(node_type&& __nh)
2147 {
2148 iterator __ret;
2149 if (__nh.empty())
2150 __ret = end();
2151 else
2152 {
2153 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
2154 auto __res = _M_get_insert_equal_pos(__nh._M_key());
2155 if (__res.second)
2156 __ret = _M_insert_node(__res.first, __res.second,
2157 _S_adapt(__nh._M_ptr));
2158 else
2159 __ret = _M_insert_equal_lower_node(_S_adapt(__nh._M_ptr));
2160 __nh.release();
2161 }
2162 return __ret;
2163 }
2164
2165 /// Re-insert an extracted node.
2166 iterator
2167 _M_reinsert_node_hint_unique(const_iterator __hint, node_type&& __nh)
2168 {
2169 iterator __ret;
2170 if (__nh.empty())
2171 __ret = end();
2172 else
2173 {
2174 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
2175 auto __res = _M_get_insert_hint_unique_pos(__hint, __nh._M_key());
2176 if (__res.second)
2177 {
2178 __ret = _M_insert_node(__res.first, __res.second,
2179 _S_adapt(__nh._M_ptr));
2180 __nh.release();
2181 }
2182 else
2183 __ret = iterator(__res.first);
2184 }
2185 return __ret;
2186 }
2187
2188 /// Re-insert an extracted node.
2189 iterator
2190 _M_reinsert_node_hint_equal(const_iterator __hint, node_type&& __nh)
2191 {
2192 iterator __ret;
2193 if (__nh.empty())
2194 __ret = end();
2195 else
2196 {
2197 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
2198 auto __res = _M_get_insert_hint_equal_pos(__hint, __nh._M_key());
2199 if (__res.second)
2200 __ret = _M_insert_node(__res.first, __res.second,
2201 _S_adapt(__nh._M_ptr));
2202 else
2203 __ret = _M_insert_equal_lower_node(_S_adapt(__nh._M_ptr));
2204 __nh.release();
2205 }
2206 return __ret;
2207 }
2208
2209 /// Extract a node.
2210 node_type
2211 extract(const_iterator __pos)
2212 {
2213 auto __ptr = _Node_traits::_S_rebalance_for_erase
2214 (__pos._M_node, _M_impl._M_header);
2215 --_M_impl._M_node_count;
2216 auto __node_ptr = static_cast<_Node&>(*__ptr)._M_node_ptr();
2217#if _GLIBCXX_USE_ALLOC_PTR_FOR_RB_TREE
2218 return { __node_ptr, _M_get_Node_allocator() };
2219#else
2220#pragma GCC diagnostic push
2221#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
2222 using __alloc_ptr = typename _Node_alloc_traits::pointer;
2223 if constexpr (is_same<_Node_ptr, __alloc_ptr>::value)
2224 return { __node_ptr, _M_get_Node_allocator() };
2225 else
2226 {
2227 auto __ap = pointer_traits<__alloc_ptr>::pointer_to(*__node_ptr);
2228 return { __ap, _M_get_Node_allocator() };
2229 }
2230#pragma GCC diagnostic pop
2231#endif
2232 }
2233
2234 /// Extract a node.
2235 node_type
2236 extract(const key_type& __k)
2237 {
2238 node_type __nh;
2239 auto __pos = find(__k);
2240 if (__pos != end())
2241 __nh = extract(const_iterator(__pos));
2242 return __nh;
2243 }
2244
2245 template <typename _Kt>
2246 node_type
2247 _M_extract_tr(const _Kt& __k)
2248 {
2249 node_type __nh;
2250 auto __pos = _M_find_tr(__k);
2251 if (__pos != end())
2252 __nh = extract(const_iterator(__pos));
2253 return __nh;
2254 }
2255
2256 template<typename _Compare2>
2257 using _Compatible_tree
2258 = _Rb_tree<_Key, _Val, _KeyOfValue, _Compare2, _Alloc>;
2259
2260 template<typename, typename>
2261 friend struct _Rb_tree_merge_helper;
2262
2263 /// Merge from a compatible container into one with unique keys.
2264 template<typename _Compare2>
2265 void
2266 _M_merge_unique(_Compatible_tree<_Compare2>& __src) noexcept
2267 {
2268 using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>;
2269 for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
2270 {
2271 auto __pos = __i++;
2272 auto __res = _M_get_insert_unique_pos(_KeyOfValue()(*__pos));
2273 if (__res.second)
2274 {
2275 auto& __src_impl = _Merge_helper::_S_get_impl(__src);
2276 auto __ptr = _Node_traits::_S_rebalance_for_erase
2277 (__pos._M_node, __src_impl._M_header);
2278 --__src_impl._M_node_count;
2279 auto __node_ptr = static_cast<_Node&>(*__ptr)._M_node_ptr();
2280 _M_insert_node(__res.first, __res.second, __node_ptr);
2281 }
2282 }
2283 }
2284
2285 /// Merge from a compatible container into one with equivalent keys.
2286 template<typename _Compare2>
2287 void
2288 _M_merge_equal(_Compatible_tree<_Compare2>& __src) noexcept
2289 {
2290 using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>;
2291 for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
2292 {
2293 auto __pos = __i++;
2294 auto __res = _M_get_insert_equal_pos(_KeyOfValue()(*__pos));
2295 if (__res.second)
2296 {
2297 auto& __src_impl = _Merge_helper::_S_get_impl(__src);
2298 auto __ptr = _Node_traits::_S_rebalance_for_erase
2299 (__pos._M_node, __src_impl._M_header);
2300 --__src_impl._M_node_count;
2301 auto __node_ptr = static_cast<_Node&>(*__ptr)._M_node_ptr();
2302 _M_insert_node(__res.first, __res.second, __node_ptr);
2303 }
2304 }
2305 }
2306#endif // C++17 node_extract
2307
2308 friend bool
2309 operator==(const _Rb_tree& __x, const _Rb_tree& __y)
2310 {
2311 return __x.size() == __y.size()
2312 && std::equal(__x.begin(), __x.end(), __y.begin());
2313 }
2314
2315#if __cpp_lib_three_way_comparison
2316 friend auto
2317 operator<=>(const _Rb_tree& __x, const _Rb_tree& __y)
2318 {
2319 if constexpr (requires { typename __detail::__synth3way_t<_Val>; })
2320 return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
2321 __y.begin(), __y.end(),
2322 __detail::__synth3way);
2323 }
2324#else
2325 friend bool
2326 operator<(const _Rb_tree& __x, const _Rb_tree& __y)
2327 {
2328 return std::lexicographical_compare(__x.begin(), __x.end(),
2329 __y.begin(), __y.end());
2330 }
2331#endif
2332
2333 private:
2334#if __cplusplus >= 201103L
2335 // An RAII _Node handle
2336 struct _Auto_node
2337 {
2338 template<typename... _Args>
2339 _Auto_node(_Rb_tree& __t, _Args&&... __args)
2340 : _M_t(__t),
2341 _M_node(__t._M_create_node(std::forward<_Args>(__args)...))
2342 { }
2343
2344 ~_Auto_node()
2345 {
2346 if (_M_node)
2347 _M_t._M_drop_node(_M_node);
2348 }
2349
2350 _Auto_node(_Auto_node&& __n)
2351 : _M_t(__n._M_t), _M_node(__n._M_node)
2352 { __n._M_node = nullptr; }
2353
2354 const _Key&
2355 _M_key() const
2356 { return _S_key(_M_node); }
2357
2358 iterator
2359 _M_insert(pair<_Base_ptr, _Base_ptr> __p)
2360 {
2361 auto __it = _M_t._M_insert_node(__p.first, __p.second, _M_node);
2362 _M_node = nullptr;
2363 return __it;
2364 }
2365
2366 iterator
2367 _M_insert_equal_lower()
2368 {
2369 auto __it = _M_t._M_insert_equal_lower_node(_M_node);
2370 _M_node = nullptr;
2371 return __it;
2372 }
2373
2374 _Rb_tree& _M_t;
2375 _Node_ptr _M_node;
2376 };
2377#endif // C++11
2378 };
2379
2380 template<typename _Key, typename _Val, typename _KeyOfValue,
2381 typename _Compare, typename _Alloc>
2382 inline void
2383 swap(_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
2384 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
2385 { __x.swap(__y); }
2386
2387#if __cplusplus >= 201103L
2388 template<typename _Key, typename _Val, typename _KeyOfValue,
2389 typename _Compare, typename _Alloc>
2390 void
2391 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2392 _M_move_data(_Rb_tree& __x, false_type)
2393 {
2394 if (_M_get_Node_allocator() == __x._M_get_Node_allocator())
2395 _M_move_data(__x, true_type());
2396 else
2397 {
2398 constexpr bool __move = !__move_if_noexcept_cond<value_type>::value;
2399 _Alloc_node __an(*this);
2400 _M_root() = _M_copy<__move>(__x, __an);
2401#pragma GCC diagnostic push
2402#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
2403 if constexpr (__move)
2404 __x.clear();
2405#pragma GCC diagnostic pop
2406 }
2407 }
2408
2409 template<typename _Key, typename _Val, typename _KeyOfValue,
2410 typename _Compare, typename _Alloc>
2411 inline void
2412 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2413 _M_move_assign(_Rb_tree& __x, true_type)
2414 {
2415 clear();
2416 if (__x._M_root())
2417 _M_move_data(__x, true_type());
2418 std::__alloc_on_move(_M_get_Node_allocator(),
2419 __x._M_get_Node_allocator());
2420 }
2421
2422 template<typename _Key, typename _Val, typename _KeyOfValue,
2423 typename _Compare, typename _Alloc>
2424 void
2425 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2426 _M_move_assign(_Rb_tree& __x, false_type)
2427 {
2428 if (_M_get_Node_allocator() == __x._M_get_Node_allocator())
2429 return _M_move_assign(__x, true_type{});
2430
2431 // Try to move each node reusing existing nodes and copying __x nodes
2432 // structure.
2433 _Reuse_or_alloc_node __roan(*this);
2434 _M_impl._M_reset();
2435 if (__x._M_root())
2436 {
2437 _M_root() = _M_copy<__as_rvalue>(__x, __roan);
2438 __x.clear();
2439 }
2440 }
2441
2442 template<typename _Key, typename _Val, typename _KeyOfValue,
2443 typename _Compare, typename _Alloc>
2444 inline _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&
2445 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2446 operator=(_Rb_tree&& __x)
2447 noexcept(_Node_alloc_traits::_S_nothrow_move()
2449 {
2450 _M_impl._M_key_compare = std::move(__x._M_impl._M_key_compare);
2451 _M_move_assign(__x,
2452 __bool_constant<_Node_alloc_traits::_S_nothrow_move()>());
2453 return *this;
2454 }
2455
2456 template<typename _Key, typename _Val, typename _KeyOfValue,
2457 typename _Compare, typename _Alloc>
2458 template<typename _Iterator>
2459 void
2460 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2461 _M_assign_unique(_Iterator __first, _Iterator __last)
2462 {
2463 _Reuse_or_alloc_node __roan(*this);
2464 _M_impl._M_reset();
2465 for (; __first != __last; ++__first)
2466 _M_insert_unique_(end(), *__first, __roan);
2467 }
2468
2469 template<typename _Key, typename _Val, typename _KeyOfValue,
2470 typename _Compare, typename _Alloc>
2471 template<typename _Iterator>
2472 void
2473 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2474 _M_assign_equal(_Iterator __first, _Iterator __last)
2475 {
2476 _Reuse_or_alloc_node __roan(*this);
2477 _M_impl._M_reset();
2478 for (; __first != __last; ++__first)
2479 _M_insert_equal_(end(), *__first, __roan);
2480 }
2481#endif // C++11
2482
2483 template<typename _Key, typename _Val, typename _KeyOfValue,
2484 typename _Compare, typename _Alloc>
2485 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&
2486 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2487 operator=(const _Rb_tree& __x)
2488 {
2489 if (this != std::__addressof(__x))
2490 {
2491 // Note that _Key may be a constant type.
2492#if __cplusplus >= 201103L
2493 if (_Node_alloc_traits::_S_propagate_on_copy_assign())
2494 {
2495 auto& __this_alloc = this->_M_get_Node_allocator();
2496 auto& __that_alloc = __x._M_get_Node_allocator();
2497 if (!_Node_alloc_traits::_S_always_equal()
2498 && __this_alloc != __that_alloc)
2499 {
2500 // Replacement allocator cannot free existing storage, we need
2501 // to erase nodes first.
2502 clear();
2503 std::__alloc_on_copy(__this_alloc, __that_alloc);
2504 }
2505 }
2506#endif
2507
2508 _Reuse_or_alloc_node __roan(*this);
2509 _M_impl._M_reset();
2510 _M_impl._M_key_compare = __x._M_impl._M_key_compare;
2511 if (__x._M_root())
2512 _M_root() = _M_copy<__as_lvalue>(__x, __roan);
2513 }
2514
2515 return *this;
2516 }
2517
2518 template<typename _Key, typename _Val, typename _KeyOfValue,
2519 typename _Compare, typename _Alloc>
2520#if __cplusplus >= 201103L
2521 template<typename _Arg, typename _NodeGen>
2522#else
2523 template<typename _NodeGen>
2524#endif
2525 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2526 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2527 _M_insert_(_Base_ptr __x, _Base_ptr __p,
2528#if __cplusplus >= 201103L
2529 _Arg&& __v,
2530#else
2531 const _Val& __v,
2532#endif
2533 _NodeGen& __node_gen)
2534 {
2535 bool __insert_left = (__x || __p == _M_end()
2536 || _M_key_compare(_KeyOfValue()(__v),
2537 _S_key(__p)));
2538
2539 _Base_ptr __z =
2540 __node_gen(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr();
2541
2542 _Node_traits::_S_insert_and_rebalance
2543 (__insert_left, __z, __p, this->_M_impl._M_header);
2544 ++_M_impl._M_node_count;
2545 return iterator(__z);
2546 }
2547
2548 template<typename _Key, typename _Val, typename _KeyOfValue,
2549 typename _Compare, typename _Alloc>
2550#if __cplusplus >= 201103L
2551 template<typename _Arg>
2552#endif
2553 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2554 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2555#if __cplusplus >= 201103L
2556 _M_insert_lower(_Base_ptr __p, _Arg&& __v)
2557#else
2558 _M_insert_lower(_Base_ptr __p, const _Val& __v)
2559#endif
2560 {
2561 bool __insert_left = (__p == _M_end()
2562 || !_M_key_compare(_S_key(__p),
2563 _KeyOfValue()(__v)));
2564
2565 _Base_ptr __z =
2566 _M_create_node(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr();
2567 _Node_traits::_S_insert_and_rebalance
2568 (__insert_left, __z, __p, this->_M_impl._M_header);
2569 ++_M_impl._M_node_count;
2570 return iterator(__z);
2571 }
2572
2573 template<typename _Key, typename _Val, typename _KeyOfValue,
2574 typename _Compare, typename _Alloc>
2575#if __cplusplus >= 201103L
2576 template<typename _Arg>
2577#endif
2578 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2579 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2580#if __cplusplus >= 201103L
2581 _M_insert_equal_lower(_Arg&& __v)
2582#else
2583 _M_insert_equal_lower(const _Val& __v)
2584#endif
2585 {
2586 _Base_ptr __x = _M_begin();
2587 _Base_ptr __y = _M_end();
2588 while (__x)
2589 {
2590 __y = __x;
2591 __x = !_M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ?
2592 _S_left(__x) : _S_right(__x);
2593 }
2594 return _M_insert_lower(__y, _GLIBCXX_FORWARD(_Arg, __v));
2595 }
2596
2597 template<typename _Key, typename _Val, typename _KoV,
2598 typename _Compare, typename _Alloc>
2599 template<bool _MoveValues, typename _NodeGen>
2600 typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Base_ptr
2601 _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::
2602 _M_copy(_Node_ptr __x, _Base_ptr __p, _NodeGen& __node_gen)
2603 {
2604 // Structural copy. __x and __p must be non-null.
2605 _Node_ptr __top = _M_clone_node<_MoveValues>(__x, __node_gen);
2606 _Base_ptr __top_base = __top->_M_base_ptr();
2607 __top->_M_parent = __p;
2608
2609 __try
2610 {
2611 if (__x->_M_right)
2612 __top->_M_right =
2613 _M_copy<_MoveValues>(_S_right(__x), __top_base, __node_gen);
2614 __p = __top_base;
2615 __x = _S_left(__x);
2616
2617 while (__x)
2618 {
2619 _Base_ptr __y =
2620 _M_clone_node<_MoveValues>(__x, __node_gen)->_M_base_ptr();
2621 __p->_M_left = __y;
2622 __y->_M_parent = __p;
2623 if (__x->_M_right)
2624 __y->_M_right = _M_copy<_MoveValues>(_S_right(__x),
2625 __y, __node_gen);
2626 __p = __y;
2627 __x = _S_left(__x);
2628 }
2629 }
2630 __catch(...)
2631 {
2632 _M_erase(__top);
2633 __throw_exception_again;
2634 }
2635 return __top_base;
2636 }
2637
2638 template<typename _Key, typename _Val, typename _KeyOfValue,
2639 typename _Compare, typename _Alloc>
2640 void
2641 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2642 _M_erase(_Node_ptr __x)
2643 {
2644 // Erase without rebalancing.
2645 while (__x)
2646 {
2647 _M_erase(_S_right(__x));
2648 _Node_ptr __y = _S_left(__x);
2649 _M_drop_node(__x);
2650 __x = __y;
2651 }
2652 }
2653
2654 template<typename _Key, typename _Val, typename _KeyOfValue,
2655 typename _Compare, typename _Alloc>
2656 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2657 _Compare, _Alloc>::_Base_ptr
2658 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2659 _M_lower_bound(_Base_ptr __x, _Base_ptr __y,
2660 const _Key& __k) const
2661 {
2662 while (__x)
2663 if (!_M_key_compare(_S_key(__x), __k))
2664 __y = __x, __x = _S_left(__x);
2665 else
2666 __x = _S_right(__x);
2667 return __y;
2668 }
2669
2670 template<typename _Key, typename _Val, typename _KeyOfValue,
2671 typename _Compare, typename _Alloc>
2672 template <typename _Kt>
2673 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr
2674 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2675 _M_lower_bound_tr(_Base_ptr __x, _Base_ptr __y, const _Kt& __k) const
2676 {
2677 while (__x)
2678 if (!_M_key_compare(_S_key(__x), __k))
2679 __y = __x, __x = _S_left(__x);
2680 else
2681 __x = _S_right(__x);
2682 return __y;
2683 }
2684
2685 template<typename _Key, typename _Val, typename _KeyOfValue,
2686 typename _Compare, typename _Alloc>
2687 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2688 _Compare, _Alloc>::_Base_ptr
2689 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2690 _M_upper_bound(_Base_ptr __x, _Base_ptr __y,
2691 const _Key& __k) const
2692 {
2693 while (__x)
2694 if (_M_key_compare(__k, _S_key(__x)))
2695 __y = __x, __x = _S_left(__x);
2696 else
2697 __x = _S_right(__x);
2698 return __y;
2699 }
2700
2701 template<typename _Key, typename _Val, typename _KeyOfValue,
2702 typename _Compare, typename _Alloc>
2703 template <typename _Kt>
2704 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr
2705 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2706 _M_upper_bound_tr(_Base_ptr __x, _Base_ptr __y, const _Kt& __k) const
2707 {
2708 while (__x)
2709 if (_M_key_compare(__k, _S_key(__x)))
2710 __y = __x, __x = _S_left(__x);
2711 else
2712 __x = _S_right(__x);
2713 return __y;
2714 }
2715
2716 template<typename _Key, typename _Val, typename _KeyOfValue,
2717 typename _Compare, typename _Alloc>
2718 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2719 _Compare, _Alloc>::iterator,
2720 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2721 _Compare, _Alloc>::iterator>
2722 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2723 equal_range(const _Key& __k)
2724 {
2725 typedef pair<iterator, iterator> _Ret;
2726
2727 _Base_ptr __x = _M_begin();
2728 _Base_ptr __y = _M_end();
2729 while (__x)
2730 {
2731 if (_M_key_compare(_S_key(__x), __k))
2732 __x = _S_right(__x);
2733 else if (_M_key_compare(__k, _S_key(__x)))
2734 __y = __x, __x = _S_left(__x);
2735 else
2736 {
2737 _Base_ptr __xu(__x);
2738 _Base_ptr __yu(__y);
2739 __y = __x, __x = _S_left(__x);
2740 __xu = _S_right(__xu);
2741 return _Ret(iterator(_M_lower_bound(__x, __y, __k)),
2742 iterator(_M_upper_bound(__xu, __yu, __k)));
2743 }
2744 }
2745 return _Ret(iterator(__y), iterator(__y));
2746 }
2747
2748 template<typename _Key, typename _Val, typename _KeyOfValue,
2749 typename _Compare, typename _Alloc>
2750 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2751 _Compare, _Alloc>::const_iterator,
2752 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2753 _Compare, _Alloc>::const_iterator>
2754 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2755 equal_range(const _Key& __k) const
2756 {
2758
2759 _Base_ptr __x = _M_begin();
2760 _Base_ptr __y = _M_end();
2761 while (__x)
2762 {
2763 if (_M_key_compare(_S_key(__x), __k))
2764 __x = _S_right(__x);
2765 else if (_M_key_compare(__k, _S_key(__x)))
2766 __y = __x, __x = _S_left(__x);
2767 else
2768 {
2769 _Base_ptr __xu(__x);
2770 _Base_ptr __yu(__y);
2771 __y = __x, __x = _S_left(__x);
2772 __xu = _S_right(__xu);
2773 return _Ret(const_iterator(_M_lower_bound(__x, __y, __k)),
2774 const_iterator(_M_upper_bound(__xu, __yu, __k)));
2775 }
2776 }
2777 return _Ret(const_iterator(__y), const_iterator(__y));
2778 }
2779
2780 template<typename _Key, typename _Val, typename _KeyOfValue,
2781 typename _Compare, typename _Alloc>
2782 void
2783 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2784 swap(_Rb_tree& __t)
2785 _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value)
2786 {
2787 if (!_M_root())
2788 {
2789 if (__t._M_root())
2790 _M_impl._M_move_data(__t._M_impl);
2791 }
2792 else if (!__t._M_root())
2793 __t._M_impl._M_move_data(_M_impl);
2794 else
2795 {
2796 std::swap(_M_root(),__t._M_root());
2797 std::swap(_M_leftmost(),__t._M_leftmost());
2798 std::swap(_M_rightmost(),__t._M_rightmost());
2799
2800 _M_root()->_M_parent = _M_end();
2801 __t._M_root()->_M_parent = __t._M_end();
2802 std::swap(this->_M_impl._M_node_count, __t._M_impl._M_node_count);
2803 }
2804 // No need to swap header's color as it does not change.
2805
2806 using std::swap;
2807 swap(this->_M_impl._M_key_compare, __t._M_impl._M_key_compare);
2808
2809 _Node_alloc_traits::_S_on_swap(_M_get_Node_allocator(),
2810 __t._M_get_Node_allocator());
2811 }
2812
2813 template<typename _Key, typename _Val, typename _KeyOfValue,
2814 typename _Compare, typename _Alloc>
2815 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2816 _Compare, _Alloc>::_Base_ptr,
2817 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2818 _Compare, _Alloc>::_Base_ptr>
2819 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2820 _M_get_insert_unique_pos(const key_type& __k)
2821 {
2822 typedef pair<_Base_ptr, _Base_ptr> _Res;
2823 _Base_ptr __x = _M_begin();
2824 _Base_ptr __y = _M_end();
2825 bool __comp = true;
2826 while (__x)
2827 {
2828 __y = __x;
2829 __comp = _M_key_compare(__k, _S_key(__x));
2830 __x = __comp ? _S_left(__x) : _S_right(__x);
2831 }
2832 iterator __j = iterator(__y);
2833 if (__comp)
2834 {
2835 if (__j == begin())
2836 return _Res(__x, __y);
2837 else
2838 --__j;
2839 }
2840 if (_M_key_compare(_S_key(__j._M_node), __k))
2841 return _Res(__x, __y);
2842 return _Res(__j._M_node, _Base_ptr());
2843 }
2844
2845 template<typename _Key, typename _Val, typename _KeyOfValue,
2846 typename _Compare, typename _Alloc>
2847 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2848 _Compare, _Alloc>::_Base_ptr,
2849 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2850 _Compare, _Alloc>::_Base_ptr>
2851 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2852 _M_get_insert_equal_pos(const key_type& __k)
2853 {
2854 typedef pair<_Base_ptr, _Base_ptr> _Res;
2855 _Base_ptr __x = _M_begin();
2856 _Base_ptr __y = _M_end();
2857 while (__x)
2858 {
2859 __y = __x;
2860 __x = _M_key_compare(__k, _S_key(__x)) ? _S_left(__x) : _S_right(__x);
2861 }
2862 return _Res(__x, __y);
2863 }
2864
2865#ifdef __glibcxx_associative_heterogeneous_insertion // C++26
2866
2867 // Multiple elements may compare equal to __k. Identify the first
2868 // of any such elements, or insert normally.
2869
2870 template <typename _Key, typename _Val, typename _KeyOfValue,
2871 typename _Compare, typename _Alloc>
2872 template <typename _Kt>
2873 auto
2874 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2875 _M_get_insert_unique_pos_tr(const _Kt& __k)
2877 {
2878 if (size() == 0)
2879 return { _M_end(), _M_end() }; // Insert as root.
2880
2881 _Base_ptr __x = _M_begin(), __y = __x;
2882 bool __k_le_y = false;
2883 do
2884 {
2885 __y = __x;
2886 __k_le_y = ! _M_key_compare(_S_key(__x), __k);
2887 __x = __k_le_y ? _S_left(__x) : _S_right(__x);
2888 }
2889 while (__x);
2890 // If !__k_le_y, __k > *__y;
2891 // If __y is rightmost, put at _M_right under *__y.
2892 // else if __k < *(__y+1), put at _M_right under *__y.
2893 // else __k == *(__y+1), do not insert, report (__y+1).
2894 // else, __k_le_y, __k <= *__y;
2895 // If __k < *__Y, put at _M_left under *__y.
2896 // else __k == *__y, do not insert, report __y.
2897 auto __j = iterator(__y);
2898 if (! __k_le_y) // k > *__y
2899 {
2900 if (__y == _M_rightmost())
2901 return { {}, __y }; // Place to right under __y.
2902 ++__j;
2903 }
2904 if (_M_key_compare(__k, _S_key(__j._M_node)))
2905 {
2906 if (__k_le_y)
2907 return { __y, __y }; // Place to left under __y.
2908 else
2909 return { {}, __y }; // Place to right under __y.
2910 }
2911 return { __j._M_node, {} }; // No insert.
2912 }
2913#endif
2914
2915 template<typename _Key, typename _Val, typename _KeyOfValue,
2916 typename _Compare, typename _Alloc>
2917#if __cplusplus >= 201103L
2918 template<typename _Arg>
2919#endif
2920 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2921 _Compare, _Alloc>::iterator, bool>
2922 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2923#if __cplusplus >= 201103L
2924 _M_insert_unique(_Arg&& __v)
2925#else
2926 _M_insert_unique(const _Val& __v)
2927#endif
2928 {
2929 typedef pair<iterator, bool> _Res;
2931 = _M_get_insert_unique_pos(_KeyOfValue()(__v));
2932
2933 if (__res.second)
2934 {
2935 _Alloc_node __an(*this);
2936 return _Res(_M_insert_(__res.first, __res.second,
2937 _GLIBCXX_FORWARD(_Arg, __v), __an),
2938 true);
2939 }
2940
2941 return _Res(iterator(__res.first), false);
2942 }
2943
2944 template<typename _Key, typename _Val, typename _KeyOfValue,
2945 typename _Compare, typename _Alloc>
2946#if __cplusplus >= 201103L
2947 template<typename _Arg>
2948#endif
2949 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2950 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2951#if __cplusplus >= 201103L
2952 _M_insert_equal(_Arg&& __v)
2953#else
2954 _M_insert_equal(const _Val& __v)
2955#endif
2956 {
2958 = _M_get_insert_equal_pos(_KeyOfValue()(__v));
2959 _Alloc_node __an(*this);
2960 return _M_insert_(__res.first, __res.second,
2961 _GLIBCXX_FORWARD(_Arg, __v), __an);
2962 }
2963
2964 template<typename _Key, typename _Val, typename _KeyOfValue,
2965 typename _Compare, typename _Alloc>
2966 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2967 _Compare, _Alloc>::_Base_ptr,
2968 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2969 _Compare, _Alloc>::_Base_ptr>
2970 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2971 _M_get_insert_hint_unique_pos(const_iterator __position,
2972 const key_type& __k)
2973 {
2974 typedef pair<_Base_ptr, _Base_ptr> _Res;
2975
2976 // end()
2977 if (__position._M_node == _M_end())
2978 {
2979 if (size() > 0 && _M_key_compare(_S_key(_M_rightmost()), __k))
2980 return _Res(_Base_ptr(), _M_rightmost());
2981 else
2982 return _M_get_insert_unique_pos(__k);
2983 }
2984 else if (_M_key_compare(__k, _S_key(__position._M_node)))
2985 {
2986 // First, try before...
2987 iterator __before(__position._M_node);
2988 if (__position._M_node == _M_leftmost()) // begin()
2989 return _Res(_M_leftmost(), _M_leftmost());
2990 else if (_M_key_compare(_S_key((--__before)._M_node), __k))
2991 {
2992 if (!_S_right(__before._M_node))
2993 return _Res(_Base_ptr(), __before._M_node);
2994 else
2995 return _Res(__position._M_node, __position._M_node);
2996 }
2997 else
2998 return _M_get_insert_unique_pos(__k);
2999 }
3000 else if (_M_key_compare(_S_key(__position._M_node), __k))
3001 {
3002 // ... then try after.
3003 iterator __after(__position._M_node);
3004 if (__position._M_node == _M_rightmost())
3005 return _Res(_Base_ptr(), _M_rightmost());
3006 else if (_M_key_compare(__k, _S_key((++__after)._M_node)))
3007 {
3008 if (!_S_right(__position._M_node))
3009 return _Res(_Base_ptr(), __position._M_node);
3010 else
3011 return _Res(__after._M_node, __after._M_node);
3012 }
3013 else
3014 return _M_get_insert_unique_pos(__k);
3015 }
3016 else
3017 // Equivalent keys.
3018 return _Res(__position._M_node, _Base_ptr());
3019 }
3020
3021#ifdef __glibcxx_associative_heterogeneous_insertion // C++26
3022 template <typename _Key, typename _Val, typename _KeyOfValue,
3023 typename _Compare, typename _Alloc>
3024 template <typename _Kt>
3025 auto
3026 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3027 _M_get_insert_hint_unique_pos_tr(const_iterator __hint, const _Kt& __k)
3029 {
3030 auto __node =__hint._M_node;
3031 if (__node == _M_end())
3032 {
3033 if (size() > 0 && _M_key_compare(_S_key(_M_rightmost()), __k))
3034 return { {}, _M_rightmost() };
3035 return _M_get_insert_unique_pos_tr(__k);
3036 }
3037 if (_M_key_compare(__k, _S_key(__node)))
3038 { // First, try before...
3039 if (__node == _M_leftmost()) // begin()
3040 return { _M_leftmost(), _M_leftmost() };
3041 iterator __before(__node);
3042 --__before;
3043 if (_M_key_compare(_S_key(__before._M_node), __k))
3044 {
3045 if (!_S_right(__before._M_node))
3046 return { {}, __before._M_node }; // put right
3047 return { __node, __node }; // put left;
3048 }
3049 return _M_get_insert_unique_pos_tr(__k);
3050 }
3051 if (_M_key_compare(_S_key(__node), __k))
3052 { // ... then try after.
3053 if (__node == _M_rightmost())
3054 return { {}, _M_rightmost() };
3055 iterator __after(__node);
3056 ++__after;
3057 if (_M_key_compare(__k, _S_key(__after._M_node)))
3058 {
3059 if (!_S_right(__node))
3060 return { {}, __node };
3061 return { __after._M_node, __after._M_node };
3062 }
3063 return _M_get_insert_unique_pos_tr(__k);
3064 }
3065 // Equal to __k; check if any more to the left.
3066 iterator __before(__node);
3067 if (__node == _M_leftmost() ||
3068 _M_key_compare(_S_key((--__before)._M_node), __k))
3069 { return { __node, {} }; }
3070 return _M_get_insert_unique_pos_tr(__k);
3071 }
3072#endif
3073
3074 template<typename _Key, typename _Val, typename _KeyOfValue,
3075 typename _Compare, typename _Alloc>
3076#if __cplusplus >= 201103L
3077 template<typename _Arg, typename _NodeGen>
3078#else
3079 template<typename _NodeGen>
3080#endif
3081 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
3082 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3083 _M_insert_unique_(const_iterator __position,
3084#if __cplusplus >= 201103L
3085 _Arg&& __v,
3086#else
3087 const _Val& __v,
3088#endif
3089 _NodeGen& __node_gen)
3090 {
3092 = _M_get_insert_hint_unique_pos(__position, _KeyOfValue()(__v));
3093
3094 if (__res.second)
3095 return _M_insert_(__res.first, __res.second,
3096 _GLIBCXX_FORWARD(_Arg, __v),
3097 __node_gen);
3098 return iterator(__res.first);
3099 }
3100
3101 template<typename _Key, typename _Val, typename _KeyOfValue,
3102 typename _Compare, typename _Alloc>
3103 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
3104 _Compare, _Alloc>::_Base_ptr,
3105 typename _Rb_tree<_Key, _Val, _KeyOfValue,
3106 _Compare, _Alloc>::_Base_ptr>
3107 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3108 _M_get_insert_hint_equal_pos(const_iterator __position, const key_type& __k)
3109 {
3110 typedef pair<_Base_ptr, _Base_ptr> _Res;
3111
3112 // end()
3113 if (__position._M_node == _M_end())
3114 {
3115 if (size() > 0
3116 && !_M_key_compare(__k, _S_key(_M_rightmost())))
3117 return _Res(_Base_ptr(), _M_rightmost());
3118 else
3119 return _M_get_insert_equal_pos(__k);
3120 }
3121 else if (!_M_key_compare(_S_key(__position._M_node), __k))
3122 {
3123 // First, try before...
3124 iterator __before(__position._M_node);
3125 if (__position._M_node == _M_leftmost()) // begin()
3126 return _Res(_M_leftmost(), _M_leftmost());
3127 else if (!_M_key_compare(__k, _S_key((--__before)._M_node)))
3128 {
3129 if (!_S_right(__before._M_node))
3130 return _Res(_Base_ptr(), __before._M_node);
3131 else
3132 return _Res(__position._M_node, __position._M_node);
3133 }
3134 else
3135 return _M_get_insert_equal_pos(__k);
3136 }
3137 else
3138 {
3139 // ... then try after.
3140 iterator __after(__position._M_node);
3141 if (__position._M_node == _M_rightmost())
3142 return _Res(_Base_ptr(), _M_rightmost());
3143 else if (!_M_key_compare(_S_key((++__after)._M_node), __k))
3144 {
3145 if (!_S_right(__position._M_node))
3146 return _Res(_Base_ptr(), __position._M_node);
3147 else
3148 return _Res(__after._M_node, __after._M_node);
3149 }
3150 else
3151 return _Res(_Base_ptr(), _Base_ptr());
3152 }
3153 }
3154
3155 template<typename _Key, typename _Val, typename _KeyOfValue,
3156 typename _Compare, typename _Alloc>
3157#if __cplusplus >= 201103L
3158 template<typename _Arg, typename _NodeGen>
3159#else
3160 template<typename _NodeGen>
3161#endif
3162 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
3163 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3164 _M_insert_equal_(const_iterator __position,
3165#if __cplusplus >= 201103L
3166 _Arg&& __v,
3167#else
3168 const _Val& __v,
3169#endif
3170 _NodeGen& __node_gen)
3171 {
3173 = _M_get_insert_hint_equal_pos(__position, _KeyOfValue()(__v));
3174
3175 if (__res.second)
3176 return _M_insert_(__res.first, __res.second,
3177 _GLIBCXX_FORWARD(_Arg, __v),
3178 __node_gen);
3179
3180 return _M_insert_equal_lower(_GLIBCXX_FORWARD(_Arg, __v));
3181 }
3182
3183#if __cplusplus >= 201103L
3184 template<typename _Key, typename _Val, typename _KeyOfValue,
3185 typename _Compare, typename _Alloc>
3186 auto
3187 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3188 _M_insert_node(_Base_ptr __x, _Base_ptr __p, _Node_ptr __z)
3189 -> iterator
3190 {
3191 bool __insert_left = (__x || __p == _M_end()
3192 || _M_key_compare(_S_key(__z), _S_key(__p)));
3193
3194 _Base_ptr __base_z = __z->_M_base_ptr();
3195 _Node_traits::_S_insert_and_rebalance
3196 (__insert_left, __base_z, __p, this->_M_impl._M_header);
3197 ++_M_impl._M_node_count;
3198 return iterator(__base_z);
3199 }
3200
3201 template<typename _Key, typename _Val, typename _KeyOfValue,
3202 typename _Compare, typename _Alloc>
3203 auto
3204 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3205 _M_insert_lower_node(_Base_ptr __p, _Node_ptr __z)
3206 -> iterator
3207 {
3208 bool __insert_left = (__p == _M_end()
3209 || !_M_key_compare(_S_key(__p), _S_key(__z)));
3210
3211 _Base_ptr __base_z = __z->_M_base_ptr();
3212 _Node_traits::_S_insert_and_rebalance
3213 (__insert_left, __base_z, __p, this->_M_impl._M_header);
3214 ++_M_impl._M_node_count;
3215 return iterator(__base_z);
3216 }
3217
3218 template<typename _Key, typename _Val, typename _KeyOfValue,
3219 typename _Compare, typename _Alloc>
3220 auto
3221 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3222 _M_insert_equal_lower_node(_Node_ptr __z)
3223 -> iterator
3224 {
3225 _Base_ptr __x = _M_begin();
3226 _Base_ptr __y = _M_end();
3227 while (__x)
3228 {
3229 __y = __x;
3230 __x = !_M_key_compare(_S_key(__x), _S_key(__z)) ?
3231 _S_left(__x) : _S_right(__x);
3232 }
3233 return _M_insert_lower_node(__y, __z);
3234 }
3235
3236 template<typename _Key, typename _Val, typename _KeyOfValue,
3237 typename _Compare, typename _Alloc>
3238 template<typename... _Args>
3239 auto
3240 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3241 _M_emplace_unique(_Args&&... __args)
3243 {
3244 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3245 auto __res = _M_get_insert_unique_pos(__z._M_key());
3246 if (__res.second)
3247 return {__z._M_insert(__res), true};
3248 return {iterator(__res.first), false};
3249 }
3250
3251 template<typename _Key, typename _Val, typename _KeyOfValue,
3252 typename _Compare, typename _Alloc>
3253 template<typename... _Args>
3254 auto
3255 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3256 _M_emplace_equal(_Args&&... __args)
3257 -> iterator
3258 {
3259 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3260 auto __res = _M_get_insert_equal_pos(__z._M_key());
3261 return __z._M_insert(__res);
3262 }
3263
3264 template<typename _Key, typename _Val, typename _KeyOfValue,
3265 typename _Compare, typename _Alloc>
3266 template<typename... _Args>
3267 auto
3268 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3269 _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args)
3270 -> iterator
3271 {
3272 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3273 auto __res = _M_get_insert_hint_unique_pos(__pos, __z._M_key());
3274 if (__res.second)
3275 return __z._M_insert(__res);
3276 return iterator(__res.first);
3277 }
3278
3279 template<typename _Key, typename _Val, typename _KeyOfValue,
3280 typename _Compare, typename _Alloc>
3281 template<typename... _Args>
3282 auto
3283 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3284 _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args)
3285 -> iterator
3286 {
3287 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3288 auto __res = _M_get_insert_hint_equal_pos(__pos, __z._M_key());
3289 if (__res.second)
3290 return __z._M_insert(__res);
3291 return __z._M_insert_equal_lower();
3292 }
3293
3294#ifdef __glibcxx_associative_heterogeneous_insertion // C++26
3295 template <typename _Key, typename _Val, typename _KeyOfValue,
3296 typename _Compare, typename _Alloc>
3297 template <typename... _Args>
3298 auto
3299 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3300 _M_emplace_here(bool __place_left, _Base_ptr __node, _Args&&... __args)
3301 -> iterator
3302 {
3303 _Auto_node __z(*this, std::forward<_Args>(__args)...);
3304 _Base_ptr __base_z = __z._M_node->_M_base_ptr();
3305 _Node_traits::_S_insert_and_rebalance(
3306 __place_left, __base_z, __node, _M_impl._M_header);
3307 __z._M_node = nullptr;
3308 ++_M_impl._M_node_count;
3309 return iterator(__base_z);
3310 }
3311#endif
3312
3313#endif // >= C++11
3314
3315
3316 template<typename _Key, typename _Val, typename _KeyOfValue,
3317 typename _Compare, typename _Alloc>
3318 void
3319 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3320 _M_erase_aux(const_iterator __position)
3321 {
3322 _Base_ptr __y = _Node_traits::_S_rebalance_for_erase
3323 (__position._M_node, this->_M_impl._M_header);
3324 _M_drop_node(static_cast<_Node&>(*__y)._M_node_ptr());
3325 --_M_impl._M_node_count;
3326 }
3327
3328 template<typename _Key, typename _Val, typename _KeyOfValue,
3329 typename _Compare, typename _Alloc>
3330 void
3331 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3332 _M_erase_aux(const_iterator __first, const_iterator __last)
3333 {
3334 if (__first == begin() && __last == end())
3335 clear();
3336 else
3337 while (__first != __last)
3338 _M_erase_aux(__first++);
3339 }
3340
3341 template<typename _Key, typename _Val, typename _KeyOfValue,
3342 typename _Compare, typename _Alloc>
3343 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
3344 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3345 erase(const _Key& __x)
3346 {
3347 pair<iterator, iterator> __p = equal_range(__x);
3348 const size_type __old_size = size();
3349 _M_erase_aux(__p.first, __p.second);
3350 return __old_size - size();
3351 }
3352
3353 template<typename _Key, typename _Val, typename _KeyOfValue,
3354 typename _Compare, typename _Alloc>
3355 template <typename _Kt>
3356 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
3357 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3358 _M_erase_tr(const _Kt& __x)
3359 {
3360 pair<iterator, iterator> __p = _M_equal_range_tr(__x);
3361 const size_type __old_size = size();
3362 _M_erase_aux(__p.first, __p.second);
3363 return __old_size - size();
3364 }
3365
3366 template<typename _Key, typename _Val, typename _KeyOfValue,
3367 typename _Compare, typename _Alloc>
3368 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
3369 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3370 _M_erase_unique(const _Key& __x)
3371 {
3372 iterator __it = find(__x);
3373 if (__it == end())
3374 return 0;
3375
3376 _M_erase_aux(__it);
3377 return 1;
3378 }
3379
3380 template<typename _Key, typename _Val, typename _KeyOfValue,
3381 typename _Compare, typename _Alloc>
3382 typename _Rb_tree<_Key, _Val, _KeyOfValue,
3383 _Compare, _Alloc>::iterator
3384 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3385 find(const _Key& __k)
3386 {
3387 iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k));
3388 return (__j == end()
3389 || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j;
3390 }
3391
3392 template<typename _Key, typename _Val, typename _KeyOfValue,
3393 typename _Compare, typename _Alloc>
3394 typename _Rb_tree<_Key, _Val, _KeyOfValue,
3395 _Compare, _Alloc>::const_iterator
3396 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3397 find(const _Key& __k) const
3398 {
3399 const_iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k));
3400 return (__j == end()
3401 || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j;
3402 }
3403
3404 template<typename _Key, typename _Val, typename _KeyOfValue,
3405 typename _Compare, typename _Alloc>
3406 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
3407 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
3408 count(const _Key& __k) const
3409 {
3410 pair<const_iterator, const_iterator> __p = equal_range(__k);
3411 const size_type __n = std::distance(__p.first, __p.second);
3412 return __n;
3413 }
3414
3415 _GLIBCXX_PURE unsigned int
3416 _Rb_tree_black_count(const _Rb_tree_node_base* __node,
3417 const _Rb_tree_node_base* __root) throw ();
3418
3419 template<typename _Key, typename _Val, typename _KeyOfValue,
3420 typename _Compare, typename _Alloc>
3421 bool
3422 _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::__rb_verify() const
3423 {
3424 if (_M_impl._M_node_count == 0 || begin() == end())
3425 return _M_impl._M_node_count == 0 && begin() == end()
3426 && this->_M_impl._M_header._M_left == _M_end()
3427 && this->_M_impl._M_header._M_right == _M_end();
3428
3429 unsigned int __len = _Rb_tree_black_count(_M_leftmost(), _M_root());
3430 for (const_iterator __it = begin(); __it != end(); ++__it)
3431 {
3432 _Base_ptr __x = __it._M_node;
3433 _Base_ptr __L = _S_left(__x);
3434 _Base_ptr __R = _S_right(__x);
3435
3436 if (__x->_M_color == _S_red)
3437 if ((__L && __L->_M_color == _S_red)
3438 || (__R && __R->_M_color == _S_red))
3439 return false;
3440
3441 if (__L && _M_key_compare(_S_key(__x), _S_key(__L)))
3442 return false;
3443 if (__R && _M_key_compare(_S_key(__R), _S_key(__x)))
3444 return false;
3445
3446 if (!__L && !__R && _Rb_tree_black_count(__x, _M_root()) != __len)
3447 return false;
3448 }
3449
3450 if (_M_leftmost() != _Node_base::_S_minimum(_M_root()))
3451 return false;
3452 if (_M_rightmost() != _Node_base::_S_maximum(_M_root()))
3453 return false;
3454 return true;
3455 }
3456
3457#ifdef __glibcxx_node_extract // >= C++17
3458 // Allow access to internals of compatible _Rb_tree specializations.
3459 template<typename _Key, typename _Val, typename _Sel, typename _Cmp1,
3460 typename _Alloc, typename _Cmp2>
3461 struct _Rb_tree_merge_helper<_Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>,
3462 _Cmp2>
3463 {
3464 private:
3465 friend class _Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>;
3466
3467 static auto&
3468 _S_get_impl(_Rb_tree<_Key, _Val, _Sel, _Cmp2, _Alloc>& __tree)
3469 { return __tree._M_impl; }
3470 };
3471#endif // C++17
3472
3473#ifdef __glibcxx_associative_heterogeneous_erasure // C++ >= 23
3474template <typename _Kt, typename _Container>
3475 concept __heterogeneous_tree_key =
3476 __transparent_comparator<typename _Container::key_compare> &&
3477 __heterogeneous_key<_Kt, _Container>;
3478#endif
3479
3480_GLIBCXX_END_NAMESPACE_VERSION
3481} // namespace
3482
3483#endif
constexpr bool operator<(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:830
__bool_constant< true > true_type
The type used as a compile-time boolean with true value.
Definition type_traits:120
__bool_constant< false > false_type
The type used as a compile-time boolean with false value.
Definition type_traits:123
pair(_T1, _T2) -> pair< _T1, _T2 >
Two pairs are equal iff their members are equal.
auto declval() noexcept -> decltype(__declval< _Tp >(0))
Definition type_traits:2742
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
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition move.h:52
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
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.
ISO C++ entities toplevel namespace is std.
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
typename pointer_traits< _Ptr >::template rebind< _Tp > __ptr_rebind
Convenience alias for rebinding pointers.
Definition ptr_traits.h:203
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.
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
constexpr auto begin(_Container &__cont) noexcept(noexcept(__cont.begin())) -> decltype(__cont.begin())
Return an iterator pointing to the first element of the container.
constexpr _Iterator __base(_Iterator __it)
is_nothrow_move_assignable
Definition type_traits:1439
The standard allocator, as per C++03 [20.4.1].
Definition allocator.h:134
Struct holding two objects (or references) of arbitrary type.
Definition stl_pair.h:307
Common iterator class.
static constexpr pointer allocate(_Node_allocator &__a, size_type __n)
static constexpr void deallocate(_Node_allocator &__a, pointer __p, size_type __n)
static constexpr size_type max_size(const _Node_allocator &__a) noexcept