1 // RB tree implementation -*- C++ -*-
2
3 // Copyright (C) 2001-2019 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 #pragma GCC system_header
62
63 #include <bits/stl_algobase.h>
64 #include <bits/allocator.h>
65 #include <bits/stl_function.h>
66 #include <bits/cpp_type_traits.h>
67 #include <ext/alloc_traits.h>
68 #if __cplusplus >= 201103L
69 # include <ext/aligned_buffer.h>
70 #endif
71 #if __cplusplus > 201402L
72 # include <bits/node_handle.h>
73 #endif
74
_GLIBCXX_VISIBILITY(default)75 namespace std _GLIBCXX_VISIBILITY(default)
76 {
77 _GLIBCXX_BEGIN_NAMESPACE_VERSION
78
79 #if __cplusplus > 201103L
80 # define __cpp_lib_generic_associative_lookup 201304
81 #endif
82
83 // Red-black tree class, designed for use in implementing STL
84 // associative containers (set, multiset, map, and multimap). The
85 // insertion and deletion algorithms are based on those in Cormen,
86 // Leiserson, and Rivest, Introduction to Algorithms (MIT Press,
87 // 1990), except that
88 //
89 // (1) the header cell is maintained with links not only to the root
90 // but also to the leftmost node of the tree, to enable constant
91 // time begin(), and to the rightmost node of the tree, to enable
92 // linear time performance when used with the generic set algorithms
93 // (set_union, etc.)
94 //
95 // (2) when a node being deleted has two children its successor node
96 // is relinked into its place, rather than copied, so that the only
97 // iterators invalidated are those referring to the deleted node.
98
99 enum _Rb_tree_color { _S_red = false, _S_black = true };
100
101 struct _Rb_tree_node_base
102 {
103 typedef _Rb_tree_node_base* _Base_ptr;
104 typedef const _Rb_tree_node_base* _Const_Base_ptr;
105
106 _Rb_tree_color _M_color;
107 _Base_ptr _M_parent;
108 _Base_ptr _M_left;
109 _Base_ptr _M_right;
110
111 static _Base_ptr
112 _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
113 {
114 while (__x->_M_left != 0) __x = __x->_M_left;
115 return __x;
116 }
117
118 static _Const_Base_ptr
119 _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT
120 {
121 while (__x->_M_left != 0) __x = __x->_M_left;
122 return __x;
123 }
124
125 static _Base_ptr
126 _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
127 {
128 while (__x->_M_right != 0) __x = __x->_M_right;
129 return __x;
130 }
131
132 static _Const_Base_ptr
133 _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT
134 {
135 while (__x->_M_right != 0) __x = __x->_M_right;
136 return __x;
137 }
138 };
139
140 // Helper type offering value initialization guarantee on the compare functor.
141 template<typename _Key_compare>
142 struct _Rb_tree_key_compare
143 {
144 _Key_compare _M_key_compare;
145
146 _Rb_tree_key_compare()
147 _GLIBCXX_NOEXCEPT_IF(
148 is_nothrow_default_constructible<_Key_compare>::value)
149 : _M_key_compare()
150 { }
151
152 _Rb_tree_key_compare(const _Key_compare& __comp)
153 : _M_key_compare(__comp)
154 { }
155
156 #if __cplusplus >= 201103L
157 // Copy constructor added for consistency with C++98 mode.
158 _Rb_tree_key_compare(const _Rb_tree_key_compare&) = default;
159
160 _Rb_tree_key_compare(_Rb_tree_key_compare&& __x)
161 noexcept(is_nothrow_copy_constructible<_Key_compare>::value)
162 : _M_key_compare(__x._M_key_compare)
163 { }
164 #endif
165 };
166
167 // Helper type to manage default initialization of node count and header.
168 struct _Rb_tree_header
169 {
170 _Rb_tree_node_base _M_header;
171 size_t _M_node_count; // Keeps track of size of tree.
172
173 _Rb_tree_header() _GLIBCXX_NOEXCEPT
174 {
175 _M_header._M_color = _S_red;
176 _M_reset();
177 }
178
179 #if __cplusplus >= 201103L
180 _Rb_tree_header(_Rb_tree_header&& __x) noexcept
181 {
182 if (__x._M_header._M_parent != nullptr)
183 _M_move_data(__x);
184 else
185 {
186 _M_header._M_color = _S_red;
187 _M_reset();
188 }
189 }
190 #endif
191
192 void
193 _M_move_data(_Rb_tree_header& __from)
194 {
195 _M_header._M_color = __from._M_header._M_color;
196 _M_header._M_parent = __from._M_header._M_parent;
197 _M_header._M_left = __from._M_header._M_left;
198 _M_header._M_right = __from._M_header._M_right;
199 _M_header._M_parent->_M_parent = &_M_header;
200 _M_node_count = __from._M_node_count;
201
202 __from._M_reset();
203 }
204
205 void
206 _M_reset()
207 {
208 _M_header._M_parent = 0;
209 _M_header._M_left = &_M_header;
210 _M_header._M_right = &_M_header;
211 _M_node_count = 0;
212 }
213 };
214
215 template<typename _Val>
216 struct _Rb_tree_node : public _Rb_tree_node_base
217 {
218 typedef _Rb_tree_node<_Val>* _Link_type;
219
220 #if __cplusplus < 201103L
221 _Val _M_value_field;
222
223 _Val*
224 _M_valptr()
225 { return std::__addressof(_M_value_field); }
226
227 const _Val*
228 _M_valptr() const
229 { return std::__addressof(_M_value_field); }
230 #else
231 __gnu_cxx::__aligned_membuf<_Val> _M_storage;
232
233 _Val*
234 _M_valptr()
235 { return _M_storage._M_ptr(); }
236
237 const _Val*
238 _M_valptr() const
239 { return _M_storage._M_ptr(); }
240 #endif
241 };
242
243 _GLIBCXX_PURE _Rb_tree_node_base*
244 _Rb_tree_increment(_Rb_tree_node_base* __x) throw ();
245
246 _GLIBCXX_PURE const _Rb_tree_node_base*
247 _Rb_tree_increment(const _Rb_tree_node_base* __x) throw ();
248
249 _GLIBCXX_PURE _Rb_tree_node_base*
250 _Rb_tree_decrement(_Rb_tree_node_base* __x) throw ();
251
252 _GLIBCXX_PURE const _Rb_tree_node_base*
253 _Rb_tree_decrement(const _Rb_tree_node_base* __x) throw ();
254
255 template<typename _Tp>
256 struct _Rb_tree_iterator
257 {
258 typedef _Tp value_type;
259 typedef _Tp& reference;
260 typedef _Tp* pointer;
261
262 typedef bidirectional_iterator_tag iterator_category;
263 typedef ptrdiff_t difference_type;
264
265 typedef _Rb_tree_iterator<_Tp> _Self;
266 typedef _Rb_tree_node_base::_Base_ptr _Base_ptr;
267 typedef _Rb_tree_node<_Tp>* _Link_type;
268
269 _Rb_tree_iterator() _GLIBCXX_NOEXCEPT
270 : _M_node() { }
271
272 explicit
273 _Rb_tree_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT
274 : _M_node(__x) { }
275
276 reference
277 operator*() const _GLIBCXX_NOEXCEPT
278 { return *static_cast<_Link_type>(_M_node)->_M_valptr(); }
279
280 pointer
281 operator->() const _GLIBCXX_NOEXCEPT
282 { return static_cast<_Link_type> (_M_node)->_M_valptr(); }
283
284 _Self&
285 operator++() _GLIBCXX_NOEXCEPT
286 {
287 _M_node = _Rb_tree_increment(_M_node);
288 return *this;
289 }
290
291 _Self
292 operator++(int) _GLIBCXX_NOEXCEPT
293 {
294 _Self __tmp = *this;
295 _M_node = _Rb_tree_increment(_M_node);
296 return __tmp;
297 }
298
299 _Self&
300 operator--() _GLIBCXX_NOEXCEPT
301 {
302 _M_node = _Rb_tree_decrement(_M_node);
303 return *this;
304 }
305
306 _Self
307 operator--(int) _GLIBCXX_NOEXCEPT
308 {
309 _Self __tmp = *this;
310 _M_node = _Rb_tree_decrement(_M_node);
311 return __tmp;
312 }
313
314 friend bool
315 operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
316 { return __x._M_node == __y._M_node; }
317
318 friend bool
319 operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
320 { return __x._M_node != __y._M_node; }
321
322 _Base_ptr _M_node;
323 };
324
325 template<typename _Tp>
326 struct _Rb_tree_const_iterator
327 {
328 typedef _Tp value_type;
329 typedef const _Tp& reference;
330 typedef const _Tp* pointer;
331
332 typedef _Rb_tree_iterator<_Tp> iterator;
333
334 typedef bidirectional_iterator_tag iterator_category;
335 typedef ptrdiff_t difference_type;
336
337 typedef _Rb_tree_const_iterator<_Tp> _Self;
338 typedef _Rb_tree_node_base::_Const_Base_ptr _Base_ptr;
339 typedef const _Rb_tree_node<_Tp>* _Link_type;
340
341 _Rb_tree_const_iterator() _GLIBCXX_NOEXCEPT
342 : _M_node() { }
343
344 explicit
345 _Rb_tree_const_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT
346 : _M_node(__x) { }
347
348 _Rb_tree_const_iterator(const iterator& __it) _GLIBCXX_NOEXCEPT
349 : _M_node(__it._M_node) { }
350
351 iterator
352 _M_const_cast() const _GLIBCXX_NOEXCEPT
353 { return iterator(const_cast<typename iterator::_Base_ptr>(_M_node)); }
354
355 reference
356 operator*() const _GLIBCXX_NOEXCEPT
357 { return *static_cast<_Link_type>(_M_node)->_M_valptr(); }
358
359 pointer
360 operator->() const _GLIBCXX_NOEXCEPT
361 { return static_cast<_Link_type>(_M_node)->_M_valptr(); }
362
363 _Self&
364 operator++() _GLIBCXX_NOEXCEPT
365 {
366 _M_node = _Rb_tree_increment(_M_node);
367 return *this;
368 }
369
370 _Self
371 operator++(int) _GLIBCXX_NOEXCEPT
372 {
373 _Self __tmp = *this;
374 _M_node = _Rb_tree_increment(_M_node);
375 return __tmp;
376 }
377
378 _Self&
379 operator--() _GLIBCXX_NOEXCEPT
380 {
381 _M_node = _Rb_tree_decrement(_M_node);
382 return *this;
383 }
384
385 _Self
386 operator--(int) _GLIBCXX_NOEXCEPT
387 {
388 _Self __tmp = *this;
389 _M_node = _Rb_tree_decrement(_M_node);
390 return __tmp;
391 }
392
393 friend bool
394 operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
395 { return __x._M_node == __y._M_node; }
396
397 friend bool
398 operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
399 { return __x._M_node != __y._M_node; }
400
401 _Base_ptr _M_node;
402 };
403
404 void
405 _Rb_tree_insert_and_rebalance(const bool __insert_left,
406 _Rb_tree_node_base* __x,
407 _Rb_tree_node_base* __p,
408 _Rb_tree_node_base& __header) throw ();
409
410 _Rb_tree_node_base*
411 _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z,
412 _Rb_tree_node_base& __header) throw ();
413
414 #if __cplusplus >= 201402L
415 template<typename _Cmp, typename _SfinaeType, typename = __void_t<>>
416 struct __has_is_transparent
417 { };
418
419 template<typename _Cmp, typename _SfinaeType>
420 struct __has_is_transparent<_Cmp, _SfinaeType,
421 __void_t<typename _Cmp::is_transparent>>
422 { typedef void type; };
423
424 template<typename _Cmp, typename _SfinaeType>
425 using __has_is_transparent_t
426 = typename __has_is_transparent<_Cmp, _SfinaeType>::type;
427 #endif
428
429 #if __cplusplus > 201402L
430 template<typename _Tree1, typename _Cmp2>
431 struct _Rb_tree_merge_helper { };
432 #endif
433
434 template<typename _Key, typename _Val, typename _KeyOfValue,
435 typename _Compare, typename _Alloc = allocator<_Val> >
436 class _Rb_tree
437 {
438 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
439 rebind<_Rb_tree_node<_Val> >::other _Node_allocator;
440
441 typedef __gnu_cxx::__alloc_traits<_Node_allocator> _Alloc_traits;
442
443 protected:
444 typedef _Rb_tree_node_base* _Base_ptr;
445 typedef const _Rb_tree_node_base* _Const_Base_ptr;
446 typedef _Rb_tree_node<_Val>* _Link_type;
447 typedef const _Rb_tree_node<_Val>* _Const_Link_type;
448
449 private:
450 // Functor recycling a pool of nodes and using allocation once the pool
451 // is empty.
452 struct _Reuse_or_alloc_node
453 {
454 _Reuse_or_alloc_node(_Rb_tree& __t)
455 : _M_root(__t._M_root()), _M_nodes(__t._M_rightmost()), _M_t(__t)
456 {
457 if (_M_root)
458 {
459 _M_root->_M_parent = 0;
460
461 if (_M_nodes->_M_left)
462 _M_nodes = _M_nodes->_M_left;
463 }
464 else
465 _M_nodes = 0;
466 }
467
468 #if __cplusplus >= 201103L
469 _Reuse_or_alloc_node(const _Reuse_or_alloc_node&) = delete;
470 #endif
471
472 ~_Reuse_or_alloc_node()
473 { _M_t._M_erase(static_cast<_Link_type>(_M_root)); }
474
475 template<typename _Arg>
476 _Link_type
477 #if __cplusplus < 201103L
478 operator()(const _Arg& __arg)
479 #else
480 operator()(_Arg&& __arg)
481 #endif
482 {
483 _Link_type __node = static_cast<_Link_type>(_M_extract());
484 if (__node)
485 {
486 _M_t._M_destroy_node(__node);
487 _M_t._M_construct_node(__node, _GLIBCXX_FORWARD(_Arg, __arg));
488 return __node;
489 }
490
491 return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg));
492 }
493
494 private:
495 _Base_ptr
496 _M_extract()
497 {
498 if (!_M_nodes)
499 return _M_nodes;
500
501 _Base_ptr __node = _M_nodes;
502 _M_nodes = _M_nodes->_M_parent;
503 if (_M_nodes)
504 {
505 if (_M_nodes->_M_right == __node)
506 {
507 _M_nodes->_M_right = 0;
508
509 if (_M_nodes->_M_left)
510 {
511 _M_nodes = _M_nodes->_M_left;
512
513 while (_M_nodes->_M_right)
514 _M_nodes = _M_nodes->_M_right;
515
516 if (_M_nodes->_M_left)
517 _M_nodes = _M_nodes->_M_left;
518 }
519 }
520 else // __node is on the left.
521 _M_nodes->_M_left = 0;
522 }
523 else
524 _M_root = 0;
525
526 return __node;
527 }
528
529 _Base_ptr _M_root;
530 _Base_ptr _M_nodes;
531 _Rb_tree& _M_t;
532 };
533
534 // Functor similar to the previous one but without any pool of nodes to
535 // recycle.
536 struct _Alloc_node
537 {
538 _Alloc_node(_Rb_tree& __t)
539 : _M_t(__t) { }
540
541 template<typename _Arg>
542 _Link_type
543 #if __cplusplus < 201103L
544 operator()(const _Arg& __arg) const
545 #else
546 operator()(_Arg&& __arg) const
547 #endif
548 { return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); }
549
550 private:
551 _Rb_tree& _M_t;
552 };
553
554 public:
555 typedef _Key key_type;
556 typedef _Val value_type;
557 typedef value_type* pointer;
558 typedef const value_type* const_pointer;
559 typedef value_type& reference;
560 typedef const value_type& const_reference;
561 typedef size_t size_type;
562 typedef ptrdiff_t difference_type;
563 typedef _Alloc allocator_type;
564
565 _Node_allocator&
566 _M_get_Node_allocator() _GLIBCXX_NOEXCEPT
567 { return this->_M_impl; }
568
569 const _Node_allocator&
570 _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT
571 { return this->_M_impl; }
572
573 allocator_type
574 get_allocator() const _GLIBCXX_NOEXCEPT
575 { return allocator_type(_M_get_Node_allocator()); }
576
577 protected:
578 _Link_type
579 _M_get_node()
580 { return _Alloc_traits::allocate(_M_get_Node_allocator(), 1); }
581
582 void
583 _M_put_node(_Link_type __p) _GLIBCXX_NOEXCEPT
584 { _Alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1); }
585
586 #if __cplusplus < 201103L
587 void
588 _M_construct_node(_Link_type __node, const value_type& __x)
589 {
590 __try
591 { get_allocator().construct(__node->_M_valptr(), __x); }
592 __catch(...)
593 {
594 _M_put_node(__node);
595 __throw_exception_again;
596 }
597 }
598
599 _Link_type
600 _M_create_node(const value_type& __x)
601 {
602 _Link_type __tmp = _M_get_node();
603 _M_construct_node(__tmp, __x);
604 return __tmp;
605 }
606 #else
607 template<typename... _Args>
608 void
609 _M_construct_node(_Link_type __node, _Args&&... __args)
610 {
611 __try
612 {
613 ::new(__node) _Rb_tree_node<_Val>;
614 _Alloc_traits::construct(_M_get_Node_allocator(),
615 __node->_M_valptr(),
616 std::forward<_Args>(__args)...);
617 }
618 __catch(...)
619 {
620 __node->~_Rb_tree_node<_Val>();
621 _M_put_node(__node);
622 __throw_exception_again;
623 }
624 }
625
626 template<typename... _Args>
627 _Link_type
628 _M_create_node(_Args&&... __args)
629 {
630 _Link_type __tmp = _M_get_node();
631 _M_construct_node(__tmp, std::forward<_Args>(__args)...);
632 return __tmp;
633 }
634 #endif
635
636 void
637 _M_destroy_node(_Link_type __p) _GLIBCXX_NOEXCEPT
638 {
639 #if __cplusplus < 201103L
640 get_allocator().destroy(__p->_M_valptr());
641 #else
642 _Alloc_traits::destroy(_M_get_Node_allocator(), __p->_M_valptr());
643 __p->~_Rb_tree_node<_Val>();
644 #endif
645 }
646
647 void
648 _M_drop_node(_Link_type __p) _GLIBCXX_NOEXCEPT
649 {
650 _M_destroy_node(__p);
651 _M_put_node(__p);
652 }
653
654 template<typename _NodeGen>
655 _Link_type
656 _M_clone_node(_Const_Link_type __x, _NodeGen& __node_gen)
657 {
658 _Link_type __tmp = __node_gen(*__x->_M_valptr());
659 __tmp->_M_color = __x->_M_color;
660 __tmp->_M_left = 0;
661 __tmp->_M_right = 0;
662 return __tmp;
663 }
664
665 protected:
666 #if _GLIBCXX_INLINE_VERSION
667 template<typename _Key_compare>
668 #else
669 // Unused _Is_pod_comparator is kept as it is part of mangled name.
670 template<typename _Key_compare,
671 bool /* _Is_pod_comparator */ = __is_pod(_Key_compare)>
672 #endif
673 struct _Rb_tree_impl
674 : public _Node_allocator
675 , public _Rb_tree_key_compare<_Key_compare>
676 , public _Rb_tree_header
677 {
678 typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare;
679
680 _Rb_tree_impl()
681 _GLIBCXX_NOEXCEPT_IF(
682 is_nothrow_default_constructible<_Node_allocator>::value
683 && is_nothrow_default_constructible<_Base_key_compare>::value )
684 : _Node_allocator()
685 { }
686
687 _Rb_tree_impl(const _Rb_tree_impl& __x)
688 : _Node_allocator(_Alloc_traits::_S_select_on_copy(__x))
689 , _Base_key_compare(__x._M_key_compare)
690 { }
691
692 #if __cplusplus < 201103L
693 _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a)
694 : _Node_allocator(__a), _Base_key_compare(__comp)
695 { }
696 #else
697 _Rb_tree_impl(_Rb_tree_impl&&) = default;
698
699 explicit
700 _Rb_tree_impl(_Node_allocator&& __a)
701 : _Node_allocator(std::move(__a))
702 { }
703
704 _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a)
705 : _Node_allocator(std::move(__a)),
706 _Base_key_compare(std::move(__x)),
707 _Rb_tree_header(std::move(__x))
708 { }
709
710 _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a)
711 : _Node_allocator(std::move(__a)), _Base_key_compare(__comp)
712 { }
713 #endif
714 };
715
716 _Rb_tree_impl<_Compare> _M_impl;
717
718 protected:
719 _Base_ptr&
720 _M_root() _GLIBCXX_NOEXCEPT
721 { return this->_M_impl._M_header._M_parent; }
722
723 _Const_Base_ptr
724 _M_root() const _GLIBCXX_NOEXCEPT
725 { return this->_M_impl._M_header._M_parent; }
726
727 _Base_ptr&
728 _M_leftmost() _GLIBCXX_NOEXCEPT
729 { return this->_M_impl._M_header._M_left; }
730
731 _Const_Base_ptr
732 _M_leftmost() const _GLIBCXX_NOEXCEPT
733 { return this->_M_impl._M_header._M_left; }
734
735 _Base_ptr&
736 _M_rightmost() _GLIBCXX_NOEXCEPT
737 { return this->_M_impl._M_header._M_right; }
738
739 _Const_Base_ptr
740 _M_rightmost() const _GLIBCXX_NOEXCEPT
741 { return this->_M_impl._M_header._M_right; }
742
743 _Link_type
744 _M_begin() _GLIBCXX_NOEXCEPT
745 { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); }
746
747 _Const_Link_type
748 _M_begin() const _GLIBCXX_NOEXCEPT
749 {
750 return static_cast<_Const_Link_type>
751 (this->_M_impl._M_header._M_parent);
752 }
753
754 _Base_ptr
755 _M_end() _GLIBCXX_NOEXCEPT
756 { return &this->_M_impl._M_header; }
757
758 _Const_Base_ptr
759 _M_end() const _GLIBCXX_NOEXCEPT
760 { return &this->_M_impl._M_header; }
761
762 static const_reference
763 _S_value(_Const_Link_type __x)
764 { return *__x->_M_valptr(); }
765
766 static const _Key&
767 _S_key(_Const_Link_type __x)
768 { return _KeyOfValue()(_S_value(__x)); }
769
770 static _Link_type
771 _S_left(_Base_ptr __x) _GLIBCXX_NOEXCEPT
772 { return static_cast<_Link_type>(__x->_M_left); }
773
774 static _Const_Link_type
775 _S_left(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT
776 { return static_cast<_Const_Link_type>(__x->_M_left); }
777
778 static _Link_type
779 _S_right(_Base_ptr __x) _GLIBCXX_NOEXCEPT
780 { return static_cast<_Link_type>(__x->_M_right); }
781
782 static _Const_Link_type
783 _S_right(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT
784 { return static_cast<_Const_Link_type>(__x->_M_right); }
785
786 static const_reference
787 _S_value(_Const_Base_ptr __x)
788 { return *static_cast<_Const_Link_type>(__x)->_M_valptr(); }
789
790 static const _Key&
791 _S_key(_Const_Base_ptr __x)
792 { return _KeyOfValue()(_S_value(__x)); }
793
794 static _Base_ptr
795 _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
796 { return _Rb_tree_node_base::_S_minimum(__x); }
797
798 static _Const_Base_ptr
799 _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT
800 { return _Rb_tree_node_base::_S_minimum(__x); }
801
802 static _Base_ptr
803 _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
804 { return _Rb_tree_node_base::_S_maximum(__x); }
805
806 static _Const_Base_ptr
807 _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT
808 { return _Rb_tree_node_base::_S_maximum(__x); }
809
810 public:
811 typedef _Rb_tree_iterator<value_type> iterator;
812 typedef _Rb_tree_const_iterator<value_type> const_iterator;
813
814 typedef std::reverse_iterator<iterator> reverse_iterator;
815 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
816
817 #if __cplusplus > 201402L
818 using node_type = _Node_handle<_Key, _Val, _Node_allocator>;
819 using insert_return_type = _Node_insert_return<
820 conditional_t<is_same_v<_Key, _Val>, const_iterator, iterator>,
821 node_type>;
822 #endif
823
824 pair<_Base_ptr, _Base_ptr>
825 _M_get_insert_unique_pos(const key_type& __k);
826
827 pair<_Base_ptr, _Base_ptr>
828 _M_get_insert_equal_pos(const key_type& __k);
829
830 pair<_Base_ptr, _Base_ptr>
831 _M_get_insert_hint_unique_pos(const_iterator __pos,
832 const key_type& __k);
833
834 pair<_Base_ptr, _Base_ptr>
835 _M_get_insert_hint_equal_pos(const_iterator __pos,
836 const key_type& __k);
837
838 private:
839 #if __cplusplus >= 201103L
840 template<typename _Arg, typename _NodeGen>
841 iterator
842 _M_insert_(_Base_ptr __x, _Base_ptr __y, _Arg&& __v, _NodeGen&);
843
844 iterator
845 _M_insert_node(_Base_ptr __x, _Base_ptr __y, _Link_type __z);
846
847 template<typename _Arg>
848 iterator
849 _M_insert_lower(_Base_ptr __y, _Arg&& __v);
850
851 template<typename _Arg>
852 iterator
853 _M_insert_equal_lower(_Arg&& __x);
854
855 iterator
856 _M_insert_lower_node(_Base_ptr __p, _Link_type __z);
857
858 iterator
859 _M_insert_equal_lower_node(_Link_type __z);
860 #else
861 template<typename _NodeGen>
862 iterator
863 _M_insert_(_Base_ptr __x, _Base_ptr __y,
864 const value_type& __v, _NodeGen&);
865
866 // _GLIBCXX_RESOLVE_LIB_DEFECTS
867 // 233. Insertion hints in associative containers.
868 iterator
869 _M_insert_lower(_Base_ptr __y, const value_type& __v);
870
871 iterator
872 _M_insert_equal_lower(const value_type& __x);
873 #endif
874
875 template<typename _NodeGen>
876 _Link_type
877 _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen&);
878
879 template<typename _NodeGen>
880 _Link_type
881 _M_copy(const _Rb_tree& __x, _NodeGen& __gen)
882 {
883 _Link_type __root = _M_copy(__x._M_begin(), _M_end(), __gen);
884 _M_leftmost() = _S_minimum(__root);
885 _M_rightmost() = _S_maximum(__root);
886 _M_impl._M_node_count = __x._M_impl._M_node_count;
887 return __root;
888 }
889
890 _Link_type
891 _M_copy(const _Rb_tree& __x)
892 {
893 _Alloc_node __an(*this);
894 return _M_copy(__x, __an);
895 }
896
897 void
898 _M_erase(_Link_type __x);
899
900 iterator
901 _M_lower_bound(_Link_type __x, _Base_ptr __y,
902 const _Key& __k);
903
904 const_iterator
905 _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y,
906 const _Key& __k) const;
907
908 iterator
909 _M_upper_bound(_Link_type __x, _Base_ptr __y,
910 const _Key& __k);
911
912 const_iterator
913 _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y,
914 const _Key& __k) const;
915
916 public:
917 // allocation/deallocation
918 #if __cplusplus < 201103L
919 _Rb_tree() { }
920 #else
921 _Rb_tree() = default;
922 #endif
923
924 _Rb_tree(const _Compare& __comp,
925 const allocator_type& __a = allocator_type())
926 : _M_impl(__comp, _Node_allocator(__a)) { }
927
928 _Rb_tree(const _Rb_tree& __x)
929 : _M_impl(__x._M_impl)
930 {
931 if (__x._M_root() != 0)
932 _M_root() = _M_copy(__x);
933 }
934
935 #if __cplusplus >= 201103L
936 _Rb_tree(const allocator_type& __a)
937 : _M_impl(_Node_allocator(__a))
938 { }
939
940 _Rb_tree(const _Rb_tree& __x, const allocator_type& __a)
941 : _M_impl(__x._M_impl._M_key_compare, _Node_allocator(__a))
942 {
943 if (__x._M_root() != nullptr)
944 _M_root() = _M_copy(__x);
945 }
946
947 _Rb_tree(_Rb_tree&&) = default;
948
949 _Rb_tree(_Rb_tree&& __x, const allocator_type& __a)
950 : _Rb_tree(std::move(__x), _Node_allocator(__a))
951 { }
952
953 private:
954 _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type)
955 noexcept(is_nothrow_default_constructible<_Compare>::value)
956 : _M_impl(std::move(__x._M_impl), std::move(__a))
957 { }
958
959 _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type)
960 : _M_impl(__x._M_impl._M_key_compare, std::move(__a))
961 {
962 if (__x._M_root() != nullptr)
963 _M_move_data(__x, false_type{});
964 }
965
966 public:
967 _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)
968 noexcept( noexcept(
969 _Rb_tree(std::declval<_Rb_tree&&>(), std::declval<_Node_allocator&&>(),
970 std::declval<typename _Alloc_traits::is_always_equal>())) )
971 : _Rb_tree(std::move(__x), std::move(__a),
972 typename _Alloc_traits::is_always_equal{})
973 { }
974 #endif
975
976 ~_Rb_tree() _GLIBCXX_NOEXCEPT
977 {
978 _M_erase(_M_begin());
979
980 #if __cplusplus >= 201103L
981 static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},
982 "comparison object must be invocable "
983 "with two arguments of key type");
984 # if __cplusplus >= 201703L
985 // _GLIBCXX_RESOLVE_LIB_DEFECTS
986 // 2542. Missing const requirements for associative containers
987 static_assert(is_invocable_v<const _Compare&, const _Key&, const _Key&>,
988 "comparison object must be invocable as const");
989 # endif // C++17
990 #endif // C++11
991 }
992
993 _Rb_tree&
994 operator=(const _Rb_tree& __x);
995
996 // Accessors.
997 _Compare
998 key_comp() const
999 { return _M_impl._M_key_compare; }
1000
1001 iterator
1002 begin() _GLIBCXX_NOEXCEPT
1003 { return iterator(this->_M_impl._M_header._M_left); }
1004
1005 const_iterator
1006 begin() const _GLIBCXX_NOEXCEPT
1007 { return const_iterator(this->_M_impl._M_header._M_left); }
1008
1009 iterator
1010 end() _GLIBCXX_NOEXCEPT
1011 { return iterator(&this->_M_impl._M_header); }
1012
1013 const_iterator
1014 end() const _GLIBCXX_NOEXCEPT
1015 { return const_iterator(&this->_M_impl._M_header); }
1016
1017 reverse_iterator
1018 rbegin() _GLIBCXX_NOEXCEPT
1019 { return reverse_iterator(end()); }
1020
1021 const_reverse_iterator
1022 rbegin() const _GLIBCXX_NOEXCEPT
1023 { return const_reverse_iterator(end()); }
1024
1025 reverse_iterator
1026 rend() _GLIBCXX_NOEXCEPT
1027 { return reverse_iterator(begin()); }
1028
1029 const_reverse_iterator
1030 rend() const _GLIBCXX_NOEXCEPT
1031 { return const_reverse_iterator(begin()); }
1032
1033 _GLIBCXX_NODISCARD bool
1034 empty() const _GLIBCXX_NOEXCEPT
1035 { return _M_impl._M_node_count == 0; }
1036
1037 size_type
1038 size() const _GLIBCXX_NOEXCEPT
1039 { return _M_impl._M_node_count; }
1040
1041 size_type
1042 max_size() const _GLIBCXX_NOEXCEPT
1043 { return _Alloc_traits::max_size(_M_get_Node_allocator()); }
1044
1045 void
1046 swap(_Rb_tree& __t)
1047 _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value);
1048
1049 // Insert/erase.
1050 #if __cplusplus >= 201103L
1051 template<typename _Arg>
1052 pair<iterator, bool>
1053 _M_insert_unique(_Arg&& __x);
1054
1055 template<typename _Arg>
1056 iterator
1057 _M_insert_equal(_Arg&& __x);
1058
1059 template<typename _Arg, typename _NodeGen>
1060 iterator
1061 _M_insert_unique_(const_iterator __pos, _Arg&& __x, _NodeGen&);
1062
1063 template<typename _Arg>
1064 iterator
1065 _M_insert_unique_(const_iterator __pos, _Arg&& __x)
1066 {
1067 _Alloc_node __an(*this);
1068 return _M_insert_unique_(__pos, std::forward<_Arg>(__x), __an);
1069 }
1070
1071 template<typename _Arg, typename _NodeGen>
1072 iterator
1073 _M_insert_equal_(const_iterator __pos, _Arg&& __x, _NodeGen&);
1074
1075 template<typename _Arg>
1076 iterator
1077 _M_insert_equal_(const_iterator __pos, _Arg&& __x)
1078 {
1079 _Alloc_node __an(*this);
1080 return _M_insert_equal_(__pos, std::forward<_Arg>(__x), __an);
1081 }
1082
1083 template<typename... _Args>
1084 pair<iterator, bool>
1085 _M_emplace_unique(_Args&&... __args);
1086
1087 template<typename... _Args>
1088 iterator
1089 _M_emplace_equal(_Args&&... __args);
1090
1091 template<typename... _Args>
1092 iterator
1093 _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args);
1094
1095 template<typename... _Args>
1096 iterator
1097 _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args);
1098
1099 template<typename _Iter>
1100 using __same_value_type
1101 = is_same<value_type, typename iterator_traits<_Iter>::value_type>;
1102
1103 template<typename _InputIterator>
1104 __enable_if_t<__same_value_type<_InputIterator>::value>
1105 _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
1106 {
1107 _Alloc_node __an(*this);
1108 for (; __first != __last; ++__first)
1109 _M_insert_unique_(end(), *__first, __an);
1110 }
1111
1112 template<typename _InputIterator>
1113 __enable_if_t<!__same_value_type<_InputIterator>::value>
1114 _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
1115 {
1116 for (; __first != __last; ++__first)
1117 _M_emplace_unique(*__first);
1118 }
1119
1120 template<typename _InputIterator>
1121 __enable_if_t<__same_value_type<_InputIterator>::value>
1122 _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
1123 {
1124 _Alloc_node __an(*this);
1125 for (; __first != __last; ++__first)
1126 _M_insert_equal_(end(), *__first, __an);
1127 }
1128
1129 template<typename _InputIterator>
1130 __enable_if_t<!__same_value_type<_InputIterator>::value>
1131 _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
1132 {
1133 _Alloc_node __an(*this);
1134 for (; __first != __last; ++__first)
1135 _M_emplace_equal(*__first);
1136 }
1137 #else
1138 pair<iterator, bool>
1139 _M_insert_unique(const value_type& __x);
1140
1141 iterator
1142 _M_insert_equal(const value_type& __x);
1143
1144 template<typename _NodeGen>
1145 iterator
1146 _M_insert_unique_(const_iterator __pos, const value_type& __x,
1147 _NodeGen&);
1148
1149 iterator
1150 _M_insert_unique_(const_iterator __pos, const value_type& __x)
1151 {
1152 _Alloc_node __an(*this);
1153 return _M_insert_unique_(__pos, __x, __an);
1154 }
1155
1156 template<typename _NodeGen>
1157 iterator
1158 _M_insert_equal_(const_iterator __pos, const value_type& __x,
1159 _NodeGen&);
1160 iterator
1161 _M_insert_equal_(const_iterator __pos, const value_type& __x)
1162 {
1163 _Alloc_node __an(*this);
1164 return _M_insert_equal_(__pos, __x, __an);
1165 }
1166
1167 template<typename _InputIterator>
1168 void
1169 _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
1170 {
1171 _Alloc_node __an(*this);
1172 for (; __first != __last; ++__first)
1173 _M_insert_unique_(end(), *__first, __an);
1174 }
1175
1176 template<typename _InputIterator>
1177 void
1178 _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
1179 {
1180 _Alloc_node __an(*this);
1181 for (; __first != __last; ++__first)
1182 _M_insert_equal_(end(), *__first, __an);
1183 }
1184 #endif
1185
1186 private:
1187 void
1188 _M_erase_aux(const_iterator __position);
1189
1190 void
1191 _M_erase_aux(const_iterator __first, const_iterator __last);
1192
1193 public:
1194 #if __cplusplus >= 201103L
1195 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1196 // DR 130. Associative erase should return an iterator.
1197 _GLIBCXX_ABI_TAG_CXX11
1198 iterator
1199 erase(const_iterator __position)
1200 {
1201 __glibcxx_assert(__position != end());
1202 const_iterator __result = __position;
1203 ++__result;
1204 _M_erase_aux(__position);
1205 return __result._M_const_cast();
1206 }
1207
1208 // LWG 2059.
1209 _GLIBCXX_ABI_TAG_CXX11
1210 iterator
1211 erase(iterator __position)
1212 {
1213 __glibcxx_assert(__position != end());
1214 iterator __result = __position;
1215 ++__result;
1216 _M_erase_aux(__position);
1217 return __result;
1218 }
1219 #else
1220 void
1221 erase(iterator __position)
1222 {
1223 __glibcxx_assert(__position != end());
1224 _M_erase_aux(__position);
1225 }
1226
1227 void
1228 erase(const_iterator __position)
1229 {
1230 __glibcxx_assert(__position != end());
1231 _M_erase_aux(__position);
1232 }
1233 #endif
1234 size_type
1235 erase(const key_type& __x);
1236
1237 #if __cplusplus >= 201103L
1238 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1239 // DR 130. Associative erase should return an iterator.
1240 _GLIBCXX_ABI_TAG_CXX11
1241 iterator
1242 erase(const_iterator __first, const_iterator __last)
1243 {
1244 _M_erase_aux(__first, __last);
1245 return __last._M_const_cast();
1246 }
1247 #else
1248 void
1249 erase(iterator __first, iterator __last)
1250 { _M_erase_aux(__first, __last); }
1251
1252 void
1253 erase(const_iterator __first, const_iterator __last)
1254 { _M_erase_aux(__first, __last); }
1255 #endif
1256 void
1257 erase(const key_type* __first, const key_type* __last);
1258
1259 void
1260 clear() _GLIBCXX_NOEXCEPT
1261 {
1262 _M_erase(_M_begin());
1263 _M_impl._M_reset();
1264 }
1265
1266 // Set operations.
1267 iterator
1268 find(const key_type& __k);
1269
1270 const_iterator
1271 find(const key_type& __k) const;
1272
1273 size_type
1274 count(const key_type& __k) const;
1275
1276 iterator
1277 lower_bound(const key_type& __k)
1278 { return _M_lower_bound(_M_begin(), _M_end(), __k); }
1279
1280 const_iterator
1281 lower_bound(const key_type& __k) const
1282 { return _M_lower_bound(_M_begin(), _M_end(), __k); }
1283
1284 iterator
1285 upper_bound(const key_type& __k)
1286 { return _M_upper_bound(_M_begin(), _M_end(), __k); }
1287
1288 const_iterator
1289 upper_bound(const key_type& __k) const
1290 { return _M_upper_bound(_M_begin(), _M_end(), __k); }
1291
1292 pair<iterator, iterator>
1293 equal_range(const key_type& __k);
1294
1295 pair<const_iterator, const_iterator>
1296 equal_range(const key_type& __k) const;
1297
1298 #if __cplusplus >= 201402L
1299 template<typename _Kt,
1300 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1301 iterator
1302 _M_find_tr(const _Kt& __k)
1303 {
1304 const _Rb_tree* __const_this = this;
1305 return __const_this->_M_find_tr(__k)._M_const_cast();
1306 }
1307
1308 template<typename _Kt,
1309 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1310 const_iterator
1311 _M_find_tr(const _Kt& __k) const
1312 {
1313 auto __j = _M_lower_bound_tr(__k);
1314 if (__j != end() && _M_impl._M_key_compare(__k, _S_key(__j._M_node)))
1315 __j = end();
1316 return __j;
1317 }
1318
1319 template<typename _Kt,
1320 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1321 size_type
1322 _M_count_tr(const _Kt& __k) const
1323 {
1324 auto __p = _M_equal_range_tr(__k);
1325 return std::distance(__p.first, __p.second);
1326 }
1327
1328 template<typename _Kt,
1329 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1330 iterator
1331 _M_lower_bound_tr(const _Kt& __k)
1332 {
1333 const _Rb_tree* __const_this = this;
1334 return __const_this->_M_lower_bound_tr(__k)._M_const_cast();
1335 }
1336
1337 template<typename _Kt,
1338 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1339 const_iterator
1340 _M_lower_bound_tr(const _Kt& __k) const
1341 {
1342 auto __x = _M_begin();
1343 auto __y = _M_end();
1344 while (__x != 0)
1345 if (!_M_impl._M_key_compare(_S_key(__x), __k))
1346 {
1347 __y = __x;
1348 __x = _S_left(__x);
1349 }
1350 else
1351 __x = _S_right(__x);
1352 return const_iterator(__y);
1353 }
1354
1355 template<typename _Kt,
1356 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1357 iterator
1358 _M_upper_bound_tr(const _Kt& __k)
1359 {
1360 const _Rb_tree* __const_this = this;
1361 return __const_this->_M_upper_bound_tr(__k)._M_const_cast();
1362 }
1363
1364 template<typename _Kt,
1365 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1366 const_iterator
1367 _M_upper_bound_tr(const _Kt& __k) const
1368 {
1369 auto __x = _M_begin();
1370 auto __y = _M_end();
1371 while (__x != 0)
1372 if (_M_impl._M_key_compare(__k, _S_key(__x)))
1373 {
1374 __y = __x;
1375 __x = _S_left(__x);
1376 }
1377 else
1378 __x = _S_right(__x);
1379 return const_iterator(__y);
1380 }
1381
1382 template<typename _Kt,
1383 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1384 pair<iterator, iterator>
1385 _M_equal_range_tr(const _Kt& __k)
1386 {
1387 const _Rb_tree* __const_this = this;
1388 auto __ret = __const_this->_M_equal_range_tr(__k);
1389 return { __ret.first._M_const_cast(), __ret.second._M_const_cast() };
1390 }
1391
1392 template<typename _Kt,
1393 typename _Req = __has_is_transparent_t<_Compare, _Kt>>
1394 pair<const_iterator, const_iterator>
1395 _M_equal_range_tr(const _Kt& __k) const
1396 {
1397 auto __low = _M_lower_bound_tr(__k);
1398 auto __high = __low;
1399 auto& __cmp = _M_impl._M_key_compare;
1400 while (__high != end() && !__cmp(__k, _S_key(__high._M_node)))
1401 ++__high;
1402 return { __low, __high };
1403 }
1404 #endif
1405
1406 // Debugging.
1407 bool
1408 __rb_verify() const;
1409
1410 #if __cplusplus >= 201103L
1411 _Rb_tree&
1412 operator=(_Rb_tree&&)
1413 noexcept(_Alloc_traits::_S_nothrow_move()
1414 && is_nothrow_move_assignable<_Compare>::value);
1415
1416 template<typename _Iterator>
1417 void
1418 _M_assign_unique(_Iterator, _Iterator);
1419
1420 template<typename _Iterator>
1421 void
1422 _M_assign_equal(_Iterator, _Iterator);
1423
1424 private:
1425 // Move elements from container with equal allocator.
1426 void
1427 _M_move_data(_Rb_tree& __x, true_type)
1428 { _M_impl._M_move_data(__x._M_impl); }
1429
1430 // Move elements from container with possibly non-equal allocator,
1431 // which might result in a copy not a move.
1432 void
1433 _M_move_data(_Rb_tree&, false_type);
1434
1435 // Move assignment from container with equal allocator.
1436 void
1437 _M_move_assign(_Rb_tree&, true_type);
1438
1439 // Move assignment from container with possibly non-equal allocator,
1440 // which might result in a copy not a move.
1441 void
1442 _M_move_assign(_Rb_tree&, false_type);
1443 #endif
1444
1445 #if __cplusplus > 201402L
1446 public:
1447 /// Re-insert an extracted node.
1448 insert_return_type
1449 _M_reinsert_node_unique(node_type&& __nh)
1450 {
1451 insert_return_type __ret;
1452 if (__nh.empty())
1453 __ret.position = end();
1454 else
1455 {
1456 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
1457
1458 auto __res = _M_get_insert_unique_pos(__nh._M_key());
1459 if (__res.second)
1460 {
1461 __ret.position
1462 = _M_insert_node(__res.first, __res.second, __nh._M_ptr);
1463 __nh._M_ptr = nullptr;
1464 __ret.inserted = true;
1465 }
1466 else
1467 {
1468 __ret.node = std::move(__nh);
1469 __ret.position = iterator(__res.first);
1470 __ret.inserted = false;
1471 }
1472 }
1473 return __ret;
1474 }
1475
1476 /// Re-insert an extracted node.
1477 iterator
1478 _M_reinsert_node_equal(node_type&& __nh)
1479 {
1480 iterator __ret;
1481 if (__nh.empty())
1482 __ret = end();
1483 else
1484 {
1485 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
1486 auto __res = _M_get_insert_equal_pos(__nh._M_key());
1487 if (__res.second)
1488 __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr);
1489 else
1490 __ret = _M_insert_equal_lower_node(__nh._M_ptr);
1491 __nh._M_ptr = nullptr;
1492 }
1493 return __ret;
1494 }
1495
1496 /// Re-insert an extracted node.
1497 iterator
1498 _M_reinsert_node_hint_unique(const_iterator __hint, node_type&& __nh)
1499 {
1500 iterator __ret;
1501 if (__nh.empty())
1502 __ret = end();
1503 else
1504 {
1505 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
1506 auto __res = _M_get_insert_hint_unique_pos(__hint, __nh._M_key());
1507 if (__res.second)
1508 {
1509 __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr);
1510 __nh._M_ptr = nullptr;
1511 }
1512 else
1513 __ret = iterator(__res.first);
1514 }
1515 return __ret;
1516 }
1517
1518 /// Re-insert an extracted node.
1519 iterator
1520 _M_reinsert_node_hint_equal(const_iterator __hint, node_type&& __nh)
1521 {
1522 iterator __ret;
1523 if (__nh.empty())
1524 __ret = end();
1525 else
1526 {
1527 __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
1528 auto __res = _M_get_insert_hint_equal_pos(__hint, __nh._M_key());
1529 if (__res.second)
1530 __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr);
1531 else
1532 __ret = _M_insert_equal_lower_node(__nh._M_ptr);
1533 __nh._M_ptr = nullptr;
1534 }
1535 return __ret;
1536 }
1537
1538 /// Extract a node.
1539 node_type
1540 extract(const_iterator __pos)
1541 {
1542 auto __ptr = _Rb_tree_rebalance_for_erase(
1543 __pos._M_const_cast()._M_node, _M_impl._M_header);
1544 --_M_impl._M_node_count;
1545 return { static_cast<_Link_type>(__ptr), _M_get_Node_allocator() };
1546 }
1547
1548 /// Extract a node.
1549 node_type
1550 extract(const key_type& __k)
1551 {
1552 node_type __nh;
1553 auto __pos = find(__k);
1554 if (__pos != end())
1555 __nh = extract(const_iterator(__pos));
1556 return __nh;
1557 }
1558
1559 template<typename _Compare2>
1560 using _Compatible_tree
1561 = _Rb_tree<_Key, _Val, _KeyOfValue, _Compare2, _Alloc>;
1562
1563 template<typename, typename>
1564 friend class _Rb_tree_merge_helper;
1565
1566 /// Merge from a compatible container into one with unique keys.
1567 template<typename _Compare2>
1568 void
1569 _M_merge_unique(_Compatible_tree<_Compare2>& __src) noexcept
1570 {
1571 using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>;
1572 for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
1573 {
1574 auto __pos = __i++;
1575 auto __res = _M_get_insert_unique_pos(_KeyOfValue()(*__pos));
1576 if (__res.second)
1577 {
1578 auto& __src_impl = _Merge_helper::_S_get_impl(__src);
1579 auto __ptr = _Rb_tree_rebalance_for_erase(
1580 __pos._M_node, __src_impl._M_header);
1581 --__src_impl._M_node_count;
1582 _M_insert_node(__res.first, __res.second,
1583 static_cast<_Link_type>(__ptr));
1584 }
1585 }
1586 }
1587
1588 /// Merge from a compatible container into one with equivalent keys.
1589 template<typename _Compare2>
1590 void
1591 _M_merge_equal(_Compatible_tree<_Compare2>& __src) noexcept
1592 {
1593 using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>;
1594 for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
1595 {
1596 auto __pos = __i++;
1597 auto __res = _M_get_insert_equal_pos(_KeyOfValue()(*__pos));
1598 if (__res.second)
1599 {
1600 auto& __src_impl = _Merge_helper::_S_get_impl(__src);
1601 auto __ptr = _Rb_tree_rebalance_for_erase(
1602 __pos._M_node, __src_impl._M_header);
1603 --__src_impl._M_node_count;
1604 _M_insert_node(__res.first, __res.second,
1605 static_cast<_Link_type>(__ptr));
1606 }
1607 }
1608 }
1609 #endif // C++17
1610
1611 friend bool
1612 operator==(const _Rb_tree& __x, const _Rb_tree& __y)
1613 {
1614 return __x.size() == __y.size()
1615 && std::equal(__x.begin(), __x.end(), __y.begin());
1616 }
1617
1618 friend bool
1619 operator<(const _Rb_tree& __x, const _Rb_tree& __y)
1620 {
1621 return std::lexicographical_compare(__x.begin(), __x.end(),
1622 __y.begin(), __y.end());
1623 }
1624
1625 friend bool _GLIBCXX_DEPRECATED
1626 operator!=(const _Rb_tree& __x, const _Rb_tree& __y)
1627 { return !(__x == __y); }
1628
1629 friend bool _GLIBCXX_DEPRECATED
1630 operator>(const _Rb_tree& __x, const _Rb_tree& __y)
1631 { return __y < __x; }
1632
1633 friend bool _GLIBCXX_DEPRECATED
1634 operator<=(const _Rb_tree& __x, const _Rb_tree& __y)
1635 { return !(__y < __x); }
1636
1637 friend bool _GLIBCXX_DEPRECATED
1638 operator>=(const _Rb_tree& __x, const _Rb_tree& __y)
1639 { return !(__x < __y); }
1640 };
1641
1642 template<typename _Key, typename _Val, typename _KeyOfValue,
1643 typename _Compare, typename _Alloc>
1644 inline void
1645 swap(_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
1646 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
1647 { __x.swap(__y); }
1648
1649 #if __cplusplus >= 201103L
1650 template<typename _Key, typename _Val, typename _KeyOfValue,
1651 typename _Compare, typename _Alloc>
1652 void
1653 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1654 _M_move_data(_Rb_tree& __x, false_type)
1655 {
1656 if (_M_get_Node_allocator() == __x._M_get_Node_allocator())
1657 _M_move_data(__x, true_type());
1658 else
1659 {
1660 _Alloc_node __an(*this);
1661 auto __lbd =
1662 [&__an](const value_type& __cval)
1663 {
1664 auto& __val = const_cast<value_type&>(__cval);
1665 return __an(std::move_if_noexcept(__val));
1666 };
1667 _M_root() = _M_copy(__x, __lbd);
1668 }
1669 }
1670
1671 template<typename _Key, typename _Val, typename _KeyOfValue,
1672 typename _Compare, typename _Alloc>
1673 inline void
1674 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1675 _M_move_assign(_Rb_tree& __x, true_type)
1676 {
1677 clear();
1678 if (__x._M_root() != nullptr)
1679 _M_move_data(__x, true_type());
1680 std::__alloc_on_move(_M_get_Node_allocator(),
1681 __x._M_get_Node_allocator());
1682 }
1683
1684 template<typename _Key, typename _Val, typename _KeyOfValue,
1685 typename _Compare, typename _Alloc>
1686 void
1687 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1688 _M_move_assign(_Rb_tree& __x, false_type)
1689 {
1690 if (_M_get_Node_allocator() == __x._M_get_Node_allocator())
1691 return _M_move_assign(__x, true_type{});
1692
1693 // Try to move each node reusing existing nodes and copying __x nodes
1694 // structure.
1695 _Reuse_or_alloc_node __roan(*this);
1696 _M_impl._M_reset();
1697 if (__x._M_root() != nullptr)
1698 {
1699 auto __lbd =
1700 [&__roan](const value_type& __cval)
1701 {
1702 auto& __val = const_cast<value_type&>(__cval);
1703 return __roan(std::move_if_noexcept(__val));
1704 };
1705 _M_root() = _M_copy(__x, __lbd);
1706 __x.clear();
1707 }
1708 }
1709
1710 template<typename _Key, typename _Val, typename _KeyOfValue,
1711 typename _Compare, typename _Alloc>
1712 inline _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&
1713 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1714 operator=(_Rb_tree&& __x)
1715 noexcept(_Alloc_traits::_S_nothrow_move()
1716 && is_nothrow_move_assignable<_Compare>::value)
1717 {
1718 _M_impl._M_key_compare = std::move(__x._M_impl._M_key_compare);
1719 _M_move_assign(__x, __bool_constant<_Alloc_traits::_S_nothrow_move()>());
1720 return *this;
1721 }
1722
1723 template<typename _Key, typename _Val, typename _KeyOfValue,
1724 typename _Compare, typename _Alloc>
1725 template<typename _Iterator>
1726 void
1727 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1728 _M_assign_unique(_Iterator __first, _Iterator __last)
1729 {
1730 _Reuse_or_alloc_node __roan(*this);
1731 _M_impl._M_reset();
1732 for (; __first != __last; ++__first)
1733 _M_insert_unique_(end(), *__first, __roan);
1734 }
1735
1736 template<typename _Key, typename _Val, typename _KeyOfValue,
1737 typename _Compare, typename _Alloc>
1738 template<typename _Iterator>
1739 void
1740 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1741 _M_assign_equal(_Iterator __first, _Iterator __last)
1742 {
1743 _Reuse_or_alloc_node __roan(*this);
1744 _M_impl._M_reset();
1745 for (; __first != __last; ++__first)
1746 _M_insert_equal_(end(), *__first, __roan);
1747 }
1748 #endif
1749
1750 template<typename _Key, typename _Val, typename _KeyOfValue,
1751 typename _Compare, typename _Alloc>
1752 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&
1753 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1754 operator=(const _Rb_tree& __x)
1755 {
1756 if (this != &__x)
1757 {
1758 // Note that _Key may be a constant type.
1759 #if __cplusplus >= 201103L
1760 if (_Alloc_traits::_S_propagate_on_copy_assign())
1761 {
1762 auto& __this_alloc = this->_M_get_Node_allocator();
1763 auto& __that_alloc = __x._M_get_Node_allocator();
1764 if (!_Alloc_traits::_S_always_equal()
1765 && __this_alloc != __that_alloc)
1766 {
1767 // Replacement allocator cannot free existing storage, we need
1768 // to erase nodes first.
1769 clear();
1770 std::__alloc_on_copy(__this_alloc, __that_alloc);
1771 }
1772 }
1773 #endif
1774
1775 _Reuse_or_alloc_node __roan(*this);
1776 _M_impl._M_reset();
1777 _M_impl._M_key_compare = __x._M_impl._M_key_compare;
1778 if (__x._M_root() != 0)
1779 _M_root() = _M_copy(__x, __roan);
1780 }
1781
1782 return *this;
1783 }
1784
1785 template<typename _Key, typename _Val, typename _KeyOfValue,
1786 typename _Compare, typename _Alloc>
1787 #if __cplusplus >= 201103L
1788 template<typename _Arg, typename _NodeGen>
1789 #else
1790 template<typename _NodeGen>
1791 #endif
1792 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
1793 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1794 _M_insert_(_Base_ptr __x, _Base_ptr __p,
1795 #if __cplusplus >= 201103L
1796 _Arg&& __v,
1797 #else
1798 const _Val& __v,
1799 #endif
1800 _NodeGen& __node_gen)
1801 {
1802 bool __insert_left = (__x != 0 || __p == _M_end()
1803 || _M_impl._M_key_compare(_KeyOfValue()(__v),
1804 _S_key(__p)));
1805
1806 _Link_type __z = __node_gen(_GLIBCXX_FORWARD(_Arg, __v));
1807
1808 _Rb_tree_insert_and_rebalance(__insert_left, __z, __p,
1809 this->_M_impl._M_header);
1810 ++_M_impl._M_node_count;
1811 return iterator(__z);
1812 }
1813
1814 template<typename _Key, typename _Val, typename _KeyOfValue,
1815 typename _Compare, typename _Alloc>
1816 #if __cplusplus >= 201103L
1817 template<typename _Arg>
1818 #endif
1819 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
1820 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1821 #if __cplusplus >= 201103L
1822 _M_insert_lower(_Base_ptr __p, _Arg&& __v)
1823 #else
1824 _M_insert_lower(_Base_ptr __p, const _Val& __v)
1825 #endif
1826 {
1827 bool __insert_left = (__p == _M_end()
1828 || !_M_impl._M_key_compare(_S_key(__p),
1829 _KeyOfValue()(__v)));
1830
1831 _Link_type __z = _M_create_node(_GLIBCXX_FORWARD(_Arg, __v));
1832
1833 _Rb_tree_insert_and_rebalance(__insert_left, __z, __p,
1834 this->_M_impl._M_header);
1835 ++_M_impl._M_node_count;
1836 return iterator(__z);
1837 }
1838
1839 template<typename _Key, typename _Val, typename _KeyOfValue,
1840 typename _Compare, typename _Alloc>
1841 #if __cplusplus >= 201103L
1842 template<typename _Arg>
1843 #endif
1844 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
1845 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1846 #if __cplusplus >= 201103L
1847 _M_insert_equal_lower(_Arg&& __v)
1848 #else
1849 _M_insert_equal_lower(const _Val& __v)
1850 #endif
1851 {
1852 _Link_type __x = _M_begin();
1853 _Base_ptr __y = _M_end();
1854 while (__x != 0)
1855 {
1856 __y = __x;
1857 __x = !_M_impl._M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ?
1858 _S_left(__x) : _S_right(__x);
1859 }
1860 return _M_insert_lower(__y, _GLIBCXX_FORWARD(_Arg, __v));
1861 }
1862
1863 template<typename _Key, typename _Val, typename _KoV,
1864 typename _Compare, typename _Alloc>
1865 template<typename _NodeGen>
1866 typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Link_type
1867 _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::
1868 _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen& __node_gen)
1869 {
1870 // Structural copy. __x and __p must be non-null.
1871 _Link_type __top = _M_clone_node(__x, __node_gen);
1872 __top->_M_parent = __p;
1873
1874 __try
1875 {
1876 if (__x->_M_right)
1877 __top->_M_right = _M_copy(_S_right(__x), __top, __node_gen);
1878 __p = __top;
1879 __x = _S_left(__x);
1880
1881 while (__x != 0)
1882 {
1883 _Link_type __y = _M_clone_node(__x, __node_gen);
1884 __p->_M_left = __y;
1885 __y->_M_parent = __p;
1886 if (__x->_M_right)
1887 __y->_M_right = _M_copy(_S_right(__x), __y, __node_gen);
1888 __p = __y;
1889 __x = _S_left(__x);
1890 }
1891 }
1892 __catch(...)
1893 {
1894 _M_erase(__top);
1895 __throw_exception_again;
1896 }
1897 return __top;
1898 }
1899
1900 template<typename _Key, typename _Val, typename _KeyOfValue,
1901 typename _Compare, typename _Alloc>
1902 void
1903 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1904 _M_erase(_Link_type __x)
1905 {
1906 // Erase without rebalancing.
1907 while (__x != 0)
1908 {
1909 _M_erase(_S_right(__x));
1910 _Link_type __y = _S_left(__x);
1911 _M_drop_node(__x);
1912 __x = __y;
1913 }
1914 }
1915
1916 template<typename _Key, typename _Val, typename _KeyOfValue,
1917 typename _Compare, typename _Alloc>
1918 typename _Rb_tree<_Key, _Val, _KeyOfValue,
1919 _Compare, _Alloc>::iterator
1920 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1921 _M_lower_bound(_Link_type __x, _Base_ptr __y,
1922 const _Key& __k)
1923 {
1924 while (__x != 0)
1925 if (!_M_impl._M_key_compare(_S_key(__x), __k))
1926 __y = __x, __x = _S_left(__x);
1927 else
1928 __x = _S_right(__x);
1929 return iterator(__y);
1930 }
1931
1932 template<typename _Key, typename _Val, typename _KeyOfValue,
1933 typename _Compare, typename _Alloc>
1934 typename _Rb_tree<_Key, _Val, _KeyOfValue,
1935 _Compare, _Alloc>::const_iterator
1936 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1937 _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y,
1938 const _Key& __k) const
1939 {
1940 while (__x != 0)
1941 if (!_M_impl._M_key_compare(_S_key(__x), __k))
1942 __y = __x, __x = _S_left(__x);
1943 else
1944 __x = _S_right(__x);
1945 return const_iterator(__y);
1946 }
1947
1948 template<typename _Key, typename _Val, typename _KeyOfValue,
1949 typename _Compare, typename _Alloc>
1950 typename _Rb_tree<_Key, _Val, _KeyOfValue,
1951 _Compare, _Alloc>::iterator
1952 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1953 _M_upper_bound(_Link_type __x, _Base_ptr __y,
1954 const _Key& __k)
1955 {
1956 while (__x != 0)
1957 if (_M_impl._M_key_compare(__k, _S_key(__x)))
1958 __y = __x, __x = _S_left(__x);
1959 else
1960 __x = _S_right(__x);
1961 return iterator(__y);
1962 }
1963
1964 template<typename _Key, typename _Val, typename _KeyOfValue,
1965 typename _Compare, typename _Alloc>
1966 typename _Rb_tree<_Key, _Val, _KeyOfValue,
1967 _Compare, _Alloc>::const_iterator
1968 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1969 _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y,
1970 const _Key& __k) const
1971 {
1972 while (__x != 0)
1973 if (_M_impl._M_key_compare(__k, _S_key(__x)))
1974 __y = __x, __x = _S_left(__x);
1975 else
1976 __x = _S_right(__x);
1977 return const_iterator(__y);
1978 }
1979
1980 template<typename _Key, typename _Val, typename _KeyOfValue,
1981 typename _Compare, typename _Alloc>
1982 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
1983 _Compare, _Alloc>::iterator,
1984 typename _Rb_tree<_Key, _Val, _KeyOfValue,
1985 _Compare, _Alloc>::iterator>
1986 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1987 equal_range(const _Key& __k)
1988 {
1989 _Link_type __x = _M_begin();
1990 _Base_ptr __y = _M_end();
1991 while (__x != 0)
1992 {
1993 if (_M_impl._M_key_compare(_S_key(__x), __k))
1994 __x = _S_right(__x);
1995 else if (_M_impl._M_key_compare(__k, _S_key(__x)))
1996 __y = __x, __x = _S_left(__x);
1997 else
1998 {
1999 _Link_type __xu(__x);
2000 _Base_ptr __yu(__y);
2001 __y = __x, __x = _S_left(__x);
2002 __xu = _S_right(__xu);
2003 return pair<iterator,
2004 iterator>(_M_lower_bound(__x, __y, __k),
2005 _M_upper_bound(__xu, __yu, __k));
2006 }
2007 }
2008 return pair<iterator, iterator>(iterator(__y),
2009 iterator(__y));
2010 }
2011
2012 template<typename _Key, typename _Val, typename _KeyOfValue,
2013 typename _Compare, typename _Alloc>
2014 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2015 _Compare, _Alloc>::const_iterator,
2016 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2017 _Compare, _Alloc>::const_iterator>
2018 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2019 equal_range(const _Key& __k) const
2020 {
2021 _Const_Link_type __x = _M_begin();
2022 _Const_Base_ptr __y = _M_end();
2023 while (__x != 0)
2024 {
2025 if (_M_impl._M_key_compare(_S_key(__x), __k))
2026 __x = _S_right(__x);
2027 else if (_M_impl._M_key_compare(__k, _S_key(__x)))
2028 __y = __x, __x = _S_left(__x);
2029 else
2030 {
2031 _Const_Link_type __xu(__x);
2032 _Const_Base_ptr __yu(__y);
2033 __y = __x, __x = _S_left(__x);
2034 __xu = _S_right(__xu);
2035 return pair<const_iterator,
2036 const_iterator>(_M_lower_bound(__x, __y, __k),
2037 _M_upper_bound(__xu, __yu, __k));
2038 }
2039 }
2040 return pair<const_iterator, const_iterator>(const_iterator(__y),
2041 const_iterator(__y));
2042 }
2043
2044 template<typename _Key, typename _Val, typename _KeyOfValue,
2045 typename _Compare, typename _Alloc>
2046 void
2047 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2048 swap(_Rb_tree& __t)
2049 _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value)
2050 {
2051 if (_M_root() == 0)
2052 {
2053 if (__t._M_root() != 0)
2054 _M_impl._M_move_data(__t._M_impl);
2055 }
2056 else if (__t._M_root() == 0)
2057 __t._M_impl._M_move_data(_M_impl);
2058 else
2059 {
2060 std::swap(_M_root(),__t._M_root());
2061 std::swap(_M_leftmost(),__t._M_leftmost());
2062 std::swap(_M_rightmost(),__t._M_rightmost());
2063
2064 _M_root()->_M_parent = _M_end();
2065 __t._M_root()->_M_parent = __t._M_end();
2066 std::swap(this->_M_impl._M_node_count, __t._M_impl._M_node_count);
2067 }
2068 // No need to swap header's color as it does not change.
2069 std::swap(this->_M_impl._M_key_compare, __t._M_impl._M_key_compare);
2070
2071 _Alloc_traits::_S_on_swap(_M_get_Node_allocator(),
2072 __t._M_get_Node_allocator());
2073 }
2074
2075 template<typename _Key, typename _Val, typename _KeyOfValue,
2076 typename _Compare, typename _Alloc>
2077 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2078 _Compare, _Alloc>::_Base_ptr,
2079 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2080 _Compare, _Alloc>::_Base_ptr>
2081 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2082 _M_get_insert_unique_pos(const key_type& __k)
2083 {
2084 typedef pair<_Base_ptr, _Base_ptr> _Res;
2085 _Link_type __x = _M_begin();
2086 _Base_ptr __y = _M_end();
2087 bool __comp = true;
2088 while (__x != 0)
2089 {
2090 __y = __x;
2091 __comp = _M_impl._M_key_compare(__k, _S_key(__x));
2092 __x = __comp ? _S_left(__x) : _S_right(__x);
2093 }
2094 iterator __j = iterator(__y);
2095 if (__comp)
2096 {
2097 if (__j == begin())
2098 return _Res(__x, __y);
2099 else
2100 --__j;
2101 }
2102 if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
2103 return _Res(__x, __y);
2104 return _Res(__j._M_node, 0);
2105 }
2106
2107 template<typename _Key, typename _Val, typename _KeyOfValue,
2108 typename _Compare, typename _Alloc>
2109 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2110 _Compare, _Alloc>::_Base_ptr,
2111 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2112 _Compare, _Alloc>::_Base_ptr>
2113 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2114 _M_get_insert_equal_pos(const key_type& __k)
2115 {
2116 typedef pair<_Base_ptr, _Base_ptr> _Res;
2117 _Link_type __x = _M_begin();
2118 _Base_ptr __y = _M_end();
2119 while (__x != 0)
2120 {
2121 __y = __x;
2122 __x = _M_impl._M_key_compare(__k, _S_key(__x)) ?
2123 _S_left(__x) : _S_right(__x);
2124 }
2125 return _Res(__x, __y);
2126 }
2127
2128 template<typename _Key, typename _Val, typename _KeyOfValue,
2129 typename _Compare, typename _Alloc>
2130 #if __cplusplus >= 201103L
2131 template<typename _Arg>
2132 #endif
2133 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2134 _Compare, _Alloc>::iterator, bool>
2135 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2136 #if __cplusplus >= 201103L
2137 _M_insert_unique(_Arg&& __v)
2138 #else
2139 _M_insert_unique(const _Val& __v)
2140 #endif
2141 {
2142 typedef pair<iterator, bool> _Res;
2143 pair<_Base_ptr, _Base_ptr> __res
2144 = _M_get_insert_unique_pos(_KeyOfValue()(__v));
2145
2146 if (__res.second)
2147 {
2148 _Alloc_node __an(*this);
2149 return _Res(_M_insert_(__res.first, __res.second,
2150 _GLIBCXX_FORWARD(_Arg, __v), __an),
2151 true);
2152 }
2153
2154 return _Res(iterator(__res.first), false);
2155 }
2156
2157 template<typename _Key, typename _Val, typename _KeyOfValue,
2158 typename _Compare, typename _Alloc>
2159 #if __cplusplus >= 201103L
2160 template<typename _Arg>
2161 #endif
2162 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2163 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2164 #if __cplusplus >= 201103L
2165 _M_insert_equal(_Arg&& __v)
2166 #else
2167 _M_insert_equal(const _Val& __v)
2168 #endif
2169 {
2170 pair<_Base_ptr, _Base_ptr> __res
2171 = _M_get_insert_equal_pos(_KeyOfValue()(__v));
2172 _Alloc_node __an(*this);
2173 return _M_insert_(__res.first, __res.second,
2174 _GLIBCXX_FORWARD(_Arg, __v), __an);
2175 }
2176
2177 template<typename _Key, typename _Val, typename _KeyOfValue,
2178 typename _Compare, typename _Alloc>
2179 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2180 _Compare, _Alloc>::_Base_ptr,
2181 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2182 _Compare, _Alloc>::_Base_ptr>
2183 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2184 _M_get_insert_hint_unique_pos(const_iterator __position,
2185 const key_type& __k)
2186 {
2187 iterator __pos = __position._M_const_cast();
2188 typedef pair<_Base_ptr, _Base_ptr> _Res;
2189
2190 // end()
2191 if (__pos._M_node == _M_end())
2192 {
2193 if (size() > 0
2194 && _M_impl._M_key_compare(_S_key(_M_rightmost()), __k))
2195 return _Res(0, _M_rightmost());
2196 else
2197 return _M_get_insert_unique_pos(__k);
2198 }
2199 else if (_M_impl._M_key_compare(__k, _S_key(__pos._M_node)))
2200 {
2201 // First, try before...
2202 iterator __before = __pos;
2203 if (__pos._M_node == _M_leftmost()) // begin()
2204 return _Res(_M_leftmost(), _M_leftmost());
2205 else if (_M_impl._M_key_compare(_S_key((--__before)._M_node), __k))
2206 {
2207 if (_S_right(__before._M_node) == 0)
2208 return _Res(0, __before._M_node);
2209 else
2210 return _Res(__pos._M_node, __pos._M_node);
2211 }
2212 else
2213 return _M_get_insert_unique_pos(__k);
2214 }
2215 else if (_M_impl._M_key_compare(_S_key(__pos._M_node), __k))
2216 {
2217 // ... then try after.
2218 iterator __after = __pos;
2219 if (__pos._M_node == _M_rightmost())
2220 return _Res(0, _M_rightmost());
2221 else if (_M_impl._M_key_compare(__k, _S_key((++__after)._M_node)))
2222 {
2223 if (_S_right(__pos._M_node) == 0)
2224 return _Res(0, __pos._M_node);
2225 else
2226 return _Res(__after._M_node, __after._M_node);
2227 }
2228 else
2229 return _M_get_insert_unique_pos(__k);
2230 }
2231 else
2232 // Equivalent keys.
2233 return _Res(__pos._M_node, 0);
2234 }
2235
2236 template<typename _Key, typename _Val, typename _KeyOfValue,
2237 typename _Compare, typename _Alloc>
2238 #if __cplusplus >= 201103L
2239 template<typename _Arg, typename _NodeGen>
2240 #else
2241 template<typename _NodeGen>
2242 #endif
2243 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2244 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2245 _M_insert_unique_(const_iterator __position,
2246 #if __cplusplus >= 201103L
2247 _Arg&& __v,
2248 #else
2249 const _Val& __v,
2250 #endif
2251 _NodeGen& __node_gen)
2252 {
2253 pair<_Base_ptr, _Base_ptr> __res
2254 = _M_get_insert_hint_unique_pos(__position, _KeyOfValue()(__v));
2255
2256 if (__res.second)
2257 return _M_insert_(__res.first, __res.second,
2258 _GLIBCXX_FORWARD(_Arg, __v),
2259 __node_gen);
2260 return iterator(__res.first);
2261 }
2262
2263 template<typename _Key, typename _Val, typename _KeyOfValue,
2264 typename _Compare, typename _Alloc>
2265 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2266 _Compare, _Alloc>::_Base_ptr,
2267 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2268 _Compare, _Alloc>::_Base_ptr>
2269 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2270 _M_get_insert_hint_equal_pos(const_iterator __position, const key_type& __k)
2271 {
2272 iterator __pos = __position._M_const_cast();
2273 typedef pair<_Base_ptr, _Base_ptr> _Res;
2274
2275 // end()
2276 if (__pos._M_node == _M_end())
2277 {
2278 if (size() > 0
2279 && !_M_impl._M_key_compare(__k, _S_key(_M_rightmost())))
2280 return _Res(0, _M_rightmost());
2281 else
2282 return _M_get_insert_equal_pos(__k);
2283 }
2284 else if (!_M_impl._M_key_compare(_S_key(__pos._M_node), __k))
2285 {
2286 // First, try before...
2287 iterator __before = __pos;
2288 if (__pos._M_node == _M_leftmost()) // begin()
2289 return _Res(_M_leftmost(), _M_leftmost());
2290 else if (!_M_impl._M_key_compare(__k, _S_key((--__before)._M_node)))
2291 {
2292 if (_S_right(__before._M_node) == 0)
2293 return _Res(0, __before._M_node);
2294 else
2295 return _Res(__pos._M_node, __pos._M_node);
2296 }
2297 else
2298 return _M_get_insert_equal_pos(__k);
2299 }
2300 else
2301 {
2302 // ... then try after.
2303 iterator __after = __pos;
2304 if (__pos._M_node == _M_rightmost())
2305 return _Res(0, _M_rightmost());
2306 else if (!_M_impl._M_key_compare(_S_key((++__after)._M_node), __k))
2307 {
2308 if (_S_right(__pos._M_node) == 0)
2309 return _Res(0, __pos._M_node);
2310 else
2311 return _Res(__after._M_node, __after._M_node);
2312 }
2313 else
2314 return _Res(0, 0);
2315 }
2316 }
2317
2318 template<typename _Key, typename _Val, typename _KeyOfValue,
2319 typename _Compare, typename _Alloc>
2320 #if __cplusplus >= 201103L
2321 template<typename _Arg, typename _NodeGen>
2322 #else
2323 template<typename _NodeGen>
2324 #endif
2325 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2326 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2327 _M_insert_equal_(const_iterator __position,
2328 #if __cplusplus >= 201103L
2329 _Arg&& __v,
2330 #else
2331 const _Val& __v,
2332 #endif
2333 _NodeGen& __node_gen)
2334 {
2335 pair<_Base_ptr, _Base_ptr> __res
2336 = _M_get_insert_hint_equal_pos(__position, _KeyOfValue()(__v));
2337
2338 if (__res.second)
2339 return _M_insert_(__res.first, __res.second,
2340 _GLIBCXX_FORWARD(_Arg, __v),
2341 __node_gen);
2342
2343 return _M_insert_equal_lower(_GLIBCXX_FORWARD(_Arg, __v));
2344 }
2345
2346 #if __cplusplus >= 201103L
2347 template<typename _Key, typename _Val, typename _KeyOfValue,
2348 typename _Compare, typename _Alloc>
2349 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2350 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2351 _M_insert_node(_Base_ptr __x, _Base_ptr __p, _Link_type __z)
2352 {
2353 bool __insert_left = (__x != 0 || __p == _M_end()
2354 || _M_impl._M_key_compare(_S_key(__z),
2355 _S_key(__p)));
2356
2357 _Rb_tree_insert_and_rebalance(__insert_left, __z, __p,
2358 this->_M_impl._M_header);
2359 ++_M_impl._M_node_count;
2360 return iterator(__z);
2361 }
2362
2363 template<typename _Key, typename _Val, typename _KeyOfValue,
2364 typename _Compare, typename _Alloc>
2365 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2366 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2367 _M_insert_lower_node(_Base_ptr __p, _Link_type __z)
2368 {
2369 bool __insert_left = (__p == _M_end()
2370 || !_M_impl._M_key_compare(_S_key(__p),
2371 _S_key(__z)));
2372
2373 _Rb_tree_insert_and_rebalance(__insert_left, __z, __p,
2374 this->_M_impl._M_header);
2375 ++_M_impl._M_node_count;
2376 return iterator(__z);
2377 }
2378
2379 template<typename _Key, typename _Val, typename _KeyOfValue,
2380 typename _Compare, typename _Alloc>
2381 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2382 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2383 _M_insert_equal_lower_node(_Link_type __z)
2384 {
2385 _Link_type __x = _M_begin();
2386 _Base_ptr __y = _M_end();
2387 while (__x != 0)
2388 {
2389 __y = __x;
2390 __x = !_M_impl._M_key_compare(_S_key(__x), _S_key(__z)) ?
2391 _S_left(__x) : _S_right(__x);
2392 }
2393 return _M_insert_lower_node(__y, __z);
2394 }
2395
2396 template<typename _Key, typename _Val, typename _KeyOfValue,
2397 typename _Compare, typename _Alloc>
2398 template<typename... _Args>
2399 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
2400 _Compare, _Alloc>::iterator, bool>
2401 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2402 _M_emplace_unique(_Args&&... __args)
2403 {
2404 _Link_type __z = _M_create_node(std::forward<_Args>(__args)...);
2405
2406 __try
2407 {
2408 typedef pair<iterator, bool> _Res;
2409 auto __res = _M_get_insert_unique_pos(_S_key(__z));
2410 if (__res.second)
2411 return _Res(_M_insert_node(__res.first, __res.second, __z), true);
2412
2413 _M_drop_node(__z);
2414 return _Res(iterator(__res.first), false);
2415 }
2416 __catch(...)
2417 {
2418 _M_drop_node(__z);
2419 __throw_exception_again;
2420 }
2421 }
2422
2423 template<typename _Key, typename _Val, typename _KeyOfValue,
2424 typename _Compare, typename _Alloc>
2425 template<typename... _Args>
2426 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2427 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2428 _M_emplace_equal(_Args&&... __args)
2429 {
2430 _Link_type __z = _M_create_node(std::forward<_Args>(__args)...);
2431
2432 __try
2433 {
2434 auto __res = _M_get_insert_equal_pos(_S_key(__z));
2435 return _M_insert_node(__res.first, __res.second, __z);
2436 }
2437 __catch(...)
2438 {
2439 _M_drop_node(__z);
2440 __throw_exception_again;
2441 }
2442 }
2443
2444 template<typename _Key, typename _Val, typename _KeyOfValue,
2445 typename _Compare, typename _Alloc>
2446 template<typename... _Args>
2447 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2448 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2449 _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args)
2450 {
2451 _Link_type __z = _M_create_node(std::forward<_Args>(__args)...);
2452
2453 __try
2454 {
2455 auto __res = _M_get_insert_hint_unique_pos(__pos, _S_key(__z));
2456
2457 if (__res.second)
2458 return _M_insert_node(__res.first, __res.second, __z);
2459
2460 _M_drop_node(__z);
2461 return iterator(__res.first);
2462 }
2463 __catch(...)
2464 {
2465 _M_drop_node(__z);
2466 __throw_exception_again;
2467 }
2468 }
2469
2470 template<typename _Key, typename _Val, typename _KeyOfValue,
2471 typename _Compare, typename _Alloc>
2472 template<typename... _Args>
2473 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
2474 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2475 _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args)
2476 {
2477 _Link_type __z = _M_create_node(std::forward<_Args>(__args)...);
2478
2479 __try
2480 {
2481 auto __res = _M_get_insert_hint_equal_pos(__pos, _S_key(__z));
2482
2483 if (__res.second)
2484 return _M_insert_node(__res.first, __res.second, __z);
2485
2486 return _M_insert_equal_lower_node(__z);
2487 }
2488 __catch(...)
2489 {
2490 _M_drop_node(__z);
2491 __throw_exception_again;
2492 }
2493 }
2494 #endif
2495
2496
2497 template<typename _Key, typename _Val, typename _KeyOfValue,
2498 typename _Compare, typename _Alloc>
2499 void
2500 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2501 _M_erase_aux(const_iterator __position)
2502 {
2503 _Link_type __y =
2504 static_cast<_Link_type>(_Rb_tree_rebalance_for_erase
2505 (const_cast<_Base_ptr>(__position._M_node),
2506 this->_M_impl._M_header));
2507 _M_drop_node(__y);
2508 --_M_impl._M_node_count;
2509 }
2510
2511 template<typename _Key, typename _Val, typename _KeyOfValue,
2512 typename _Compare, typename _Alloc>
2513 void
2514 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2515 _M_erase_aux(const_iterator __first, const_iterator __last)
2516 {
2517 if (__first == begin() && __last == end())
2518 clear();
2519 else
2520 while (__first != __last)
2521 _M_erase_aux(__first++);
2522 }
2523
2524 template<typename _Key, typename _Val, typename _KeyOfValue,
2525 typename _Compare, typename _Alloc>
2526 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
2527 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2528 erase(const _Key& __x)
2529 {
2530 pair<iterator, iterator> __p = equal_range(__x);
2531 const size_type __old_size = size();
2532 _M_erase_aux(__p.first, __p.second);
2533 return __old_size - size();
2534 }
2535
2536 template<typename _Key, typename _Val, typename _KeyOfValue,
2537 typename _Compare, typename _Alloc>
2538 void
2539 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2540 erase(const _Key* __first, const _Key* __last)
2541 {
2542 while (__first != __last)
2543 erase(*__first++);
2544 }
2545
2546 template<typename _Key, typename _Val, typename _KeyOfValue,
2547 typename _Compare, typename _Alloc>
2548 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2549 _Compare, _Alloc>::iterator
2550 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2551 find(const _Key& __k)
2552 {
2553 iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k);
2554 return (__j == end()
2555 || _M_impl._M_key_compare(__k,
2556 _S_key(__j._M_node))) ? end() : __j;
2557 }
2558
2559 template<typename _Key, typename _Val, typename _KeyOfValue,
2560 typename _Compare, typename _Alloc>
2561 typename _Rb_tree<_Key, _Val, _KeyOfValue,
2562 _Compare, _Alloc>::const_iterator
2563 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2564 find(const _Key& __k) const
2565 {
2566 const_iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k);
2567 return (__j == end()
2568 || _M_impl._M_key_compare(__k,
2569 _S_key(__j._M_node))) ? end() : __j;
2570 }
2571
2572 template<typename _Key, typename _Val, typename _KeyOfValue,
2573 typename _Compare, typename _Alloc>
2574 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
2575 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2576 count(const _Key& __k) const
2577 {
2578 pair<const_iterator, const_iterator> __p = equal_range(__k);
2579 const size_type __n = std::distance(__p.first, __p.second);
2580 return __n;
2581 }
2582
2583 _GLIBCXX_PURE unsigned int
2584 _Rb_tree_black_count(const _Rb_tree_node_base* __node,
2585 const _Rb_tree_node_base* __root) throw ();
2586
2587 template<typename _Key, typename _Val, typename _KeyOfValue,
2588 typename _Compare, typename _Alloc>
2589 bool
2590 _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::__rb_verify() const
2591 {
2592 if (_M_impl._M_node_count == 0 || begin() == end())
2593 return _M_impl._M_node_count == 0 && begin() == end()
2594 && this->_M_impl._M_header._M_left == _M_end()
2595 && this->_M_impl._M_header._M_right == _M_end();
2596
2597 unsigned int __len = _Rb_tree_black_count(_M_leftmost(), _M_root());
2598 for (const_iterator __it = begin(); __it != end(); ++__it)
2599 {
2600 _Const_Link_type __x = static_cast<_Const_Link_type>(__it._M_node);
2601 _Const_Link_type __L = _S_left(__x);
2602 _Const_Link_type __R = _S_right(__x);
2603
2604 if (__x->_M_color == _S_red)
2605 if ((__L && __L->_M_color == _S_red)
2606 || (__R && __R->_M_color == _S_red))
2607 return false;
2608
2609 if (__L && _M_impl._M_key_compare(_S_key(__x), _S_key(__L)))
2610 return false;
2611 if (__R && _M_impl._M_key_compare(_S_key(__R), _S_key(__x)))
2612 return false;
2613
2614 if (!__L && !__R && _Rb_tree_black_count(__x, _M_root()) != __len)
2615 return false;
2616 }
2617
2618 if (_M_leftmost() != _Rb_tree_node_base::_S_minimum(_M_root()))
2619 return false;
2620 if (_M_rightmost() != _Rb_tree_node_base::_S_maximum(_M_root()))
2621 return false;
2622 return true;
2623 }
2624
2625 #if __cplusplus > 201402L
2626 // Allow access to internals of compatible _Rb_tree specializations.
2627 template<typename _Key, typename _Val, typename _Sel, typename _Cmp1,
2628 typename _Alloc, typename _Cmp2>
2629 struct _Rb_tree_merge_helper<_Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>,
2630 _Cmp2>
2631 {
2632 private:
2633 friend class _Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>;
2634
2635 static auto&
2636 _S_get_impl(_Rb_tree<_Key, _Val, _Sel, _Cmp2, _Alloc>& __tree)
2637 { return __tree._M_impl; }
2638 };
2639 #endif // C++17
2640
2641 _GLIBCXX_END_NAMESPACE_VERSION
2642 } // namespace
2643
2644 #endif
2645