blob: 3a00e2aa9c4f8c504fa65688319882a6ed30247c [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP___TREE
12#define _LIBCPP___TREE
13
14#include <__config>
15#include <iterator>
16#include <memory>
17#include <stdexcept>
18#include <algorithm>
19
20#pragma GCC system_header
21
22_LIBCPP_BEGIN_NAMESPACE_STD
23
24template <class, class, class> class __tree;
Howard Hinnant333f50d2010-09-21 20:16:37 +000025template <class, class, class> class _LIBCPP_VISIBLE __tree_iterator;
26template <class, class, class> class _LIBCPP_VISIBLE __tree_const_iterator;
27template <class, class, class, class> class _LIBCPP_VISIBLE map;
28template <class, class, class, class> class _LIBCPP_VISIBLE multimap;
29template <class, class, class> class _LIBCPP_VISIBLE set;
30template <class, class, class> class _LIBCPP_VISIBLE multiset;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031
32/*
33
34_NodePtr algorithms
35
36The algorithms taking _NodePtr are red black tree algorithms. Those
37algorithms taking a parameter named __root should assume that __root
38points to a proper red black tree (unless otherwise specified).
39
40Each algorithm herein assumes that __root->__parent_ points to a non-null
41structure which has a member __left_ which points back to __root. No other
42member is read or written to at __root->__parent_.
43
44__root->__parent_ will be referred to below (in comments only) as end_node.
45end_node->__left_ is an externably accessible lvalue for __root, and can be
46changed by node insertion and removal (without explicit reference to end_node).
47
48All nodes (with the exception of end_node), even the node referred to as
49__root, have a non-null __parent_ field.
50
51*/
52
53// Returns: true if __x is a left child of its parent, else false
54// Precondition: __x != nullptr.
55template <class _NodePtr>
Howard Hinnant333f50d2010-09-21 20:16:37 +000056inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000057bool
58__tree_is_left_child(_NodePtr __x)
59{
60 return __x == __x->__parent_->__left_;
61}
62
63// Determintes if the subtree rooted at __x is a proper red black subtree. If
64// __x is a proper subtree, returns the black height (null counts as 1). If
65// __x is an improper subtree, returns 0.
66template <class _NodePtr>
67unsigned
68__tree_sub_invariant(_NodePtr __x)
69{
70 if (__x == nullptr)
71 return 1;
72 // parent consistency checked by caller
73 // check __x->__left_ consistency
74 if (__x->__left_ != nullptr && __x->__left_->__parent_ != __x)
75 return 0;
76 // check __x->__right_ consistency
77 if (__x->__right_ != nullptr && __x->__right_->__parent_ != __x)
78 return 0;
79 // check __x->__left_ != __x->__right_ unless both are nullptr
80 if (__x->__left_ == __x->__right_ && __x->__left_ != nullptr)
81 return 0;
82 // If this is red, neither child can be red
83 if (!__x->__is_black_)
84 {
85 if (__x->__left_ && !__x->__left_->__is_black_)
86 return 0;
87 if (__x->__right_ && !__x->__right_->__is_black_)
88 return 0;
89 }
90 unsigned __h = __tree_sub_invariant(__x->__left_);
91 if (__h == 0)
92 return 0; // invalid left subtree
93 if (__h != __tree_sub_invariant(__x->__right_))
94 return 0; // invalid or different height right subtree
95 return __h + __x->__is_black_; // return black height of this node
96}
97
98// Determintes if the red black tree rooted at __root is a proper red black tree.
99// __root == nullptr is a proper tree. Returns true is __root is a proper
100// red black tree, else returns false.
101template <class _NodePtr>
102bool
103__tree_invariant(_NodePtr __root)
104{
105 if (__root == nullptr)
106 return true;
107 // check __x->__parent_ consistency
108 if (__root->__parent_ == nullptr)
109 return false;
110 if (!__tree_is_left_child(__root))
111 return false;
112 // root must be black
113 if (!__root->__is_black_)
114 return false;
115 // do normal node checks
116 return __tree_sub_invariant(__root) != 0;
117}
118
119// Returns: pointer to the left-most node under __x.
120// Precondition: __x != nullptr.
121template <class _NodePtr>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000122inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000123_NodePtr
124__tree_min(_NodePtr __x)
125{
126 while (__x->__left_ != nullptr)
127 __x = __x->__left_;
128 return __x;
129}
130
131// Returns: pointer to the right-most node under __x.
132// Precondition: __x != nullptr.
133template <class _NodePtr>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000134inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000135_NodePtr
136__tree_max(_NodePtr __x)
137{
138 while (__x->__right_ != nullptr)
139 __x = __x->__right_;
140 return __x;
141}
142
143// Returns: pointer to the next in-order node after __x.
144// Precondition: __x != nullptr.
145template <class _NodePtr>
146_NodePtr
147__tree_next(_NodePtr __x)
148{
149 if (__x->__right_ != nullptr)
150 return __tree_min(__x->__right_);
151 while (!__tree_is_left_child(__x))
152 __x = __x->__parent_;
153 return __x->__parent_;
154}
155
156// Returns: pointer to the previous in-order node before __x.
157// Precondition: __x != nullptr.
158template <class _NodePtr>
159_NodePtr
160__tree_prev(_NodePtr __x)
161{
162 if (__x->__left_ != nullptr)
163 return __tree_max(__x->__left_);
164 while (__tree_is_left_child(__x))
165 __x = __x->__parent_;
166 return __x->__parent_;
167}
168
169// Returns: pointer to a node which has no children
170// Precondition: __x != nullptr.
171template <class _NodePtr>
172_NodePtr
173__tree_leaf(_NodePtr __x)
174{
175 while (true)
176 {
177 if (__x->__left_ != nullptr)
178 {
179 __x = __x->__left_;
180 continue;
181 }
182 if (__x->__right_ != nullptr)
183 {
184 __x = __x->__right_;
185 continue;
186 }
187 break;
188 }
189 return __x;
190}
191
192// Effects: Makes __x->__right_ the subtree root with __x as its left child
193// while preserving in-order order.
194// Precondition: __x->__right_ != nullptr
195template <class _NodePtr>
196void
197__tree_left_rotate(_NodePtr __x)
198{
199 _NodePtr __y = __x->__right_;
200 __x->__right_ = __y->__left_;
201 if (__x->__right_ != nullptr)
202 __x->__right_->__parent_ = __x;
203 __y->__parent_ = __x->__parent_;
204 if (__tree_is_left_child(__x))
205 __x->__parent_->__left_ = __y;
206 else
207 __x->__parent_->__right_ = __y;
208 __y->__left_ = __x;
209 __x->__parent_ = __y;
210}
211
212// Effects: Makes __x->__left_ the subtree root with __x as its right child
213// while preserving in-order order.
214// Precondition: __x->__left_ != nullptr
215template <class _NodePtr>
216void
217__tree_right_rotate(_NodePtr __x)
218{
219 _NodePtr __y = __x->__left_;
220 __x->__left_ = __y->__right_;
221 if (__x->__left_ != nullptr)
222 __x->__left_->__parent_ = __x;
223 __y->__parent_ = __x->__parent_;
224 if (__tree_is_left_child(__x))
225 __x->__parent_->__left_ = __y;
226 else
227 __x->__parent_->__right_ = __y;
228 __y->__right_ = __x;
229 __x->__parent_ = __y;
230}
231
232// Effects: Rebalances __root after attaching __x to a leaf.
233// Precondition: __root != nulptr && __x != nullptr.
234// __x has no children.
235// __x == __root or == a direct or indirect child of __root.
236// If __x were to be unlinked from __root (setting __root to
237// nullptr if __root == __x), __tree_invariant(__root) == true.
238// Postcondition: __tree_invariant(end_node->__left_) == true. end_node->__left_
239// may be different than the value passed in as __root.
240template <class _NodePtr>
241void
242__tree_balance_after_insert(_NodePtr __root, _NodePtr __x)
243{
244 __x->__is_black_ = __x == __root;
245 while (__x != __root && !__x->__parent_->__is_black_)
246 {
247 // __x->__parent_ != __root because __x->__parent_->__is_black == false
248 if (__tree_is_left_child(__x->__parent_))
249 {
250 _NodePtr __y = __x->__parent_->__parent_->__right_;
251 if (__y != nullptr && !__y->__is_black_)
252 {
253 __x = __x->__parent_;
254 __x->__is_black_ = true;
255 __x = __x->__parent_;
256 __x->__is_black_ = __x == __root;
257 __y->__is_black_ = true;
258 }
259 else
260 {
261 if (!__tree_is_left_child(__x))
262 {
263 __x = __x->__parent_;
264 __tree_left_rotate(__x);
265 }
266 __x = __x->__parent_;
267 __x->__is_black_ = true;
268 __x = __x->__parent_;
269 __x->__is_black_ = false;
270 __tree_right_rotate(__x);
271 break;
272 }
273 }
274 else
275 {
276 _NodePtr __y = __x->__parent_->__parent_->__left_;
277 if (__y != nullptr && !__y->__is_black_)
278 {
279 __x = __x->__parent_;
280 __x->__is_black_ = true;
281 __x = __x->__parent_;
282 __x->__is_black_ = __x == __root;
283 __y->__is_black_ = true;
284 }
285 else
286 {
287 if (__tree_is_left_child(__x))
288 {
289 __x = __x->__parent_;
290 __tree_right_rotate(__x);
291 }
292 __x = __x->__parent_;
293 __x->__is_black_ = true;
294 __x = __x->__parent_;
295 __x->__is_black_ = false;
296 __tree_left_rotate(__x);
297 break;
298 }
299 }
300 }
301}
302
303// Precondition: __root != nullptr && __z != nullptr.
304// __tree_invariant(__root) == true.
305// __z == __root or == a direct or indirect child of __root.
306// Effects: unlinks __z from the tree rooted at __root, rebalancing as needed.
307// Postcondition: __tree_invariant(end_node->__left_) == true && end_node->__left_
308// nor any of its children refer to __z. end_node->__left_
309// may be different than the value passed in as __root.
310template <class _NodePtr>
311void
312__tree_remove(_NodePtr __root, _NodePtr __z)
313{
314 // __z will be removed from the tree. Client still needs to destruct/deallocate it
315 // __y is either __z, or if __z has two children, __tree_next(__z).
316 // __y will have at most one child.
317 // __y will be the initial hole in the tree (make the hole at a leaf)
318 _NodePtr __y = (__z->__left_ == nullptr || __z->__right_ == nullptr) ?
319 __z : __tree_next(__z);
320 // __x is __y's possibly null single child
321 _NodePtr __x = __y->__left_ != nullptr ? __y->__left_ : __y->__right_;
322 // __w is __x's possibly null uncle (will become __x's sibling)
323 _NodePtr __w = nullptr;
324 // link __x to __y's parent, and find __w
325 if (__x != nullptr)
326 __x->__parent_ = __y->__parent_;
327 if (__tree_is_left_child(__y))
328 {
329 __y->__parent_->__left_ = __x;
330 if (__y != __root)
331 __w = __y->__parent_->__right_;
332 else
333 __root = __x; // __w == nullptr
334 }
335 else
336 {
337 __y->__parent_->__right_ = __x;
338 // __y can't be root if it is a right child
339 __w = __y->__parent_->__left_;
340 }
341 bool __removed_black = __y->__is_black_;
342 // If we didn't remove __z, do so now by splicing in __y for __z,
343 // but copy __z's color. This does not impact __x or __w.
344 if (__y != __z)
345 {
Howard Hinnant324bb032010-08-22 00:02:43 +0000346 // __z->__left_ != nulptr but __z->__right_ might == __x == nullptr
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000347 __y->__parent_ = __z->__parent_;
348 if (__tree_is_left_child(__z))
349 __y->__parent_->__left_ = __y;
350 else
351 __y->__parent_->__right_ = __y;
352 __y->__left_ = __z->__left_;
353 __y->__left_->__parent_ = __y;
354 __y->__right_ = __z->__right_;
355 if (__y->__right_ != nullptr)
356 __y->__right_->__parent_ = __y;
357 __y->__is_black_ = __z->__is_black_;
358 if (__root == __z)
359 __root = __y;
360 }
361 // There is no need to rebalance if we removed a red, or if we removed
362 // the last node.
363 if (__removed_black && __root != nullptr)
364 {
365 // Rebalance:
366 // __x has an implicit black color (transferred from the removed __y)
367 // associated with it, no matter what its color is.
368 // If __x is __root (in which case it can't be null), it is supposed
369 // to be black anyway, and if it is doubly black, then the double
370 // can just be ignored.
371 // If __x is red (in which case it can't be null), then it can absorb
372 // the implicit black just by setting its color to black.
373 // Since __y was black and only had one child (which __x points to), __x
374 // is either red with no children, else null, otherwise __y would have
375 // different black heights under left and right pointers.
376 // if (__x == __root || __x != nullptr && !__x->__is_black_)
377 if (__x != nullptr)
378 __x->__is_black_ = true;
379 else
380 {
381 // Else __x isn't root, and is "doubly black", even though it may
382 // be null. __w can not be null here, else the parent would
383 // see a black height >= 2 on the __x side and a black height
384 // of 1 on the __w side (__w must be a non-null black or a red
385 // with a non-null black child).
386 while (true)
387 {
388 if (!__tree_is_left_child(__w)) // if x is left child
389 {
390 if (!__w->__is_black_)
391 {
392 __w->__is_black_ = true;
393 __w->__parent_->__is_black_ = false;
394 __tree_left_rotate(__w->__parent_);
395 // __x is still valid
396 // reset __root only if necessary
397 if (__root == __w->__left_)
398 __root = __w;
399 // reset sibling, and it still can't be null
400 __w = __w->__left_->__right_;
401 }
402 // __w->__is_black_ is now true, __w may have null children
403 if ((__w->__left_ == nullptr || __w->__left_->__is_black_) &&
404 (__w->__right_ == nullptr || __w->__right_->__is_black_))
405 {
406 __w->__is_black_ = false;
407 __x = __w->__parent_;
408 // __x can no longer be null
409 if (__x == __root || !__x->__is_black_)
410 {
411 __x->__is_black_ = true;
412 break;
413 }
414 // reset sibling, and it still can't be null
415 __w = __tree_is_left_child(__x) ?
Howard Hinnant324bb032010-08-22 00:02:43 +0000416 __x->__parent_->__right_ :
417 __x->__parent_->__left_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000418 // continue;
419 }
420 else // __w has a red child
421 {
422 if (__w->__right_ == nullptr || __w->__right_->__is_black_)
423 {
424 // __w left child is non-null and red
425 __w->__left_->__is_black_ = true;
426 __w->__is_black_ = false;
427 __tree_right_rotate(__w);
428 // __w is known not to be root, so root hasn't changed
429 // reset sibling, and it still can't be null
430 __w = __w->__parent_;
431 }
432 // __w has a right red child, left child may be null
433 __w->__is_black_ = __w->__parent_->__is_black_;
434 __w->__parent_->__is_black_ = true;
435 __w->__right_->__is_black_ = true;
436 __tree_left_rotate(__w->__parent_);
437 break;
438 }
439 }
440 else
441 {
442 if (!__w->__is_black_)
443 {
444 __w->__is_black_ = true;
445 __w->__parent_->__is_black_ = false;
446 __tree_right_rotate(__w->__parent_);
447 // __x is still valid
448 // reset __root only if necessary
449 if (__root == __w->__right_)
450 __root = __w;
451 // reset sibling, and it still can't be null
452 __w = __w->__right_->__left_;
453 }
454 // __w->__is_black_ is now true, __w may have null children
455 if ((__w->__left_ == nullptr || __w->__left_->__is_black_) &&
456 (__w->__right_ == nullptr || __w->__right_->__is_black_))
457 {
458 __w->__is_black_ = false;
459 __x = __w->__parent_;
460 // __x can no longer be null
461 if (!__x->__is_black_ || __x == __root)
462 {
463 __x->__is_black_ = true;
464 break;
465 }
466 // reset sibling, and it still can't be null
467 __w = __tree_is_left_child(__x) ?
Howard Hinnant324bb032010-08-22 00:02:43 +0000468 __x->__parent_->__right_ :
469 __x->__parent_->__left_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000470 // continue;
471 }
472 else // __w has a red child
473 {
474 if (__w->__left_ == nullptr || __w->__left_->__is_black_)
475 {
476 // __w right child is non-null and red
477 __w->__right_->__is_black_ = true;
478 __w->__is_black_ = false;
479 __tree_left_rotate(__w);
480 // __w is known not to be root, so root hasn't changed
481 // reset sibling, and it still can't be null
482 __w = __w->__parent_;
483 }
484 // __w has a left red child, right child may be null
485 __w->__is_black_ = __w->__parent_->__is_black_;
486 __w->__parent_->__is_black_ = true;
487 __w->__left_->__is_black_ = true;
488 __tree_right_rotate(__w->__parent_);
489 break;
490 }
491 }
492 }
493 }
494 }
495}
496
497template <class> class __map_node_destructor;
498
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000499template <class _Allocator>
500class __tree_node_destructor
501{
502 typedef _Allocator allocator_type;
503 typedef allocator_traits<allocator_type> __alloc_traits;
504 typedef typename __alloc_traits::value_type::value_type value_type;
505public:
506 typedef typename __alloc_traits::pointer pointer;
507private:
508
509 allocator_type& __na_;
510
511 __tree_node_destructor& operator=(const __tree_node_destructor&);
512
513public:
514 bool __value_constructed;
515
Howard Hinnant333f50d2010-09-21 20:16:37 +0000516 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000517 explicit __tree_node_destructor(allocator_type& __na)
518 : __na_(__na),
519 __value_constructed(false)
520 {}
521
Howard Hinnant333f50d2010-09-21 20:16:37 +0000522 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000523 void operator()(pointer __p)
524 {
525 if (__value_constructed)
Howard Hinnant2529d022011-02-02 17:36:20 +0000526 __alloc_traits::destroy(__na_, _STD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000527 if (__p)
528 __alloc_traits::deallocate(__na_, __p, 1);
529 }
530
531 template <class> friend class __map_node_destructor;
532};
533
534// node
535
536template <class _Pointer>
537class __tree_end_node
538{
539public:
540 typedef _Pointer pointer;
541 pointer __left_;
542
Howard Hinnant333f50d2010-09-21 20:16:37 +0000543 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000544 __tree_end_node() : __left_() {}
545};
546
547template <class _VoidPtr>
548class __tree_node_base
549 : public __tree_end_node
550 <
551 typename pointer_traits<_VoidPtr>::template
552#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
553 rebind<__tree_node_base<_VoidPtr> >
554#else
555 rebind<__tree_node_base<_VoidPtr> >::other
556#endif
557 >
558{
559 __tree_node_base(const __tree_node_base&);
560 __tree_node_base& operator=(const __tree_node_base&);
561public:
562 typedef typename pointer_traits<_VoidPtr>::template
563#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
564 rebind<__tree_node_base>
565#else
566 rebind<__tree_node_base>::other
567#endif
568 pointer;
569 typedef typename pointer_traits<_VoidPtr>::template
570#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
571 rebind<const __tree_node_base>
572#else
573 rebind<const __tree_node_base>::other
574#endif
575 const_pointer;
576 typedef __tree_end_node<pointer> base;
577
578 pointer __right_;
579 pointer __parent_;
580 bool __is_black_;
581
Howard Hinnant333f50d2010-09-21 20:16:37 +0000582 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000583 __tree_node_base() : __right_(), __parent_(), __is_black_(false) {}
584};
585
586template <class _Tp, class _VoidPtr>
587class __tree_node
588 : public __tree_node_base<_VoidPtr>
589{
590public:
591 typedef __tree_node_base<_VoidPtr> base;
592 typedef _Tp value_type;
593
594 value_type __value_;
595
Howard Hinnant73d21a42010-09-04 23:28:19 +0000596#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000597 template <class ..._Args>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000598 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000599 explicit __tree_node(_Args&& ...__args)
600 : __value_(_STD::forward<_Args>(__args)...) {}
Howard Hinnant73d21a42010-09-04 23:28:19 +0000601#else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnant333f50d2010-09-21 20:16:37 +0000602 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000603 explicit __tree_node(const value_type& __v)
604 : __value_(__v) {}
Howard Hinnant73d21a42010-09-04 23:28:19 +0000605#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000606};
607
608template <class> class __map_iterator;
609template <class> class __map_const_iterator;
610
611template <class _Tp, class _NodePtr, class _DiffType>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000612class _LIBCPP_VISIBLE __tree_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000613{
614 typedef _NodePtr __node_pointer;
615 typedef typename pointer_traits<__node_pointer>::element_type __node;
616 typedef typename __node::base __node_base;
617 typedef typename __node_base::pointer __node_base_pointer;
618
619 __node_pointer __ptr_;
620
621 typedef pointer_traits<__node_pointer> __pointer_traits;
622public:
623 typedef bidirectional_iterator_tag iterator_category;
624 typedef _Tp value_type;
625 typedef _DiffType difference_type;
626 typedef value_type& reference;
627 typedef typename pointer_traits<__node_pointer>::template
628#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
629 rebind<value_type>
630#else
631 rebind<value_type>::other
632#endif
633 pointer;
634
Howard Hinnant333f50d2010-09-21 20:16:37 +0000635 _LIBCPP_INLINE_VISIBILITY __tree_iterator() {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000636
Howard Hinnant333f50d2010-09-21 20:16:37 +0000637 _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;}
638 _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return &__ptr_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000639
Howard Hinnant333f50d2010-09-21 20:16:37 +0000640 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000641 __tree_iterator& operator++()
642 {__ptr_ = static_cast<__node_pointer>(__tree_next(static_cast<__node_base_pointer>(__ptr_)));
643 return *this;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000644 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000645 __tree_iterator operator++(int)
646 {__tree_iterator __t(*this); ++(*this); return __t;}
647
Howard Hinnant333f50d2010-09-21 20:16:37 +0000648 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000649 __tree_iterator& operator--()
650 {__ptr_ = static_cast<__node_pointer>(__tree_prev(static_cast<__node_base_pointer>(__ptr_)));
651 return *this;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000652 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000653 __tree_iterator operator--(int)
654 {__tree_iterator __t(*this); --(*this); return __t;}
655
Howard Hinnant333f50d2010-09-21 20:16:37 +0000656 friend _LIBCPP_INLINE_VISIBILITY
657 bool operator==(const __tree_iterator& __x, const __tree_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000658 {return __x.__ptr_ == __y.__ptr_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000659 friend _LIBCPP_INLINE_VISIBILITY
660 bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000661 {return !(__x == __y);}
662
663private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000664 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000665 explicit __tree_iterator(__node_pointer __p) : __ptr_(__p) {}
666 template <class, class, class> friend class __tree;
Howard Hinnant333f50d2010-09-21 20:16:37 +0000667 template <class, class, class> friend class _LIBCPP_VISIBLE __tree_const_iterator;
668 template <class> friend class _LIBCPP_VISIBLE __map_iterator;
669 template <class, class, class, class> friend class _LIBCPP_VISIBLE map;
670 template <class, class, class, class> friend class _LIBCPP_VISIBLE multimap;
671 template <class, class, class> friend class _LIBCPP_VISIBLE set;
672 template <class, class, class> friend class _LIBCPP_VISIBLE multiset;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000673};
674
675template <class _Tp, class _ConstNodePtr, class _DiffType>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000676class _LIBCPP_VISIBLE __tree_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000677{
678 typedef _ConstNodePtr __node_pointer;
679 typedef typename pointer_traits<__node_pointer>::element_type __node;
680 typedef const typename __node::base __node_base;
681 typedef typename pointer_traits<__node_pointer>::template
682#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
683 rebind<__node_base>
684#else
685 rebind<__node_base>::other
686#endif
687 __node_base_pointer;
688
689 __node_pointer __ptr_;
690
691 typedef pointer_traits<__node_pointer> __pointer_traits;
692public:
693 typedef bidirectional_iterator_tag iterator_category;
694 typedef _Tp value_type;
695 typedef _DiffType difference_type;
696 typedef const value_type& reference;
697 typedef typename pointer_traits<__node_pointer>::template
698#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
699 rebind<const value_type>
700#else
701 rebind<const value_type>::other
702#endif
703 pointer;
704
Howard Hinnant333f50d2010-09-21 20:16:37 +0000705 _LIBCPP_INLINE_VISIBILITY __tree_const_iterator() {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000706private:
707 typedef typename remove_const<__node>::type __non_const_node;
708 typedef typename pointer_traits<__node_pointer>::template
709#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
710 rebind<__non_const_node>
711#else
712 rebind<__non_const_node>::other
713#endif
714 __non_const_node_pointer;
715 typedef __tree_iterator<value_type, __non_const_node_pointer, difference_type>
716 __non_const_iterator;
717public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000718 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000719 __tree_const_iterator(__non_const_iterator __p) : __ptr_(__p.__ptr_) {}
720
Howard Hinnant333f50d2010-09-21 20:16:37 +0000721 _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;}
722 _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return &__ptr_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000723
Howard Hinnant333f50d2010-09-21 20:16:37 +0000724 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000725 __tree_const_iterator& operator++()
726 {__ptr_ = static_cast<__node_pointer>(__tree_next(static_cast<__node_base_pointer>(__ptr_)));
727 return *this;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000728 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000729 __tree_const_iterator operator++(int)
730 {__tree_const_iterator __t(*this); ++(*this); return __t;}
731
Howard Hinnant333f50d2010-09-21 20:16:37 +0000732 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000733 __tree_const_iterator& operator--()
734 {__ptr_ = static_cast<__node_pointer>(__tree_prev(static_cast<__node_base_pointer>(__ptr_)));
735 return *this;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000736 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000737 __tree_const_iterator operator--(int)
738 {__tree_const_iterator __t(*this); --(*this); return __t;}
739
Howard Hinnant333f50d2010-09-21 20:16:37 +0000740 friend _LIBCPP_INLINE_VISIBILITY
741 bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000742 {return __x.__ptr_ == __y.__ptr_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000743 friend _LIBCPP_INLINE_VISIBILITY
744 bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000745 {return !(__x == __y);}
746
747private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000748 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000749 explicit __tree_const_iterator(__node_pointer __p) : __ptr_(__p) {}
750 template <class, class, class> friend class __tree;
Howard Hinnant333f50d2010-09-21 20:16:37 +0000751 template <class, class, class, class> friend class _LIBCPP_VISIBLE map;
752 template <class, class, class, class> friend class _LIBCPP_VISIBLE multimap;
753 template <class, class, class> friend class _LIBCPP_VISIBLE set;
754 template <class, class, class> friend class _LIBCPP_VISIBLE multiset;
755 template <class> friend class _LIBCPP_VISIBLE __map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000756};
757
758template <class _Tp, class _Compare, class _Allocator>
759class __tree
760{
761public:
762 typedef _Tp value_type;
763 typedef _Compare value_compare;
764 typedef _Allocator allocator_type;
765 typedef allocator_traits<allocator_type> __alloc_traits;
766 typedef typename __alloc_traits::pointer pointer;
767 typedef typename __alloc_traits::const_pointer const_pointer;
768 typedef typename __alloc_traits::size_type size_type;
769 typedef typename __alloc_traits::difference_type difference_type;
770
771 typedef __tree_node<value_type, typename __alloc_traits::void_pointer> __node;
772 typedef typename __alloc_traits::template
773#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
774 rebind_alloc<__node>
775#else
776 rebind_alloc<__node>::other
777#endif
778 __node_allocator;
779 typedef allocator_traits<__node_allocator> __node_traits;
780 typedef typename __node_traits::pointer __node_pointer;
781 typedef typename __node_traits::const_pointer __node_const_pointer;
782 typedef typename __node::base::pointer __node_base_pointer;
783 typedef typename __node::base::const_pointer __node_base_const_pointer;
784private:
785 typedef typename __node::base::base __end_node_t;
786 typedef typename pointer_traits<__node_pointer>::template
787#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
788 rebind<__end_node_t>
789#else
790 rebind<__end_node_t>::other
791#endif
792 __end_node_ptr;
793 typedef typename pointer_traits<__node_pointer>::template
794#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
795 rebind<const __end_node_t>
796#else
797 rebind<const __end_node_t>::other
798#endif
799 __end_node_const_ptr;
800
801 __node_pointer __begin_node_;
802 __compressed_pair<__end_node_t, __node_allocator> __pair1_;
803 __compressed_pair<size_type, value_compare> __pair3_;
804
805public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000806 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000807 __node_pointer __end_node()
808 {
809 return static_cast<__node_pointer>
810 (
811 pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first())
812 );
813 }
Howard Hinnant333f50d2010-09-21 20:16:37 +0000814 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000815 __node_const_pointer __end_node() const
816 {
817 return static_cast<__node_const_pointer>
818 (
819 pointer_traits<__end_node_const_ptr>::pointer_to(__pair1_.first())
820 );
821 }
Howard Hinnant333f50d2010-09-21 20:16:37 +0000822 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000823 __node_allocator& __node_alloc() {return __pair1_.second();}
824private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000825 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000826 const __node_allocator& __node_alloc() const {return __pair1_.second();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000827 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000828 __node_pointer& __begin_node() {return __begin_node_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000829 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000830 const __node_pointer& __begin_node() const {return __begin_node_;}
831public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000832 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000833 allocator_type __alloc() const {return allocator_type(__node_alloc());}
834private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000835 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000836 size_type& size() {return __pair3_.first();}
837public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000838 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000839 const size_type& size() const {return __pair3_.first();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000840 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000841 value_compare& value_comp() {return __pair3_.second();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000842 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000843 const value_compare& value_comp() const {return __pair3_.second();}
844public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000845 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000846 __node_pointer __root()
847 {return static_cast<__node_pointer> (__end_node()->__left_);}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000848 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000849 __node_const_pointer __root() const
850 {return static_cast<__node_const_pointer>(__end_node()->__left_);}
851
852 typedef __tree_iterator<value_type, __node_pointer, difference_type> iterator;
853 typedef __tree_const_iterator<value_type, __node_const_pointer, difference_type> const_iterator;
854
855 explicit __tree(const value_compare& __comp);
856 explicit __tree(const allocator_type& __a);
857 __tree(const value_compare& __comp, const allocator_type& __a);
858 __tree(const __tree& __t);
859 __tree& operator=(const __tree& __t);
860 template <class _InputIterator>
861 void __assign_unique(_InputIterator __first, _InputIterator __last);
862 template <class _InputIterator>
863 void __assign_multi(_InputIterator __first, _InputIterator __last);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000864#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000865 __tree(__tree&& __t);
866 __tree(__tree&& __t, const allocator_type& __a);
867 __tree& operator=(__tree&& __t);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000868#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000869
870 ~__tree();
871
Howard Hinnant333f50d2010-09-21 20:16:37 +0000872 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000873 iterator begin() {return iterator(__begin_node());}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000874 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000875 const_iterator begin() const {return const_iterator(__begin_node());}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000876 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000877 iterator end() {return iterator(__end_node());}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000878 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000879 const_iterator end() const {return const_iterator(__end_node());}
880
Howard Hinnant333f50d2010-09-21 20:16:37 +0000881 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000882 size_type max_size() const {return __node_traits::max_size(__node_alloc());}
883
884 void clear();
885
886 void swap(__tree& __t);
887
Howard Hinnant73d21a42010-09-04 23:28:19 +0000888#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
889#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000890 template <class... _Args>
891 pair<iterator, bool>
892 __emplace_unique(_Args&&... __args);
893 template <class... _Args>
894 iterator
895 __emplace_multi(_Args&&... __args);
896
897 template <class... _Args>
898 iterator
899 __emplace_hint_unique(const_iterator __p, _Args&&... __args);
900 template <class... _Args>
901 iterator
902 __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000903#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000904
905 template <class _V>
906 pair<iterator, bool> __insert_unique(_V&& __v);
907 template <class _V>
908 iterator __insert_unique(const_iterator __p, _V&& __v);
909 template <class _V>
910 iterator __insert_multi(_V&& __v);
911 template <class _V>
912 iterator __insert_multi(const_iterator __p, _V&& __v);
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +0000913#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000914
915 pair<iterator, bool> __insert_unique(const value_type& __v);
916 iterator __insert_unique(const_iterator __p, const value_type& __v);
917 iterator __insert_multi(const value_type& __v);
918 iterator __insert_multi(const_iterator __p, const value_type& __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000919
920 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
921 iterator __node_insert_unique(const_iterator __p,
922 __node_pointer __nd);
923
924 iterator __node_insert_multi(__node_pointer __nd);
925 iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
926
927 iterator erase(const_iterator __p);
928 iterator erase(const_iterator __f, const_iterator __l);
929 template <class _Key>
930 size_type __erase_unique(const _Key& __k);
931 template <class _Key>
932 size_type __erase_multi(const _Key& __k);
933
934 void __insert_node_at(__node_base_pointer __parent,
935 __node_base_pointer& __child,
936 __node_base_pointer __new_node);
937
938 template <class _Key>
939 iterator find(const _Key& __v);
940 template <class _Key>
941 const_iterator find(const _Key& __v) const;
942
943 template <class _Key>
944 size_type __count_unique(const _Key& __k) const;
945 template <class _Key>
946 size_type __count_multi(const _Key& __k) const;
947
948 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000949 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000950 iterator lower_bound(const _Key& __v)
951 {return __lower_bound(__v, __root(), __end_node());}
952 template <class _Key>
953 iterator __lower_bound(const _Key& __v,
954 __node_pointer __root,
955 __node_pointer __result);
956 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000957 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000958 const_iterator lower_bound(const _Key& __v) const
959 {return __lower_bound(__v, __root(), __end_node());}
960 template <class _Key>
961 const_iterator __lower_bound(const _Key& __v,
962 __node_const_pointer __root,
963 __node_const_pointer __result) const;
964 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000965 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000966 iterator upper_bound(const _Key& __v)
967 {return __upper_bound(__v, __root(), __end_node());}
968 template <class _Key>
969 iterator __upper_bound(const _Key& __v,
970 __node_pointer __root,
971 __node_pointer __result);
972 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000973 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000974 const_iterator upper_bound(const _Key& __v) const
975 {return __upper_bound(__v, __root(), __end_node());}
976 template <class _Key>
977 const_iterator __upper_bound(const _Key& __v,
978 __node_const_pointer __root,
979 __node_const_pointer __result) const;
980 template <class _Key>
981 pair<iterator, iterator>
982 __equal_range_unique(const _Key& __k);
983 template <class _Key>
984 pair<const_iterator, const_iterator>
985 __equal_range_unique(const _Key& __k) const;
986
987 template <class _Key>
988 pair<iterator, iterator>
989 __equal_range_multi(const _Key& __k);
990 template <class _Key>
991 pair<const_iterator, const_iterator>
992 __equal_range_multi(const _Key& __k) const;
993
994 typedef __tree_node_destructor<__node_allocator> _D;
995 typedef unique_ptr<__node, _D> __node_holder;
996
997 __node_holder remove(const_iterator __p);
998private:
999 typename __node::base::pointer&
1000 __find_leaf_low(typename __node::base::pointer& __parent, const value_type& __v);
1001 typename __node::base::pointer&
1002 __find_leaf_high(typename __node::base::pointer& __parent, const value_type& __v);
1003 typename __node::base::pointer&
1004 __find_leaf(const_iterator __hint,
1005 typename __node::base::pointer& __parent, const value_type& __v);
1006 template <class _Key>
1007 typename __node::base::pointer&
1008 __find_equal(typename __node::base::pointer& __parent, const _Key& __v);
1009 template <class _Key>
1010 typename __node::base::pointer&
1011 __find_equal(const_iterator __hint, typename __node::base::pointer& __parent,
1012 const _Key& __v);
1013
Howard Hinnant73d21a42010-09-04 23:28:19 +00001014#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001015 template <class ..._Args>
1016 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnant73d21a42010-09-04 23:28:19 +00001017#else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001018 __node_holder __construct_node(const value_type& __v);
1019#endif
1020
1021 void destroy(__node_pointer __nd);
1022
Howard Hinnant333f50d2010-09-21 20:16:37 +00001023 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001024 void __copy_assign_alloc(const __tree& __t)
1025 {__copy_assign_alloc(__t, integral_constant<bool,
1026 __node_traits::propagate_on_container_copy_assignment::value>());}
1027
Howard Hinnant333f50d2010-09-21 20:16:37 +00001028 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001029 void __copy_assign_alloc(const __tree& __t, true_type)
1030 {__node_alloc() = __t.__node_alloc();}
Howard Hinnant333f50d2010-09-21 20:16:37 +00001031 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001032 void __copy_assign_alloc(const __tree& __t, false_type) {}
1033
1034 void __move_assign(__tree& __t, false_type);
1035 void __move_assign(__tree& __t, true_type);
1036
Howard Hinnant333f50d2010-09-21 20:16:37 +00001037 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001038 void __move_assign_alloc(__tree& __t)
1039 {__move_assign_alloc(__t, integral_constant<bool,
1040 __node_traits::propagate_on_container_move_assignment::value>());}
1041
Howard Hinnant333f50d2010-09-21 20:16:37 +00001042 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043 void __move_assign_alloc(__tree& __t, true_type)
1044 {__node_alloc() = _STD::move(__t.__node_alloc());}
Howard Hinnant333f50d2010-09-21 20:16:37 +00001045 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001046 void __move_assign_alloc(__tree& __t, false_type) {}
1047
Howard Hinnant333f50d2010-09-21 20:16:37 +00001048 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001049 static void __swap_alloc(__node_allocator& __x, __node_allocator& __y)
1050 {__swap_alloc(__x, __y, integral_constant<bool,
1051 __node_traits::propagate_on_container_swap::value>());}
Howard Hinnant333f50d2010-09-21 20:16:37 +00001052 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001053 static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, true_type)
1054 {
1055 using _STD::swap;
1056 swap(__x, __y);
1057 }
Howard Hinnant333f50d2010-09-21 20:16:37 +00001058 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001059 static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, false_type)
1060 {}
1061
1062 __node_pointer __detach();
1063 static __node_pointer __detach(__node_pointer);
1064};
1065
1066template <class _Tp, class _Compare, class _Allocator>
1067__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp)
1068 : __pair3_(0, __comp)
1069{
1070 __begin_node() = __end_node();
1071}
1072
1073template <class _Tp, class _Compare, class _Allocator>
1074__tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a)
1075 : __pair1_(__node_allocator(__a)),
1076 __begin_node_(__node_pointer()),
1077 __pair3_(0)
1078{
1079 __begin_node() = __end_node();
1080}
1081
1082template <class _Tp, class _Compare, class _Allocator>
1083__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp,
1084 const allocator_type& __a)
1085 : __pair1_(__node_allocator(__a)),
1086 __begin_node_(__node_pointer()),
1087 __pair3_(0, __comp)
1088{
1089 __begin_node() = __end_node();
1090}
1091
1092// Precondition: size() != 0
1093template <class _Tp, class _Compare, class _Allocator>
1094typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
1095__tree<_Tp, _Compare, _Allocator>::__detach()
1096{
1097 __node_pointer __cache = __begin_node();
1098 __begin_node() = __end_node();
1099 __end_node()->__left_->__parent_ = nullptr;
1100 __end_node()->__left_ = nullptr;
1101 size() = 0;
1102 // __cache->__left_ == nullptr
1103 if (__cache->__right_ != nullptr)
1104 __cache = static_cast<__node_pointer>(__cache->__right_);
1105 // __cache->__left_ == nullptr
1106 // __cache->__right_ == nullptr
1107 return __cache;
1108}
1109
1110// Precondition: __cache != nullptr
1111// __cache->left_ == nullptr
1112// __cache->right_ == nullptr
1113// This is no longer a red-black tree
1114template <class _Tp, class _Compare, class _Allocator>
1115typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
1116__tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache)
1117{
1118 if (__cache->__parent_ == nullptr)
1119 return nullptr;
1120 if (__tree_is_left_child(__cache))
1121 {
1122 __cache->__parent_->__left_ = nullptr;
1123 __cache = static_cast<__node_pointer>(__cache->__parent_);
1124 if (__cache->__right_ == nullptr)
1125 return __cache;
1126 return static_cast<__node_pointer>(__tree_leaf(__cache->__right_));
1127 }
1128 // __cache is right child
1129 __cache->__parent_->__right_ = nullptr;
1130 __cache = static_cast<__node_pointer>(__cache->__parent_);
1131 if (__cache->__left_ == nullptr)
1132 return __cache;
1133 return static_cast<__node_pointer>(__tree_leaf(__cache->__left_));
1134}
1135
1136template <class _Tp, class _Compare, class _Allocator>
1137__tree<_Tp, _Compare, _Allocator>&
1138__tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t)
1139{
1140 if (this != &__t)
1141 {
1142 value_comp() = __t.value_comp();
1143 __copy_assign_alloc(__t);
1144 __assign_multi(__t.begin(), __t.end());
1145 }
1146 return *this;
1147}
1148
1149template <class _Tp, class _Compare, class _Allocator>
1150template <class _InputIterator>
1151void
1152__tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last)
1153{
1154 if (size() != 0)
1155 {
1156 __node_pointer __cache = __detach();
Howard Hinnantd4444702010-08-11 17:04:31 +00001157#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001158 try
1159 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001160#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001161 for (; __cache != nullptr && __first != __last; ++__first)
1162 {
1163 __cache->__value_ = *__first;
1164 __node_pointer __next = __detach(__cache);
1165 __node_insert_unique(__cache);
1166 __cache = __next;
1167 }
Howard Hinnantd4444702010-08-11 17:04:31 +00001168#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001169 }
1170 catch (...)
1171 {
1172 while (__cache->__parent_ != nullptr)
1173 __cache = static_cast<__node_pointer>(__cache->__parent_);
1174 destroy(__cache);
1175 throw;
1176 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001177#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001178 if (__cache != nullptr)
1179 {
1180 while (__cache->__parent_ != nullptr)
1181 __cache = static_cast<__node_pointer>(__cache->__parent_);
1182 destroy(__cache);
1183 }
1184 }
1185 for (; __first != __last; ++__first)
1186 __insert_unique(*__first);
1187}
1188
1189template <class _Tp, class _Compare, class _Allocator>
1190template <class _InputIterator>
1191void
1192__tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last)
1193{
1194 if (size() != 0)
1195 {
1196 __node_pointer __cache = __detach();
Howard Hinnantd4444702010-08-11 17:04:31 +00001197#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001198 try
1199 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001200#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001201 for (; __cache != nullptr && __first != __last; ++__first)
1202 {
1203 __cache->__value_ = *__first;
1204 __node_pointer __next = __detach(__cache);
1205 __node_insert_multi(__cache);
1206 __cache = __next;
1207 }
Howard Hinnantd4444702010-08-11 17:04:31 +00001208#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001209 }
1210 catch (...)
1211 {
1212 while (__cache->__parent_ != nullptr)
1213 __cache = static_cast<__node_pointer>(__cache->__parent_);
1214 destroy(__cache);
1215 throw;
1216 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001217#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001218 if (__cache != nullptr)
1219 {
1220 while (__cache->__parent_ != nullptr)
1221 __cache = static_cast<__node_pointer>(__cache->__parent_);
1222 destroy(__cache);
1223 }
1224 }
1225 for (; __first != __last; ++__first)
1226 __insert_multi(*__first);
1227}
1228
1229template <class _Tp, class _Compare, class _Allocator>
1230__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
1231 : __begin_node_(__node_pointer()),
1232 __pair1_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())),
1233 __pair3_(0, __t.value_comp())
1234{
1235 __begin_node() = __end_node();
1236}
1237
Howard Hinnant73d21a42010-09-04 23:28:19 +00001238#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001239
1240template <class _Tp, class _Compare, class _Allocator>
1241__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t)
1242 : __begin_node_(_STD::move(__t.__begin_node_)),
1243 __pair1_(_STD::move(__t.__pair1_)),
1244 __pair3_(_STD::move(__t.__pair3_))
1245{
1246 if (size() == 0)
1247 __begin_node() = __end_node();
1248 else
1249 {
1250 __end_node()->__left_->__parent_ = __end_node();
1251 __t.__begin_node() = __t.__end_node();
1252 __t.__end_node()->__left_ = nullptr;
1253 __t.size() = 0;
1254 }
1255}
1256
1257template <class _Tp, class _Compare, class _Allocator>
1258__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a)
1259 : __pair1_(__node_allocator(__a)),
1260 __pair3_(0, _STD::move(__t.value_comp()))
1261{
1262 if (__a == __t.__alloc())
1263 {
1264 if (__t.size() == 0)
1265 __begin_node() = __end_node();
1266 else
1267 {
1268 __begin_node() = __t.__begin_node();
1269 __end_node()->__left_ = __t.__end_node()->__left_;
1270 __end_node()->__left_->__parent_ = __end_node();
1271 size() = __t.size();
1272 __t.__begin_node() = __t.__end_node();
1273 __t.__end_node()->__left_ = nullptr;
1274 __t.size() = 0;
1275 }
1276 }
1277 else
1278 {
1279 __begin_node() = __end_node();
1280 }
1281}
1282
1283template <class _Tp, class _Compare, class _Allocator>
1284void
1285__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type)
1286{
1287 destroy(static_cast<__node_pointer>(__end_node()->__left_));
1288 __begin_node_ = __t.__begin_node_;
1289 __pair1_.first() = __t.__pair1_.first();
1290 __move_assign_alloc(__t);
1291 __pair3_ = _STD::move(__t.__pair3_);
1292 if (size() == 0)
1293 __begin_node() = __end_node();
1294 else
1295 {
1296 __end_node()->__left_->__parent_ = __end_node();
1297 __t.__begin_node() = __t.__end_node();
1298 __t.__end_node()->__left_ = nullptr;
1299 __t.size() = 0;
1300 }
1301}
1302
1303template <class _Tp, class _Compare, class _Allocator>
1304void
1305__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type)
1306{
1307 if (__node_alloc() == __t.__node_alloc())
1308 __move_assign(__t, true_type());
1309 else
1310 {
1311 value_comp() = _STD::move(__t.value_comp());
1312 const_iterator __e = end();
1313 if (size() != 0)
1314 {
1315 __node_pointer __cache = __detach();
Howard Hinnantd4444702010-08-11 17:04:31 +00001316#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001317 try
1318 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001319#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001320 while (__cache != nullptr && __t.size() != 0)
1321 {
1322 __cache->__value_ = _STD::move(__t.remove(__t.begin())->__value_);
1323 __node_pointer __next = __detach(__cache);
1324 __node_insert_multi(__cache);
1325 __cache = __next;
1326 }
Howard Hinnantd4444702010-08-11 17:04:31 +00001327#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001328 }
1329 catch (...)
1330 {
1331 while (__cache->__parent_ != nullptr)
1332 __cache = static_cast<__node_pointer>(__cache->__parent_);
1333 destroy(__cache);
1334 throw;
1335 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001336#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001337 if (__cache != nullptr)
1338 {
1339 while (__cache->__parent_ != nullptr)
1340 __cache = static_cast<__node_pointer>(__cache->__parent_);
1341 destroy(__cache);
1342 }
1343 }
1344 while (__t.size() != 0)
1345 __insert_multi(__e, _STD::move(__t.remove(__t.begin())->__value_));
1346 }
1347}
1348
1349template <class _Tp, class _Compare, class _Allocator>
1350__tree<_Tp, _Compare, _Allocator>&
1351__tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t)
1352{
1353 __move_assign(__t, integral_constant<bool,
1354 __node_traits::propagate_on_container_move_assignment::value>());
1355 return *this;
1356}
1357
Howard Hinnant73d21a42010-09-04 23:28:19 +00001358#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001359
1360template <class _Tp, class _Compare, class _Allocator>
1361__tree<_Tp, _Compare, _Allocator>::~__tree()
1362{
1363 destroy(__root());
1364}
1365
1366template <class _Tp, class _Compare, class _Allocator>
1367void
1368__tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd)
1369{
1370 if (__nd != nullptr)
1371 {
1372 destroy(static_cast<__node_pointer>(__nd->__left_));
1373 destroy(static_cast<__node_pointer>(__nd->__right_));
1374 __node_allocator& __na = __node_alloc();
Howard Hinnant2529d022011-02-02 17:36:20 +00001375 __node_traits::destroy(__na, _STD::addressof(__nd->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001376 __node_traits::deallocate(__na, __nd, 1);
1377 }
1378}
1379
1380template <class _Tp, class _Compare, class _Allocator>
1381void
1382__tree<_Tp, _Compare, _Allocator>::swap(__tree& __t)
1383{
1384 using _STD::swap;
1385 swap(__begin_node_, __t.__begin_node_);
1386 swap(__pair1_.first(), __t.__pair1_.first());
1387 __swap_alloc(__node_alloc(), __t.__node_alloc());
1388 __pair3_.swap(__t.__pair3_);
1389 if (size() == 0)
1390 __begin_node() = __end_node();
1391 else
1392 __end_node()->__left_->__parent_ = __end_node();
1393 if (__t.size() == 0)
1394 __t.__begin_node() = __t.__end_node();
1395 else
1396 __t.__end_node()->__left_->__parent_ = __t.__end_node();
1397}
1398
1399template <class _Tp, class _Compare, class _Allocator>
1400void
1401__tree<_Tp, _Compare, _Allocator>::clear()
1402{
1403 destroy(__root());
1404 size() = 0;
1405 __begin_node() = __end_node();
1406 __end_node()->__left_ = nullptr;
1407}
1408
1409// Find lower_bound place to insert
1410// Set __parent to parent of null leaf
1411// Return reference to null leaf
1412template <class _Tp, class _Compare, class _Allocator>
1413typename __tree<_Tp, _Compare, _Allocator>::__node::base::pointer&
1414__tree<_Tp, _Compare, _Allocator>::__find_leaf_low(typename __node::base::pointer& __parent,
1415 const value_type& __v)
1416{
1417 __node_pointer __nd = __root();
1418 if (__nd != nullptr)
1419 {
1420 while (true)
1421 {
1422 if (value_comp()(__nd->__value_, __v))
1423 {
1424 if (__nd->__right_ != nullptr)
1425 __nd = static_cast<__node_pointer>(__nd->__right_);
1426 else
1427 {
1428 __parent = __nd;
1429 return __parent->__right_;
1430 }
1431 }
1432 else
1433 {
1434 if (__nd->__left_ != nullptr)
1435 __nd = static_cast<__node_pointer>(__nd->__left_);
1436 else
1437 {
1438 __parent = __nd;
1439 return __parent->__left_;
1440 }
1441 }
1442 }
1443 }
1444 __parent = __end_node();
1445 return __parent->__left_;
1446}
1447
1448// Find upper_bound place to insert
1449// Set __parent to parent of null leaf
1450// Return reference to null leaf
1451template <class _Tp, class _Compare, class _Allocator>
1452typename __tree<_Tp, _Compare, _Allocator>::__node::base::pointer&
1453__tree<_Tp, _Compare, _Allocator>::__find_leaf_high(typename __node::base::pointer& __parent,
1454 const value_type& __v)
1455{
1456 __node_pointer __nd = __root();
1457 if (__nd != nullptr)
1458 {
1459 while (true)
1460 {
1461 if (value_comp()(__v, __nd->__value_))
1462 {
1463 if (__nd->__left_ != nullptr)
1464 __nd = static_cast<__node_pointer>(__nd->__left_);
1465 else
1466 {
1467 __parent = __nd;
1468 return __parent->__left_;
1469 }
1470 }
1471 else
1472 {
1473 if (__nd->__right_ != nullptr)
1474 __nd = static_cast<__node_pointer>(__nd->__right_);
1475 else
1476 {
1477 __parent = __nd;
1478 return __parent->__right_;
1479 }
1480 }
1481 }
1482 }
1483 __parent = __end_node();
1484 return __parent->__left_;
1485}
1486
1487// Find leaf place to insert closest to __hint
1488// First check prior to __hint.
1489// Next check after __hint.
1490// Next do O(log N) search.
1491// Set __parent to parent of null leaf
1492// Return reference to null leaf
1493template <class _Tp, class _Compare, class _Allocator>
1494typename __tree<_Tp, _Compare, _Allocator>::__node::base::pointer&
1495__tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint,
1496 typename __node::base::pointer& __parent,
1497 const value_type& __v)
1498{
1499 if (__hint == end() || !value_comp()(*__hint, __v)) // check before
1500 {
1501 // __v <= *__hint
1502 const_iterator __prior = __hint;
1503 if (__prior == begin() || !value_comp()(__v, *--__prior))
1504 {
1505 // *prev(__hint) <= __v <= *__hint
1506 if (__hint.__ptr_->__left_ == nullptr)
1507 {
1508 __parent = const_cast<__node_pointer&>(__hint.__ptr_);
1509 return __parent->__left_;
1510 }
1511 else
1512 {
1513 __parent = const_cast<__node_pointer&>(__prior.__ptr_);
1514 return __parent->__right_;
1515 }
1516 }
1517 // __v < *prev(__hint)
1518 return __find_leaf_high(__parent, __v);
1519 }
1520 // else __v > *__hint
1521 return __find_leaf_low(__parent, __v);
1522}
1523
1524// Find place to insert if __v doesn't exist
1525// Set __parent to parent of null leaf
1526// Return reference to null leaf
1527// If __v exists, set parent to node of __v and return reference to node of __v
1528template <class _Tp, class _Compare, class _Allocator>
1529template <class _Key>
1530typename __tree<_Tp, _Compare, _Allocator>::__node::base::pointer&
1531__tree<_Tp, _Compare, _Allocator>::__find_equal(typename __node::base::pointer& __parent,
1532 const _Key& __v)
1533{
1534 __node_pointer __nd = __root();
1535 if (__nd != nullptr)
1536 {
1537 while (true)
1538 {
1539 if (value_comp()(__v, __nd->__value_))
1540 {
1541 if (__nd->__left_ != nullptr)
1542 __nd = static_cast<__node_pointer>(__nd->__left_);
1543 else
1544 {
1545 __parent = __nd;
1546 return __parent->__left_;
1547 }
1548 }
1549 else if (value_comp()(__nd->__value_, __v))
1550 {
1551 if (__nd->__right_ != nullptr)
1552 __nd = static_cast<__node_pointer>(__nd->__right_);
1553 else
1554 {
1555 __parent = __nd;
1556 return __parent->__right_;
1557 }
1558 }
1559 else
1560 {
1561 __parent = __nd;
1562 return __parent;
1563 }
1564 }
1565 }
1566 __parent = __end_node();
1567 return __parent->__left_;
1568}
1569
1570// Find place to insert if __v doesn't exist
1571// First check prior to __hint.
1572// Next check after __hint.
1573// Next do O(log N) search.
1574// Set __parent to parent of null leaf
1575// Return reference to null leaf
1576// If __v exists, set parent to node of __v and return reference to node of __v
1577template <class _Tp, class _Compare, class _Allocator>
1578template <class _Key>
1579typename __tree<_Tp, _Compare, _Allocator>::__node::base::pointer&
1580__tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint,
1581 typename __node::base::pointer& __parent,
1582 const _Key& __v)
1583{
1584 if (__hint == end() || value_comp()(__v, *__hint)) // check before
1585 {
1586 // __v < *__hint
1587 const_iterator __prior = __hint;
1588 if (__prior == begin() || value_comp()(*--__prior, __v))
1589 {
1590 // *prev(__hint) < __v < *__hint
1591 if (__hint.__ptr_->__left_ == nullptr)
1592 {
1593 __parent = const_cast<__node_pointer&>(__hint.__ptr_);
1594 return __parent->__left_;
1595 }
1596 else
1597 {
1598 __parent = const_cast<__node_pointer&>(__prior.__ptr_);
1599 return __parent->__right_;
1600 }
1601 }
1602 // __v <= *prev(__hint)
1603 return __find_equal(__parent, __v);
1604 }
1605 else if (value_comp()(*__hint, __v)) // check after
1606 {
1607 // *__hint < __v
1608 const_iterator __next = _STD::next(__hint);
1609 if (__next == end() || value_comp()(__v, *__next))
1610 {
1611 // *__hint < __v < *next(__hint)
1612 if (__hint.__ptr_->__right_ == nullptr)
1613 {
1614 __parent = const_cast<__node_pointer&>(__hint.__ptr_);
1615 return __parent->__right_;
1616 }
1617 else
1618 {
1619 __parent = const_cast<__node_pointer&>(__next.__ptr_);
1620 return __parent->__left_;
1621 }
1622 }
1623 // *next(__hint) <= __v
1624 return __find_equal(__parent, __v);
1625 }
1626 // else __v == *__hint
1627 __parent = const_cast<__node_pointer&>(__hint.__ptr_);
1628 return __parent;
1629}
1630
1631template <class _Tp, class _Compare, class _Allocator>
1632void
1633__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__node_base_pointer __parent,
1634 __node_base_pointer& __child,
1635 __node_base_pointer __new_node)
1636{
1637 __new_node->__left_ = nullptr;
1638 __new_node->__right_ = nullptr;
1639 __new_node->__parent_ = __parent;
1640 __child = __new_node;
1641 if (__begin_node()->__left_ != nullptr)
1642 __begin_node() = static_cast<__node_pointer>(__begin_node()->__left_);
1643 __tree_balance_after_insert(__end_node()->__left_, __child);
1644 ++size();
1645}
1646
Howard Hinnant73d21a42010-09-04 23:28:19 +00001647#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1648#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001649
1650template <class _Tp, class _Compare, class _Allocator>
1651template <class ..._Args>
1652typename __tree<_Tp, _Compare, _Allocator>::__node_holder
1653__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args)
1654{
1655 __node_allocator& __na = __node_alloc();
1656 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant2529d022011-02-02 17:36:20 +00001657 __node_traits::construct(__na, _STD::addressof(__h->__value_), _STD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001658 __h.get_deleter().__value_constructed = true;
1659 return __h;
1660}
1661
1662template <class _Tp, class _Compare, class _Allocator>
1663template <class... _Args>
1664pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1665__tree<_Tp, _Compare, _Allocator>::__emplace_unique(_Args&&... __args)
1666{
1667 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1668 __node_base_pointer __parent;
1669 __node_base_pointer& __child = __find_equal(__parent, __h->__value_);
1670 __node_pointer __r = static_cast<__node_pointer>(__child);
1671 bool __inserted = false;
1672 if (__child == nullptr)
1673 {
1674 __insert_node_at(__parent, __child, __h.get());
1675 __r = __h.release();
1676 __inserted = true;
1677 }
1678 return pair<iterator, bool>(iterator(__r), __inserted);
1679}
1680
1681template <class _Tp, class _Compare, class _Allocator>
1682template <class... _Args>
1683typename __tree<_Tp, _Compare, _Allocator>::iterator
1684__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique(const_iterator __p, _Args&&... __args)
1685{
1686 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1687 __node_base_pointer __parent;
1688 __node_base_pointer& __child = __find_equal(__p, __parent, __h->__value_);
1689 __node_pointer __r = static_cast<__node_pointer>(__child);
1690 if (__child == nullptr)
1691 {
1692 __insert_node_at(__parent, __child, __h.get());
1693 __r = __h.release();
1694 }
1695 return iterator(__r);
1696}
1697
1698template <class _Tp, class _Compare, class _Allocator>
1699template <class... _Args>
1700typename __tree<_Tp, _Compare, _Allocator>::iterator
1701__tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args)
1702{
1703 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1704 __node_base_pointer __parent;
1705 __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
1706 __insert_node_at(__parent, __child, __h.get());
1707 return iterator(static_cast<__node_pointer>(__h.release()));
1708}
1709
1710template <class _Tp, class _Compare, class _Allocator>
1711template <class... _Args>
1712typename __tree<_Tp, _Compare, _Allocator>::iterator
1713__tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p,
1714 _Args&&... __args)
1715{
1716 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1717 __node_base_pointer __parent;
1718 __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
1719 __insert_node_at(__parent, __child, __h.get());
1720 return iterator(static_cast<__node_pointer>(__h.release()));
1721}
1722
Howard Hinnant73d21a42010-09-04 23:28:19 +00001723#endif // _LIBCPP_HAS_NO_VARIADICS
1724
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001725template <class _Tp, class _Compare, class _Allocator>
1726template <class _V>
1727pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1728__tree<_Tp, _Compare, _Allocator>::__insert_unique(_V&& __v)
1729{
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001730 __node_holder __h = __construct_node(_STD::forward<_V>(__v));
1731 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1732 if (__r.second)
1733 __h.release();
1734 return __r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001735}
1736
1737template <class _Tp, class _Compare, class _Allocator>
1738template <class _V>
1739typename __tree<_Tp, _Compare, _Allocator>::iterator
1740__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, _V&& __v)
1741{
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001742 __node_holder __h = __construct_node(_STD::forward<_V>(__v));
1743 iterator __r = __node_insert_unique(__p, __h.get());
1744 if (__r.__ptr_ == __h.get())
1745 __h.release();
1746 return __r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001747}
1748
1749template <class _Tp, class _Compare, class _Allocator>
1750template <class _V>
1751typename __tree<_Tp, _Compare, _Allocator>::iterator
1752__tree<_Tp, _Compare, _Allocator>::__insert_multi(_V&& __v)
1753{
1754 __node_holder __h = __construct_node(_STD::forward<_V>(__v));
1755 __node_base_pointer __parent;
1756 __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
1757 __insert_node_at(__parent, __child, __h.get());
1758 return iterator(__h.release());
1759}
1760
1761template <class _Tp, class _Compare, class _Allocator>
1762template <class _V>
1763typename __tree<_Tp, _Compare, _Allocator>::iterator
1764__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, _V&& __v)
1765{
1766 __node_holder __h = __construct_node(_STD::forward<_V>(__v));
1767 __node_base_pointer __parent;
1768 __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
1769 __insert_node_at(__parent, __child, __h.get());
1770 return iterator(__h.release());
1771}
1772
Howard Hinnant73d21a42010-09-04 23:28:19 +00001773#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001774
1775template <class _Tp, class _Compare, class _Allocator>
1776typename __tree<_Tp, _Compare, _Allocator>::__node_holder
1777__tree<_Tp, _Compare, _Allocator>::__construct_node(const value_type& __v)
1778{
1779 __node_allocator& __na = __node_alloc();
1780 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant2529d022011-02-02 17:36:20 +00001781 __node_traits::construct(__na, _STD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001782 __h.get_deleter().__value_constructed = true;
1783 return _STD::move(__h);
1784}
1785
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001786#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
1787
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001788template <class _Tp, class _Compare, class _Allocator>
1789pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1790__tree<_Tp, _Compare, _Allocator>::__insert_unique(const value_type& __v)
1791{
1792 __node_base_pointer __parent;
1793 __node_base_pointer& __child = __find_equal(__parent, __v);
1794 __node_pointer __r = static_cast<__node_pointer>(__child);
1795 bool __inserted = false;
1796 if (__child == nullptr)
1797 {
1798 __node_holder __h = __construct_node(__v);
1799 __insert_node_at(__parent, __child, __h.get());
1800 __r = __h.release();
1801 __inserted = true;
1802 }
1803 return pair<iterator, bool>(iterator(__r), __inserted);
1804}
1805
1806template <class _Tp, class _Compare, class _Allocator>
1807typename __tree<_Tp, _Compare, _Allocator>::iterator
1808__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, const value_type& __v)
1809{
1810 __node_base_pointer __parent;
1811 __node_base_pointer& __child = __find_equal(__p, __parent, __v);
1812 __node_pointer __r = static_cast<__node_pointer>(__child);
1813 if (__child == nullptr)
1814 {
1815 __node_holder __h = __construct_node(__v);
1816 __insert_node_at(__parent, __child, __h.get());
1817 __r = __h.release();
1818 }
1819 return iterator(__r);
1820}
1821
1822template <class _Tp, class _Compare, class _Allocator>
1823typename __tree<_Tp, _Compare, _Allocator>::iterator
1824__tree<_Tp, _Compare, _Allocator>::__insert_multi(const value_type& __v)
1825{
1826 __node_base_pointer __parent;
1827 __node_base_pointer& __child = __find_leaf_high(__parent, __v);
1828 __node_holder __h = __construct_node(__v);
1829 __insert_node_at(__parent, __child, __h.get());
1830 return iterator(__h.release());
1831}
1832
1833template <class _Tp, class _Compare, class _Allocator>
1834typename __tree<_Tp, _Compare, _Allocator>::iterator
1835__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const value_type& __v)
1836{
1837 __node_base_pointer __parent;
1838 __node_base_pointer& __child = __find_leaf(__p, __parent, __v);
1839 __node_holder __h = __construct_node(__v);
1840 __insert_node_at(__parent, __child, __h.get());
1841 return iterator(__h.release());
1842}
1843
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001844template <class _Tp, class _Compare, class _Allocator>
1845pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1846__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd)
1847{
1848 __node_base_pointer __parent;
1849 __node_base_pointer& __child = __find_equal(__parent, __nd->__value_);
1850 __node_pointer __r = static_cast<__node_pointer>(__child);
1851 bool __inserted = false;
1852 if (__child == nullptr)
1853 {
1854 __insert_node_at(__parent, __child, __nd);
1855 __r = __nd;
1856 __inserted = true;
1857 }
1858 return pair<iterator, bool>(iterator(__r), __inserted);
1859}
1860
1861template <class _Tp, class _Compare, class _Allocator>
1862typename __tree<_Tp, _Compare, _Allocator>::iterator
1863__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p,
1864 __node_pointer __nd)
1865{
1866 __node_base_pointer __parent;
1867 __node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_);
1868 __node_pointer __r = static_cast<__node_pointer>(__child);
1869 if (__child == nullptr)
1870 {
1871 __insert_node_at(__parent, __child, __nd);
1872 __r = __nd;
1873 }
1874 return iterator(__r);
1875}
1876
1877template <class _Tp, class _Compare, class _Allocator>
1878typename __tree<_Tp, _Compare, _Allocator>::iterator
1879__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd)
1880{
1881 __node_base_pointer __parent;
1882 __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__value_);
1883 __insert_node_at(__parent, __child, __nd);
1884 return iterator(__nd);
1885}
1886
1887template <class _Tp, class _Compare, class _Allocator>
1888typename __tree<_Tp, _Compare, _Allocator>::iterator
1889__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p,
1890 __node_pointer __nd)
1891{
1892 __node_base_pointer __parent;
1893 __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__value_);
1894 __insert_node_at(__parent, __child, __nd);
1895 return iterator(__nd);
1896}
1897
1898template <class _Tp, class _Compare, class _Allocator>
1899typename __tree<_Tp, _Compare, _Allocator>::iterator
1900__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p)
1901{
1902 __node_pointer __np = const_cast<__node_pointer>(__p.__ptr_);
1903 iterator __r(__np);
1904 ++__r;
1905 if (__begin_node() == __np)
1906 __begin_node() = __r.__ptr_;
1907 --size();
1908 __node_allocator& __na = __node_alloc();
Howard Hinnant2529d022011-02-02 17:36:20 +00001909 __node_traits::destroy(__na, const_cast<value_type*>(_STD::addressof(*__p)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001910 __tree_remove(__end_node()->__left_,
1911 static_cast<__node_base_pointer>(__np));
1912 __node_traits::deallocate(__na, __np, 1);
1913 return __r;
1914}
1915
1916template <class _Tp, class _Compare, class _Allocator>
1917typename __tree<_Tp, _Compare, _Allocator>::iterator
1918__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l)
1919{
1920 while (__f != __l)
1921 __f = erase(__f);
1922 return iterator(const_cast<__node_pointer>(__l.__ptr_));
1923}
1924
1925template <class _Tp, class _Compare, class _Allocator>
1926template <class _Key>
1927typename __tree<_Tp, _Compare, _Allocator>::size_type
1928__tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k)
1929{
1930 iterator __i = find(__k);
1931 if (__i == end())
1932 return 0;
1933 erase(__i);
1934 return 1;
1935}
1936
1937template <class _Tp, class _Compare, class _Allocator>
1938template <class _Key>
1939typename __tree<_Tp, _Compare, _Allocator>::size_type
1940__tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k)
1941{
1942 pair<iterator, iterator> __p = __equal_range_multi(__k);
1943 size_type __r = 0;
1944 for (; __p.first != __p.second; ++__r)
1945 __p.first = erase(__p.first);
1946 return __r;
1947}
1948
1949template <class _Tp, class _Compare, class _Allocator>
1950template <class _Key>
1951typename __tree<_Tp, _Compare, _Allocator>::iterator
1952__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v)
1953{
1954 iterator __p = __lower_bound(__v, __root(), __end_node());
1955 if (__p != end() && !value_comp()(__v, *__p))
1956 return __p;
1957 return end();
1958}
1959
1960template <class _Tp, class _Compare, class _Allocator>
1961template <class _Key>
1962typename __tree<_Tp, _Compare, _Allocator>::const_iterator
1963__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) const
1964{
1965 const_iterator __p = __lower_bound(__v, __root(), __end_node());
1966 if (__p != end() && !value_comp()(__v, *__p))
1967 return __p;
1968 return end();
1969}
1970
1971template <class _Tp, class _Compare, class _Allocator>
1972template <class _Key>
1973typename __tree<_Tp, _Compare, _Allocator>::size_type
1974__tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const
1975{
1976 __node_const_pointer __result = __end_node();
1977 __node_const_pointer __rt = __root();
1978 while (__rt != nullptr)
1979 {
1980 if (value_comp()(__k, __rt->__value_))
1981 {
1982 __result = __rt;
1983 __rt = static_cast<__node_const_pointer>(__rt->__left_);
1984 }
1985 else if (value_comp()(__rt->__value_, __k))
1986 __rt = static_cast<__node_const_pointer>(__rt->__right_);
1987 else
1988 return 1;
1989 }
1990 return 0;
1991}
1992
1993template <class _Tp, class _Compare, class _Allocator>
1994template <class _Key>
1995typename __tree<_Tp, _Compare, _Allocator>::size_type
1996__tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const
1997{
1998 typedef pair<const_iterator, const_iterator> _P;
1999 __node_const_pointer __result = __end_node();
2000 __node_const_pointer __rt = __root();
2001 while (__rt != nullptr)
2002 {
2003 if (value_comp()(__k, __rt->__value_))
2004 {
2005 __result = __rt;
2006 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2007 }
2008 else if (value_comp()(__rt->__value_, __k))
2009 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2010 else
2011 return _STD::distance(
2012 __lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt),
2013 __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result)
2014 );
2015 }
2016 return 0;
2017}
2018
2019template <class _Tp, class _Compare, class _Allocator>
2020template <class _Key>
2021typename __tree<_Tp, _Compare, _Allocator>::iterator
2022__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
2023 __node_pointer __root,
2024 __node_pointer __result)
2025{
2026 while (__root != nullptr)
2027 {
2028 if (!value_comp()(__root->__value_, __v))
2029 {
2030 __result = __root;
2031 __root = static_cast<__node_pointer>(__root->__left_);
2032 }
2033 else
2034 __root = static_cast<__node_pointer>(__root->__right_);
2035 }
2036 return iterator(__result);
2037}
2038
2039template <class _Tp, class _Compare, class _Allocator>
2040template <class _Key>
2041typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2042__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
2043 __node_const_pointer __root,
2044 __node_const_pointer __result) const
2045{
2046 while (__root != nullptr)
2047 {
2048 if (!value_comp()(__root->__value_, __v))
2049 {
2050 __result = __root;
2051 __root = static_cast<__node_const_pointer>(__root->__left_);
2052 }
2053 else
2054 __root = static_cast<__node_const_pointer>(__root->__right_);
2055 }
2056 return const_iterator(__result);
2057}
2058
2059template <class _Tp, class _Compare, class _Allocator>
2060template <class _Key>
2061typename __tree<_Tp, _Compare, _Allocator>::iterator
2062__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
2063 __node_pointer __root,
2064 __node_pointer __result)
2065{
2066 while (__root != nullptr)
2067 {
2068 if (value_comp()(__v, __root->__value_))
2069 {
2070 __result = __root;
2071 __root = static_cast<__node_pointer>(__root->__left_);
2072 }
2073 else
2074 __root = static_cast<__node_pointer>(__root->__right_);
2075 }
2076 return iterator(__result);
2077}
2078
2079template <class _Tp, class _Compare, class _Allocator>
2080template <class _Key>
2081typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2082__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
2083 __node_const_pointer __root,
2084 __node_const_pointer __result) const
2085{
2086 while (__root != nullptr)
2087 {
2088 if (value_comp()(__v, __root->__value_))
2089 {
2090 __result = __root;
2091 __root = static_cast<__node_const_pointer>(__root->__left_);
2092 }
2093 else
2094 __root = static_cast<__node_const_pointer>(__root->__right_);
2095 }
2096 return const_iterator(__result);
2097}
2098
2099template <class _Tp, class _Compare, class _Allocator>
2100template <class _Key>
2101pair<typename __tree<_Tp, _Compare, _Allocator>::iterator,
2102 typename __tree<_Tp, _Compare, _Allocator>::iterator>
2103__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k)
2104{
2105 typedef pair<iterator, iterator> _P;
2106 __node_pointer __result = __end_node();
2107 __node_pointer __rt = __root();
2108 while (__rt != nullptr)
2109 {
2110 if (value_comp()(__k, __rt->__value_))
2111 {
2112 __result = __rt;
2113 __rt = static_cast<__node_pointer>(__rt->__left_);
2114 }
2115 else if (value_comp()(__rt->__value_, __k))
2116 __rt = static_cast<__node_pointer>(__rt->__right_);
2117 else
2118 return _P(iterator(__rt),
2119 iterator(
2120 __rt->__right_ != nullptr ?
2121 static_cast<__node_pointer>(__tree_min(__rt->__right_))
2122 : __result));
2123 }
2124 return _P(iterator(__result), iterator(__result));
2125}
2126
2127template <class _Tp, class _Compare, class _Allocator>
2128template <class _Key>
2129pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
2130 typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
2131__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const
2132{
2133 typedef pair<const_iterator, const_iterator> _P;
2134 __node_const_pointer __result = __end_node();
2135 __node_const_pointer __rt = __root();
2136 while (__rt != nullptr)
2137 {
2138 if (value_comp()(__k, __rt->__value_))
2139 {
2140 __result = __rt;
2141 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2142 }
2143 else if (value_comp()(__rt->__value_, __k))
2144 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2145 else
2146 return _P(const_iterator(__rt),
2147 const_iterator(
2148 __rt->__right_ != nullptr ?
2149 static_cast<__node_const_pointer>(__tree_min(__rt->__right_))
2150 : __result));
2151 }
2152 return _P(const_iterator(__result), const_iterator(__result));
2153}
2154
2155template <class _Tp, class _Compare, class _Allocator>
2156template <class _Key>
2157pair<typename __tree<_Tp, _Compare, _Allocator>::iterator,
2158 typename __tree<_Tp, _Compare, _Allocator>::iterator>
2159__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k)
2160{
2161 typedef pair<iterator, iterator> _P;
2162 __node_pointer __result = __end_node();
2163 __node_pointer __rt = __root();
2164 while (__rt != nullptr)
2165 {
2166 if (value_comp()(__k, __rt->__value_))
2167 {
2168 __result = __rt;
2169 __rt = static_cast<__node_pointer>(__rt->__left_);
2170 }
2171 else if (value_comp()(__rt->__value_, __k))
2172 __rt = static_cast<__node_pointer>(__rt->__right_);
2173 else
2174 return _P(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt),
2175 __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
2176 }
2177 return _P(iterator(__result), iterator(__result));
2178}
2179
2180template <class _Tp, class _Compare, class _Allocator>
2181template <class _Key>
2182pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
2183 typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
2184__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const
2185{
2186 typedef pair<const_iterator, const_iterator> _P;
2187 __node_const_pointer __result = __end_node();
2188 __node_const_pointer __rt = __root();
2189 while (__rt != nullptr)
2190 {
2191 if (value_comp()(__k, __rt->__value_))
2192 {
2193 __result = __rt;
2194 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2195 }
2196 else if (value_comp()(__rt->__value_, __k))
2197 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2198 else
2199 return _P(__lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt),
2200 __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result));
2201 }
2202 return _P(const_iterator(__result), const_iterator(__result));
2203}
2204
2205template <class _Tp, class _Compare, class _Allocator>
2206typename __tree<_Tp, _Compare, _Allocator>::__node_holder
2207__tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p)
2208{
2209 __node_pointer __np = const_cast<__node_pointer>(__p.__ptr_);
2210 if (__begin_node() == __np)
2211 {
2212 if (__np->__right_ != nullptr)
2213 __begin_node() = static_cast<__node_pointer>(__np->__right_);
2214 else
2215 __begin_node() = static_cast<__node_pointer>(__np->__parent_);
2216 }
2217 --size();
2218 __tree_remove(__end_node()->__left_,
2219 static_cast<__node_base_pointer>(__np));
2220 return __node_holder(__np, _D(__node_alloc()));
2221}
2222
2223_LIBCPP_END_NAMESPACE_STD
2224
2225#endif // _LIBCPP___TREE