blob: 1536b5d6d2c9c2d312a6bc54561a9480626dc2f1 [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantc566dc32010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00005//
Howard Hinnantee11c312010-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 Hinnantc51e1022010-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
Howard Hinnantaaaa52b2011-10-17 20:05:10 +000020#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantc51e1022010-05-11 19:42:16 +000021#pragma GCC system_header
Howard Hinnantaaaa52b2011-10-17 20:05:10 +000022#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000023
24_LIBCPP_BEGIN_NAMESPACE_STD
25
Howard Hinnant944510a2011-06-14 19:58:17 +000026template <class _Tp, class _Compare, class _Allocator> class __tree;
27template <class _Tp, class _NodePtr, class _DiffType>
Howard Hinnanta37d3cf2013-08-12 18:38:34 +000028 class _LIBCPP_TYPE_VIS_ONLY __tree_iterator;
Howard Hinnant944510a2011-06-14 19:58:17 +000029template <class _Tp, class _ConstNodePtr, class _DiffType>
Howard Hinnanta37d3cf2013-08-12 18:38:34 +000030 class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator;
Howard Hinnantc51e1022010-05-11 19:42:16 +000031
Eric Fiseliera00b4842016-02-20 05:28:30 +000032template <class _Pointer> class __tree_end_node;
33template <class _VoidPtr> class __tree_node_base;
34template <class _Tp, class _VoidPtr> class __tree_node;
35
36#ifndef _LIBCPP_CXX03_LANG
37template <class _Key, class _Value>
38union __value_type;
39#else
40template <class _Key, class _Value>
41struct __value_type;
42#endif
43
44template <class _Allocator> class __map_node_destructor;
45template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_iterator;
46template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator;
47
Howard Hinnantc51e1022010-05-11 19:42:16 +000048/*
49
50_NodePtr algorithms
51
52The algorithms taking _NodePtr are red black tree algorithms. Those
53algorithms taking a parameter named __root should assume that __root
54points to a proper red black tree (unless otherwise specified).
55
56Each algorithm herein assumes that __root->__parent_ points to a non-null
57structure which has a member __left_ which points back to __root. No other
58member is read or written to at __root->__parent_.
59
60__root->__parent_ will be referred to below (in comments only) as end_node.
61end_node->__left_ is an externably accessible lvalue for __root, and can be
62changed by node insertion and removal (without explicit reference to end_node).
63
64All nodes (with the exception of end_node), even the node referred to as
65__root, have a non-null __parent_ field.
66
67*/
68
69// Returns: true if __x is a left child of its parent, else false
70// Precondition: __x != nullptr.
71template <class _NodePtr>
Howard Hinnant8e29cda2010-09-21 20:16:37 +000072inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +000073bool
Howard Hinnant1113b5e2011-06-04 17:10:24 +000074__tree_is_left_child(_NodePtr __x) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +000075{
76 return __x == __x->__parent_->__left_;
77}
78
79// Determintes if the subtree rooted at __x is a proper red black subtree. If
80// __x is a proper subtree, returns the black height (null counts as 1). If
81// __x is an improper subtree, returns 0.
82template <class _NodePtr>
83unsigned
84__tree_sub_invariant(_NodePtr __x)
85{
86 if (__x == nullptr)
87 return 1;
88 // parent consistency checked by caller
89 // check __x->__left_ consistency
90 if (__x->__left_ != nullptr && __x->__left_->__parent_ != __x)
91 return 0;
92 // check __x->__right_ consistency
93 if (__x->__right_ != nullptr && __x->__right_->__parent_ != __x)
94 return 0;
95 // check __x->__left_ != __x->__right_ unless both are nullptr
96 if (__x->__left_ == __x->__right_ && __x->__left_ != nullptr)
97 return 0;
98 // If this is red, neither child can be red
99 if (!__x->__is_black_)
100 {
101 if (__x->__left_ && !__x->__left_->__is_black_)
102 return 0;
103 if (__x->__right_ && !__x->__right_->__is_black_)
104 return 0;
105 }
106 unsigned __h = __tree_sub_invariant(__x->__left_);
107 if (__h == 0)
108 return 0; // invalid left subtree
109 if (__h != __tree_sub_invariant(__x->__right_))
110 return 0; // invalid or different height right subtree
111 return __h + __x->__is_black_; // return black height of this node
112}
113
114// Determintes if the red black tree rooted at __root is a proper red black tree.
115// __root == nullptr is a proper tree. Returns true is __root is a proper
116// red black tree, else returns false.
117template <class _NodePtr>
118bool
119__tree_invariant(_NodePtr __root)
120{
121 if (__root == nullptr)
122 return true;
123 // check __x->__parent_ consistency
124 if (__root->__parent_ == nullptr)
125 return false;
126 if (!__tree_is_left_child(__root))
127 return false;
128 // root must be black
129 if (!__root->__is_black_)
130 return false;
131 // do normal node checks
132 return __tree_sub_invariant(__root) != 0;
133}
134
135// Returns: pointer to the left-most node under __x.
136// Precondition: __x != nullptr.
137template <class _NodePtr>
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000138inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000139_NodePtr
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000140__tree_min(_NodePtr __x) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000141{
142 while (__x->__left_ != nullptr)
143 __x = __x->__left_;
144 return __x;
145}
146
147// Returns: pointer to the right-most node under __x.
148// Precondition: __x != nullptr.
149template <class _NodePtr>
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000150inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000151_NodePtr
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000152__tree_max(_NodePtr __x) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000153{
154 while (__x->__right_ != nullptr)
155 __x = __x->__right_;
156 return __x;
157}
158
159// Returns: pointer to the next in-order node after __x.
160// Precondition: __x != nullptr.
161template <class _NodePtr>
162_NodePtr
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000163__tree_next(_NodePtr __x) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000164{
165 if (__x->__right_ != nullptr)
166 return __tree_min(__x->__right_);
167 while (!__tree_is_left_child(__x))
168 __x = __x->__parent_;
169 return __x->__parent_;
170}
171
172// Returns: pointer to the previous in-order node before __x.
173// Precondition: __x != nullptr.
174template <class _NodePtr>
175_NodePtr
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000176__tree_prev(_NodePtr __x) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000177{
178 if (__x->__left_ != nullptr)
179 return __tree_max(__x->__left_);
180 while (__tree_is_left_child(__x))
181 __x = __x->__parent_;
182 return __x->__parent_;
183}
184
185// Returns: pointer to a node which has no children
186// Precondition: __x != nullptr.
187template <class _NodePtr>
188_NodePtr
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000189__tree_leaf(_NodePtr __x) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000190{
191 while (true)
192 {
193 if (__x->__left_ != nullptr)
194 {
195 __x = __x->__left_;
196 continue;
197 }
198 if (__x->__right_ != nullptr)
199 {
200 __x = __x->__right_;
201 continue;
202 }
203 break;
204 }
205 return __x;
206}
207
208// Effects: Makes __x->__right_ the subtree root with __x as its left child
209// while preserving in-order order.
210// Precondition: __x->__right_ != nullptr
211template <class _NodePtr>
212void
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000213__tree_left_rotate(_NodePtr __x) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000214{
215 _NodePtr __y = __x->__right_;
216 __x->__right_ = __y->__left_;
217 if (__x->__right_ != nullptr)
218 __x->__right_->__parent_ = __x;
219 __y->__parent_ = __x->__parent_;
220 if (__tree_is_left_child(__x))
221 __x->__parent_->__left_ = __y;
222 else
223 __x->__parent_->__right_ = __y;
224 __y->__left_ = __x;
225 __x->__parent_ = __y;
226}
227
228// Effects: Makes __x->__left_ the subtree root with __x as its right child
229// while preserving in-order order.
230// Precondition: __x->__left_ != nullptr
231template <class _NodePtr>
232void
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000233__tree_right_rotate(_NodePtr __x) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000234{
235 _NodePtr __y = __x->__left_;
236 __x->__left_ = __y->__right_;
237 if (__x->__left_ != nullptr)
238 __x->__left_->__parent_ = __x;
239 __y->__parent_ = __x->__parent_;
240 if (__tree_is_left_child(__x))
241 __x->__parent_->__left_ = __y;
242 else
243 __x->__parent_->__right_ = __y;
244 __y->__right_ = __x;
245 __x->__parent_ = __y;
246}
247
248// Effects: Rebalances __root after attaching __x to a leaf.
249// Precondition: __root != nulptr && __x != nullptr.
250// __x has no children.
251// __x == __root or == a direct or indirect child of __root.
252// If __x were to be unlinked from __root (setting __root to
253// nullptr if __root == __x), __tree_invariant(__root) == true.
254// Postcondition: __tree_invariant(end_node->__left_) == true. end_node->__left_
255// may be different than the value passed in as __root.
256template <class _NodePtr>
257void
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000258__tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000259{
260 __x->__is_black_ = __x == __root;
261 while (__x != __root && !__x->__parent_->__is_black_)
262 {
263 // __x->__parent_ != __root because __x->__parent_->__is_black == false
264 if (__tree_is_left_child(__x->__parent_))
265 {
266 _NodePtr __y = __x->__parent_->__parent_->__right_;
267 if (__y != nullptr && !__y->__is_black_)
268 {
269 __x = __x->__parent_;
270 __x->__is_black_ = true;
271 __x = __x->__parent_;
272 __x->__is_black_ = __x == __root;
273 __y->__is_black_ = true;
274 }
275 else
276 {
277 if (!__tree_is_left_child(__x))
278 {
279 __x = __x->__parent_;
280 __tree_left_rotate(__x);
281 }
282 __x = __x->__parent_;
283 __x->__is_black_ = true;
284 __x = __x->__parent_;
285 __x->__is_black_ = false;
286 __tree_right_rotate(__x);
287 break;
288 }
289 }
290 else
291 {
292 _NodePtr __y = __x->__parent_->__parent_->__left_;
293 if (__y != nullptr && !__y->__is_black_)
294 {
295 __x = __x->__parent_;
296 __x->__is_black_ = true;
297 __x = __x->__parent_;
298 __x->__is_black_ = __x == __root;
299 __y->__is_black_ = true;
300 }
301 else
302 {
303 if (__tree_is_left_child(__x))
304 {
305 __x = __x->__parent_;
306 __tree_right_rotate(__x);
307 }
308 __x = __x->__parent_;
309 __x->__is_black_ = true;
310 __x = __x->__parent_;
311 __x->__is_black_ = false;
312 __tree_left_rotate(__x);
313 break;
314 }
315 }
316 }
317}
318
319// Precondition: __root != nullptr && __z != nullptr.
320// __tree_invariant(__root) == true.
321// __z == __root or == a direct or indirect child of __root.
322// Effects: unlinks __z from the tree rooted at __root, rebalancing as needed.
323// Postcondition: __tree_invariant(end_node->__left_) == true && end_node->__left_
324// nor any of its children refer to __z. end_node->__left_
325// may be different than the value passed in as __root.
326template <class _NodePtr>
327void
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000328__tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000329{
330 // __z will be removed from the tree. Client still needs to destruct/deallocate it
331 // __y is either __z, or if __z has two children, __tree_next(__z).
332 // __y will have at most one child.
333 // __y will be the initial hole in the tree (make the hole at a leaf)
334 _NodePtr __y = (__z->__left_ == nullptr || __z->__right_ == nullptr) ?
335 __z : __tree_next(__z);
336 // __x is __y's possibly null single child
337 _NodePtr __x = __y->__left_ != nullptr ? __y->__left_ : __y->__right_;
338 // __w is __x's possibly null uncle (will become __x's sibling)
339 _NodePtr __w = nullptr;
340 // link __x to __y's parent, and find __w
341 if (__x != nullptr)
342 __x->__parent_ = __y->__parent_;
343 if (__tree_is_left_child(__y))
344 {
345 __y->__parent_->__left_ = __x;
346 if (__y != __root)
347 __w = __y->__parent_->__right_;
348 else
349 __root = __x; // __w == nullptr
350 }
351 else
352 {
353 __y->__parent_->__right_ = __x;
354 // __y can't be root if it is a right child
355 __w = __y->__parent_->__left_;
356 }
357 bool __removed_black = __y->__is_black_;
358 // If we didn't remove __z, do so now by splicing in __y for __z,
359 // but copy __z's color. This does not impact __x or __w.
360 if (__y != __z)
361 {
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000362 // __z->__left_ != nulptr but __z->__right_ might == __x == nullptr
Howard Hinnantc51e1022010-05-11 19:42:16 +0000363 __y->__parent_ = __z->__parent_;
364 if (__tree_is_left_child(__z))
365 __y->__parent_->__left_ = __y;
366 else
367 __y->__parent_->__right_ = __y;
368 __y->__left_ = __z->__left_;
369 __y->__left_->__parent_ = __y;
370 __y->__right_ = __z->__right_;
371 if (__y->__right_ != nullptr)
372 __y->__right_->__parent_ = __y;
373 __y->__is_black_ = __z->__is_black_;
374 if (__root == __z)
375 __root = __y;
376 }
377 // There is no need to rebalance if we removed a red, or if we removed
378 // the last node.
379 if (__removed_black && __root != nullptr)
380 {
381 // Rebalance:
382 // __x has an implicit black color (transferred from the removed __y)
383 // associated with it, no matter what its color is.
384 // If __x is __root (in which case it can't be null), it is supposed
385 // to be black anyway, and if it is doubly black, then the double
386 // can just be ignored.
387 // If __x is red (in which case it can't be null), then it can absorb
388 // the implicit black just by setting its color to black.
389 // Since __y was black and only had one child (which __x points to), __x
390 // is either red with no children, else null, otherwise __y would have
391 // different black heights under left and right pointers.
392 // if (__x == __root || __x != nullptr && !__x->__is_black_)
393 if (__x != nullptr)
394 __x->__is_black_ = true;
395 else
396 {
397 // Else __x isn't root, and is "doubly black", even though it may
398 // be null. __w can not be null here, else the parent would
399 // see a black height >= 2 on the __x side and a black height
400 // of 1 on the __w side (__w must be a non-null black or a red
401 // with a non-null black child).
402 while (true)
403 {
404 if (!__tree_is_left_child(__w)) // if x is left child
405 {
406 if (!__w->__is_black_)
407 {
408 __w->__is_black_ = true;
409 __w->__parent_->__is_black_ = false;
410 __tree_left_rotate(__w->__parent_);
411 // __x is still valid
412 // reset __root only if necessary
413 if (__root == __w->__left_)
414 __root = __w;
415 // reset sibling, and it still can't be null
416 __w = __w->__left_->__right_;
417 }
418 // __w->__is_black_ is now true, __w may have null children
419 if ((__w->__left_ == nullptr || __w->__left_->__is_black_) &&
420 (__w->__right_ == nullptr || __w->__right_->__is_black_))
421 {
422 __w->__is_black_ = false;
423 __x = __w->__parent_;
424 // __x can no longer be null
425 if (__x == __root || !__x->__is_black_)
426 {
427 __x->__is_black_ = true;
428 break;
429 }
430 // reset sibling, and it still can't be null
431 __w = __tree_is_left_child(__x) ?
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000432 __x->__parent_->__right_ :
433 __x->__parent_->__left_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000434 // continue;
435 }
436 else // __w has a red child
437 {
438 if (__w->__right_ == nullptr || __w->__right_->__is_black_)
439 {
440 // __w left child is non-null and red
441 __w->__left_->__is_black_ = true;
442 __w->__is_black_ = false;
443 __tree_right_rotate(__w);
444 // __w is known not to be root, so root hasn't changed
445 // reset sibling, and it still can't be null
446 __w = __w->__parent_;
447 }
448 // __w has a right red child, left child may be null
449 __w->__is_black_ = __w->__parent_->__is_black_;
450 __w->__parent_->__is_black_ = true;
451 __w->__right_->__is_black_ = true;
452 __tree_left_rotate(__w->__parent_);
453 break;
454 }
455 }
456 else
457 {
458 if (!__w->__is_black_)
459 {
460 __w->__is_black_ = true;
461 __w->__parent_->__is_black_ = false;
462 __tree_right_rotate(__w->__parent_);
463 // __x is still valid
464 // reset __root only if necessary
465 if (__root == __w->__right_)
466 __root = __w;
467 // reset sibling, and it still can't be null
468 __w = __w->__right_->__left_;
469 }
470 // __w->__is_black_ is now true, __w may have null children
471 if ((__w->__left_ == nullptr || __w->__left_->__is_black_) &&
472 (__w->__right_ == nullptr || __w->__right_->__is_black_))
473 {
474 __w->__is_black_ = false;
475 __x = __w->__parent_;
476 // __x can no longer be null
477 if (!__x->__is_black_ || __x == __root)
478 {
479 __x->__is_black_ = true;
480 break;
481 }
482 // reset sibling, and it still can't be null
483 __w = __tree_is_left_child(__x) ?
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000484 __x->__parent_->__right_ :
485 __x->__parent_->__left_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000486 // continue;
487 }
488 else // __w has a red child
489 {
490 if (__w->__left_ == nullptr || __w->__left_->__is_black_)
491 {
492 // __w right child is non-null and red
493 __w->__right_->__is_black_ = true;
494 __w->__is_black_ = false;
495 __tree_left_rotate(__w);
496 // __w is known not to be root, so root hasn't changed
497 // reset sibling, and it still can't be null
498 __w = __w->__parent_;
499 }
500 // __w has a left red child, right child may be null
501 __w->__is_black_ = __w->__parent_->__is_black_;
502 __w->__parent_->__is_black_ = true;
503 __w->__left_->__is_black_ = true;
504 __tree_right_rotate(__w->__parent_);
505 break;
506 }
507 }
508 }
509 }
510 }
511}
512
Howard Hinnantc51e1022010-05-11 19:42:16 +0000513template <class _Allocator>
514class __tree_node_destructor
515{
516 typedef _Allocator allocator_type;
517 typedef allocator_traits<allocator_type> __alloc_traits;
Eric Fiseliera00b4842016-02-20 05:28:30 +0000518
Howard Hinnantc51e1022010-05-11 19:42:16 +0000519public:
520 typedef typename __alloc_traits::pointer pointer;
521private:
522
523 allocator_type& __na_;
524
525 __tree_node_destructor& operator=(const __tree_node_destructor&);
526
527public:
528 bool __value_constructed;
529
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000530 _LIBCPP_INLINE_VISIBILITY
Marshall Clow95af65e2015-01-28 19:54:25 +0000531 explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000532 : __na_(__na),
Marshall Clow95af65e2015-01-28 19:54:25 +0000533 __value_constructed(__val)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000534 {}
535
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000536 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000537 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000538 {
539 if (__value_constructed)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000540 __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000541 if (__p)
542 __alloc_traits::deallocate(__na_, __p, 1);
543 }
544
545 template <class> friend class __map_node_destructor;
546};
547
Eric Fiseliera00b4842016-02-20 05:28:30 +0000548// node traits
549
550template <class _Tp>
551struct __tree_key_value_types {
552 typedef _Tp key_type;
553 typedef _Tp __node_value_type;
554 typedef _Tp __container_value_type;
555 static const bool __is_map = false;
556};
557
558template <class _Key, class _Tp>
559struct __tree_key_value_types<__value_type<_Key, _Tp> > {
560 typedef _Key key_type;
561 typedef _Tp mapped_type;
562 typedef __value_type<_Key, _Tp> __node_value_type;
563 typedef pair<const _Key, _Tp> __container_value_type;
564 typedef pair<_Key, _Tp> __nc_value_type;
565 typedef __container_value_type __map_value_type;
566 static const bool __is_map = true;
567};
568
569template <class _VoidPtr>
570struct __tree_node_base_types {
571 typedef _VoidPtr __void_pointer;
572
573 typedef __tree_node_base<__void_pointer> __node_base_type;
574 typedef typename __rebind_pointer<_VoidPtr, __node_base_type>::type
575 __node_base_pointer;
576
577 typedef __tree_end_node<__node_base_pointer> __end_node_type;
578 typedef typename __rebind_pointer<_VoidPtr, __end_node_type>::type
579 __end_node_pointer;
580private:
581 static_assert((is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value),
582 "_VoidPtr does not point to unqualified void type");
583};
584
585template <class _Tp, class _AllocPtr, class _KVTypes = __tree_key_value_types<_Tp>,
586 bool = _KVTypes::__is_map>
587struct __tree_map_pointer_types {};
588
589template <class _Tp, class _AllocPtr, class _KVTypes>
590struct __tree_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
591 typedef typename _KVTypes::__map_value_type _Mv;
592 typedef typename __rebind_pointer<_AllocPtr, _Mv>::type
593 __map_value_type_pointer;
594 typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type
595 __const_map_value_type_pointer;
596};
597
598template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
599struct __tree_node_types;
600
601template <class _NodePtr, class _Tp, class _VoidPtr>
602struct __tree_node_types<_NodePtr, __tree_node<_Tp, _VoidPtr> >
603 : public __tree_node_base_types<_VoidPtr>,
604 __tree_key_value_types<_Tp>,
605 __tree_map_pointer_types<_Tp, _VoidPtr>
606{
607 typedef __tree_node_base_types<_VoidPtr> __base;
608 typedef __tree_key_value_types<_Tp> __key_base;
609 typedef __tree_map_pointer_types<_Tp, _VoidPtr> __map_pointer_base;
610public:
611
612 typedef typename pointer_traits<_NodePtr>::element_type __node_type;
613 typedef _NodePtr __node_pointer;
614
615 typedef _Tp __node_value_type;
616 typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type
617 __node_value_type_pointer;
618 typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type
619 __const_node_value_type_pointer;
620private:
621 static_assert(!is_const<__node_type>::value,
622 "_NodePtr should never be a pointer to const");
623 static_assert((is_same<typename __rebind_pointer<_VoidPtr, __node_type>::type,
624 _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr.");
625};
626
627template <class _ValueTp, class _VoidPtr>
628struct __make_tree_node_types {
629 typedef typename __rebind_pointer<_VoidPtr, __tree_node<_ValueTp, _VoidPtr> >::type
630 _NodePtr;
631 typedef __tree_node_types<_NodePtr> type;
632};
633
Howard Hinnantc51e1022010-05-11 19:42:16 +0000634// node
635
636template <class _Pointer>
637class __tree_end_node
638{
639public:
640 typedef _Pointer pointer;
641 pointer __left_;
642
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000643 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000644 __tree_end_node() _NOEXCEPT : __left_() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000645};
646
647template <class _VoidPtr>
648class __tree_node_base
Eric Fiseliera00b4842016-02-20 05:28:30 +0000649 : public __tree_node_base_types<_VoidPtr>::__end_node_type
Howard Hinnantc51e1022010-05-11 19:42:16 +0000650{
Eric Fiseliera00b4842016-02-20 05:28:30 +0000651 typedef __tree_node_base_types<_VoidPtr> _NodeBaseTypes;
652
Howard Hinnantc51e1022010-05-11 19:42:16 +0000653 __tree_node_base(const __tree_node_base&);
654 __tree_node_base& operator=(const __tree_node_base&);
655public:
Eric Fiseliera00b4842016-02-20 05:28:30 +0000656 typedef typename _NodeBaseTypes::__node_base_pointer pointer;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000657
658 pointer __right_;
659 pointer __parent_;
660 bool __is_black_;
661
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000662 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant1113b5e2011-06-04 17:10:24 +0000663 __tree_node_base() _NOEXCEPT
664 : __right_(), __parent_(), __is_black_(false) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000665};
666
667template <class _Tp, class _VoidPtr>
668class __tree_node
669 : public __tree_node_base<_VoidPtr>
670{
671public:
Eric Fiseliera00b4842016-02-20 05:28:30 +0000672 typedef _Tp __node_value_type;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000673
Eric Fiseliera00b4842016-02-20 05:28:30 +0000674 __node_value_type __value_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000675
Howard Hinnant74279a52010-09-04 23:28:19 +0000676#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000677 template <class ..._Args>
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000678 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000679 explicit __tree_node(_Args&& ...__args)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000680 : __value_(_VSTD::forward<_Args>(__args)...) {}
Howard Hinnant74279a52010-09-04 23:28:19 +0000681#else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000682 _LIBCPP_INLINE_VISIBILITY
Eric Fiseliera00b4842016-02-20 05:28:30 +0000683 explicit __tree_node(const __node_value_type& __v)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000684 : __value_(__v) {}
Howard Hinnant74279a52010-09-04 23:28:19 +0000685#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000686};
687
Howard Hinnantc51e1022010-05-11 19:42:16 +0000688template <class _Tp, class _NodePtr, class _DiffType>
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000689class _LIBCPP_TYPE_VIS_ONLY __tree_iterator
Howard Hinnantc51e1022010-05-11 19:42:16 +0000690{
Eric Fiseliera00b4842016-02-20 05:28:30 +0000691 typedef __tree_node_types<_NodePtr> _NodeTypes;
692 typedef _NodePtr __node_pointer;
693 typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
694 typedef pointer_traits<__node_pointer> __pointer_traits;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000695
696 __node_pointer __ptr_;
697
Howard Hinnantc51e1022010-05-11 19:42:16 +0000698public:
Eric Fiseliera00b4842016-02-20 05:28:30 +0000699 typedef bidirectional_iterator_tag iterator_category;
700 typedef _Tp value_type;
701 typedef _DiffType difference_type;
702 typedef value_type& reference;
703 typedef typename _NodeTypes::__node_value_type_pointer pointer;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000704
Marshall Clow8fc07302013-08-08 21:52:50 +0000705 _LIBCPP_INLINE_VISIBILITY __tree_iterator() _NOEXCEPT
706#if _LIBCPP_STD_VER > 11
707 : __ptr_(nullptr)
708#endif
709 {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000710
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000711 _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;}
Howard Hinnant2d0046b2013-06-19 21:29:40 +0000712 _LIBCPP_INLINE_VISIBILITY pointer operator->() const
713 {return pointer_traits<pointer>::pointer_to(__ptr_->__value_);}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000714
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000715 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier44f9fd02015-03-03 20:10:01 +0000716 __tree_iterator& operator++() {
717 __ptr_ = static_cast<__node_pointer>(
Eric Fiseliera00b4842016-02-20 05:28:30 +0000718 __tree_next(static_cast<__node_base_pointer>(__ptr_)));
Eric Fiselier44f9fd02015-03-03 20:10:01 +0000719 return *this;
720 }
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000721 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000722 __tree_iterator operator++(int)
723 {__tree_iterator __t(*this); ++(*this); return __t;}
724
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000725 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier44f9fd02015-03-03 20:10:01 +0000726 __tree_iterator& operator--() {
727 __ptr_ = static_cast<__node_pointer>(
Eric Fiseliera00b4842016-02-20 05:28:30 +0000728 __tree_prev(static_cast<__node_base_pointer>(__ptr_)));
Eric Fiselier44f9fd02015-03-03 20:10:01 +0000729 return *this;
730 }
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000731 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000732 __tree_iterator operator--(int)
733 {__tree_iterator __t(*this); --(*this); return __t;}
734
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000735 friend _LIBCPP_INLINE_VISIBILITY
736 bool operator==(const __tree_iterator& __x, const __tree_iterator& __y)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000737 {return __x.__ptr_ == __y.__ptr_;}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000738 friend _LIBCPP_INLINE_VISIBILITY
739 bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000740 {return !(__x == __y);}
741
742private:
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000743 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000744 explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000745 template <class, class, class> friend class __tree;
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000746 template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator;
747 template <class> friend class _LIBCPP_TYPE_VIS_ONLY __map_iterator;
748 template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY map;
749 template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multimap;
750 template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY set;
751 template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multiset;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000752};
753
Eric Fiseliera00b4842016-02-20 05:28:30 +0000754template <class _Tp, class _NodePtr, class _DiffType>
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000755class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator
Howard Hinnantc51e1022010-05-11 19:42:16 +0000756{
Eric Fiseliera00b4842016-02-20 05:28:30 +0000757 typedef __tree_node_types<_NodePtr> _NodeTypes;
758 typedef typename _NodeTypes::__node_pointer __node_pointer;
759 typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
760 typedef pointer_traits<__node_pointer> __pointer_traits;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000761
762 __node_pointer __ptr_;
763
Howard Hinnantc51e1022010-05-11 19:42:16 +0000764public:
Eric Fiseliera00b4842016-02-20 05:28:30 +0000765 typedef bidirectional_iterator_tag iterator_category;
766 typedef _Tp value_type;
767 typedef _DiffType difference_type;
768 typedef const value_type& reference;
769 typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000770
Marshall Clow8fc07302013-08-08 21:52:50 +0000771 _LIBCPP_INLINE_VISIBILITY __tree_const_iterator() _NOEXCEPT
772#if _LIBCPP_STD_VER > 11
773 : __ptr_(nullptr)
774#endif
775 {}
776
Howard Hinnantc51e1022010-05-11 19:42:16 +0000777private:
Eric Fiseliera00b4842016-02-20 05:28:30 +0000778 typedef __tree_iterator<value_type, __node_pointer, difference_type>
779 __non_const_iterator;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000780public:
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000781 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000782 __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT
783 : __ptr_(__p.__ptr_) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000784
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000785 _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;}
Howard Hinnant2d0046b2013-06-19 21:29:40 +0000786 _LIBCPP_INLINE_VISIBILITY pointer operator->() const
787 {return pointer_traits<pointer>::pointer_to(__ptr_->__value_);}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000788
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000789 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier44f9fd02015-03-03 20:10:01 +0000790 __tree_const_iterator& operator++() {
Eric Fiselier44f9fd02015-03-03 20:10:01 +0000791 __ptr_ = static_cast<__node_pointer>(
792 __tree_next(static_cast<__node_base_pointer>(__ptr_)));
793 return *this;
794 }
795
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000796 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000797 __tree_const_iterator operator++(int)
798 {__tree_const_iterator __t(*this); ++(*this); return __t;}
799
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000800 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier44f9fd02015-03-03 20:10:01 +0000801 __tree_const_iterator& operator--() {
Eric Fiselier44f9fd02015-03-03 20:10:01 +0000802 __ptr_ = static_cast<__node_pointer>(
803 __tree_prev(static_cast<__node_base_pointer>(__ptr_)));
804 return *this;
805 }
806
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000807 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000808 __tree_const_iterator operator--(int)
809 {__tree_const_iterator __t(*this); --(*this); return __t;}
810
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000811 friend _LIBCPP_INLINE_VISIBILITY
812 bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000813 {return __x.__ptr_ == __y.__ptr_;}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000814 friend _LIBCPP_INLINE_VISIBILITY
815 bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000816 {return !(__x == __y);}
817
818private:
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000819 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000820 explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT
821 : __ptr_(__p) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000822 template <class, class, class> friend class __tree;
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000823 template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY map;
824 template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multimap;
825 template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY set;
826 template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multiset;
827 template <class> friend class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000828};
829
830template <class _Tp, class _Compare, class _Allocator>
831class __tree
832{
833public:
834 typedef _Tp value_type;
835 typedef _Compare value_compare;
836 typedef _Allocator allocator_type;
Eric Fiseliera00b4842016-02-20 05:28:30 +0000837
838private:
Howard Hinnantc51e1022010-05-11 19:42:16 +0000839 typedef allocator_traits<allocator_type> __alloc_traits;
Eric Fiseliera00b4842016-02-20 05:28:30 +0000840 typedef typename __make_tree_node_types<value_type,
841 typename __alloc_traits::void_pointer>::type
842 _NodeTypes;
843public:
844 typedef typename _NodeTypes::__node_value_type __node_value_type;
845 typedef typename _NodeTypes::__container_value_type __container_value_type;
846
Howard Hinnantc51e1022010-05-11 19:42:16 +0000847 typedef typename __alloc_traits::pointer pointer;
848 typedef typename __alloc_traits::const_pointer const_pointer;
849 typedef typename __alloc_traits::size_type size_type;
850 typedef typename __alloc_traits::difference_type difference_type;
851
Eric Fiseliera00b4842016-02-20 05:28:30 +0000852public:
853 typedef typename _NodeTypes::__void_pointer __void_pointer;
Howard Hinnant2d0046b2013-06-19 21:29:40 +0000854
Eric Fiseliera00b4842016-02-20 05:28:30 +0000855 typedef typename _NodeTypes::__node_type __node;
856 typedef typename _NodeTypes::__node_pointer __node_pointer;
857 typedef typename _NodeTypes::__node_pointer __node_const_pointer;
858
859 typedef typename _NodeTypes::__node_base_type __node_base;
860 typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
861 typedef typename _NodeTypes::__node_base_pointer __node_base_const_pointer;
862
863 typedef typename _NodeTypes::__end_node_type __end_node_t;
864 typedef typename _NodeTypes::__end_node_pointer __end_node_ptr;
865 typedef typename _NodeTypes::__end_node_pointer __end_node_const_ptr;
866
Marshall Clow940e01c2015-04-07 05:21:38 +0000867 typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator;
Eric Fiseliera00b4842016-02-20 05:28:30 +0000868 typedef allocator_traits<__node_allocator> __node_traits;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000869
Eric Fiseliera00b4842016-02-20 05:28:30 +0000870private:
871 // check for sane allocator pointer rebinding semantics. Rebinding the
872 // allocator for a new pointer type should be exactly the same as rebinding
873 // the pointer using 'pointer_traits'.
874 static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value),
875 "Allocator does not rebind pointers in a sane manner.");
876 typedef typename __rebind_alloc_helper<__node_traits, __node_base>::type
877 __node_base_allocator;
878 typedef allocator_traits<__node_base_allocator> __node_base_traits;
879 static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value),
880 "Allocator does not rebind pointers in a sane manner.");
881
882private:
Howard Hinnantc51e1022010-05-11 19:42:16 +0000883 __node_pointer __begin_node_;
884 __compressed_pair<__end_node_t, __node_allocator> __pair1_;
885 __compressed_pair<size_type, value_compare> __pair3_;
886
887public:
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000888 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000889 __node_pointer __end_node() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000890 {
891 return static_cast<__node_pointer>
892 (
893 pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first())
894 );
895 }
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000896 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000897 __node_const_pointer __end_node() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000898 {
899 return static_cast<__node_const_pointer>
900 (
Howard Hinnant2d0046b2013-06-19 21:29:40 +0000901 pointer_traits<__end_node_const_ptr>::pointer_to(const_cast<__end_node_t&>(__pair1_.first()))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000902 );
903 }
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000904 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000905 __node_allocator& __node_alloc() _NOEXCEPT {return __pair1_.second();}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000906private:
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000907 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000908 const __node_allocator& __node_alloc() const _NOEXCEPT
909 {return __pair1_.second();}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000910 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000911 __node_pointer& __begin_node() _NOEXCEPT {return __begin_node_;}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000912 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000913 const __node_pointer& __begin_node() const _NOEXCEPT {return __begin_node_;}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000914public:
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000915 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000916 allocator_type __alloc() const _NOEXCEPT
917 {return allocator_type(__node_alloc());}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000918private:
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000919 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000920 size_type& size() _NOEXCEPT {return __pair3_.first();}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000921public:
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000922 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000923 const size_type& size() const _NOEXCEPT {return __pair3_.first();}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000924 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000925 value_compare& value_comp() _NOEXCEPT {return __pair3_.second();}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000926 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000927 const value_compare& value_comp() const _NOEXCEPT
928 {return __pair3_.second();}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000929public:
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000930 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000931 __node_pointer __root() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000932 {return static_cast<__node_pointer> (__end_node()->__left_);}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000933 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000934 __node_const_pointer __root() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000935 {return static_cast<__node_const_pointer>(__end_node()->__left_);}
936
937 typedef __tree_iterator<value_type, __node_pointer, difference_type> iterator;
Howard Hinnant2d0046b2013-06-19 21:29:40 +0000938 typedef __tree_const_iterator<value_type, __node_pointer, difference_type> const_iterator;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000939
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000940 explicit __tree(const value_compare& __comp)
941 _NOEXCEPT_(
942 is_nothrow_default_constructible<__node_allocator>::value &&
943 is_nothrow_copy_constructible<value_compare>::value);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000944 explicit __tree(const allocator_type& __a);
945 __tree(const value_compare& __comp, const allocator_type& __a);
946 __tree(const __tree& __t);
947 __tree& operator=(const __tree& __t);
948 template <class _InputIterator>
949 void __assign_unique(_InputIterator __first, _InputIterator __last);
950 template <class _InputIterator>
951 void __assign_multi(_InputIterator __first, _InputIterator __last);
Howard Hinnant74279a52010-09-04 23:28:19 +0000952#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000953 __tree(__tree&& __t)
954 _NOEXCEPT_(
955 is_nothrow_move_constructible<__node_allocator>::value &&
956 is_nothrow_move_constructible<value_compare>::value);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000957 __tree(__tree&& __t, const allocator_type& __a);
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000958 __tree& operator=(__tree&& __t)
959 _NOEXCEPT_(
960 __node_traits::propagate_on_container_move_assignment::value &&
961 is_nothrow_move_assignable<value_compare>::value &&
962 is_nothrow_move_assignable<__node_allocator>::value);
Howard Hinnant74279a52010-09-04 23:28:19 +0000963#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantc51e1022010-05-11 19:42:16 +0000964
965 ~__tree();
966
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000967 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000968 iterator begin() _NOEXCEPT {return iterator(__begin_node());}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000969 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000970 const_iterator begin() const _NOEXCEPT {return const_iterator(__begin_node());}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000971 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000972 iterator end() _NOEXCEPT {return iterator(__end_node());}
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000973 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000974 const_iterator end() const _NOEXCEPT {return const_iterator(__end_node());}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000975
Howard Hinnant8e29cda2010-09-21 20:16:37 +0000976 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000977 size_type max_size() const _NOEXCEPT
978 {return __node_traits::max_size(__node_alloc());}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000979
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000980 void clear() _NOEXCEPT;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000981
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +0000982 void swap(__tree& __t)
983 _NOEXCEPT_(
Marshall Clow8982dcd2015-07-13 20:04:56 +0000984 __is_nothrow_swappable<value_compare>::value
985#if _LIBCPP_STD_VER <= 11
986 && (!__node_traits::propagate_on_container_swap::value ||
987 __is_nothrow_swappable<__node_allocator>::value)
988#endif
989 );
Howard Hinnantc51e1022010-05-11 19:42:16 +0000990
Howard Hinnant74279a52010-09-04 23:28:19 +0000991#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
992#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000993 template <class... _Args>
994 pair<iterator, bool>
995 __emplace_unique(_Args&&... __args);
996 template <class... _Args>
997 iterator
998 __emplace_multi(_Args&&... __args);
999
1000 template <class... _Args>
1001 iterator
1002 __emplace_hint_unique(const_iterator __p, _Args&&... __args);
1003 template <class... _Args>
1004 iterator
1005 __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant74279a52010-09-04 23:28:19 +00001006#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001007
Howard Hinnantc834c512011-11-29 18:15:50 +00001008 template <class _Vp>
1009 pair<iterator, bool> __insert_unique(_Vp&& __v);
1010 template <class _Vp>
1011 iterator __insert_unique(const_iterator __p, _Vp&& __v);
1012 template <class _Vp>
1013 iterator __insert_multi(_Vp&& __v);
1014 template <class _Vp>
1015 iterator __insert_multi(const_iterator __p, _Vp&& __v);
Howard Hinnantc5bc8672011-03-10 17:27:57 +00001016#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantc51e1022010-05-11 19:42:16 +00001017
1018 pair<iterator, bool> __insert_unique(const value_type& __v);
1019 iterator __insert_unique(const_iterator __p, const value_type& __v);
1020 iterator __insert_multi(const value_type& __v);
1021 iterator __insert_multi(const_iterator __p, const value_type& __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001022
Marshall Clowd430d022016-01-05 19:32:41 +00001023#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1024 pair<iterator, bool> __insert_unique( value_type&& __v);
1025 iterator __insert_unique(const_iterator __p, value_type&& __v);
1026 iterator __insert_multi( value_type&& __v);
1027 iterator __insert_multi(const_iterator __p, value_type&& __v);
1028#endif
1029
Howard Hinnantc51e1022010-05-11 19:42:16 +00001030 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
1031 iterator __node_insert_unique(const_iterator __p,
1032 __node_pointer __nd);
1033
1034 iterator __node_insert_multi(__node_pointer __nd);
1035 iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
1036
1037 iterator erase(const_iterator __p);
1038 iterator erase(const_iterator __f, const_iterator __l);
1039 template <class _Key>
1040 size_type __erase_unique(const _Key& __k);
1041 template <class _Key>
1042 size_type __erase_multi(const _Key& __k);
1043
1044 void __insert_node_at(__node_base_pointer __parent,
1045 __node_base_pointer& __child,
1046 __node_base_pointer __new_node);
1047
1048 template <class _Key>
1049 iterator find(const _Key& __v);
1050 template <class _Key>
1051 const_iterator find(const _Key& __v) const;
1052
1053 template <class _Key>
1054 size_type __count_unique(const _Key& __k) const;
1055 template <class _Key>
1056 size_type __count_multi(const _Key& __k) const;
1057
1058 template <class _Key>
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001059 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001060 iterator lower_bound(const _Key& __v)
1061 {return __lower_bound(__v, __root(), __end_node());}
1062 template <class _Key>
1063 iterator __lower_bound(const _Key& __v,
1064 __node_pointer __root,
1065 __node_pointer __result);
1066 template <class _Key>
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001067 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001068 const_iterator lower_bound(const _Key& __v) const
1069 {return __lower_bound(__v, __root(), __end_node());}
1070 template <class _Key>
1071 const_iterator __lower_bound(const _Key& __v,
1072 __node_const_pointer __root,
1073 __node_const_pointer __result) const;
1074 template <class _Key>
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001075 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001076 iterator upper_bound(const _Key& __v)
1077 {return __upper_bound(__v, __root(), __end_node());}
1078 template <class _Key>
1079 iterator __upper_bound(const _Key& __v,
1080 __node_pointer __root,
1081 __node_pointer __result);
1082 template <class _Key>
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001083 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001084 const_iterator upper_bound(const _Key& __v) const
1085 {return __upper_bound(__v, __root(), __end_node());}
1086 template <class _Key>
1087 const_iterator __upper_bound(const _Key& __v,
1088 __node_const_pointer __root,
1089 __node_const_pointer __result) const;
1090 template <class _Key>
1091 pair<iterator, iterator>
1092 __equal_range_unique(const _Key& __k);
1093 template <class _Key>
1094 pair<const_iterator, const_iterator>
1095 __equal_range_unique(const _Key& __k) const;
1096
1097 template <class _Key>
1098 pair<iterator, iterator>
1099 __equal_range_multi(const _Key& __k);
1100 template <class _Key>
1101 pair<const_iterator, const_iterator>
1102 __equal_range_multi(const _Key& __k) const;
1103
Howard Hinnantc834c512011-11-29 18:15:50 +00001104 typedef __tree_node_destructor<__node_allocator> _Dp;
1105 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001106
Howard Hinnant1113b5e2011-06-04 17:10:24 +00001107 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001108private:
Howard Hinnant6108fd72011-04-03 20:05:29 +00001109 typename __node_base::pointer&
1110 __find_leaf_low(typename __node_base::pointer& __parent, const value_type& __v);
1111 typename __node_base::pointer&
1112 __find_leaf_high(typename __node_base::pointer& __parent, const value_type& __v);
1113 typename __node_base::pointer&
Howard Hinnantc51e1022010-05-11 19:42:16 +00001114 __find_leaf(const_iterator __hint,
Howard Hinnant6108fd72011-04-03 20:05:29 +00001115 typename __node_base::pointer& __parent, const value_type& __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001116 template <class _Key>
Howard Hinnant6108fd72011-04-03 20:05:29 +00001117 typename __node_base::pointer&
1118 __find_equal(typename __node_base::pointer& __parent, const _Key& __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001119 template <class _Key>
Howard Hinnant6108fd72011-04-03 20:05:29 +00001120 typename __node_base::pointer&
1121 __find_equal(const_iterator __hint, typename __node_base::pointer& __parent,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001122 const _Key& __v);
1123
Howard Hinnant74279a52010-09-04 23:28:19 +00001124#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001125 template <class ..._Args>
1126 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnant74279a52010-09-04 23:28:19 +00001127#else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001128 __node_holder __construct_node(const value_type& __v);
1129#endif
1130
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001131 void destroy(__node_pointer __nd) _NOEXCEPT;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001132
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001133 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001134 void __copy_assign_alloc(const __tree& __t)
1135 {__copy_assign_alloc(__t, integral_constant<bool,
1136 __node_traits::propagate_on_container_copy_assignment::value>());}
1137
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001138 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001139 void __copy_assign_alloc(const __tree& __t, true_type)
1140 {__node_alloc() = __t.__node_alloc();}
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001141 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001142 void __copy_assign_alloc(const __tree& __t, false_type) {}
1143
1144 void __move_assign(__tree& __t, false_type);
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001145 void __move_assign(__tree& __t, true_type)
1146 _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value &&
1147 is_nothrow_move_assignable<__node_allocator>::value);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001148
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001149 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001150 void __move_assign_alloc(__tree& __t)
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001151 _NOEXCEPT_(
1152 !__node_traits::propagate_on_container_move_assignment::value ||
1153 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001154 {__move_assign_alloc(__t, integral_constant<bool,
1155 __node_traits::propagate_on_container_move_assignment::value>());}
1156
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001157 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001158 void __move_assign_alloc(__tree& __t, true_type)
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001159 _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001160 {__node_alloc() = _VSTD::move(__t.__node_alloc());}
Howard Hinnant8e29cda2010-09-21 20:16:37 +00001161 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001162 void __move_assign_alloc(__tree& __t, false_type) _NOEXCEPT {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001163
Howard Hinnantc51e1022010-05-11 19:42:16 +00001164 __node_pointer __detach();
1165 static __node_pointer __detach(__node_pointer);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001166
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00001167 template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY map;
1168 template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multimap;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001169};
1170
1171template <class _Tp, class _Compare, class _Allocator>
1172__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp)
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001173 _NOEXCEPT_(
1174 is_nothrow_default_constructible<__node_allocator>::value &&
1175 is_nothrow_copy_constructible<value_compare>::value)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001176 : __pair3_(0, __comp)
1177{
1178 __begin_node() = __end_node();
1179}
1180
1181template <class _Tp, class _Compare, class _Allocator>
1182__tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a)
Eric Fiselier9975e702015-07-18 23:56:04 +00001183 : __begin_node_(__node_pointer()),
1184 __pair1_(__node_allocator(__a)),
Howard Hinnantc51e1022010-05-11 19:42:16 +00001185 __pair3_(0)
1186{
1187 __begin_node() = __end_node();
1188}
1189
1190template <class _Tp, class _Compare, class _Allocator>
1191__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp,
1192 const allocator_type& __a)
Eric Fiselier9975e702015-07-18 23:56:04 +00001193 : __begin_node_(__node_pointer()),
1194 __pair1_(__node_allocator(__a)),
Howard Hinnantc51e1022010-05-11 19:42:16 +00001195 __pair3_(0, __comp)
1196{
1197 __begin_node() = __end_node();
1198}
1199
1200// Precondition: size() != 0
1201template <class _Tp, class _Compare, class _Allocator>
1202typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
1203__tree<_Tp, _Compare, _Allocator>::__detach()
1204{
1205 __node_pointer __cache = __begin_node();
1206 __begin_node() = __end_node();
1207 __end_node()->__left_->__parent_ = nullptr;
1208 __end_node()->__left_ = nullptr;
1209 size() = 0;
1210 // __cache->__left_ == nullptr
1211 if (__cache->__right_ != nullptr)
1212 __cache = static_cast<__node_pointer>(__cache->__right_);
1213 // __cache->__left_ == nullptr
1214 // __cache->__right_ == nullptr
1215 return __cache;
1216}
1217
1218// Precondition: __cache != nullptr
1219// __cache->left_ == nullptr
1220// __cache->right_ == nullptr
1221// This is no longer a red-black tree
1222template <class _Tp, class _Compare, class _Allocator>
1223typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
1224__tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache)
1225{
1226 if (__cache->__parent_ == nullptr)
1227 return nullptr;
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001228 if (__tree_is_left_child(static_cast<__node_base_pointer>(__cache)))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001229 {
1230 __cache->__parent_->__left_ = nullptr;
1231 __cache = static_cast<__node_pointer>(__cache->__parent_);
1232 if (__cache->__right_ == nullptr)
1233 return __cache;
1234 return static_cast<__node_pointer>(__tree_leaf(__cache->__right_));
1235 }
1236 // __cache is right child
1237 __cache->__parent_->__right_ = nullptr;
1238 __cache = static_cast<__node_pointer>(__cache->__parent_);
1239 if (__cache->__left_ == nullptr)
1240 return __cache;
1241 return static_cast<__node_pointer>(__tree_leaf(__cache->__left_));
1242}
1243
1244template <class _Tp, class _Compare, class _Allocator>
1245__tree<_Tp, _Compare, _Allocator>&
1246__tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t)
1247{
1248 if (this != &__t)
1249 {
1250 value_comp() = __t.value_comp();
1251 __copy_assign_alloc(__t);
1252 __assign_multi(__t.begin(), __t.end());
1253 }
1254 return *this;
1255}
1256
1257template <class _Tp, class _Compare, class _Allocator>
1258template <class _InputIterator>
1259void
1260__tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last)
1261{
1262 if (size() != 0)
1263 {
1264 __node_pointer __cache = __detach();
Howard Hinnant72f73582010-08-11 17:04:31 +00001265#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001266 try
1267 {
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001268#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001269 for (; __cache != nullptr && __first != __last; ++__first)
1270 {
1271 __cache->__value_ = *__first;
1272 __node_pointer __next = __detach(__cache);
1273 __node_insert_unique(__cache);
1274 __cache = __next;
1275 }
Howard Hinnant72f73582010-08-11 17:04:31 +00001276#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001277 }
1278 catch (...)
1279 {
1280 while (__cache->__parent_ != nullptr)
1281 __cache = static_cast<__node_pointer>(__cache->__parent_);
1282 destroy(__cache);
1283 throw;
1284 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001285#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001286 if (__cache != nullptr)
1287 {
1288 while (__cache->__parent_ != nullptr)
1289 __cache = static_cast<__node_pointer>(__cache->__parent_);
1290 destroy(__cache);
1291 }
1292 }
1293 for (; __first != __last; ++__first)
1294 __insert_unique(*__first);
1295}
1296
1297template <class _Tp, class _Compare, class _Allocator>
1298template <class _InputIterator>
1299void
1300__tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last)
1301{
1302 if (size() != 0)
1303 {
1304 __node_pointer __cache = __detach();
Howard Hinnant72f73582010-08-11 17:04:31 +00001305#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001306 try
1307 {
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001308#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001309 for (; __cache != nullptr && __first != __last; ++__first)
1310 {
1311 __cache->__value_ = *__first;
1312 __node_pointer __next = __detach(__cache);
1313 __node_insert_multi(__cache);
1314 __cache = __next;
1315 }
Howard Hinnant72f73582010-08-11 17:04:31 +00001316#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001317 }
1318 catch (...)
1319 {
1320 while (__cache->__parent_ != nullptr)
1321 __cache = static_cast<__node_pointer>(__cache->__parent_);
1322 destroy(__cache);
1323 throw;
1324 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001325#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001326 if (__cache != nullptr)
1327 {
1328 while (__cache->__parent_ != nullptr)
1329 __cache = static_cast<__node_pointer>(__cache->__parent_);
1330 destroy(__cache);
1331 }
1332 }
1333 for (; __first != __last; ++__first)
1334 __insert_multi(*__first);
1335}
1336
1337template <class _Tp, class _Compare, class _Allocator>
1338__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
1339 : __begin_node_(__node_pointer()),
1340 __pair1_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())),
1341 __pair3_(0, __t.value_comp())
1342{
1343 __begin_node() = __end_node();
1344}
1345
Howard Hinnant74279a52010-09-04 23:28:19 +00001346#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantc51e1022010-05-11 19:42:16 +00001347
1348template <class _Tp, class _Compare, class _Allocator>
1349__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t)
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001350 _NOEXCEPT_(
1351 is_nothrow_move_constructible<__node_allocator>::value &&
1352 is_nothrow_move_constructible<value_compare>::value)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001353 : __begin_node_(_VSTD::move(__t.__begin_node_)),
1354 __pair1_(_VSTD::move(__t.__pair1_)),
1355 __pair3_(_VSTD::move(__t.__pair3_))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001356{
1357 if (size() == 0)
1358 __begin_node() = __end_node();
1359 else
1360 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001361 __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001362 __t.__begin_node() = __t.__end_node();
1363 __t.__end_node()->__left_ = nullptr;
1364 __t.size() = 0;
1365 }
1366}
1367
1368template <class _Tp, class _Compare, class _Allocator>
1369__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a)
1370 : __pair1_(__node_allocator(__a)),
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001371 __pair3_(0, _VSTD::move(__t.value_comp()))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001372{
1373 if (__a == __t.__alloc())
1374 {
1375 if (__t.size() == 0)
1376 __begin_node() = __end_node();
1377 else
1378 {
1379 __begin_node() = __t.__begin_node();
1380 __end_node()->__left_ = __t.__end_node()->__left_;
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001381 __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001382 size() = __t.size();
1383 __t.__begin_node() = __t.__end_node();
1384 __t.__end_node()->__left_ = nullptr;
1385 __t.size() = 0;
1386 }
1387 }
1388 else
1389 {
1390 __begin_node() = __end_node();
1391 }
1392}
1393
1394template <class _Tp, class _Compare, class _Allocator>
1395void
1396__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type)
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001397 _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value &&
1398 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001399{
1400 destroy(static_cast<__node_pointer>(__end_node()->__left_));
1401 __begin_node_ = __t.__begin_node_;
1402 __pair1_.first() = __t.__pair1_.first();
1403 __move_assign_alloc(__t);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001404 __pair3_ = _VSTD::move(__t.__pair3_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001405 if (size() == 0)
1406 __begin_node() = __end_node();
1407 else
1408 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001409 __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001410 __t.__begin_node() = __t.__end_node();
1411 __t.__end_node()->__left_ = nullptr;
1412 __t.size() = 0;
1413 }
1414}
1415
1416template <class _Tp, class _Compare, class _Allocator>
1417void
1418__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type)
1419{
1420 if (__node_alloc() == __t.__node_alloc())
1421 __move_assign(__t, true_type());
1422 else
1423 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001424 value_comp() = _VSTD::move(__t.value_comp());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001425 const_iterator __e = end();
1426 if (size() != 0)
1427 {
1428 __node_pointer __cache = __detach();
Howard Hinnant72f73582010-08-11 17:04:31 +00001429#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001430 try
1431 {
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001432#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001433 while (__cache != nullptr && __t.size() != 0)
1434 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001435 __cache->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001436 __node_pointer __next = __detach(__cache);
1437 __node_insert_multi(__cache);
1438 __cache = __next;
1439 }
Howard Hinnant72f73582010-08-11 17:04:31 +00001440#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001441 }
1442 catch (...)
1443 {
1444 while (__cache->__parent_ != nullptr)
1445 __cache = static_cast<__node_pointer>(__cache->__parent_);
1446 destroy(__cache);
1447 throw;
1448 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001449#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001450 if (__cache != nullptr)
1451 {
1452 while (__cache->__parent_ != nullptr)
1453 __cache = static_cast<__node_pointer>(__cache->__parent_);
1454 destroy(__cache);
1455 }
1456 }
1457 while (__t.size() != 0)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001458 __insert_multi(__e, _VSTD::move(__t.remove(__t.begin())->__value_));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001459 }
1460}
1461
1462template <class _Tp, class _Compare, class _Allocator>
1463__tree<_Tp, _Compare, _Allocator>&
1464__tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t)
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001465 _NOEXCEPT_(
1466 __node_traits::propagate_on_container_move_assignment::value &&
1467 is_nothrow_move_assignable<value_compare>::value &&
1468 is_nothrow_move_assignable<__node_allocator>::value)
1469
Howard Hinnantc51e1022010-05-11 19:42:16 +00001470{
1471 __move_assign(__t, integral_constant<bool,
1472 __node_traits::propagate_on_container_move_assignment::value>());
1473 return *this;
1474}
1475
Howard Hinnant74279a52010-09-04 23:28:19 +00001476#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantc51e1022010-05-11 19:42:16 +00001477
1478template <class _Tp, class _Compare, class _Allocator>
1479__tree<_Tp, _Compare, _Allocator>::~__tree()
1480{
1481 destroy(__root());
1482}
1483
1484template <class _Tp, class _Compare, class _Allocator>
1485void
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001486__tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001487{
1488 if (__nd != nullptr)
1489 {
1490 destroy(static_cast<__node_pointer>(__nd->__left_));
1491 destroy(static_cast<__node_pointer>(__nd->__right_));
1492 __node_allocator& __na = __node_alloc();
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001493 __node_traits::destroy(__na, _VSTD::addressof(__nd->__value_));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001494 __node_traits::deallocate(__na, __nd, 1);
1495 }
1496}
1497
1498template <class _Tp, class _Compare, class _Allocator>
1499void
1500__tree<_Tp, _Compare, _Allocator>::swap(__tree& __t)
Marshall Clow8982dcd2015-07-13 20:04:56 +00001501 _NOEXCEPT_(
1502 __is_nothrow_swappable<value_compare>::value
1503#if _LIBCPP_STD_VER <= 11
1504 && (!__node_traits::propagate_on_container_swap::value ||
1505 __is_nothrow_swappable<__node_allocator>::value)
1506#endif
1507 )
Howard Hinnantc51e1022010-05-11 19:42:16 +00001508{
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001509 using _VSTD::swap;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001510 swap(__begin_node_, __t.__begin_node_);
1511 swap(__pair1_.first(), __t.__pair1_.first());
Marshall Clow8982dcd2015-07-13 20:04:56 +00001512 __swap_allocator(__node_alloc(), __t.__node_alloc());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001513 __pair3_.swap(__t.__pair3_);
1514 if (size() == 0)
1515 __begin_node() = __end_node();
1516 else
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001517 __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001518 if (__t.size() == 0)
1519 __t.__begin_node() = __t.__end_node();
1520 else
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001521 __t.__end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__t.__end_node());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001522}
1523
1524template <class _Tp, class _Compare, class _Allocator>
1525void
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00001526__tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001527{
1528 destroy(__root());
1529 size() = 0;
1530 __begin_node() = __end_node();
1531 __end_node()->__left_ = nullptr;
1532}
1533
1534// Find lower_bound place to insert
1535// Set __parent to parent of null leaf
1536// Return reference to null leaf
1537template <class _Tp, class _Compare, class _Allocator>
Howard Hinnant6108fd72011-04-03 20:05:29 +00001538typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
1539__tree<_Tp, _Compare, _Allocator>::__find_leaf_low(typename __node_base::pointer& __parent,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001540 const value_type& __v)
1541{
1542 __node_pointer __nd = __root();
1543 if (__nd != nullptr)
1544 {
1545 while (true)
1546 {
1547 if (value_comp()(__nd->__value_, __v))
1548 {
1549 if (__nd->__right_ != nullptr)
1550 __nd = static_cast<__node_pointer>(__nd->__right_);
1551 else
1552 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001553 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001554 return __parent->__right_;
1555 }
1556 }
1557 else
1558 {
1559 if (__nd->__left_ != nullptr)
1560 __nd = static_cast<__node_pointer>(__nd->__left_);
1561 else
1562 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001563 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001564 return __parent->__left_;
1565 }
1566 }
1567 }
1568 }
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001569 __parent = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001570 return __parent->__left_;
1571}
1572
1573// Find upper_bound place to insert
1574// Set __parent to parent of null leaf
1575// Return reference to null leaf
1576template <class _Tp, class _Compare, class _Allocator>
Howard Hinnant6108fd72011-04-03 20:05:29 +00001577typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
1578__tree<_Tp, _Compare, _Allocator>::__find_leaf_high(typename __node_base::pointer& __parent,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001579 const value_type& __v)
1580{
1581 __node_pointer __nd = __root();
1582 if (__nd != nullptr)
1583 {
1584 while (true)
1585 {
1586 if (value_comp()(__v, __nd->__value_))
1587 {
1588 if (__nd->__left_ != nullptr)
1589 __nd = static_cast<__node_pointer>(__nd->__left_);
1590 else
1591 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001592 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001593 return __parent->__left_;
1594 }
1595 }
1596 else
1597 {
1598 if (__nd->__right_ != nullptr)
1599 __nd = static_cast<__node_pointer>(__nd->__right_);
1600 else
1601 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001602 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001603 return __parent->__right_;
1604 }
1605 }
1606 }
1607 }
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001608 __parent = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001609 return __parent->__left_;
1610}
1611
1612// Find leaf place to insert closest to __hint
1613// First check prior to __hint.
1614// Next check after __hint.
1615// Next do O(log N) search.
1616// Set __parent to parent of null leaf
1617// Return reference to null leaf
1618template <class _Tp, class _Compare, class _Allocator>
Howard Hinnant6108fd72011-04-03 20:05:29 +00001619typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
Howard Hinnantc51e1022010-05-11 19:42:16 +00001620__tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint,
Howard Hinnant6108fd72011-04-03 20:05:29 +00001621 typename __node_base::pointer& __parent,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001622 const value_type& __v)
1623{
1624 if (__hint == end() || !value_comp()(*__hint, __v)) // check before
1625 {
1626 // __v <= *__hint
1627 const_iterator __prior = __hint;
1628 if (__prior == begin() || !value_comp()(__v, *--__prior))
1629 {
1630 // *prev(__hint) <= __v <= *__hint
1631 if (__hint.__ptr_->__left_ == nullptr)
1632 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001633 __parent = static_cast<__node_base_pointer>(__hint.__ptr_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001634 return __parent->__left_;
1635 }
1636 else
1637 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001638 __parent = static_cast<__node_base_pointer>(__prior.__ptr_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001639 return __parent->__right_;
1640 }
1641 }
1642 // __v < *prev(__hint)
1643 return __find_leaf_high(__parent, __v);
1644 }
1645 // else __v > *__hint
1646 return __find_leaf_low(__parent, __v);
1647}
1648
1649// Find place to insert if __v doesn't exist
1650// Set __parent to parent of null leaf
1651// Return reference to null leaf
1652// If __v exists, set parent to node of __v and return reference to node of __v
1653template <class _Tp, class _Compare, class _Allocator>
1654template <class _Key>
Howard Hinnant6108fd72011-04-03 20:05:29 +00001655typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
1656__tree<_Tp, _Compare, _Allocator>::__find_equal(typename __node_base::pointer& __parent,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001657 const _Key& __v)
1658{
1659 __node_pointer __nd = __root();
1660 if (__nd != nullptr)
1661 {
1662 while (true)
1663 {
1664 if (value_comp()(__v, __nd->__value_))
1665 {
1666 if (__nd->__left_ != nullptr)
1667 __nd = static_cast<__node_pointer>(__nd->__left_);
1668 else
1669 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001670 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001671 return __parent->__left_;
1672 }
1673 }
1674 else if (value_comp()(__nd->__value_, __v))
1675 {
1676 if (__nd->__right_ != nullptr)
1677 __nd = static_cast<__node_pointer>(__nd->__right_);
1678 else
1679 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001680 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001681 return __parent->__right_;
1682 }
1683 }
1684 else
1685 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001686 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001687 return __parent;
1688 }
1689 }
1690 }
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001691 __parent = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantc51e1022010-05-11 19:42:16 +00001692 return __parent->__left_;
1693}
1694
1695// Find place to insert if __v doesn't exist
1696// First check prior to __hint.
1697// Next check after __hint.
1698// Next do O(log N) search.
1699// Set __parent to parent of null leaf
1700// Return reference to null leaf
1701// If __v exists, set parent to node of __v and return reference to node of __v
1702template <class _Tp, class _Compare, class _Allocator>
1703template <class _Key>
Howard Hinnant6108fd72011-04-03 20:05:29 +00001704typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
Howard Hinnantc51e1022010-05-11 19:42:16 +00001705__tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint,
Howard Hinnant6108fd72011-04-03 20:05:29 +00001706 typename __node_base::pointer& __parent,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001707 const _Key& __v)
1708{
1709 if (__hint == end() || value_comp()(__v, *__hint)) // check before
1710 {
1711 // __v < *__hint
1712 const_iterator __prior = __hint;
1713 if (__prior == begin() || value_comp()(*--__prior, __v))
1714 {
1715 // *prev(__hint) < __v < *__hint
1716 if (__hint.__ptr_->__left_ == nullptr)
1717 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001718 __parent = static_cast<__node_base_pointer>(__hint.__ptr_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001719 return __parent->__left_;
1720 }
1721 else
1722 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001723 __parent = static_cast<__node_base_pointer>(__prior.__ptr_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001724 return __parent->__right_;
1725 }
1726 }
1727 // __v <= *prev(__hint)
1728 return __find_equal(__parent, __v);
1729 }
1730 else if (value_comp()(*__hint, __v)) // check after
1731 {
1732 // *__hint < __v
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001733 const_iterator __next = _VSTD::next(__hint);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001734 if (__next == end() || value_comp()(__v, *__next))
1735 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001736 // *__hint < __v < *_VSTD::next(__hint)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001737 if (__hint.__ptr_->__right_ == nullptr)
1738 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001739 __parent = static_cast<__node_base_pointer>(__hint.__ptr_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001740 return __parent->__right_;
1741 }
1742 else
1743 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001744 __parent = static_cast<__node_base_pointer>(__next.__ptr_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001745 return __parent->__left_;
1746 }
1747 }
1748 // *next(__hint) <= __v
1749 return __find_equal(__parent, __v);
1750 }
1751 // else __v == *__hint
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001752 __parent = static_cast<__node_base_pointer>(__hint.__ptr_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001753 return __parent;
1754}
1755
1756template <class _Tp, class _Compare, class _Allocator>
1757void
1758__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__node_base_pointer __parent,
1759 __node_base_pointer& __child,
1760 __node_base_pointer __new_node)
1761{
1762 __new_node->__left_ = nullptr;
1763 __new_node->__right_ = nullptr;
1764 __new_node->__parent_ = __parent;
1765 __child = __new_node;
1766 if (__begin_node()->__left_ != nullptr)
1767 __begin_node() = static_cast<__node_pointer>(__begin_node()->__left_);
1768 __tree_balance_after_insert(__end_node()->__left_, __child);
1769 ++size();
1770}
1771
Howard Hinnant74279a52010-09-04 23:28:19 +00001772#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1773#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001774
1775template <class _Tp, class _Compare, class _Allocator>
1776template <class ..._Args>
1777typename __tree<_Tp, _Compare, _Allocator>::__node_holder
1778__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args)
1779{
1780 __node_allocator& __na = __node_alloc();
Howard Hinnantc834c512011-11-29 18:15:50 +00001781 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001782 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001783 __h.get_deleter().__value_constructed = true;
1784 return __h;
1785}
1786
1787template <class _Tp, class _Compare, class _Allocator>
1788template <class... _Args>
1789pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1790__tree<_Tp, _Compare, _Allocator>::__emplace_unique(_Args&&... __args)
1791{
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001792 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001793 __node_base_pointer __parent;
1794 __node_base_pointer& __child = __find_equal(__parent, __h->__value_);
1795 __node_pointer __r = static_cast<__node_pointer>(__child);
1796 bool __inserted = false;
1797 if (__child == nullptr)
1798 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001799 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001800 __r = __h.release();
1801 __inserted = true;
1802 }
1803 return pair<iterator, bool>(iterator(__r), __inserted);
1804}
1805
1806template <class _Tp, class _Compare, class _Allocator>
1807template <class... _Args>
1808typename __tree<_Tp, _Compare, _Allocator>::iterator
1809__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique(const_iterator __p, _Args&&... __args)
1810{
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001811 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001812 __node_base_pointer __parent;
1813 __node_base_pointer& __child = __find_equal(__p, __parent, __h->__value_);
1814 __node_pointer __r = static_cast<__node_pointer>(__child);
1815 if (__child == nullptr)
1816 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001817 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001818 __r = __h.release();
1819 }
1820 return iterator(__r);
1821}
1822
1823template <class _Tp, class _Compare, class _Allocator>
1824template <class... _Args>
1825typename __tree<_Tp, _Compare, _Allocator>::iterator
1826__tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args)
1827{
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001828 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001829 __node_base_pointer __parent;
1830 __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001831 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001832 return iterator(static_cast<__node_pointer>(__h.release()));
1833}
1834
1835template <class _Tp, class _Compare, class _Allocator>
1836template <class... _Args>
1837typename __tree<_Tp, _Compare, _Allocator>::iterator
1838__tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p,
1839 _Args&&... __args)
1840{
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001841 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001842 __node_base_pointer __parent;
1843 __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001844 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001845 return iterator(static_cast<__node_pointer>(__h.release()));
1846}
1847
Howard Hinnant74279a52010-09-04 23:28:19 +00001848#endif // _LIBCPP_HAS_NO_VARIADICS
1849
Howard Hinnantc51e1022010-05-11 19:42:16 +00001850template <class _Tp, class _Compare, class _Allocator>
Marshall Clowd430d022016-01-05 19:32:41 +00001851pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1852__tree<_Tp, _Compare, _Allocator>::__insert_unique(value_type&& __v)
1853{
1854 __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
1855 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1856 if (__r.second)
1857 __h.release();
1858 return __r;
1859}
1860
1861template <class _Tp, class _Compare, class _Allocator>
1862typename __tree<_Tp, _Compare, _Allocator>::iterator
1863__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, value_type&& __v)
1864{
1865 __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
1866 iterator __r = __node_insert_unique(__p, __h.get());
1867 if (__r.__ptr_ == __h.get())
1868 __h.release();
1869 return __r;
1870}
1871
1872template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantc834c512011-11-29 18:15:50 +00001873template <class _Vp>
Howard Hinnantc51e1022010-05-11 19:42:16 +00001874pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
Howard Hinnantc834c512011-11-29 18:15:50 +00001875__tree<_Tp, _Compare, _Allocator>::__insert_unique(_Vp&& __v)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001876{
Howard Hinnantc834c512011-11-29 18:15:50 +00001877 __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
Howard Hinnantc5bc8672011-03-10 17:27:57 +00001878 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1879 if (__r.second)
1880 __h.release();
1881 return __r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001882}
1883
1884template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantc834c512011-11-29 18:15:50 +00001885template <class _Vp>
Howard Hinnantc51e1022010-05-11 19:42:16 +00001886typename __tree<_Tp, _Compare, _Allocator>::iterator
Howard Hinnantc834c512011-11-29 18:15:50 +00001887__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, _Vp&& __v)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001888{
Howard Hinnantc834c512011-11-29 18:15:50 +00001889 __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
Howard Hinnantc5bc8672011-03-10 17:27:57 +00001890 iterator __r = __node_insert_unique(__p, __h.get());
1891 if (__r.__ptr_ == __h.get())
1892 __h.release();
1893 return __r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001894}
1895
1896template <class _Tp, class _Compare, class _Allocator>
Marshall Clowd430d022016-01-05 19:32:41 +00001897typename __tree<_Tp, _Compare, _Allocator>::iterator
1898__tree<_Tp, _Compare, _Allocator>::__insert_multi(value_type&& __v)
1899{
1900 __node_base_pointer __parent;
1901 __node_base_pointer& __child = __find_leaf_high(__parent, __v);
1902 __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
1903 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
1904 return iterator(__h.release());
1905}
1906
1907template <class _Tp, class _Compare, class _Allocator>
1908typename __tree<_Tp, _Compare, _Allocator>::iterator
1909__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, value_type&& __v)
1910{
1911 __node_base_pointer __parent;
1912 __node_base_pointer& __child = __find_leaf(__p, __parent, __v);
1913 __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
1914 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
1915 return iterator(__h.release());
1916}
1917
1918template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantc834c512011-11-29 18:15:50 +00001919template <class _Vp>
Howard Hinnantc51e1022010-05-11 19:42:16 +00001920typename __tree<_Tp, _Compare, _Allocator>::iterator
Howard Hinnantc834c512011-11-29 18:15:50 +00001921__tree<_Tp, _Compare, _Allocator>::__insert_multi(_Vp&& __v)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001922{
Howard Hinnantc834c512011-11-29 18:15:50 +00001923 __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001924 __node_base_pointer __parent;
1925 __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001926 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001927 return iterator(__h.release());
1928}
1929
1930template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantc834c512011-11-29 18:15:50 +00001931template <class _Vp>
Howard Hinnantc51e1022010-05-11 19:42:16 +00001932typename __tree<_Tp, _Compare, _Allocator>::iterator
Howard Hinnantc834c512011-11-29 18:15:50 +00001933__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, _Vp&& __v)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001934{
Howard Hinnantc834c512011-11-29 18:15:50 +00001935 __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001936 __node_base_pointer __parent;
1937 __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001938 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001939 return iterator(__h.release());
1940}
1941
Howard Hinnant74279a52010-09-04 23:28:19 +00001942#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantc51e1022010-05-11 19:42:16 +00001943
1944template <class _Tp, class _Compare, class _Allocator>
1945typename __tree<_Tp, _Compare, _Allocator>::__node_holder
1946__tree<_Tp, _Compare, _Allocator>::__construct_node(const value_type& __v)
1947{
1948 __node_allocator& __na = __node_alloc();
Howard Hinnantc834c512011-11-29 18:15:50 +00001949 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00001950 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001951 __h.get_deleter().__value_constructed = true;
Dimitry Andric830fb602015-08-19 06:43:33 +00001952 return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03
Howard Hinnantc51e1022010-05-11 19:42:16 +00001953}
1954
Howard Hinnantc5bc8672011-03-10 17:27:57 +00001955#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
1956
Howard Hinnantc51e1022010-05-11 19:42:16 +00001957template <class _Tp, class _Compare, class _Allocator>
1958pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1959__tree<_Tp, _Compare, _Allocator>::__insert_unique(const value_type& __v)
1960{
1961 __node_base_pointer __parent;
1962 __node_base_pointer& __child = __find_equal(__parent, __v);
1963 __node_pointer __r = static_cast<__node_pointer>(__child);
1964 bool __inserted = false;
1965 if (__child == nullptr)
1966 {
1967 __node_holder __h = __construct_node(__v);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001968 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001969 __r = __h.release();
1970 __inserted = true;
1971 }
1972 return pair<iterator, bool>(iterator(__r), __inserted);
1973}
1974
1975template <class _Tp, class _Compare, class _Allocator>
1976typename __tree<_Tp, _Compare, _Allocator>::iterator
1977__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, const value_type& __v)
1978{
1979 __node_base_pointer __parent;
1980 __node_base_pointer& __child = __find_equal(__p, __parent, __v);
1981 __node_pointer __r = static_cast<__node_pointer>(__child);
1982 if (__child == nullptr)
1983 {
1984 __node_holder __h = __construct_node(__v);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001985 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001986 __r = __h.release();
1987 }
1988 return iterator(__r);
1989}
1990
1991template <class _Tp, class _Compare, class _Allocator>
1992typename __tree<_Tp, _Compare, _Allocator>::iterator
1993__tree<_Tp, _Compare, _Allocator>::__insert_multi(const value_type& __v)
1994{
1995 __node_base_pointer __parent;
1996 __node_base_pointer& __child = __find_leaf_high(__parent, __v);
1997 __node_holder __h = __construct_node(__v);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00001998 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001999 return iterator(__h.release());
2000}
2001
2002template <class _Tp, class _Compare, class _Allocator>
2003typename __tree<_Tp, _Compare, _Allocator>::iterator
2004__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const value_type& __v)
2005{
2006 __node_base_pointer __parent;
2007 __node_base_pointer& __child = __find_leaf(__p, __parent, __v);
2008 __node_holder __h = __construct_node(__v);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00002009 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002010 return iterator(__h.release());
2011}
2012
Howard Hinnantc51e1022010-05-11 19:42:16 +00002013template <class _Tp, class _Compare, class _Allocator>
2014pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
2015__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd)
2016{
2017 __node_base_pointer __parent;
2018 __node_base_pointer& __child = __find_equal(__parent, __nd->__value_);
2019 __node_pointer __r = static_cast<__node_pointer>(__child);
2020 bool __inserted = false;
2021 if (__child == nullptr)
2022 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00002023 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002024 __r = __nd;
2025 __inserted = true;
2026 }
2027 return pair<iterator, bool>(iterator(__r), __inserted);
2028}
2029
2030template <class _Tp, class _Compare, class _Allocator>
2031typename __tree<_Tp, _Compare, _Allocator>::iterator
2032__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p,
2033 __node_pointer __nd)
2034{
2035 __node_base_pointer __parent;
2036 __node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_);
2037 __node_pointer __r = static_cast<__node_pointer>(__child);
2038 if (__child == nullptr)
2039 {
Howard Hinnant2d0046b2013-06-19 21:29:40 +00002040 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002041 __r = __nd;
2042 }
2043 return iterator(__r);
2044}
2045
2046template <class _Tp, class _Compare, class _Allocator>
2047typename __tree<_Tp, _Compare, _Allocator>::iterator
2048__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd)
2049{
2050 __node_base_pointer __parent;
2051 __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__value_);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00002052 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002053 return iterator(__nd);
2054}
2055
2056template <class _Tp, class _Compare, class _Allocator>
2057typename __tree<_Tp, _Compare, _Allocator>::iterator
2058__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p,
2059 __node_pointer __nd)
2060{
2061 __node_base_pointer __parent;
2062 __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__value_);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00002063 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002064 return iterator(__nd);
2065}
2066
2067template <class _Tp, class _Compare, class _Allocator>
2068typename __tree<_Tp, _Compare, _Allocator>::iterator
2069__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p)
2070{
Howard Hinnant2d0046b2013-06-19 21:29:40 +00002071 __node_pointer __np = __p.__ptr_;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002072 iterator __r(__np);
2073 ++__r;
2074 if (__begin_node() == __np)
2075 __begin_node() = __r.__ptr_;
2076 --size();
2077 __node_allocator& __na = __node_alloc();
Howard Hinnantc51e1022010-05-11 19:42:16 +00002078 __tree_remove(__end_node()->__left_,
2079 static_cast<__node_base_pointer>(__np));
Marshall Clowc5a20902014-04-11 08:22:42 +00002080 __node_traits::destroy(__na, const_cast<value_type*>(_VSTD::addressof(*__p)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002081 __node_traits::deallocate(__na, __np, 1);
2082 return __r;
2083}
2084
2085template <class _Tp, class _Compare, class _Allocator>
2086typename __tree<_Tp, _Compare, _Allocator>::iterator
2087__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l)
2088{
2089 while (__f != __l)
2090 __f = erase(__f);
Howard Hinnant2d0046b2013-06-19 21:29:40 +00002091 return iterator(__l.__ptr_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002092}
2093
2094template <class _Tp, class _Compare, class _Allocator>
2095template <class _Key>
2096typename __tree<_Tp, _Compare, _Allocator>::size_type
2097__tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k)
2098{
2099 iterator __i = find(__k);
2100 if (__i == end())
2101 return 0;
2102 erase(__i);
2103 return 1;
2104}
2105
2106template <class _Tp, class _Compare, class _Allocator>
2107template <class _Key>
2108typename __tree<_Tp, _Compare, _Allocator>::size_type
2109__tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k)
2110{
2111 pair<iterator, iterator> __p = __equal_range_multi(__k);
2112 size_type __r = 0;
2113 for (; __p.first != __p.second; ++__r)
2114 __p.first = erase(__p.first);
2115 return __r;
2116}
2117
2118template <class _Tp, class _Compare, class _Allocator>
2119template <class _Key>
2120typename __tree<_Tp, _Compare, _Allocator>::iterator
2121__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v)
2122{
2123 iterator __p = __lower_bound(__v, __root(), __end_node());
2124 if (__p != end() && !value_comp()(__v, *__p))
2125 return __p;
2126 return end();
2127}
2128
2129template <class _Tp, class _Compare, class _Allocator>
2130template <class _Key>
2131typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2132__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) const
2133{
2134 const_iterator __p = __lower_bound(__v, __root(), __end_node());
2135 if (__p != end() && !value_comp()(__v, *__p))
2136 return __p;
2137 return end();
2138}
2139
2140template <class _Tp, class _Compare, class _Allocator>
2141template <class _Key>
2142typename __tree<_Tp, _Compare, _Allocator>::size_type
2143__tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const
2144{
2145 __node_const_pointer __result = __end_node();
2146 __node_const_pointer __rt = __root();
2147 while (__rt != nullptr)
2148 {
2149 if (value_comp()(__k, __rt->__value_))
2150 {
2151 __result = __rt;
2152 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2153 }
2154 else if (value_comp()(__rt->__value_, __k))
2155 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2156 else
2157 return 1;
2158 }
2159 return 0;
2160}
2161
2162template <class _Tp, class _Compare, class _Allocator>
2163template <class _Key>
2164typename __tree<_Tp, _Compare, _Allocator>::size_type
2165__tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const
2166{
Howard Hinnantc51e1022010-05-11 19:42:16 +00002167 __node_const_pointer __result = __end_node();
2168 __node_const_pointer __rt = __root();
2169 while (__rt != nullptr)
2170 {
2171 if (value_comp()(__k, __rt->__value_))
2172 {
2173 __result = __rt;
2174 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2175 }
2176 else if (value_comp()(__rt->__value_, __k))
2177 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2178 else
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00002179 return _VSTD::distance(
Howard Hinnantc51e1022010-05-11 19:42:16 +00002180 __lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt),
2181 __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result)
2182 );
2183 }
2184 return 0;
2185}
2186
2187template <class _Tp, class _Compare, class _Allocator>
2188template <class _Key>
2189typename __tree<_Tp, _Compare, _Allocator>::iterator
2190__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
2191 __node_pointer __root,
2192 __node_pointer __result)
2193{
2194 while (__root != nullptr)
2195 {
2196 if (!value_comp()(__root->__value_, __v))
2197 {
2198 __result = __root;
2199 __root = static_cast<__node_pointer>(__root->__left_);
2200 }
2201 else
2202 __root = static_cast<__node_pointer>(__root->__right_);
2203 }
2204 return iterator(__result);
2205}
2206
2207template <class _Tp, class _Compare, class _Allocator>
2208template <class _Key>
2209typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2210__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
2211 __node_const_pointer __root,
2212 __node_const_pointer __result) const
2213{
2214 while (__root != nullptr)
2215 {
2216 if (!value_comp()(__root->__value_, __v))
2217 {
2218 __result = __root;
2219 __root = static_cast<__node_const_pointer>(__root->__left_);
2220 }
2221 else
2222 __root = static_cast<__node_const_pointer>(__root->__right_);
2223 }
2224 return const_iterator(__result);
2225}
2226
2227template <class _Tp, class _Compare, class _Allocator>
2228template <class _Key>
2229typename __tree<_Tp, _Compare, _Allocator>::iterator
2230__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
2231 __node_pointer __root,
2232 __node_pointer __result)
2233{
2234 while (__root != nullptr)
2235 {
2236 if (value_comp()(__v, __root->__value_))
2237 {
2238 __result = __root;
2239 __root = static_cast<__node_pointer>(__root->__left_);
2240 }
2241 else
2242 __root = static_cast<__node_pointer>(__root->__right_);
2243 }
2244 return iterator(__result);
2245}
2246
2247template <class _Tp, class _Compare, class _Allocator>
2248template <class _Key>
2249typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2250__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
2251 __node_const_pointer __root,
2252 __node_const_pointer __result) const
2253{
2254 while (__root != nullptr)
2255 {
2256 if (value_comp()(__v, __root->__value_))
2257 {
2258 __result = __root;
2259 __root = static_cast<__node_const_pointer>(__root->__left_);
2260 }
2261 else
2262 __root = static_cast<__node_const_pointer>(__root->__right_);
2263 }
2264 return const_iterator(__result);
2265}
2266
2267template <class _Tp, class _Compare, class _Allocator>
2268template <class _Key>
2269pair<typename __tree<_Tp, _Compare, _Allocator>::iterator,
2270 typename __tree<_Tp, _Compare, _Allocator>::iterator>
2271__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k)
2272{
Howard Hinnantc834c512011-11-29 18:15:50 +00002273 typedef pair<iterator, iterator> _Pp;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002274 __node_pointer __result = __end_node();
2275 __node_pointer __rt = __root();
2276 while (__rt != nullptr)
2277 {
2278 if (value_comp()(__k, __rt->__value_))
2279 {
2280 __result = __rt;
2281 __rt = static_cast<__node_pointer>(__rt->__left_);
2282 }
2283 else if (value_comp()(__rt->__value_, __k))
2284 __rt = static_cast<__node_pointer>(__rt->__right_);
2285 else
Howard Hinnantc834c512011-11-29 18:15:50 +00002286 return _Pp(iterator(__rt),
Howard Hinnantc51e1022010-05-11 19:42:16 +00002287 iterator(
2288 __rt->__right_ != nullptr ?
2289 static_cast<__node_pointer>(__tree_min(__rt->__right_))
2290 : __result));
2291 }
Howard Hinnantc834c512011-11-29 18:15:50 +00002292 return _Pp(iterator(__result), iterator(__result));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002293}
2294
2295template <class _Tp, class _Compare, class _Allocator>
2296template <class _Key>
2297pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
2298 typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
2299__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const
2300{
Howard Hinnantc834c512011-11-29 18:15:50 +00002301 typedef pair<const_iterator, const_iterator> _Pp;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002302 __node_const_pointer __result = __end_node();
2303 __node_const_pointer __rt = __root();
2304 while (__rt != nullptr)
2305 {
2306 if (value_comp()(__k, __rt->__value_))
2307 {
2308 __result = __rt;
2309 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2310 }
2311 else if (value_comp()(__rt->__value_, __k))
2312 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2313 else
Howard Hinnantc834c512011-11-29 18:15:50 +00002314 return _Pp(const_iterator(__rt),
Howard Hinnantc51e1022010-05-11 19:42:16 +00002315 const_iterator(
2316 __rt->__right_ != nullptr ?
2317 static_cast<__node_const_pointer>(__tree_min(__rt->__right_))
2318 : __result));
2319 }
Howard Hinnantc834c512011-11-29 18:15:50 +00002320 return _Pp(const_iterator(__result), const_iterator(__result));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002321}
2322
2323template <class _Tp, class _Compare, class _Allocator>
2324template <class _Key>
2325pair<typename __tree<_Tp, _Compare, _Allocator>::iterator,
2326 typename __tree<_Tp, _Compare, _Allocator>::iterator>
2327__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k)
2328{
Howard Hinnantc834c512011-11-29 18:15:50 +00002329 typedef pair<iterator, iterator> _Pp;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002330 __node_pointer __result = __end_node();
2331 __node_pointer __rt = __root();
2332 while (__rt != nullptr)
2333 {
2334 if (value_comp()(__k, __rt->__value_))
2335 {
2336 __result = __rt;
2337 __rt = static_cast<__node_pointer>(__rt->__left_);
2338 }
2339 else if (value_comp()(__rt->__value_, __k))
2340 __rt = static_cast<__node_pointer>(__rt->__right_);
2341 else
Howard Hinnantc834c512011-11-29 18:15:50 +00002342 return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt),
Howard Hinnantc51e1022010-05-11 19:42:16 +00002343 __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
2344 }
Howard Hinnantc834c512011-11-29 18:15:50 +00002345 return _Pp(iterator(__result), iterator(__result));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002346}
2347
2348template <class _Tp, class _Compare, class _Allocator>
2349template <class _Key>
2350pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
2351 typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
2352__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const
2353{
Howard Hinnantc834c512011-11-29 18:15:50 +00002354 typedef pair<const_iterator, const_iterator> _Pp;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002355 __node_const_pointer __result = __end_node();
2356 __node_const_pointer __rt = __root();
2357 while (__rt != nullptr)
2358 {
2359 if (value_comp()(__k, __rt->__value_))
2360 {
2361 __result = __rt;
2362 __rt = static_cast<__node_const_pointer>(__rt->__left_);
2363 }
2364 else if (value_comp()(__rt->__value_, __k))
2365 __rt = static_cast<__node_const_pointer>(__rt->__right_);
2366 else
Howard Hinnantc834c512011-11-29 18:15:50 +00002367 return _Pp(__lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt),
Howard Hinnantc51e1022010-05-11 19:42:16 +00002368 __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result));
2369 }
Howard Hinnantc834c512011-11-29 18:15:50 +00002370 return _Pp(const_iterator(__result), const_iterator(__result));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002371}
2372
2373template <class _Tp, class _Compare, class _Allocator>
2374typename __tree<_Tp, _Compare, _Allocator>::__node_holder
Howard Hinnant1113b5e2011-06-04 17:10:24 +00002375__tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00002376{
Howard Hinnant2d0046b2013-06-19 21:29:40 +00002377 __node_pointer __np = __p.__ptr_;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002378 if (__begin_node() == __np)
2379 {
2380 if (__np->__right_ != nullptr)
2381 __begin_node() = static_cast<__node_pointer>(__np->__right_);
2382 else
2383 __begin_node() = static_cast<__node_pointer>(__np->__parent_);
2384 }
2385 --size();
2386 __tree_remove(__end_node()->__left_,
2387 static_cast<__node_base_pointer>(__np));
Marshall Clow95af65e2015-01-28 19:54:25 +00002388 return __node_holder(__np, _Dp(__node_alloc(), true));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002389}
2390
Howard Hinnant2f1ea9c2011-06-04 14:31:57 +00002391template <class _Tp, class _Compare, class _Allocator>
2392inline _LIBCPP_INLINE_VISIBILITY
2393void
2394swap(__tree<_Tp, _Compare, _Allocator>& __x,
2395 __tree<_Tp, _Compare, _Allocator>& __y)
2396 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
2397{
2398 __x.swap(__y);
2399}
2400
Howard Hinnantc51e1022010-05-11 19:42:16 +00002401_LIBCPP_END_NAMESPACE_STD
2402
2403#endif // _LIBCPP___TREE