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