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