blob: 6c4b6e60ae787b530b376f21388b12b84128a949 [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
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000024template <class _Tp, class _Compare, class _Allocator> class __tree;
25template <class _Tp, class _NodePtr, class _DiffType>
26 class _LIBCPP_VISIBLE __tree_iterator;
27template <class _Tp, class _ConstNodePtr, class _DiffType>
28 class _LIBCPP_VISIBLE __tree_const_iterator;
29template <class _Key, class _Tp, class _Compare, class _Allocator>
30 class _LIBCPP_VISIBLE map;
31template <class _Key, class _Tp, class _Compare, class _Allocator>
32 class _LIBCPP_VISIBLE multimap;
33template <class _Key, class _Compare, class _Allocator>
34 class _LIBCPP_VISIBLE set;
35template <class _Key, class _Compare, class _Allocator>
36 class _LIBCPP_VISIBLE multiset;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000037
38/*
39
40_NodePtr algorithms
41
42The algorithms taking _NodePtr are red black tree algorithms. Those
43algorithms taking a parameter named __root should assume that __root
44points to a proper red black tree (unless otherwise specified).
45
46Each algorithm herein assumes that __root->__parent_ points to a non-null
47structure which has a member __left_ which points back to __root. No other
48member is read or written to at __root->__parent_.
49
50__root->__parent_ will be referred to below (in comments only) as end_node.
51end_node->__left_ is an externably accessible lvalue for __root, and can be
52changed by node insertion and removal (without explicit reference to end_node).
53
54All nodes (with the exception of end_node), even the node referred to as
55__root, have a non-null __parent_ field.
56
57*/
58
59// Returns: true if __x is a left child of its parent, else false
60// Precondition: __x != nullptr.
61template <class _NodePtr>
Howard Hinnant333f50d2010-09-21 20:16:37 +000062inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000063bool
Howard Hinnant8b537682011-06-04 17:10:24 +000064__tree_is_left_child(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000065{
66 return __x == __x->__parent_->__left_;
67}
68
69// Determintes if the subtree rooted at __x is a proper red black subtree. If
70// __x is a proper subtree, returns the black height (null counts as 1). If
71// __x is an improper subtree, returns 0.
72template <class _NodePtr>
73unsigned
74__tree_sub_invariant(_NodePtr __x)
75{
76 if (__x == nullptr)
77 return 1;
78 // parent consistency checked by caller
79 // check __x->__left_ consistency
80 if (__x->__left_ != nullptr && __x->__left_->__parent_ != __x)
81 return 0;
82 // check __x->__right_ consistency
83 if (__x->__right_ != nullptr && __x->__right_->__parent_ != __x)
84 return 0;
85 // check __x->__left_ != __x->__right_ unless both are nullptr
86 if (__x->__left_ == __x->__right_ && __x->__left_ != nullptr)
87 return 0;
88 // If this is red, neither child can be red
89 if (!__x->__is_black_)
90 {
91 if (__x->__left_ && !__x->__left_->__is_black_)
92 return 0;
93 if (__x->__right_ && !__x->__right_->__is_black_)
94 return 0;
95 }
96 unsigned __h = __tree_sub_invariant(__x->__left_);
97 if (__h == 0)
98 return 0; // invalid left subtree
99 if (__h != __tree_sub_invariant(__x->__right_))
100 return 0; // invalid or different height right subtree
101 return __h + __x->__is_black_; // return black height of this node
102}
103
104// Determintes if the red black tree rooted at __root is a proper red black tree.
105// __root == nullptr is a proper tree. Returns true is __root is a proper
106// red black tree, else returns false.
107template <class _NodePtr>
108bool
109__tree_invariant(_NodePtr __root)
110{
111 if (__root == nullptr)
112 return true;
113 // check __x->__parent_ consistency
114 if (__root->__parent_ == nullptr)
115 return false;
116 if (!__tree_is_left_child(__root))
117 return false;
118 // root must be black
119 if (!__root->__is_black_)
120 return false;
121 // do normal node checks
122 return __tree_sub_invariant(__root) != 0;
123}
124
125// Returns: pointer to the left-most node under __x.
126// Precondition: __x != nullptr.
127template <class _NodePtr>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000128inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000129_NodePtr
Howard Hinnant8b537682011-06-04 17:10:24 +0000130__tree_min(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000131{
132 while (__x->__left_ != nullptr)
133 __x = __x->__left_;
134 return __x;
135}
136
137// Returns: pointer to the right-most node under __x.
138// Precondition: __x != nullptr.
139template <class _NodePtr>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000140inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000141_NodePtr
Howard Hinnant8b537682011-06-04 17:10:24 +0000142__tree_max(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000143{
144 while (__x->__right_ != nullptr)
145 __x = __x->__right_;
146 return __x;
147}
148
149// Returns: pointer to the next in-order node after __x.
150// Precondition: __x != nullptr.
151template <class _NodePtr>
152_NodePtr
Howard Hinnant8b537682011-06-04 17:10:24 +0000153__tree_next(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000154{
155 if (__x->__right_ != nullptr)
156 return __tree_min(__x->__right_);
157 while (!__tree_is_left_child(__x))
158 __x = __x->__parent_;
159 return __x->__parent_;
160}
161
162// Returns: pointer to the previous in-order node before __x.
163// Precondition: __x != nullptr.
164template <class _NodePtr>
165_NodePtr
Howard Hinnant8b537682011-06-04 17:10:24 +0000166__tree_prev(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000167{
168 if (__x->__left_ != nullptr)
169 return __tree_max(__x->__left_);
170 while (__tree_is_left_child(__x))
171 __x = __x->__parent_;
172 return __x->__parent_;
173}
174
175// Returns: pointer to a node which has no children
176// Precondition: __x != nullptr.
177template <class _NodePtr>
178_NodePtr
Howard Hinnant8b537682011-06-04 17:10:24 +0000179__tree_leaf(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000180{
181 while (true)
182 {
183 if (__x->__left_ != nullptr)
184 {
185 __x = __x->__left_;
186 continue;
187 }
188 if (__x->__right_ != nullptr)
189 {
190 __x = __x->__right_;
191 continue;
192 }
193 break;
194 }
195 return __x;
196}
197
198// Effects: Makes __x->__right_ the subtree root with __x as its left child
199// while preserving in-order order.
200// Precondition: __x->__right_ != nullptr
201template <class _NodePtr>
202void
Howard Hinnant8b537682011-06-04 17:10:24 +0000203__tree_left_rotate(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000204{
205 _NodePtr __y = __x->__right_;
206 __x->__right_ = __y->__left_;
207 if (__x->__right_ != nullptr)
208 __x->__right_->__parent_ = __x;
209 __y->__parent_ = __x->__parent_;
210 if (__tree_is_left_child(__x))
211 __x->__parent_->__left_ = __y;
212 else
213 __x->__parent_->__right_ = __y;
214 __y->__left_ = __x;
215 __x->__parent_ = __y;
216}
217
218// Effects: Makes __x->__left_ the subtree root with __x as its right child
219// while preserving in-order order.
220// Precondition: __x->__left_ != nullptr
221template <class _NodePtr>
222void
Howard Hinnant8b537682011-06-04 17:10:24 +0000223__tree_right_rotate(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000224{
225 _NodePtr __y = __x->__left_;
226 __x->__left_ = __y->__right_;
227 if (__x->__left_ != nullptr)
228 __x->__left_->__parent_ = __x;
229 __y->__parent_ = __x->__parent_;
230 if (__tree_is_left_child(__x))
231 __x->__parent_->__left_ = __y;
232 else
233 __x->__parent_->__right_ = __y;
234 __y->__right_ = __x;
235 __x->__parent_ = __y;
236}
237
238// Effects: Rebalances __root after attaching __x to a leaf.
239// Precondition: __root != nulptr && __x != nullptr.
240// __x has no children.
241// __x == __root or == a direct or indirect child of __root.
242// If __x were to be unlinked from __root (setting __root to
243// nullptr if __root == __x), __tree_invariant(__root) == true.
244// Postcondition: __tree_invariant(end_node->__left_) == true. end_node->__left_
245// may be different than the value passed in as __root.
246template <class _NodePtr>
247void
Howard Hinnant8b537682011-06-04 17:10:24 +0000248__tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000249{
250 __x->__is_black_ = __x == __root;
251 while (__x != __root && !__x->__parent_->__is_black_)
252 {
253 // __x->__parent_ != __root because __x->__parent_->__is_black == false
254 if (__tree_is_left_child(__x->__parent_))
255 {
256 _NodePtr __y = __x->__parent_->__parent_->__right_;
257 if (__y != nullptr && !__y->__is_black_)
258 {
259 __x = __x->__parent_;
260 __x->__is_black_ = true;
261 __x = __x->__parent_;
262 __x->__is_black_ = __x == __root;
263 __y->__is_black_ = true;
264 }
265 else
266 {
267 if (!__tree_is_left_child(__x))
268 {
269 __x = __x->__parent_;
270 __tree_left_rotate(__x);
271 }
272 __x = __x->__parent_;
273 __x->__is_black_ = true;
274 __x = __x->__parent_;
275 __x->__is_black_ = false;
276 __tree_right_rotate(__x);
277 break;
278 }
279 }
280 else
281 {
282 _NodePtr __y = __x->__parent_->__parent_->__left_;
283 if (__y != nullptr && !__y->__is_black_)
284 {
285 __x = __x->__parent_;
286 __x->__is_black_ = true;
287 __x = __x->__parent_;
288 __x->__is_black_ = __x == __root;
289 __y->__is_black_ = true;
290 }
291 else
292 {
293 if (__tree_is_left_child(__x))
294 {
295 __x = __x->__parent_;
296 __tree_right_rotate(__x);
297 }
298 __x = __x->__parent_;
299 __x->__is_black_ = true;
300 __x = __x->__parent_;
301 __x->__is_black_ = false;
302 __tree_left_rotate(__x);
303 break;
304 }
305 }
306 }
307}
308
309// Precondition: __root != nullptr && __z != nullptr.
310// __tree_invariant(__root) == true.
311// __z == __root or == a direct or indirect child of __root.
312// Effects: unlinks __z from the tree rooted at __root, rebalancing as needed.
313// Postcondition: __tree_invariant(end_node->__left_) == true && end_node->__left_
314// nor any of its children refer to __z. end_node->__left_
315// may be different than the value passed in as __root.
316template <class _NodePtr>
317void
Howard Hinnant8b537682011-06-04 17:10:24 +0000318__tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000319{
320 // __z will be removed from the tree. Client still needs to destruct/deallocate it
321 // __y is either __z, or if __z has two children, __tree_next(__z).
322 // __y will have at most one child.
323 // __y will be the initial hole in the tree (make the hole at a leaf)
324 _NodePtr __y = (__z->__left_ == nullptr || __z->__right_ == nullptr) ?
325 __z : __tree_next(__z);
326 // __x is __y's possibly null single child
327 _NodePtr __x = __y->__left_ != nullptr ? __y->__left_ : __y->__right_;
328 // __w is __x's possibly null uncle (will become __x's sibling)
329 _NodePtr __w = nullptr;
330 // link __x to __y's parent, and find __w
331 if (__x != nullptr)
332 __x->__parent_ = __y->__parent_;
333 if (__tree_is_left_child(__y))
334 {
335 __y->__parent_->__left_ = __x;
336 if (__y != __root)
337 __w = __y->__parent_->__right_;
338 else
339 __root = __x; // __w == nullptr
340 }
341 else
342 {
343 __y->__parent_->__right_ = __x;
344 // __y can't be root if it is a right child
345 __w = __y->__parent_->__left_;
346 }
347 bool __removed_black = __y->__is_black_;
348 // If we didn't remove __z, do so now by splicing in __y for __z,
349 // but copy __z's color. This does not impact __x or __w.
350 if (__y != __z)
351 {
Howard Hinnant324bb032010-08-22 00:02:43 +0000352 // __z->__left_ != nulptr but __z->__right_ might == __x == nullptr
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000353 __y->__parent_ = __z->__parent_;
354 if (__tree_is_left_child(__z))
355 __y->__parent_->__left_ = __y;
356 else
357 __y->__parent_->__right_ = __y;
358 __y->__left_ = __z->__left_;
359 __y->__left_->__parent_ = __y;
360 __y->__right_ = __z->__right_;
361 if (__y->__right_ != nullptr)
362 __y->__right_->__parent_ = __y;
363 __y->__is_black_ = __z->__is_black_;
364 if (__root == __z)
365 __root = __y;
366 }
367 // There is no need to rebalance if we removed a red, or if we removed
368 // the last node.
369 if (__removed_black && __root != nullptr)
370 {
371 // Rebalance:
372 // __x has an implicit black color (transferred from the removed __y)
373 // associated with it, no matter what its color is.
374 // If __x is __root (in which case it can't be null), it is supposed
375 // to be black anyway, and if it is doubly black, then the double
376 // can just be ignored.
377 // If __x is red (in which case it can't be null), then it can absorb
378 // the implicit black just by setting its color to black.
379 // Since __y was black and only had one child (which __x points to), __x
380 // is either red with no children, else null, otherwise __y would have
381 // different black heights under left and right pointers.
382 // if (__x == __root || __x != nullptr && !__x->__is_black_)
383 if (__x != nullptr)
384 __x->__is_black_ = true;
385 else
386 {
387 // Else __x isn't root, and is "doubly black", even though it may
388 // be null. __w can not be null here, else the parent would
389 // see a black height >= 2 on the __x side and a black height
390 // of 1 on the __w side (__w must be a non-null black or a red
391 // with a non-null black child).
392 while (true)
393 {
394 if (!__tree_is_left_child(__w)) // if x is left child
395 {
396 if (!__w->__is_black_)
397 {
398 __w->__is_black_ = true;
399 __w->__parent_->__is_black_ = false;
400 __tree_left_rotate(__w->__parent_);
401 // __x is still valid
402 // reset __root only if necessary
403 if (__root == __w->__left_)
404 __root = __w;
405 // reset sibling, and it still can't be null
406 __w = __w->__left_->__right_;
407 }
408 // __w->__is_black_ is now true, __w may have null children
409 if ((__w->__left_ == nullptr || __w->__left_->__is_black_) &&
410 (__w->__right_ == nullptr || __w->__right_->__is_black_))
411 {
412 __w->__is_black_ = false;
413 __x = __w->__parent_;
414 // __x can no longer be null
415 if (__x == __root || !__x->__is_black_)
416 {
417 __x->__is_black_ = true;
418 break;
419 }
420 // reset sibling, and it still can't be null
421 __w = __tree_is_left_child(__x) ?
Howard Hinnant324bb032010-08-22 00:02:43 +0000422 __x->__parent_->__right_ :
423 __x->__parent_->__left_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000424 // continue;
425 }
426 else // __w has a red child
427 {
428 if (__w->__right_ == nullptr || __w->__right_->__is_black_)
429 {
430 // __w left child is non-null and red
431 __w->__left_->__is_black_ = true;
432 __w->__is_black_ = false;
433 __tree_right_rotate(__w);
434 // __w is known not to be root, so root hasn't changed
435 // reset sibling, and it still can't be null
436 __w = __w->__parent_;
437 }
438 // __w has a right red child, left child may be null
439 __w->__is_black_ = __w->__parent_->__is_black_;
440 __w->__parent_->__is_black_ = true;
441 __w->__right_->__is_black_ = true;
442 __tree_left_rotate(__w->__parent_);
443 break;
444 }
445 }
446 else
447 {
448 if (!__w->__is_black_)
449 {
450 __w->__is_black_ = true;
451 __w->__parent_->__is_black_ = false;
452 __tree_right_rotate(__w->__parent_);
453 // __x is still valid
454 // reset __root only if necessary
455 if (__root == __w->__right_)
456 __root = __w;
457 // reset sibling, and it still can't be null
458 __w = __w->__right_->__left_;
459 }
460 // __w->__is_black_ is now true, __w may have null children
461 if ((__w->__left_ == nullptr || __w->__left_->__is_black_) &&
462 (__w->__right_ == nullptr || __w->__right_->__is_black_))
463 {
464 __w->__is_black_ = false;
465 __x = __w->__parent_;
466 // __x can no longer be null
467 if (!__x->__is_black_ || __x == __root)
468 {
469 __x->__is_black_ = true;
470 break;
471 }
472 // reset sibling, and it still can't be null
473 __w = __tree_is_left_child(__x) ?
Howard Hinnant324bb032010-08-22 00:02:43 +0000474 __x->__parent_->__right_ :
475 __x->__parent_->__left_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000476 // continue;
477 }
478 else // __w has a red child
479 {
480 if (__w->__left_ == nullptr || __w->__left_->__is_black_)
481 {
482 // __w right child is non-null and red
483 __w->__right_->__is_black_ = true;
484 __w->__is_black_ = false;
485 __tree_left_rotate(__w);
486 // __w is known not to be root, so root hasn't changed
487 // reset sibling, and it still can't be null
488 __w = __w->__parent_;
489 }
490 // __w has a left red child, right child may be null
491 __w->__is_black_ = __w->__parent_->__is_black_;
492 __w->__parent_->__is_black_ = true;
493 __w->__left_->__is_black_ = true;
494 __tree_right_rotate(__w->__parent_);
495 break;
496 }
497 }
498 }
499 }
500 }
501}
502
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000503template <class _Allocator> class __map_node_destructor;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000504
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000505template <class _Allocator>
506class __tree_node_destructor
507{
508 typedef _Allocator allocator_type;
509 typedef allocator_traits<allocator_type> __alloc_traits;
510 typedef typename __alloc_traits::value_type::value_type value_type;
511public:
512 typedef typename __alloc_traits::pointer pointer;
513private:
514
515 allocator_type& __na_;
516
517 __tree_node_destructor& operator=(const __tree_node_destructor&);
518
519public:
520 bool __value_constructed;
521
Howard Hinnant333f50d2010-09-21 20:16:37 +0000522 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant8b537682011-06-04 17:10:24 +0000523 explicit __tree_node_destructor(allocator_type& __na) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000524 : __na_(__na),
525 __value_constructed(false)
526 {}
527
Howard Hinnant333f50d2010-09-21 20:16:37 +0000528 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant8b537682011-06-04 17:10:24 +0000529 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000530 {
531 if (__value_constructed)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000532 __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000533 if (__p)
534 __alloc_traits::deallocate(__na_, __p, 1);
535 }
536
537 template <class> friend class __map_node_destructor;
538};
539
540// node
541
542template <class _Pointer>
543class __tree_end_node
544{
545public:
546 typedef _Pointer pointer;
547 pointer __left_;
548
Howard Hinnant333f50d2010-09-21 20:16:37 +0000549 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant8b537682011-06-04 17:10:24 +0000550 __tree_end_node() _NOEXCEPT : __left_() {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000551};
552
553template <class _VoidPtr>
554class __tree_node_base
555 : public __tree_end_node
556 <
557 typename pointer_traits<_VoidPtr>::template
558#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
559 rebind<__tree_node_base<_VoidPtr> >
560#else
561 rebind<__tree_node_base<_VoidPtr> >::other
562#endif
563 >
564{
565 __tree_node_base(const __tree_node_base&);
566 __tree_node_base& operator=(const __tree_node_base&);
567public:
568 typedef typename pointer_traits<_VoidPtr>::template
569#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
570 rebind<__tree_node_base>
571#else
572 rebind<__tree_node_base>::other
573#endif
574 pointer;
575 typedef typename pointer_traits<_VoidPtr>::template
576#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
577 rebind<const __tree_node_base>
578#else
579 rebind<const __tree_node_base>::other
580#endif
581 const_pointer;
582 typedef __tree_end_node<pointer> base;
583
584 pointer __right_;
585 pointer __parent_;
586 bool __is_black_;
587
Howard Hinnant333f50d2010-09-21 20:16:37 +0000588 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant8b537682011-06-04 17:10:24 +0000589 __tree_node_base() _NOEXCEPT
590 : __right_(), __parent_(), __is_black_(false) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000591};
592
593template <class _Tp, class _VoidPtr>
594class __tree_node
595 : public __tree_node_base<_VoidPtr>
596{
597public:
598 typedef __tree_node_base<_VoidPtr> base;
599 typedef _Tp value_type;
600
601 value_type __value_;
602
Howard Hinnant73d21a42010-09-04 23:28:19 +0000603#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000604 template <class ..._Args>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000605 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000606 explicit __tree_node(_Args&& ...__args)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000607 : __value_(_VSTD::forward<_Args>(__args)...) {}
Howard Hinnant73d21a42010-09-04 23:28:19 +0000608#else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnant333f50d2010-09-21 20:16:37 +0000609 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000610 explicit __tree_node(const value_type& __v)
611 : __value_(__v) {}
Howard Hinnant73d21a42010-09-04 23:28:19 +0000612#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000613};
614
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000615template <class _TreeIterator> class __map_iterator;
616template <class _TreeIterator> class __map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000617
618template <class _Tp, class _NodePtr, class _DiffType>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000619class _LIBCPP_VISIBLE __tree_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000620{
621 typedef _NodePtr __node_pointer;
622 typedef typename pointer_traits<__node_pointer>::element_type __node;
623 typedef typename __node::base __node_base;
624 typedef typename __node_base::pointer __node_base_pointer;
625
626 __node_pointer __ptr_;
627
628 typedef pointer_traits<__node_pointer> __pointer_traits;
629public:
630 typedef bidirectional_iterator_tag iterator_category;
631 typedef _Tp value_type;
632 typedef _DiffType difference_type;
633 typedef value_type& reference;
634 typedef typename pointer_traits<__node_pointer>::template
635#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
636 rebind<value_type>
637#else
638 rebind<value_type>::other
639#endif
640 pointer;
641
Howard Hinnant7686add2011-06-04 14:31:57 +0000642 _LIBCPP_INLINE_VISIBILITY __tree_iterator() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000643
Howard Hinnant333f50d2010-09-21 20:16:37 +0000644 _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;}
645 _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return &__ptr_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000646
Howard Hinnant333f50d2010-09-21 20:16:37 +0000647 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000648 __tree_iterator& operator++()
649 {__ptr_ = static_cast<__node_pointer>(__tree_next(static_cast<__node_base_pointer>(__ptr_)));
650 return *this;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000651 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000652 __tree_iterator operator++(int)
653 {__tree_iterator __t(*this); ++(*this); return __t;}
654
Howard Hinnant333f50d2010-09-21 20:16:37 +0000655 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000656 __tree_iterator& operator--()
657 {__ptr_ = static_cast<__node_pointer>(__tree_prev(static_cast<__node_base_pointer>(__ptr_)));
658 return *this;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000659 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000660 __tree_iterator operator--(int)
661 {__tree_iterator __t(*this); --(*this); return __t;}
662
Howard Hinnant333f50d2010-09-21 20:16:37 +0000663 friend _LIBCPP_INLINE_VISIBILITY
664 bool operator==(const __tree_iterator& __x, const __tree_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000665 {return __x.__ptr_ == __y.__ptr_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000666 friend _LIBCPP_INLINE_VISIBILITY
667 bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000668 {return !(__x == __y);}
669
670private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000671 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000672 explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000673 template <class, class, class> friend class __tree;
Howard Hinnant333f50d2010-09-21 20:16:37 +0000674 template <class, class, class> friend class _LIBCPP_VISIBLE __tree_const_iterator;
675 template <class> friend class _LIBCPP_VISIBLE __map_iterator;
676 template <class, class, class, class> friend class _LIBCPP_VISIBLE map;
677 template <class, class, class, class> friend class _LIBCPP_VISIBLE multimap;
678 template <class, class, class> friend class _LIBCPP_VISIBLE set;
679 template <class, class, class> friend class _LIBCPP_VISIBLE multiset;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000680};
681
682template <class _Tp, class _ConstNodePtr, class _DiffType>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000683class _LIBCPP_VISIBLE __tree_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000684{
685 typedef _ConstNodePtr __node_pointer;
686 typedef typename pointer_traits<__node_pointer>::element_type __node;
687 typedef const typename __node::base __node_base;
688 typedef typename pointer_traits<__node_pointer>::template
689#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
690 rebind<__node_base>
691#else
692 rebind<__node_base>::other
693#endif
694 __node_base_pointer;
695
696 __node_pointer __ptr_;
697
698 typedef pointer_traits<__node_pointer> __pointer_traits;
699public:
700 typedef bidirectional_iterator_tag iterator_category;
701 typedef _Tp value_type;
702 typedef _DiffType difference_type;
703 typedef const value_type& reference;
704 typedef typename pointer_traits<__node_pointer>::template
705#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
706 rebind<const value_type>
707#else
708 rebind<const value_type>::other
709#endif
710 pointer;
711
Howard Hinnant333f50d2010-09-21 20:16:37 +0000712 _LIBCPP_INLINE_VISIBILITY __tree_const_iterator() {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000713private:
714 typedef typename remove_const<__node>::type __non_const_node;
715 typedef typename pointer_traits<__node_pointer>::template
716#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
717 rebind<__non_const_node>
718#else
719 rebind<__non_const_node>::other
720#endif
721 __non_const_node_pointer;
722 typedef __tree_iterator<value_type, __non_const_node_pointer, difference_type>
723 __non_const_iterator;
724public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000725 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000726 __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT
727 : __ptr_(__p.__ptr_) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000728
Howard Hinnant333f50d2010-09-21 20:16:37 +0000729 _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;}
730 _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return &__ptr_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000731
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_next(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 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000741 __tree_const_iterator& operator--()
742 {__ptr_ = static_cast<__node_pointer>(__tree_prev(static_cast<__node_base_pointer>(__ptr_)));
743 return *this;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000744 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000745 __tree_const_iterator operator--(int)
746 {__tree_const_iterator __t(*this); --(*this); return __t;}
747
Howard Hinnant333f50d2010-09-21 20:16:37 +0000748 friend _LIBCPP_INLINE_VISIBILITY
749 bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000750 {return __x.__ptr_ == __y.__ptr_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000751 friend _LIBCPP_INLINE_VISIBILITY
752 bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000753 {return !(__x == __y);}
754
755private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000756 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000757 explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT
758 : __ptr_(__p) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000759 template <class, class, class> friend class __tree;
Howard Hinnant333f50d2010-09-21 20:16:37 +0000760 template <class, class, class, class> friend class _LIBCPP_VISIBLE map;
761 template <class, class, class, class> friend class _LIBCPP_VISIBLE multimap;
762 template <class, class, class> friend class _LIBCPP_VISIBLE set;
763 template <class, class, class> friend class _LIBCPP_VISIBLE multiset;
764 template <class> friend class _LIBCPP_VISIBLE __map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000765};
766
767template <class _Tp, class _Compare, class _Allocator>
768class __tree
769{
770public:
771 typedef _Tp value_type;
772 typedef _Compare value_compare;
773 typedef _Allocator allocator_type;
774 typedef allocator_traits<allocator_type> __alloc_traits;
775 typedef typename __alloc_traits::pointer pointer;
776 typedef typename __alloc_traits::const_pointer const_pointer;
777 typedef typename __alloc_traits::size_type size_type;
778 typedef typename __alloc_traits::difference_type difference_type;
779
780 typedef __tree_node<value_type, typename __alloc_traits::void_pointer> __node;
Howard Hinnantd615e472011-04-03 20:05:29 +0000781 typedef __tree_node_base<typename __alloc_traits::void_pointer> __node_base;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000782 typedef typename __alloc_traits::template
783#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
784 rebind_alloc<__node>
785#else
786 rebind_alloc<__node>::other
787#endif
788 __node_allocator;
789 typedef allocator_traits<__node_allocator> __node_traits;
790 typedef typename __node_traits::pointer __node_pointer;
791 typedef typename __node_traits::const_pointer __node_const_pointer;
Howard Hinnantd615e472011-04-03 20:05:29 +0000792 typedef typename __node_base::pointer __node_base_pointer;
793 typedef typename __node_base::const_pointer __node_base_const_pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000794private:
Howard Hinnantd615e472011-04-03 20:05:29 +0000795 typedef typename __node_base::base __end_node_t;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000796 typedef typename pointer_traits<__node_pointer>::template
797#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
798 rebind<__end_node_t>
799#else
800 rebind<__end_node_t>::other
801#endif
802 __end_node_ptr;
803 typedef typename pointer_traits<__node_pointer>::template
804#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
805 rebind<const __end_node_t>
806#else
807 rebind<const __end_node_t>::other
808#endif
809 __end_node_const_ptr;
810
811 __node_pointer __begin_node_;
812 __compressed_pair<__end_node_t, __node_allocator> __pair1_;
813 __compressed_pair<size_type, value_compare> __pair3_;
814
815public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000816 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000817 __node_pointer __end_node() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000818 {
819 return static_cast<__node_pointer>
820 (
821 pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first())
822 );
823 }
Howard Hinnant333f50d2010-09-21 20:16:37 +0000824 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000825 __node_const_pointer __end_node() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000826 {
827 return static_cast<__node_const_pointer>
828 (
829 pointer_traits<__end_node_const_ptr>::pointer_to(__pair1_.first())
830 );
831 }
Howard Hinnant333f50d2010-09-21 20:16:37 +0000832 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000833 __node_allocator& __node_alloc() _NOEXCEPT {return __pair1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000834private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000835 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000836 const __node_allocator& __node_alloc() const _NOEXCEPT
837 {return __pair1_.second();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000838 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000839 __node_pointer& __begin_node() _NOEXCEPT {return __begin_node_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000840 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000841 const __node_pointer& __begin_node() const _NOEXCEPT {return __begin_node_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000842public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000843 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000844 allocator_type __alloc() const _NOEXCEPT
845 {return allocator_type(__node_alloc());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000846private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000847 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000848 size_type& size() _NOEXCEPT {return __pair3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000849public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000850 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000851 const size_type& size() const _NOEXCEPT {return __pair3_.first();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000852 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000853 value_compare& value_comp() _NOEXCEPT {return __pair3_.second();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000854 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000855 const value_compare& value_comp() const _NOEXCEPT
856 {return __pair3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000857public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000858 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000859 __node_pointer __root() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000860 {return static_cast<__node_pointer> (__end_node()->__left_);}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000861 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000862 __node_const_pointer __root() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000863 {return static_cast<__node_const_pointer>(__end_node()->__left_);}
864
865 typedef __tree_iterator<value_type, __node_pointer, difference_type> iterator;
866 typedef __tree_const_iterator<value_type, __node_const_pointer, difference_type> const_iterator;
867
Howard Hinnant7686add2011-06-04 14:31:57 +0000868 explicit __tree(const value_compare& __comp)
869 _NOEXCEPT_(
870 is_nothrow_default_constructible<__node_allocator>::value &&
871 is_nothrow_copy_constructible<value_compare>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000872 explicit __tree(const allocator_type& __a);
873 __tree(const value_compare& __comp, const allocator_type& __a);
874 __tree(const __tree& __t);
875 __tree& operator=(const __tree& __t);
876 template <class _InputIterator>
877 void __assign_unique(_InputIterator __first, _InputIterator __last);
878 template <class _InputIterator>
879 void __assign_multi(_InputIterator __first, _InputIterator __last);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000880#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant7686add2011-06-04 14:31:57 +0000881 __tree(__tree&& __t)
882 _NOEXCEPT_(
883 is_nothrow_move_constructible<__node_allocator>::value &&
884 is_nothrow_move_constructible<value_compare>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000885 __tree(__tree&& __t, const allocator_type& __a);
Howard Hinnant7686add2011-06-04 14:31:57 +0000886 __tree& operator=(__tree&& __t)
887 _NOEXCEPT_(
888 __node_traits::propagate_on_container_move_assignment::value &&
889 is_nothrow_move_assignable<value_compare>::value &&
890 is_nothrow_move_assignable<__node_allocator>::value);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000891#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000892
893 ~__tree();
894
Howard Hinnant333f50d2010-09-21 20:16:37 +0000895 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000896 iterator begin() _NOEXCEPT {return iterator(__begin_node());}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000897 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000898 const_iterator begin() const _NOEXCEPT {return const_iterator(__begin_node());}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000899 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000900 iterator end() _NOEXCEPT {return iterator(__end_node());}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000901 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000902 const_iterator end() const _NOEXCEPT {return const_iterator(__end_node());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000903
Howard Hinnant333f50d2010-09-21 20:16:37 +0000904 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000905 size_type max_size() const _NOEXCEPT
906 {return __node_traits::max_size(__node_alloc());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000907
Howard Hinnant7686add2011-06-04 14:31:57 +0000908 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000909
Howard Hinnant7686add2011-06-04 14:31:57 +0000910 void swap(__tree& __t)
911 _NOEXCEPT_(
912 __is_nothrow_swappable<value_compare>::value &&
913 (!__node_traits::propagate_on_container_swap::value ||
914 __is_nothrow_swappable<__node_allocator>::value));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000915
Howard Hinnant73d21a42010-09-04 23:28:19 +0000916#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
917#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000918 template <class... _Args>
919 pair<iterator, bool>
920 __emplace_unique(_Args&&... __args);
921 template <class... _Args>
922 iterator
923 __emplace_multi(_Args&&... __args);
924
925 template <class... _Args>
926 iterator
927 __emplace_hint_unique(const_iterator __p, _Args&&... __args);
928 template <class... _Args>
929 iterator
930 __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000931#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000932
933 template <class _V>
934 pair<iterator, bool> __insert_unique(_V&& __v);
935 template <class _V>
936 iterator __insert_unique(const_iterator __p, _V&& __v);
937 template <class _V>
938 iterator __insert_multi(_V&& __v);
939 template <class _V>
940 iterator __insert_multi(const_iterator __p, _V&& __v);
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +0000941#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000942
943 pair<iterator, bool> __insert_unique(const value_type& __v);
944 iterator __insert_unique(const_iterator __p, const value_type& __v);
945 iterator __insert_multi(const value_type& __v);
946 iterator __insert_multi(const_iterator __p, const value_type& __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000947
948 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
949 iterator __node_insert_unique(const_iterator __p,
950 __node_pointer __nd);
951
952 iterator __node_insert_multi(__node_pointer __nd);
953 iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
954
955 iterator erase(const_iterator __p);
956 iterator erase(const_iterator __f, const_iterator __l);
957 template <class _Key>
958 size_type __erase_unique(const _Key& __k);
959 template <class _Key>
960 size_type __erase_multi(const _Key& __k);
961
962 void __insert_node_at(__node_base_pointer __parent,
963 __node_base_pointer& __child,
964 __node_base_pointer __new_node);
965
966 template <class _Key>
967 iterator find(const _Key& __v);
968 template <class _Key>
969 const_iterator find(const _Key& __v) const;
970
971 template <class _Key>
972 size_type __count_unique(const _Key& __k) const;
973 template <class _Key>
974 size_type __count_multi(const _Key& __k) const;
975
976 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000977 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000978 iterator lower_bound(const _Key& __v)
979 {return __lower_bound(__v, __root(), __end_node());}
980 template <class _Key>
981 iterator __lower_bound(const _Key& __v,
982 __node_pointer __root,
983 __node_pointer __result);
984 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000985 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000986 const_iterator lower_bound(const _Key& __v) const
987 {return __lower_bound(__v, __root(), __end_node());}
988 template <class _Key>
989 const_iterator __lower_bound(const _Key& __v,
990 __node_const_pointer __root,
991 __node_const_pointer __result) const;
992 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000993 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000994 iterator upper_bound(const _Key& __v)
995 {return __upper_bound(__v, __root(), __end_node());}
996 template <class _Key>
997 iterator __upper_bound(const _Key& __v,
998 __node_pointer __root,
999 __node_pointer __result);
1000 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +00001001 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001002 const_iterator upper_bound(const _Key& __v) const
1003 {return __upper_bound(__v, __root(), __end_node());}
1004 template <class _Key>
1005 const_iterator __upper_bound(const _Key& __v,
1006 __node_const_pointer __root,
1007 __node_const_pointer __result) const;
1008 template <class _Key>
1009 pair<iterator, iterator>
1010 __equal_range_unique(const _Key& __k);
1011 template <class _Key>
1012 pair<const_iterator, const_iterator>
1013 __equal_range_unique(const _Key& __k) const;
1014
1015 template <class _Key>
1016 pair<iterator, iterator>
1017 __equal_range_multi(const _Key& __k);
1018 template <class _Key>
1019 pair<const_iterator, const_iterator>
1020 __equal_range_multi(const _Key& __k) const;
1021
1022 typedef __tree_node_destructor<__node_allocator> _D;
1023 typedef unique_ptr<__node, _D> __node_holder;
1024
Howard Hinnant8b537682011-06-04 17:10:24 +00001025 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001026private:
Howard Hinnantd615e472011-04-03 20:05:29 +00001027 typename __node_base::pointer&
1028 __find_leaf_low(typename __node_base::pointer& __parent, const value_type& __v);
1029 typename __node_base::pointer&
1030 __find_leaf_high(typename __node_base::pointer& __parent, const value_type& __v);
1031 typename __node_base::pointer&
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001032 __find_leaf(const_iterator __hint,
Howard Hinnantd615e472011-04-03 20:05:29 +00001033 typename __node_base::pointer& __parent, const value_type& __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001034 template <class _Key>
Howard Hinnantd615e472011-04-03 20:05:29 +00001035 typename __node_base::pointer&
1036 __find_equal(typename __node_base::pointer& __parent, const _Key& __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001037 template <class _Key>
Howard Hinnantd615e472011-04-03 20:05:29 +00001038 typename __node_base::pointer&
1039 __find_equal(const_iterator __hint, typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001040 const _Key& __v);
1041
Howard Hinnant73d21a42010-09-04 23:28:19 +00001042#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043 template <class ..._Args>
1044 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnant73d21a42010-09-04 23:28:19 +00001045#else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001046 __node_holder __construct_node(const value_type& __v);
1047#endif
1048
Howard Hinnant7686add2011-06-04 14:31:57 +00001049 void destroy(__node_pointer __nd) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001050
Howard Hinnant333f50d2010-09-21 20:16:37 +00001051 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001052 void __copy_assign_alloc(const __tree& __t)
1053 {__copy_assign_alloc(__t, integral_constant<bool,
1054 __node_traits::propagate_on_container_copy_assignment::value>());}
1055
Howard Hinnant333f50d2010-09-21 20:16:37 +00001056 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001057 void __copy_assign_alloc(const __tree& __t, true_type)
1058 {__node_alloc() = __t.__node_alloc();}
Howard Hinnant333f50d2010-09-21 20:16:37 +00001059 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001060 void __copy_assign_alloc(const __tree& __t, false_type) {}
1061
1062 void __move_assign(__tree& __t, false_type);
Howard Hinnant7686add2011-06-04 14:31:57 +00001063 void __move_assign(__tree& __t, true_type)
1064 _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value &&
1065 is_nothrow_move_assignable<__node_allocator>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001066
Howard Hinnant333f50d2010-09-21 20:16:37 +00001067 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001068 void __move_assign_alloc(__tree& __t)
Howard Hinnant7686add2011-06-04 14:31:57 +00001069 _NOEXCEPT_(
1070 !__node_traits::propagate_on_container_move_assignment::value ||
1071 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001072 {__move_assign_alloc(__t, integral_constant<bool,
1073 __node_traits::propagate_on_container_move_assignment::value>());}
1074
Howard Hinnant333f50d2010-09-21 20:16:37 +00001075 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001076 void __move_assign_alloc(__tree& __t, true_type)
Howard Hinnant7686add2011-06-04 14:31:57 +00001077 _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001078 {__node_alloc() = _VSTD::move(__t.__node_alloc());}
Howard Hinnant333f50d2010-09-21 20:16:37 +00001079 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +00001080 void __move_assign_alloc(__tree& __t, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001081
Howard Hinnant333f50d2010-09-21 20:16:37 +00001082 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001083 static void __swap_alloc(__node_allocator& __x, __node_allocator& __y)
Howard Hinnant7686add2011-06-04 14:31:57 +00001084 _NOEXCEPT_(
1085 !__node_traits::propagate_on_container_swap::value ||
1086 __is_nothrow_swappable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001087 {__swap_alloc(__x, __y, integral_constant<bool,
1088 __node_traits::propagate_on_container_swap::value>());}
Howard Hinnant333f50d2010-09-21 20:16:37 +00001089 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001090 static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, true_type)
Howard Hinnant7686add2011-06-04 14:31:57 +00001091 _NOEXCEPT_(__is_nothrow_swappable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001092 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001093 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001094 swap(__x, __y);
1095 }
Howard Hinnant333f50d2010-09-21 20:16:37 +00001096 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001097 static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, false_type)
Howard Hinnant7686add2011-06-04 14:31:57 +00001098 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001099 {}
1100
1101 __node_pointer __detach();
1102 static __node_pointer __detach(__node_pointer);
1103};
1104
1105template <class _Tp, class _Compare, class _Allocator>
1106__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp)
Howard Hinnant7686add2011-06-04 14:31:57 +00001107 _NOEXCEPT_(
1108 is_nothrow_default_constructible<__node_allocator>::value &&
1109 is_nothrow_copy_constructible<value_compare>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001110 : __pair3_(0, __comp)
1111{
1112 __begin_node() = __end_node();
1113}
1114
1115template <class _Tp, class _Compare, class _Allocator>
1116__tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a)
1117 : __pair1_(__node_allocator(__a)),
1118 __begin_node_(__node_pointer()),
1119 __pair3_(0)
1120{
1121 __begin_node() = __end_node();
1122}
1123
1124template <class _Tp, class _Compare, class _Allocator>
1125__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp,
1126 const allocator_type& __a)
1127 : __pair1_(__node_allocator(__a)),
1128 __begin_node_(__node_pointer()),
1129 __pair3_(0, __comp)
1130{
1131 __begin_node() = __end_node();
1132}
1133
1134// Precondition: size() != 0
1135template <class _Tp, class _Compare, class _Allocator>
1136typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
1137__tree<_Tp, _Compare, _Allocator>::__detach()
1138{
1139 __node_pointer __cache = __begin_node();
1140 __begin_node() = __end_node();
1141 __end_node()->__left_->__parent_ = nullptr;
1142 __end_node()->__left_ = nullptr;
1143 size() = 0;
1144 // __cache->__left_ == nullptr
1145 if (__cache->__right_ != nullptr)
1146 __cache = static_cast<__node_pointer>(__cache->__right_);
1147 // __cache->__left_ == nullptr
1148 // __cache->__right_ == nullptr
1149 return __cache;
1150}
1151
1152// Precondition: __cache != nullptr
1153// __cache->left_ == nullptr
1154// __cache->right_ == nullptr
1155// This is no longer a red-black tree
1156template <class _Tp, class _Compare, class _Allocator>
1157typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
1158__tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache)
1159{
1160 if (__cache->__parent_ == nullptr)
1161 return nullptr;
1162 if (__tree_is_left_child(__cache))
1163 {
1164 __cache->__parent_->__left_ = nullptr;
1165 __cache = static_cast<__node_pointer>(__cache->__parent_);
1166 if (__cache->__right_ == nullptr)
1167 return __cache;
1168 return static_cast<__node_pointer>(__tree_leaf(__cache->__right_));
1169 }
1170 // __cache is right child
1171 __cache->__parent_->__right_ = nullptr;
1172 __cache = static_cast<__node_pointer>(__cache->__parent_);
1173 if (__cache->__left_ == nullptr)
1174 return __cache;
1175 return static_cast<__node_pointer>(__tree_leaf(__cache->__left_));
1176}
1177
1178template <class _Tp, class _Compare, class _Allocator>
1179__tree<_Tp, _Compare, _Allocator>&
1180__tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t)
1181{
1182 if (this != &__t)
1183 {
1184 value_comp() = __t.value_comp();
1185 __copy_assign_alloc(__t);
1186 __assign_multi(__t.begin(), __t.end());
1187 }
1188 return *this;
1189}
1190
1191template <class _Tp, class _Compare, class _Allocator>
1192template <class _InputIterator>
1193void
1194__tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last)
1195{
1196 if (size() != 0)
1197 {
1198 __node_pointer __cache = __detach();
Howard Hinnantd4444702010-08-11 17:04:31 +00001199#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200 try
1201 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001202#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001203 for (; __cache != nullptr && __first != __last; ++__first)
1204 {
1205 __cache->__value_ = *__first;
1206 __node_pointer __next = __detach(__cache);
1207 __node_insert_unique(__cache);
1208 __cache = __next;
1209 }
Howard Hinnantd4444702010-08-11 17:04:31 +00001210#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001211 }
1212 catch (...)
1213 {
1214 while (__cache->__parent_ != nullptr)
1215 __cache = static_cast<__node_pointer>(__cache->__parent_);
1216 destroy(__cache);
1217 throw;
1218 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001219#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001220 if (__cache != nullptr)
1221 {
1222 while (__cache->__parent_ != nullptr)
1223 __cache = static_cast<__node_pointer>(__cache->__parent_);
1224 destroy(__cache);
1225 }
1226 }
1227 for (; __first != __last; ++__first)
1228 __insert_unique(*__first);
1229}
1230
1231template <class _Tp, class _Compare, class _Allocator>
1232template <class _InputIterator>
1233void
1234__tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last)
1235{
1236 if (size() != 0)
1237 {
1238 __node_pointer __cache = __detach();
Howard Hinnantd4444702010-08-11 17:04:31 +00001239#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 try
1241 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001242#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001243 for (; __cache != nullptr && __first != __last; ++__first)
1244 {
1245 __cache->__value_ = *__first;
1246 __node_pointer __next = __detach(__cache);
1247 __node_insert_multi(__cache);
1248 __cache = __next;
1249 }
Howard Hinnantd4444702010-08-11 17:04:31 +00001250#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001251 }
1252 catch (...)
1253 {
1254 while (__cache->__parent_ != nullptr)
1255 __cache = static_cast<__node_pointer>(__cache->__parent_);
1256 destroy(__cache);
1257 throw;
1258 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001259#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001260 if (__cache != nullptr)
1261 {
1262 while (__cache->__parent_ != nullptr)
1263 __cache = static_cast<__node_pointer>(__cache->__parent_);
1264 destroy(__cache);
1265 }
1266 }
1267 for (; __first != __last; ++__first)
1268 __insert_multi(*__first);
1269}
1270
1271template <class _Tp, class _Compare, class _Allocator>
1272__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
1273 : __begin_node_(__node_pointer()),
1274 __pair1_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())),
1275 __pair3_(0, __t.value_comp())
1276{
1277 __begin_node() = __end_node();
1278}
1279
Howard Hinnant73d21a42010-09-04 23:28:19 +00001280#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001281
1282template <class _Tp, class _Compare, class _Allocator>
1283__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t)
Howard Hinnant7686add2011-06-04 14:31:57 +00001284 _NOEXCEPT_(
1285 is_nothrow_move_constructible<__node_allocator>::value &&
1286 is_nothrow_move_constructible<value_compare>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001287 : __begin_node_(_VSTD::move(__t.__begin_node_)),
1288 __pair1_(_VSTD::move(__t.__pair1_)),
1289 __pair3_(_VSTD::move(__t.__pair3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001290{
1291 if (size() == 0)
1292 __begin_node() = __end_node();
1293 else
1294 {
1295 __end_node()->__left_->__parent_ = __end_node();
1296 __t.__begin_node() = __t.__end_node();
1297 __t.__end_node()->__left_ = nullptr;
1298 __t.size() = 0;
1299 }
1300}
1301
1302template <class _Tp, class _Compare, class _Allocator>
1303__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a)
1304 : __pair1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:19 +00001305 __pair3_(0, _VSTD::move(__t.value_comp()))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001306{
1307 if (__a == __t.__alloc())
1308 {
1309 if (__t.size() == 0)
1310 __begin_node() = __end_node();
1311 else
1312 {
1313 __begin_node() = __t.__begin_node();
1314 __end_node()->__left_ = __t.__end_node()->__left_;
1315 __end_node()->__left_->__parent_ = __end_node();
1316 size() = __t.size();
1317 __t.__begin_node() = __t.__end_node();
1318 __t.__end_node()->__left_ = nullptr;
1319 __t.size() = 0;
1320 }
1321 }
1322 else
1323 {
1324 __begin_node() = __end_node();
1325 }
1326}
1327
1328template <class _Tp, class _Compare, class _Allocator>
1329void
1330__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type)
Howard Hinnant7686add2011-06-04 14:31:57 +00001331 _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value &&
1332 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001333{
1334 destroy(static_cast<__node_pointer>(__end_node()->__left_));
1335 __begin_node_ = __t.__begin_node_;
1336 __pair1_.first() = __t.__pair1_.first();
1337 __move_assign_alloc(__t);
Howard Hinnant0949eed2011-06-30 21:18:19 +00001338 __pair3_ = _VSTD::move(__t.__pair3_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001339 if (size() == 0)
1340 __begin_node() = __end_node();
1341 else
1342 {
1343 __end_node()->__left_->__parent_ = __end_node();
1344 __t.__begin_node() = __t.__end_node();
1345 __t.__end_node()->__left_ = nullptr;
1346 __t.size() = 0;
1347 }
1348}
1349
1350template <class _Tp, class _Compare, class _Allocator>
1351void
1352__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type)
1353{
1354 if (__node_alloc() == __t.__node_alloc())
1355 __move_assign(__t, true_type());
1356 else
1357 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001358 value_comp() = _VSTD::move(__t.value_comp());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001359 const_iterator __e = end();
1360 if (size() != 0)
1361 {
1362 __node_pointer __cache = __detach();
Howard Hinnantd4444702010-08-11 17:04:31 +00001363#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001364 try
1365 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001366#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001367 while (__cache != nullptr && __t.size() != 0)
1368 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001369 __cache->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001370 __node_pointer __next = __detach(__cache);
1371 __node_insert_multi(__cache);
1372 __cache = __next;
1373 }
Howard Hinnantd4444702010-08-11 17:04:31 +00001374#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001375 }
1376 catch (...)
1377 {
1378 while (__cache->__parent_ != nullptr)
1379 __cache = static_cast<__node_pointer>(__cache->__parent_);
1380 destroy(__cache);
1381 throw;
1382 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001383#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001384 if (__cache != nullptr)
1385 {
1386 while (__cache->__parent_ != nullptr)
1387 __cache = static_cast<__node_pointer>(__cache->__parent_);
1388 destroy(__cache);
1389 }
1390 }
1391 while (__t.size() != 0)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001392 __insert_multi(__e, _VSTD::move(__t.remove(__t.begin())->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001393 }
1394}
1395
1396template <class _Tp, class _Compare, class _Allocator>
1397__tree<_Tp, _Compare, _Allocator>&
1398__tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t)
Howard Hinnant7686add2011-06-04 14:31:57 +00001399 _NOEXCEPT_(
1400 __node_traits::propagate_on_container_move_assignment::value &&
1401 is_nothrow_move_assignable<value_compare>::value &&
1402 is_nothrow_move_assignable<__node_allocator>::value)
1403
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001404{
1405 __move_assign(__t, integral_constant<bool,
1406 __node_traits::propagate_on_container_move_assignment::value>());
1407 return *this;
1408}
1409
Howard Hinnant73d21a42010-09-04 23:28:19 +00001410#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001411
1412template <class _Tp, class _Compare, class _Allocator>
1413__tree<_Tp, _Compare, _Allocator>::~__tree()
1414{
1415 destroy(__root());
1416}
1417
1418template <class _Tp, class _Compare, class _Allocator>
1419void
Howard Hinnant7686add2011-06-04 14:31:57 +00001420__tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001421{
1422 if (__nd != nullptr)
1423 {
1424 destroy(static_cast<__node_pointer>(__nd->__left_));
1425 destroy(static_cast<__node_pointer>(__nd->__right_));
1426 __node_allocator& __na = __node_alloc();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001427 __node_traits::destroy(__na, _VSTD::addressof(__nd->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001428 __node_traits::deallocate(__na, __nd, 1);
1429 }
1430}
1431
1432template <class _Tp, class _Compare, class _Allocator>
1433void
1434__tree<_Tp, _Compare, _Allocator>::swap(__tree& __t)
Howard Hinnant7686add2011-06-04 14:31:57 +00001435 _NOEXCEPT_(
1436 __is_nothrow_swappable<value_compare>::value &&
1437 (!__node_traits::propagate_on_container_swap::value ||
1438 __is_nothrow_swappable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001439{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001440 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001441 swap(__begin_node_, __t.__begin_node_);
1442 swap(__pair1_.first(), __t.__pair1_.first());
1443 __swap_alloc(__node_alloc(), __t.__node_alloc());
1444 __pair3_.swap(__t.__pair3_);
1445 if (size() == 0)
1446 __begin_node() = __end_node();
1447 else
1448 __end_node()->__left_->__parent_ = __end_node();
1449 if (__t.size() == 0)
1450 __t.__begin_node() = __t.__end_node();
1451 else
1452 __t.__end_node()->__left_->__parent_ = __t.__end_node();
1453}
1454
1455template <class _Tp, class _Compare, class _Allocator>
1456void
Howard Hinnant7686add2011-06-04 14:31:57 +00001457__tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458{
1459 destroy(__root());
1460 size() = 0;
1461 __begin_node() = __end_node();
1462 __end_node()->__left_ = nullptr;
1463}
1464
1465// Find lower_bound place to insert
1466// Set __parent to parent of null leaf
1467// Return reference to null leaf
1468template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantd615e472011-04-03 20:05:29 +00001469typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
1470__tree<_Tp, _Compare, _Allocator>::__find_leaf_low(typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001471 const value_type& __v)
1472{
1473 __node_pointer __nd = __root();
1474 if (__nd != nullptr)
1475 {
1476 while (true)
1477 {
1478 if (value_comp()(__nd->__value_, __v))
1479 {
1480 if (__nd->__right_ != nullptr)
1481 __nd = static_cast<__node_pointer>(__nd->__right_);
1482 else
1483 {
1484 __parent = __nd;
1485 return __parent->__right_;
1486 }
1487 }
1488 else
1489 {
1490 if (__nd->__left_ != nullptr)
1491 __nd = static_cast<__node_pointer>(__nd->__left_);
1492 else
1493 {
1494 __parent = __nd;
1495 return __parent->__left_;
1496 }
1497 }
1498 }
1499 }
1500 __parent = __end_node();
1501 return __parent->__left_;
1502}
1503
1504// Find upper_bound place to insert
1505// Set __parent to parent of null leaf
1506// Return reference to null leaf
1507template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantd615e472011-04-03 20:05:29 +00001508typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
1509__tree<_Tp, _Compare, _Allocator>::__find_leaf_high(typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001510 const value_type& __v)
1511{
1512 __node_pointer __nd = __root();
1513 if (__nd != nullptr)
1514 {
1515 while (true)
1516 {
1517 if (value_comp()(__v, __nd->__value_))
1518 {
1519 if (__nd->__left_ != nullptr)
1520 __nd = static_cast<__node_pointer>(__nd->__left_);
1521 else
1522 {
1523 __parent = __nd;
1524 return __parent->__left_;
1525 }
1526 }
1527 else
1528 {
1529 if (__nd->__right_ != nullptr)
1530 __nd = static_cast<__node_pointer>(__nd->__right_);
1531 else
1532 {
1533 __parent = __nd;
1534 return __parent->__right_;
1535 }
1536 }
1537 }
1538 }
1539 __parent = __end_node();
1540 return __parent->__left_;
1541}
1542
1543// Find leaf place to insert closest to __hint
1544// First check prior to __hint.
1545// Next check after __hint.
1546// Next do O(log N) search.
1547// Set __parent to parent of null leaf
1548// Return reference to null leaf
1549template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantd615e472011-04-03 20:05:29 +00001550typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001551__tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint,
Howard Hinnantd615e472011-04-03 20:05:29 +00001552 typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001553 const value_type& __v)
1554{
1555 if (__hint == end() || !value_comp()(*__hint, __v)) // check before
1556 {
1557 // __v <= *__hint
1558 const_iterator __prior = __hint;
1559 if (__prior == begin() || !value_comp()(__v, *--__prior))
1560 {
1561 // *prev(__hint) <= __v <= *__hint
1562 if (__hint.__ptr_->__left_ == nullptr)
1563 {
1564 __parent = const_cast<__node_pointer&>(__hint.__ptr_);
1565 return __parent->__left_;
1566 }
1567 else
1568 {
1569 __parent = const_cast<__node_pointer&>(__prior.__ptr_);
1570 return __parent->__right_;
1571 }
1572 }
1573 // __v < *prev(__hint)
1574 return __find_leaf_high(__parent, __v);
1575 }
1576 // else __v > *__hint
1577 return __find_leaf_low(__parent, __v);
1578}
1579
1580// Find place to insert if __v doesn't exist
1581// Set __parent to parent of null leaf
1582// Return reference to null leaf
1583// If __v exists, set parent to node of __v and return reference to node of __v
1584template <class _Tp, class _Compare, class _Allocator>
1585template <class _Key>
Howard Hinnantd615e472011-04-03 20:05:29 +00001586typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
1587__tree<_Tp, _Compare, _Allocator>::__find_equal(typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001588 const _Key& __v)
1589{
1590 __node_pointer __nd = __root();
1591 if (__nd != nullptr)
1592 {
1593 while (true)
1594 {
1595 if (value_comp()(__v, __nd->__value_))
1596 {
1597 if (__nd->__left_ != nullptr)
1598 __nd = static_cast<__node_pointer>(__nd->__left_);
1599 else
1600 {
1601 __parent = __nd;
1602 return __parent->__left_;
1603 }
1604 }
1605 else if (value_comp()(__nd->__value_, __v))
1606 {
1607 if (__nd->__right_ != nullptr)
1608 __nd = static_cast<__node_pointer>(__nd->__right_);
1609 else
1610 {
1611 __parent = __nd;
1612 return __parent->__right_;
1613 }
1614 }
1615 else
1616 {
1617 __parent = __nd;
1618 return __parent;
1619 }
1620 }
1621 }
1622 __parent = __end_node();
1623 return __parent->__left_;
1624}
1625
1626// Find place to insert if __v doesn't exist
1627// First check prior to __hint.
1628// Next check after __hint.
1629// Next do O(log N) search.
1630// Set __parent to parent of null leaf
1631// Return reference to null leaf
1632// If __v exists, set parent to node of __v and return reference to node of __v
1633template <class _Tp, class _Compare, class _Allocator>
1634template <class _Key>
Howard Hinnantd615e472011-04-03 20:05:29 +00001635typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001636__tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint,
Howard Hinnantd615e472011-04-03 20:05:29 +00001637 typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001638 const _Key& __v)
1639{
1640 if (__hint == end() || value_comp()(__v, *__hint)) // check before
1641 {
1642 // __v < *__hint
1643 const_iterator __prior = __hint;
1644 if (__prior == begin() || value_comp()(*--__prior, __v))
1645 {
1646 // *prev(__hint) < __v < *__hint
1647 if (__hint.__ptr_->__left_ == nullptr)
1648 {
1649 __parent = const_cast<__node_pointer&>(__hint.__ptr_);
1650 return __parent->__left_;
1651 }
1652 else
1653 {
1654 __parent = const_cast<__node_pointer&>(__prior.__ptr_);
1655 return __parent->__right_;
1656 }
1657 }
1658 // __v <= *prev(__hint)
1659 return __find_equal(__parent, __v);
1660 }
1661 else if (value_comp()(*__hint, __v)) // check after
1662 {
1663 // *__hint < __v
Howard Hinnant0949eed2011-06-30 21:18:19 +00001664 const_iterator __next = _VSTD::next(__hint);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001665 if (__next == end() || value_comp()(__v, *__next))
1666 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001667 // *__hint < __v < *_VSTD::next(__hint)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001668 if (__hint.__ptr_->__right_ == nullptr)
1669 {
1670 __parent = const_cast<__node_pointer&>(__hint.__ptr_);
1671 return __parent->__right_;
1672 }
1673 else
1674 {
1675 __parent = const_cast<__node_pointer&>(__next.__ptr_);
1676 return __parent->__left_;
1677 }
1678 }
1679 // *next(__hint) <= __v
1680 return __find_equal(__parent, __v);
1681 }
1682 // else __v == *__hint
1683 __parent = const_cast<__node_pointer&>(__hint.__ptr_);
1684 return __parent;
1685}
1686
1687template <class _Tp, class _Compare, class _Allocator>
1688void
1689__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__node_base_pointer __parent,
1690 __node_base_pointer& __child,
1691 __node_base_pointer __new_node)
1692{
1693 __new_node->__left_ = nullptr;
1694 __new_node->__right_ = nullptr;
1695 __new_node->__parent_ = __parent;
1696 __child = __new_node;
1697 if (__begin_node()->__left_ != nullptr)
1698 __begin_node() = static_cast<__node_pointer>(__begin_node()->__left_);
1699 __tree_balance_after_insert(__end_node()->__left_, __child);
1700 ++size();
1701}
1702
Howard Hinnant73d21a42010-09-04 23:28:19 +00001703#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1704#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001705
1706template <class _Tp, class _Compare, class _Allocator>
1707template <class ..._Args>
1708typename __tree<_Tp, _Compare, _Allocator>::__node_holder
1709__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args)
1710{
1711 __node_allocator& __na = __node_alloc();
1712 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001713 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001714 __h.get_deleter().__value_constructed = true;
1715 return __h;
1716}
1717
1718template <class _Tp, class _Compare, class _Allocator>
1719template <class... _Args>
1720pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1721__tree<_Tp, _Compare, _Allocator>::__emplace_unique(_Args&&... __args)
1722{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001723 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001724 __node_base_pointer __parent;
1725 __node_base_pointer& __child = __find_equal(__parent, __h->__value_);
1726 __node_pointer __r = static_cast<__node_pointer>(__child);
1727 bool __inserted = false;
1728 if (__child == nullptr)
1729 {
1730 __insert_node_at(__parent, __child, __h.get());
1731 __r = __h.release();
1732 __inserted = true;
1733 }
1734 return pair<iterator, bool>(iterator(__r), __inserted);
1735}
1736
1737template <class _Tp, class _Compare, class _Allocator>
1738template <class... _Args>
1739typename __tree<_Tp, _Compare, _Allocator>::iterator
1740__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique(const_iterator __p, _Args&&... __args)
1741{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001742 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001743 __node_base_pointer __parent;
1744 __node_base_pointer& __child = __find_equal(__p, __parent, __h->__value_);
1745 __node_pointer __r = static_cast<__node_pointer>(__child);
1746 if (__child == nullptr)
1747 {
1748 __insert_node_at(__parent, __child, __h.get());
1749 __r = __h.release();
1750 }
1751 return iterator(__r);
1752}
1753
1754template <class _Tp, class _Compare, class _Allocator>
1755template <class... _Args>
1756typename __tree<_Tp, _Compare, _Allocator>::iterator
1757__tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args)
1758{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001759 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001760 __node_base_pointer __parent;
1761 __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
1762 __insert_node_at(__parent, __child, __h.get());
1763 return iterator(static_cast<__node_pointer>(__h.release()));
1764}
1765
1766template <class _Tp, class _Compare, class _Allocator>
1767template <class... _Args>
1768typename __tree<_Tp, _Compare, _Allocator>::iterator
1769__tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p,
1770 _Args&&... __args)
1771{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001772 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001773 __node_base_pointer __parent;
1774 __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
1775 __insert_node_at(__parent, __child, __h.get());
1776 return iterator(static_cast<__node_pointer>(__h.release()));
1777}
1778
Howard Hinnant73d21a42010-09-04 23:28:19 +00001779#endif // _LIBCPP_HAS_NO_VARIADICS
1780
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001781template <class _Tp, class _Compare, class _Allocator>
1782template <class _V>
1783pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1784__tree<_Tp, _Compare, _Allocator>::__insert_unique(_V&& __v)
1785{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001786 __node_holder __h = __construct_node(_VSTD::forward<_V>(__v));
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001787 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1788 if (__r.second)
1789 __h.release();
1790 return __r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001791}
1792
1793template <class _Tp, class _Compare, class _Allocator>
1794template <class _V>
1795typename __tree<_Tp, _Compare, _Allocator>::iterator
1796__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, _V&& __v)
1797{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001798 __node_holder __h = __construct_node(_VSTD::forward<_V>(__v));
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001799 iterator __r = __node_insert_unique(__p, __h.get());
1800 if (__r.__ptr_ == __h.get())
1801 __h.release();
1802 return __r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001803}
1804
1805template <class _Tp, class _Compare, class _Allocator>
1806template <class _V>
1807typename __tree<_Tp, _Compare, _Allocator>::iterator
1808__tree<_Tp, _Compare, _Allocator>::__insert_multi(_V&& __v)
1809{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001810 __node_holder __h = __construct_node(_VSTD::forward<_V>(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001811 __node_base_pointer __parent;
1812 __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
1813 __insert_node_at(__parent, __child, __h.get());
1814 return iterator(__h.release());
1815}
1816
1817template <class _Tp, class _Compare, class _Allocator>
1818template <class _V>
1819typename __tree<_Tp, _Compare, _Allocator>::iterator
1820__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, _V&& __v)
1821{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001822 __node_holder __h = __construct_node(_VSTD::forward<_V>(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001823 __node_base_pointer __parent;
1824 __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
1825 __insert_node_at(__parent, __child, __h.get());
1826 return iterator(__h.release());
1827}
1828
Howard Hinnant73d21a42010-09-04 23:28:19 +00001829#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001830
1831template <class _Tp, class _Compare, class _Allocator>
1832typename __tree<_Tp, _Compare, _Allocator>::__node_holder
1833__tree<_Tp, _Compare, _Allocator>::__construct_node(const value_type& __v)
1834{
1835 __node_allocator& __na = __node_alloc();
1836 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001837 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001838 __h.get_deleter().__value_constructed = true;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001839 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001840}
1841
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001842#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
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>::__insert_unique(const value_type& __v)
1847{
1848 __node_base_pointer __parent;
1849 __node_base_pointer& __child = __find_equal(__parent, __v);
1850 __node_pointer __r = static_cast<__node_pointer>(__child);
1851 bool __inserted = false;
1852 if (__child == nullptr)
1853 {
1854 __node_holder __h = __construct_node(__v);
1855 __insert_node_at(__parent, __child, __h.get());
1856 __r = __h.release();
1857 __inserted = true;
1858 }
1859 return pair<iterator, bool>(iterator(__r), __inserted);
1860}
1861
1862template <class _Tp, class _Compare, class _Allocator>
1863typename __tree<_Tp, _Compare, _Allocator>::iterator
1864__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, const value_type& __v)
1865{
1866 __node_base_pointer __parent;
1867 __node_base_pointer& __child = __find_equal(__p, __parent, __v);
1868 __node_pointer __r = static_cast<__node_pointer>(__child);
1869 if (__child == nullptr)
1870 {
1871 __node_holder __h = __construct_node(__v);
1872 __insert_node_at(__parent, __child, __h.get());
1873 __r = __h.release();
1874 }
1875 return iterator(__r);
1876}
1877
1878template <class _Tp, class _Compare, class _Allocator>
1879typename __tree<_Tp, _Compare, _Allocator>::iterator
1880__tree<_Tp, _Compare, _Allocator>::__insert_multi(const value_type& __v)
1881{
1882 __node_base_pointer __parent;
1883 __node_base_pointer& __child = __find_leaf_high(__parent, __v);
1884 __node_holder __h = __construct_node(__v);
1885 __insert_node_at(__parent, __child, __h.get());
1886 return iterator(__h.release());
1887}
1888
1889template <class _Tp, class _Compare, class _Allocator>
1890typename __tree<_Tp, _Compare, _Allocator>::iterator
1891__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const value_type& __v)
1892{
1893 __node_base_pointer __parent;
1894 __node_base_pointer& __child = __find_leaf(__p, __parent, __v);
1895 __node_holder __h = __construct_node(__v);
1896 __insert_node_at(__parent, __child, __h.get());
1897 return iterator(__h.release());
1898}
1899
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001900template <class _Tp, class _Compare, class _Allocator>
1901pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1902__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd)
1903{
1904 __node_base_pointer __parent;
1905 __node_base_pointer& __child = __find_equal(__parent, __nd->__value_);
1906 __node_pointer __r = static_cast<__node_pointer>(__child);
1907 bool __inserted = false;
1908 if (__child == nullptr)
1909 {
1910 __insert_node_at(__parent, __child, __nd);
1911 __r = __nd;
1912 __inserted = true;
1913 }
1914 return pair<iterator, bool>(iterator(__r), __inserted);
1915}
1916
1917template <class _Tp, class _Compare, class _Allocator>
1918typename __tree<_Tp, _Compare, _Allocator>::iterator
1919__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p,
1920 __node_pointer __nd)
1921{
1922 __node_base_pointer __parent;
1923 __node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_);
1924 __node_pointer __r = static_cast<__node_pointer>(__child);
1925 if (__child == nullptr)
1926 {
1927 __insert_node_at(__parent, __child, __nd);
1928 __r = __nd;
1929 }
1930 return iterator(__r);
1931}
1932
1933template <class _Tp, class _Compare, class _Allocator>
1934typename __tree<_Tp, _Compare, _Allocator>::iterator
1935__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd)
1936{
1937 __node_base_pointer __parent;
1938 __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__value_);
1939 __insert_node_at(__parent, __child, __nd);
1940 return iterator(__nd);
1941}
1942
1943template <class _Tp, class _Compare, class _Allocator>
1944typename __tree<_Tp, _Compare, _Allocator>::iterator
1945__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p,
1946 __node_pointer __nd)
1947{
1948 __node_base_pointer __parent;
1949 __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__value_);
1950 __insert_node_at(__parent, __child, __nd);
1951 return iterator(__nd);
1952}
1953
1954template <class _Tp, class _Compare, class _Allocator>
1955typename __tree<_Tp, _Compare, _Allocator>::iterator
1956__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p)
1957{
1958 __node_pointer __np = const_cast<__node_pointer>(__p.__ptr_);
1959 iterator __r(__np);
1960 ++__r;
1961 if (__begin_node() == __np)
1962 __begin_node() = __r.__ptr_;
1963 --size();
1964 __node_allocator& __na = __node_alloc();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001965 __node_traits::destroy(__na, const_cast<value_type*>(_VSTD::addressof(*__p)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001966 __tree_remove(__end_node()->__left_,
1967 static_cast<__node_base_pointer>(__np));
1968 __node_traits::deallocate(__na, __np, 1);
1969 return __r;
1970}
1971
1972template <class _Tp, class _Compare, class _Allocator>
1973typename __tree<_Tp, _Compare, _Allocator>::iterator
1974__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l)
1975{
1976 while (__f != __l)
1977 __f = erase(__f);
1978 return iterator(const_cast<__node_pointer>(__l.__ptr_));
1979}
1980
1981template <class _Tp, class _Compare, class _Allocator>
1982template <class _Key>
1983typename __tree<_Tp, _Compare, _Allocator>::size_type
1984__tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k)
1985{
1986 iterator __i = find(__k);
1987 if (__i == end())
1988 return 0;
1989 erase(__i);
1990 return 1;
1991}
1992
1993template <class _Tp, class _Compare, class _Allocator>
1994template <class _Key>
1995typename __tree<_Tp, _Compare, _Allocator>::size_type
1996__tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k)
1997{
1998 pair<iterator, iterator> __p = __equal_range_multi(__k);
1999 size_type __r = 0;
2000 for (; __p.first != __p.second; ++__r)
2001 __p.first = erase(__p.first);
2002 return __r;
2003}
2004
2005template <class _Tp, class _Compare, class _Allocator>
2006template <class _Key>
2007typename __tree<_Tp, _Compare, _Allocator>::iterator
2008__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v)
2009{
2010 iterator __p = __lower_bound(__v, __root(), __end_node());
2011 if (__p != end() && !value_comp()(__v, *__p))
2012 return __p;
2013 return end();
2014}
2015
2016template <class _Tp, class _Compare, class _Allocator>
2017template <class _Key>
2018typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2019__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) const
2020{
2021 const_iterator __p = __lower_bound(__v, __root(), __end_node());
2022 if (__p != end() && !value_comp()(__v, *__p))
2023 return __p;
2024 return end();
2025}
2026
2027template <class _Tp, class _Compare, class _Allocator>
2028template <class _Key>
2029typename __tree<_Tp, _Compare, _Allocator>::size_type
2030__tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const
2031{
2032 __node_const_pointer __result = __end_node();
2033 __node_const_pointer __rt = __root();
2034 while (__rt != nullptr)
2035 {
2036 if (value_comp()(__k, __rt->__value_))
2037 {
2038 __result = __rt;
2039 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2040 }
2041 else if (value_comp()(__rt->__value_, __k))
2042 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2043 else
2044 return 1;
2045 }
2046 return 0;
2047}
2048
2049template <class _Tp, class _Compare, class _Allocator>
2050template <class _Key>
2051typename __tree<_Tp, _Compare, _Allocator>::size_type
2052__tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const
2053{
2054 typedef pair<const_iterator, const_iterator> _P;
2055 __node_const_pointer __result = __end_node();
2056 __node_const_pointer __rt = __root();
2057 while (__rt != nullptr)
2058 {
2059 if (value_comp()(__k, __rt->__value_))
2060 {
2061 __result = __rt;
2062 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2063 }
2064 else if (value_comp()(__rt->__value_, __k))
2065 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2066 else
Howard Hinnant0949eed2011-06-30 21:18:19 +00002067 return _VSTD::distance(
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002068 __lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt),
2069 __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result)
2070 );
2071 }
2072 return 0;
2073}
2074
2075template <class _Tp, class _Compare, class _Allocator>
2076template <class _Key>
2077typename __tree<_Tp, _Compare, _Allocator>::iterator
2078__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
2079 __node_pointer __root,
2080 __node_pointer __result)
2081{
2082 while (__root != nullptr)
2083 {
2084 if (!value_comp()(__root->__value_, __v))
2085 {
2086 __result = __root;
2087 __root = static_cast<__node_pointer>(__root->__left_);
2088 }
2089 else
2090 __root = static_cast<__node_pointer>(__root->__right_);
2091 }
2092 return iterator(__result);
2093}
2094
2095template <class _Tp, class _Compare, class _Allocator>
2096template <class _Key>
2097typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2098__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
2099 __node_const_pointer __root,
2100 __node_const_pointer __result) const
2101{
2102 while (__root != nullptr)
2103 {
2104 if (!value_comp()(__root->__value_, __v))
2105 {
2106 __result = __root;
2107 __root = static_cast<__node_const_pointer>(__root->__left_);
2108 }
2109 else
2110 __root = static_cast<__node_const_pointer>(__root->__right_);
2111 }
2112 return const_iterator(__result);
2113}
2114
2115template <class _Tp, class _Compare, class _Allocator>
2116template <class _Key>
2117typename __tree<_Tp, _Compare, _Allocator>::iterator
2118__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
2119 __node_pointer __root,
2120 __node_pointer __result)
2121{
2122 while (__root != nullptr)
2123 {
2124 if (value_comp()(__v, __root->__value_))
2125 {
2126 __result = __root;
2127 __root = static_cast<__node_pointer>(__root->__left_);
2128 }
2129 else
2130 __root = static_cast<__node_pointer>(__root->__right_);
2131 }
2132 return iterator(__result);
2133}
2134
2135template <class _Tp, class _Compare, class _Allocator>
2136template <class _Key>
2137typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2138__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
2139 __node_const_pointer __root,
2140 __node_const_pointer __result) const
2141{
2142 while (__root != nullptr)
2143 {
2144 if (value_comp()(__v, __root->__value_))
2145 {
2146 __result = __root;
2147 __root = static_cast<__node_const_pointer>(__root->__left_);
2148 }
2149 else
2150 __root = static_cast<__node_const_pointer>(__root->__right_);
2151 }
2152 return 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_unique(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(iterator(__rt),
2175 iterator(
2176 __rt->__right_ != nullptr ?
2177 static_cast<__node_pointer>(__tree_min(__rt->__right_))
2178 : __result));
2179 }
2180 return _P(iterator(__result), iterator(__result));
2181}
2182
2183template <class _Tp, class _Compare, class _Allocator>
2184template <class _Key>
2185pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
2186 typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
2187__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const
2188{
2189 typedef pair<const_iterator, const_iterator> _P;
2190 __node_const_pointer __result = __end_node();
2191 __node_const_pointer __rt = __root();
2192 while (__rt != nullptr)
2193 {
2194 if (value_comp()(__k, __rt->__value_))
2195 {
2196 __result = __rt;
2197 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2198 }
2199 else if (value_comp()(__rt->__value_, __k))
2200 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2201 else
2202 return _P(const_iterator(__rt),
2203 const_iterator(
2204 __rt->__right_ != nullptr ?
2205 static_cast<__node_const_pointer>(__tree_min(__rt->__right_))
2206 : __result));
2207 }
2208 return _P(const_iterator(__result), const_iterator(__result));
2209}
2210
2211template <class _Tp, class _Compare, class _Allocator>
2212template <class _Key>
2213pair<typename __tree<_Tp, _Compare, _Allocator>::iterator,
2214 typename __tree<_Tp, _Compare, _Allocator>::iterator>
2215__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k)
2216{
2217 typedef pair<iterator, iterator> _P;
2218 __node_pointer __result = __end_node();
2219 __node_pointer __rt = __root();
2220 while (__rt != nullptr)
2221 {
2222 if (value_comp()(__k, __rt->__value_))
2223 {
2224 __result = __rt;
2225 __rt = static_cast<__node_pointer>(__rt->__left_);
2226 }
2227 else if (value_comp()(__rt->__value_, __k))
2228 __rt = static_cast<__node_pointer>(__rt->__right_);
2229 else
2230 return _P(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt),
2231 __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
2232 }
2233 return _P(iterator(__result), iterator(__result));
2234}
2235
2236template <class _Tp, class _Compare, class _Allocator>
2237template <class _Key>
2238pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
2239 typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
2240__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const
2241{
2242 typedef pair<const_iterator, const_iterator> _P;
2243 __node_const_pointer __result = __end_node();
2244 __node_const_pointer __rt = __root();
2245 while (__rt != nullptr)
2246 {
2247 if (value_comp()(__k, __rt->__value_))
2248 {
2249 __result = __rt;
2250 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2251 }
2252 else if (value_comp()(__rt->__value_, __k))
2253 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2254 else
2255 return _P(__lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt),
2256 __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result));
2257 }
2258 return _P(const_iterator(__result), const_iterator(__result));
2259}
2260
2261template <class _Tp, class _Compare, class _Allocator>
2262typename __tree<_Tp, _Compare, _Allocator>::__node_holder
Howard Hinnant8b537682011-06-04 17:10:24 +00002263__tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002264{
2265 __node_pointer __np = const_cast<__node_pointer>(__p.__ptr_);
2266 if (__begin_node() == __np)
2267 {
2268 if (__np->__right_ != nullptr)
2269 __begin_node() = static_cast<__node_pointer>(__np->__right_);
2270 else
2271 __begin_node() = static_cast<__node_pointer>(__np->__parent_);
2272 }
2273 --size();
2274 __tree_remove(__end_node()->__left_,
2275 static_cast<__node_base_pointer>(__np));
2276 return __node_holder(__np, _D(__node_alloc()));
2277}
2278
Howard Hinnant7686add2011-06-04 14:31:57 +00002279template <class _Tp, class _Compare, class _Allocator>
2280inline _LIBCPP_INLINE_VISIBILITY
2281void
2282swap(__tree<_Tp, _Compare, _Allocator>& __x,
2283 __tree<_Tp, _Compare, _Allocator>& __y)
2284 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
2285{
2286 __x.swap(__y);
2287}
2288
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002289_LIBCPP_END_NAMESPACE_STD
2290
2291#endif // _LIBCPP___TREE