blob: d35ed122b2d6bd521397e9ed9534d5bd2f22125b [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP___TREE
12#define _LIBCPP___TREE
13
14#include <__config>
15#include <iterator>
16#include <memory>
17#include <stdexcept>
18#include <algorithm>
19
Howard Hinnant08e17472011-10-17 20:05:10 +000020#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000021#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +000022#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000023
24_LIBCPP_BEGIN_NAMESPACE_STD
25
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000026template <class _Tp, class _Compare, class _Allocator> class __tree;
27template <class _Tp, class _NodePtr, class _DiffType>
Howard Hinnant0f678bd2013-08-12 18:38:34 +000028 class _LIBCPP_TYPE_VIS_ONLY __tree_iterator;
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000029template <class _Tp, class _ConstNodePtr, class _DiffType>
Howard Hinnant0f678bd2013-08-12 18:38:34 +000030 class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031
Eric Fiselier55263482016-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 Hinnantbc8d3f92010-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 Hinnant333f50d2010-09-21 20:16:37 +000072inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000073bool
Howard Hinnant8b537682011-06-04 17:10:24 +000074__tree_is_left_child(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant333f50d2010-09-21 20:16:37 +0000138inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000139_NodePtr
Howard Hinnant8b537682011-06-04 17:10:24 +0000140__tree_min(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant333f50d2010-09-21 20:16:37 +0000150inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000151_NodePtr
Howard Hinnant8b537682011-06-04 17:10:24 +0000152__tree_max(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant8b537682011-06-04 17:10:24 +0000163__tree_next(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant8b537682011-06-04 17:10:24 +0000176__tree_prev(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant8b537682011-06-04 17:10:24 +0000189__tree_leaf(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant8b537682011-06-04 17:10:24 +0000213__tree_left_rotate(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant8b537682011-06-04 17:10:24 +0000233__tree_right_rotate(_NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant8b537682011-06-04 17:10:24 +0000258__tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant8b537682011-06-04 17:10:24 +0000328__tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnant324bb032010-08-22 00:02:43 +0000362 // __z->__left_ != nulptr but __z->__right_ might == __x == nullptr
Howard Hinnantbc8d3f92010-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 Hinnant324bb032010-08-22 00:02:43 +0000432 __x->__parent_->__right_ :
433 __x->__parent_->__left_;
Howard Hinnantbc8d3f92010-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 Hinnant324bb032010-08-22 00:02:43 +0000484 __x->__parent_->__right_ :
485 __x->__parent_->__left_;
Howard Hinnantbc8d3f92010-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 Hinnantbc8d3f92010-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 Fiselier55263482016-02-20 05:28:30 +0000518
Howard Hinnantbc8d3f92010-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 Hinnant333f50d2010-09-21 20:16:37 +0000530 _LIBCPP_INLINE_VISIBILITY
Marshall Clow01c1c6f2015-01-28 19:54:25 +0000531 explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000532 : __na_(__na),
Marshall Clow01c1c6f2015-01-28 19:54:25 +0000533 __value_constructed(__val)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000534 {}
535
Howard Hinnant333f50d2010-09-21 20:16:37 +0000536 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant8b537682011-06-04 17:10:24 +0000537 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000538 {
539 if (__value_constructed)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000540 __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-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 Fiselier55263482016-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 Hinnantbc8d3f92010-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 Hinnant333f50d2010-09-21 20:16:37 +0000643 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant8b537682011-06-04 17:10:24 +0000644 __tree_end_node() _NOEXCEPT : __left_() {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000645};
646
647template <class _VoidPtr>
648class __tree_node_base
Eric Fiselier55263482016-02-20 05:28:30 +0000649 : public __tree_node_base_types<_VoidPtr>::__end_node_type
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000650{
Eric Fiselier55263482016-02-20 05:28:30 +0000651 typedef __tree_node_base_types<_VoidPtr> _NodeBaseTypes;
652
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000653 __tree_node_base(const __tree_node_base&);
654 __tree_node_base& operator=(const __tree_node_base&);
655public:
Eric Fiselier55263482016-02-20 05:28:30 +0000656 typedef typename _NodeBaseTypes::__node_base_pointer pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000657
658 pointer __right_;
659 pointer __parent_;
660 bool __is_black_;
661
Howard Hinnant333f50d2010-09-21 20:16:37 +0000662 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant8b537682011-06-04 17:10:24 +0000663 __tree_node_base() _NOEXCEPT
664 : __right_(), __parent_(), __is_black_(false) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000665};
666
667template <class _Tp, class _VoidPtr>
668class __tree_node
669 : public __tree_node_base<_VoidPtr>
670{
671public:
Eric Fiselier55263482016-02-20 05:28:30 +0000672 typedef _Tp __node_value_type;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000673
Eric Fiselier55263482016-02-20 05:28:30 +0000674 __node_value_type __value_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000675
Howard Hinnant73d21a42010-09-04 23:28:19 +0000676#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000677 template <class ..._Args>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000678 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000679 explicit __tree_node(_Args&& ...__args)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000680 : __value_(_VSTD::forward<_Args>(__args)...) {}
Howard Hinnant73d21a42010-09-04 23:28:19 +0000681#else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnant333f50d2010-09-21 20:16:37 +0000682 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier55263482016-02-20 05:28:30 +0000683 explicit __tree_node(const __node_value_type& __v)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000684 : __value_(__v) {}
Howard Hinnant73d21a42010-09-04 23:28:19 +0000685#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000686};
687
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000688template <class _Tp, class _NodePtr, class _DiffType>
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000689class _LIBCPP_TYPE_VIS_ONLY __tree_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000690{
Eric Fiselier55263482016-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000695
696 __node_pointer __ptr_;
697
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000698public:
Eric Fiselier55263482016-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000704
Marshall Clow051c8482013-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000710
Howard Hinnant333f50d2010-09-21 20:16:37 +0000711 _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;}
Howard Hinnant70342b92013-06-19 21:29:40 +0000712 _LIBCPP_INLINE_VISIBILITY pointer operator->() const
713 {return pointer_traits<pointer>::pointer_to(__ptr_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000714
Howard Hinnant333f50d2010-09-21 20:16:37 +0000715 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier9c8e6632015-03-03 20:10:01 +0000716 __tree_iterator& operator++() {
717 __ptr_ = static_cast<__node_pointer>(
Eric Fiselier55263482016-02-20 05:28:30 +0000718 __tree_next(static_cast<__node_base_pointer>(__ptr_)));
Eric Fiselier9c8e6632015-03-03 20:10:01 +0000719 return *this;
720 }
Howard Hinnant333f50d2010-09-21 20:16:37 +0000721 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000722 __tree_iterator operator++(int)
723 {__tree_iterator __t(*this); ++(*this); return __t;}
724
Howard Hinnant333f50d2010-09-21 20:16:37 +0000725 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier9c8e6632015-03-03 20:10:01 +0000726 __tree_iterator& operator--() {
727 __ptr_ = static_cast<__node_pointer>(
Eric Fiselier55263482016-02-20 05:28:30 +0000728 __tree_prev(static_cast<__node_base_pointer>(__ptr_)));
Eric Fiselier9c8e6632015-03-03 20:10:01 +0000729 return *this;
730 }
Howard Hinnant333f50d2010-09-21 20:16:37 +0000731 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000732 __tree_iterator operator--(int)
733 {__tree_iterator __t(*this); --(*this); return __t;}
734
Howard Hinnant333f50d2010-09-21 20:16:37 +0000735 friend _LIBCPP_INLINE_VISIBILITY
736 bool operator==(const __tree_iterator& __x, const __tree_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000737 {return __x.__ptr_ == __y.__ptr_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000738 friend _LIBCPP_INLINE_VISIBILITY
739 bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000740 {return !(__x == __y);}
741
742private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000743 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000744 explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000745 template <class, class, class> friend class __tree;
Howard Hinnant0f678bd2013-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000752};
753
Eric Fiselier55263482016-02-20 05:28:30 +0000754template <class _Tp, class _NodePtr, class _DiffType>
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000755class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000756{
Eric Fiselier55263482016-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000761
762 __node_pointer __ptr_;
763
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000764public:
Eric Fiselier55263482016-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000770
Marshall Clow051c8482013-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000777private:
Eric Fiselier55263482016-02-20 05:28:30 +0000778 typedef __tree_iterator<value_type, __node_pointer, difference_type>
779 __non_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000780public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000781 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000782 __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT
783 : __ptr_(__p.__ptr_) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000784
Howard Hinnant333f50d2010-09-21 20:16:37 +0000785 _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;}
Howard Hinnant70342b92013-06-19 21:29:40 +0000786 _LIBCPP_INLINE_VISIBILITY pointer operator->() const
787 {return pointer_traits<pointer>::pointer_to(__ptr_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000788
Howard Hinnant333f50d2010-09-21 20:16:37 +0000789 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier9c8e6632015-03-03 20:10:01 +0000790 __tree_const_iterator& operator++() {
Eric Fiselier9c8e6632015-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 Hinnant333f50d2010-09-21 20:16:37 +0000796 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000797 __tree_const_iterator operator++(int)
798 {__tree_const_iterator __t(*this); ++(*this); return __t;}
799
Howard Hinnant333f50d2010-09-21 20:16:37 +0000800 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier9c8e6632015-03-03 20:10:01 +0000801 __tree_const_iterator& operator--() {
Eric Fiselier9c8e6632015-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 Hinnant333f50d2010-09-21 20:16:37 +0000807 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000808 __tree_const_iterator operator--(int)
809 {__tree_const_iterator __t(*this); --(*this); return __t;}
810
Howard Hinnant333f50d2010-09-21 20:16:37 +0000811 friend _LIBCPP_INLINE_VISIBILITY
812 bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000813 {return __x.__ptr_ == __y.__ptr_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000814 friend _LIBCPP_INLINE_VISIBILITY
815 bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000816 {return !(__x == __y);}
817
818private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000819 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000820 explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT
821 : __ptr_(__p) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000822 template <class, class, class> friend class __tree;
Howard Hinnant0f678bd2013-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 Hinnantbc8d3f92010-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 Fiselier55263482016-02-20 05:28:30 +0000837
838private:
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000839 typedef allocator_traits<allocator_type> __alloc_traits;
Eric Fiselier55263482016-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 Hinnantbc8d3f92010-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 Fiselier55263482016-02-20 05:28:30 +0000852public:
853 typedef typename _NodeTypes::__void_pointer __void_pointer;
Howard Hinnant70342b92013-06-19 21:29:40 +0000854
Eric Fiselier55263482016-02-20 05:28:30 +0000855 typedef typename _NodeTypes::__node_type __node;
856 typedef typename _NodeTypes::__node_pointer __node_pointer;
Eric Fiselier55263482016-02-20 05:28:30 +0000857
858 typedef typename _NodeTypes::__node_base_type __node_base;
859 typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
Eric Fiselier55263482016-02-20 05:28:30 +0000860
861 typedef typename _NodeTypes::__end_node_type __end_node_t;
862 typedef typename _NodeTypes::__end_node_pointer __end_node_ptr;
Eric Fiselier55263482016-02-20 05:28:30 +0000863
Marshall Clow66302c62015-04-07 05:21:38 +0000864 typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator;
Eric Fiselier55263482016-02-20 05:28:30 +0000865 typedef allocator_traits<__node_allocator> __node_traits;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000866
Eric Fiselier55263482016-02-20 05:28:30 +0000867private:
868 // check for sane allocator pointer rebinding semantics. Rebinding the
869 // allocator for a new pointer type should be exactly the same as rebinding
870 // the pointer using 'pointer_traits'.
871 static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value),
872 "Allocator does not rebind pointers in a sane manner.");
873 typedef typename __rebind_alloc_helper<__node_traits, __node_base>::type
874 __node_base_allocator;
875 typedef allocator_traits<__node_base_allocator> __node_base_traits;
876 static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value),
877 "Allocator does not rebind pointers in a sane manner.");
878
879private:
Eric Fiselier227b47c2016-02-20 07:12:17 +0000880 __node_pointer __begin_node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000881 __compressed_pair<__end_node_t, __node_allocator> __pair1_;
882 __compressed_pair<size_type, value_compare> __pair3_;
883
884public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000885 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000886 __node_pointer __end_node() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000887 {
Eric Fiselier227b47c2016-02-20 07:12:17 +0000888 return static_cast<__node_pointer>(
889 pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first())
890 );
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000891 }
Howard Hinnant333f50d2010-09-21 20:16:37 +0000892 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier227b47c2016-02-20 07:12:17 +0000893 __node_pointer __end_node() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000894 {
Eric Fiselier227b47c2016-02-20 07:12:17 +0000895 return static_cast<__node_pointer>(
896 pointer_traits<__end_node_ptr>::pointer_to(
897 const_cast<__end_node_t&>(__pair1_.first())
898 )
899 );
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000900 }
Howard Hinnant333f50d2010-09-21 20:16:37 +0000901 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000902 __node_allocator& __node_alloc() _NOEXCEPT {return __pair1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000903private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000904 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000905 const __node_allocator& __node_alloc() const _NOEXCEPT
906 {return __pair1_.second();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000907 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000908 __node_pointer& __begin_node() _NOEXCEPT {return __begin_node_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000909 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000910 const __node_pointer& __begin_node() const _NOEXCEPT {return __begin_node_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000911public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000912 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000913 allocator_type __alloc() const _NOEXCEPT
914 {return allocator_type(__node_alloc());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000915private:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000916 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000917 size_type& size() _NOEXCEPT {return __pair3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000918public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000919 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000920 const size_type& size() const _NOEXCEPT {return __pair3_.first();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000921 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000922 value_compare& value_comp() _NOEXCEPT {return __pair3_.second();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000923 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000924 const value_compare& value_comp() const _NOEXCEPT
925 {return __pair3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000926public:
Eric Fiselier227b47c2016-02-20 07:12:17 +0000927
Howard Hinnant333f50d2010-09-21 20:16:37 +0000928 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier227b47c2016-02-20 07:12:17 +0000929 __node_pointer __root() const _NOEXCEPT
930 {return static_cast<__node_pointer>(__end_node()->__left_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000931
932 typedef __tree_iterator<value_type, __node_pointer, difference_type> iterator;
Howard Hinnant70342b92013-06-19 21:29:40 +0000933 typedef __tree_const_iterator<value_type, __node_pointer, difference_type> const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000934
Howard Hinnant7686add2011-06-04 14:31:57 +0000935 explicit __tree(const value_compare& __comp)
936 _NOEXCEPT_(
937 is_nothrow_default_constructible<__node_allocator>::value &&
938 is_nothrow_copy_constructible<value_compare>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000939 explicit __tree(const allocator_type& __a);
940 __tree(const value_compare& __comp, const allocator_type& __a);
941 __tree(const __tree& __t);
942 __tree& operator=(const __tree& __t);
943 template <class _InputIterator>
944 void __assign_unique(_InputIterator __first, _InputIterator __last);
945 template <class _InputIterator>
946 void __assign_multi(_InputIterator __first, _InputIterator __last);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000947#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant7686add2011-06-04 14:31:57 +0000948 __tree(__tree&& __t)
949 _NOEXCEPT_(
950 is_nothrow_move_constructible<__node_allocator>::value &&
951 is_nothrow_move_constructible<value_compare>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000952 __tree(__tree&& __t, const allocator_type& __a);
Howard Hinnant7686add2011-06-04 14:31:57 +0000953 __tree& operator=(__tree&& __t)
954 _NOEXCEPT_(
955 __node_traits::propagate_on_container_move_assignment::value &&
956 is_nothrow_move_assignable<value_compare>::value &&
957 is_nothrow_move_assignable<__node_allocator>::value);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000958#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000959
960 ~__tree();
961
Howard Hinnant333f50d2010-09-21 20:16:37 +0000962 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000963 iterator begin() _NOEXCEPT {return iterator(__begin_node());}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000964 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000965 const_iterator begin() const _NOEXCEPT {return const_iterator(__begin_node());}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000966 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000967 iterator end() _NOEXCEPT {return iterator(__end_node());}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000968 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000969 const_iterator end() const _NOEXCEPT {return const_iterator(__end_node());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000970
Howard Hinnant333f50d2010-09-21 20:16:37 +0000971 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +0000972 size_type max_size() const _NOEXCEPT
973 {return __node_traits::max_size(__node_alloc());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000974
Howard Hinnant7686add2011-06-04 14:31:57 +0000975 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000976
Howard Hinnant7686add2011-06-04 14:31:57 +0000977 void swap(__tree& __t)
978 _NOEXCEPT_(
Marshall Clow7d914d12015-07-13 20:04:56 +0000979 __is_nothrow_swappable<value_compare>::value
980#if _LIBCPP_STD_VER <= 11
981 && (!__node_traits::propagate_on_container_swap::value ||
982 __is_nothrow_swappable<__node_allocator>::value)
983#endif
984 );
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000985
Howard Hinnant73d21a42010-09-04 23:28:19 +0000986#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
987#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000988 template <class... _Args>
989 pair<iterator, bool>
990 __emplace_unique(_Args&&... __args);
991 template <class... _Args>
992 iterator
993 __emplace_multi(_Args&&... __args);
994
995 template <class... _Args>
996 iterator
997 __emplace_hint_unique(const_iterator __p, _Args&&... __args);
998 template <class... _Args>
999 iterator
1000 __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +00001001#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001002
Howard Hinnant99968442011-11-29 18:15:50 +00001003 template <class _Vp>
1004 pair<iterator, bool> __insert_unique(_Vp&& __v);
1005 template <class _Vp>
1006 iterator __insert_unique(const_iterator __p, _Vp&& __v);
1007 template <class _Vp>
1008 iterator __insert_multi(_Vp&& __v);
1009 template <class _Vp>
1010 iterator __insert_multi(const_iterator __p, _Vp&& __v);
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001011#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001012
1013 pair<iterator, bool> __insert_unique(const value_type& __v);
1014 iterator __insert_unique(const_iterator __p, const value_type& __v);
1015 iterator __insert_multi(const value_type& __v);
1016 iterator __insert_multi(const_iterator __p, const value_type& __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001017
Marshall Clow3426a862016-01-05 19:32:41 +00001018#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1019 pair<iterator, bool> __insert_unique( value_type&& __v);
1020 iterator __insert_unique(const_iterator __p, value_type&& __v);
1021 iterator __insert_multi( value_type&& __v);
1022 iterator __insert_multi(const_iterator __p, value_type&& __v);
1023#endif
1024
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
1026 iterator __node_insert_unique(const_iterator __p,
1027 __node_pointer __nd);
1028
1029 iterator __node_insert_multi(__node_pointer __nd);
1030 iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
1031
1032 iterator erase(const_iterator __p);
1033 iterator erase(const_iterator __f, const_iterator __l);
1034 template <class _Key>
1035 size_type __erase_unique(const _Key& __k);
1036 template <class _Key>
1037 size_type __erase_multi(const _Key& __k);
1038
1039 void __insert_node_at(__node_base_pointer __parent,
1040 __node_base_pointer& __child,
1041 __node_base_pointer __new_node);
1042
1043 template <class _Key>
1044 iterator find(const _Key& __v);
1045 template <class _Key>
1046 const_iterator find(const _Key& __v) const;
1047
1048 template <class _Key>
1049 size_type __count_unique(const _Key& __k) const;
1050 template <class _Key>
1051 size_type __count_multi(const _Key& __k) const;
1052
1053 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +00001054 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001055 iterator lower_bound(const _Key& __v)
1056 {return __lower_bound(__v, __root(), __end_node());}
1057 template <class _Key>
1058 iterator __lower_bound(const _Key& __v,
1059 __node_pointer __root,
1060 __node_pointer __result);
1061 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +00001062 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001063 const_iterator lower_bound(const _Key& __v) const
1064 {return __lower_bound(__v, __root(), __end_node());}
1065 template <class _Key>
1066 const_iterator __lower_bound(const _Key& __v,
Eric Fiselier227b47c2016-02-20 07:12:17 +00001067 __node_pointer __root,
1068 __node_pointer __result) const;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001069 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +00001070 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001071 iterator upper_bound(const _Key& __v)
1072 {return __upper_bound(__v, __root(), __end_node());}
1073 template <class _Key>
1074 iterator __upper_bound(const _Key& __v,
1075 __node_pointer __root,
1076 __node_pointer __result);
1077 template <class _Key>
Howard Hinnant333f50d2010-09-21 20:16:37 +00001078 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001079 const_iterator upper_bound(const _Key& __v) const
1080 {return __upper_bound(__v, __root(), __end_node());}
1081 template <class _Key>
1082 const_iterator __upper_bound(const _Key& __v,
Eric Fiselier227b47c2016-02-20 07:12:17 +00001083 __node_pointer __root,
1084 __node_pointer __result) const;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001085 template <class _Key>
1086 pair<iterator, iterator>
1087 __equal_range_unique(const _Key& __k);
1088 template <class _Key>
1089 pair<const_iterator, const_iterator>
1090 __equal_range_unique(const _Key& __k) const;
1091
1092 template <class _Key>
1093 pair<iterator, iterator>
1094 __equal_range_multi(const _Key& __k);
1095 template <class _Key>
1096 pair<const_iterator, const_iterator>
1097 __equal_range_multi(const _Key& __k) const;
1098
Howard Hinnant99968442011-11-29 18:15:50 +00001099 typedef __tree_node_destructor<__node_allocator> _Dp;
1100 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001101
Howard Hinnant8b537682011-06-04 17:10:24 +00001102 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001103private:
Howard Hinnantd615e472011-04-03 20:05:29 +00001104 typename __node_base::pointer&
1105 __find_leaf_low(typename __node_base::pointer& __parent, const value_type& __v);
1106 typename __node_base::pointer&
1107 __find_leaf_high(typename __node_base::pointer& __parent, const value_type& __v);
1108 typename __node_base::pointer&
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001109 __find_leaf(const_iterator __hint,
Howard Hinnantd615e472011-04-03 20:05:29 +00001110 typename __node_base::pointer& __parent, const value_type& __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001111 template <class _Key>
Howard Hinnantd615e472011-04-03 20:05:29 +00001112 typename __node_base::pointer&
1113 __find_equal(typename __node_base::pointer& __parent, const _Key& __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001114 template <class _Key>
Howard Hinnantd615e472011-04-03 20:05:29 +00001115 typename __node_base::pointer&
1116 __find_equal(const_iterator __hint, typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001117 const _Key& __v);
1118
Howard Hinnant73d21a42010-09-04 23:28:19 +00001119#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001120 template <class ..._Args>
1121 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnant73d21a42010-09-04 23:28:19 +00001122#else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001123 __node_holder __construct_node(const value_type& __v);
1124#endif
1125
Howard Hinnant7686add2011-06-04 14:31:57 +00001126 void destroy(__node_pointer __nd) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001127
Howard Hinnant333f50d2010-09-21 20:16:37 +00001128 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001129 void __copy_assign_alloc(const __tree& __t)
1130 {__copy_assign_alloc(__t, integral_constant<bool,
1131 __node_traits::propagate_on_container_copy_assignment::value>());}
1132
Howard Hinnant333f50d2010-09-21 20:16:37 +00001133 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001134 void __copy_assign_alloc(const __tree& __t, true_type)
1135 {__node_alloc() = __t.__node_alloc();}
Howard Hinnant333f50d2010-09-21 20:16:37 +00001136 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001137 void __copy_assign_alloc(const __tree& __t, false_type) {}
1138
1139 void __move_assign(__tree& __t, false_type);
Howard Hinnant7686add2011-06-04 14:31:57 +00001140 void __move_assign(__tree& __t, true_type)
1141 _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value &&
1142 is_nothrow_move_assignable<__node_allocator>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001143
Howard Hinnant333f50d2010-09-21 20:16:37 +00001144 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001145 void __move_assign_alloc(__tree& __t)
Howard Hinnant7686add2011-06-04 14:31:57 +00001146 _NOEXCEPT_(
1147 !__node_traits::propagate_on_container_move_assignment::value ||
1148 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001149 {__move_assign_alloc(__t, integral_constant<bool,
1150 __node_traits::propagate_on_container_move_assignment::value>());}
1151
Howard Hinnant333f50d2010-09-21 20:16:37 +00001152 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001153 void __move_assign_alloc(__tree& __t, true_type)
Howard Hinnant7686add2011-06-04 14:31:57 +00001154 _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001155 {__node_alloc() = _VSTD::move(__t.__node_alloc());}
Howard Hinnant333f50d2010-09-21 20:16:37 +00001156 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7686add2011-06-04 14:31:57 +00001157 void __move_assign_alloc(__tree& __t, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001158
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001159 __node_pointer __detach();
1160 static __node_pointer __detach(__node_pointer);
Howard Hinnant70342b92013-06-19 21:29:40 +00001161
Howard Hinnant0f678bd2013-08-12 18:38:34 +00001162 template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY map;
1163 template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001164};
1165
1166template <class _Tp, class _Compare, class _Allocator>
1167__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp)
Howard Hinnant7686add2011-06-04 14:31:57 +00001168 _NOEXCEPT_(
1169 is_nothrow_default_constructible<__node_allocator>::value &&
1170 is_nothrow_copy_constructible<value_compare>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001171 : __pair3_(0, __comp)
1172{
1173 __begin_node() = __end_node();
1174}
1175
1176template <class _Tp, class _Compare, class _Allocator>
1177__tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a)
Eric Fiselier02bb4bd2015-07-18 23:56:04 +00001178 : __begin_node_(__node_pointer()),
1179 __pair1_(__node_allocator(__a)),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001180 __pair3_(0)
1181{
1182 __begin_node() = __end_node();
1183}
1184
1185template <class _Tp, class _Compare, class _Allocator>
1186__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp,
1187 const allocator_type& __a)
Eric Fiselier02bb4bd2015-07-18 23:56:04 +00001188 : __begin_node_(__node_pointer()),
1189 __pair1_(__node_allocator(__a)),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001190 __pair3_(0, __comp)
1191{
1192 __begin_node() = __end_node();
1193}
1194
1195// Precondition: size() != 0
1196template <class _Tp, class _Compare, class _Allocator>
1197typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
1198__tree<_Tp, _Compare, _Allocator>::__detach()
1199{
1200 __node_pointer __cache = __begin_node();
1201 __begin_node() = __end_node();
1202 __end_node()->__left_->__parent_ = nullptr;
1203 __end_node()->__left_ = nullptr;
1204 size() = 0;
1205 // __cache->__left_ == nullptr
1206 if (__cache->__right_ != nullptr)
1207 __cache = static_cast<__node_pointer>(__cache->__right_);
1208 // __cache->__left_ == nullptr
1209 // __cache->__right_ == nullptr
1210 return __cache;
1211}
1212
1213// Precondition: __cache != nullptr
1214// __cache->left_ == nullptr
1215// __cache->right_ == nullptr
1216// This is no longer a red-black tree
1217template <class _Tp, class _Compare, class _Allocator>
1218typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
1219__tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache)
1220{
1221 if (__cache->__parent_ == nullptr)
1222 return nullptr;
Howard Hinnant70342b92013-06-19 21:29:40 +00001223 if (__tree_is_left_child(static_cast<__node_base_pointer>(__cache)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001224 {
1225 __cache->__parent_->__left_ = nullptr;
1226 __cache = static_cast<__node_pointer>(__cache->__parent_);
1227 if (__cache->__right_ == nullptr)
1228 return __cache;
1229 return static_cast<__node_pointer>(__tree_leaf(__cache->__right_));
1230 }
1231 // __cache is right child
1232 __cache->__parent_->__right_ = nullptr;
1233 __cache = static_cast<__node_pointer>(__cache->__parent_);
1234 if (__cache->__left_ == nullptr)
1235 return __cache;
1236 return static_cast<__node_pointer>(__tree_leaf(__cache->__left_));
1237}
1238
1239template <class _Tp, class _Compare, class _Allocator>
1240__tree<_Tp, _Compare, _Allocator>&
1241__tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t)
1242{
1243 if (this != &__t)
1244 {
1245 value_comp() = __t.value_comp();
1246 __copy_assign_alloc(__t);
1247 __assign_multi(__t.begin(), __t.end());
1248 }
1249 return *this;
1250}
1251
1252template <class _Tp, class _Compare, class _Allocator>
1253template <class _InputIterator>
1254void
1255__tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last)
1256{
1257 if (size() != 0)
1258 {
1259 __node_pointer __cache = __detach();
Howard Hinnantd4444702010-08-11 17:04:31 +00001260#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001261 try
1262 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001263#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001264 for (; __cache != nullptr && __first != __last; ++__first)
1265 {
1266 __cache->__value_ = *__first;
1267 __node_pointer __next = __detach(__cache);
1268 __node_insert_unique(__cache);
1269 __cache = __next;
1270 }
Howard Hinnantd4444702010-08-11 17:04:31 +00001271#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001272 }
1273 catch (...)
1274 {
1275 while (__cache->__parent_ != nullptr)
1276 __cache = static_cast<__node_pointer>(__cache->__parent_);
1277 destroy(__cache);
1278 throw;
1279 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001280#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001281 if (__cache != nullptr)
1282 {
1283 while (__cache->__parent_ != nullptr)
1284 __cache = static_cast<__node_pointer>(__cache->__parent_);
1285 destroy(__cache);
1286 }
1287 }
1288 for (; __first != __last; ++__first)
1289 __insert_unique(*__first);
1290}
1291
1292template <class _Tp, class _Compare, class _Allocator>
1293template <class _InputIterator>
1294void
1295__tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last)
1296{
1297 if (size() != 0)
1298 {
1299 __node_pointer __cache = __detach();
Howard Hinnantd4444702010-08-11 17:04:31 +00001300#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001301 try
1302 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001303#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001304 for (; __cache != nullptr && __first != __last; ++__first)
1305 {
1306 __cache->__value_ = *__first;
1307 __node_pointer __next = __detach(__cache);
1308 __node_insert_multi(__cache);
1309 __cache = __next;
1310 }
Howard Hinnantd4444702010-08-11 17:04:31 +00001311#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001312 }
1313 catch (...)
1314 {
1315 while (__cache->__parent_ != nullptr)
1316 __cache = static_cast<__node_pointer>(__cache->__parent_);
1317 destroy(__cache);
1318 throw;
1319 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001320#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001321 if (__cache != nullptr)
1322 {
1323 while (__cache->__parent_ != nullptr)
1324 __cache = static_cast<__node_pointer>(__cache->__parent_);
1325 destroy(__cache);
1326 }
1327 }
1328 for (; __first != __last; ++__first)
1329 __insert_multi(*__first);
1330}
1331
1332template <class _Tp, class _Compare, class _Allocator>
1333__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
1334 : __begin_node_(__node_pointer()),
1335 __pair1_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())),
1336 __pair3_(0, __t.value_comp())
1337{
1338 __begin_node() = __end_node();
1339}
1340
Howard Hinnant73d21a42010-09-04 23:28:19 +00001341#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001342
1343template <class _Tp, class _Compare, class _Allocator>
1344__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t)
Howard Hinnant7686add2011-06-04 14:31:57 +00001345 _NOEXCEPT_(
1346 is_nothrow_move_constructible<__node_allocator>::value &&
1347 is_nothrow_move_constructible<value_compare>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001348 : __begin_node_(_VSTD::move(__t.__begin_node_)),
1349 __pair1_(_VSTD::move(__t.__pair1_)),
1350 __pair3_(_VSTD::move(__t.__pair3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001351{
1352 if (size() == 0)
1353 __begin_node() = __end_node();
1354 else
1355 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001356 __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001357 __t.__begin_node() = __t.__end_node();
1358 __t.__end_node()->__left_ = nullptr;
1359 __t.size() = 0;
1360 }
1361}
1362
1363template <class _Tp, class _Compare, class _Allocator>
1364__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a)
1365 : __pair1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:19 +00001366 __pair3_(0, _VSTD::move(__t.value_comp()))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001367{
1368 if (__a == __t.__alloc())
1369 {
1370 if (__t.size() == 0)
1371 __begin_node() = __end_node();
1372 else
1373 {
1374 __begin_node() = __t.__begin_node();
1375 __end_node()->__left_ = __t.__end_node()->__left_;
Howard Hinnant70342b92013-06-19 21:29:40 +00001376 __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001377 size() = __t.size();
1378 __t.__begin_node() = __t.__end_node();
1379 __t.__end_node()->__left_ = nullptr;
1380 __t.size() = 0;
1381 }
1382 }
1383 else
1384 {
1385 __begin_node() = __end_node();
1386 }
1387}
1388
1389template <class _Tp, class _Compare, class _Allocator>
1390void
1391__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type)
Howard Hinnant7686add2011-06-04 14:31:57 +00001392 _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value &&
1393 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001394{
1395 destroy(static_cast<__node_pointer>(__end_node()->__left_));
1396 __begin_node_ = __t.__begin_node_;
1397 __pair1_.first() = __t.__pair1_.first();
1398 __move_assign_alloc(__t);
Howard Hinnant0949eed2011-06-30 21:18:19 +00001399 __pair3_ = _VSTD::move(__t.__pair3_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001400 if (size() == 0)
1401 __begin_node() = __end_node();
1402 else
1403 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001404 __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001405 __t.__begin_node() = __t.__end_node();
1406 __t.__end_node()->__left_ = nullptr;
1407 __t.size() = 0;
1408 }
1409}
1410
1411template <class _Tp, class _Compare, class _Allocator>
1412void
1413__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type)
1414{
1415 if (__node_alloc() == __t.__node_alloc())
1416 __move_assign(__t, true_type());
1417 else
1418 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001419 value_comp() = _VSTD::move(__t.value_comp());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001420 const_iterator __e = end();
1421 if (size() != 0)
1422 {
1423 __node_pointer __cache = __detach();
Howard Hinnantd4444702010-08-11 17:04:31 +00001424#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001425 try
1426 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001427#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001428 while (__cache != nullptr && __t.size() != 0)
1429 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001430 __cache->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001431 __node_pointer __next = __detach(__cache);
1432 __node_insert_multi(__cache);
1433 __cache = __next;
1434 }
Howard Hinnantd4444702010-08-11 17:04:31 +00001435#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001436 }
1437 catch (...)
1438 {
1439 while (__cache->__parent_ != nullptr)
1440 __cache = static_cast<__node_pointer>(__cache->__parent_);
1441 destroy(__cache);
1442 throw;
1443 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001444#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001445 if (__cache != nullptr)
1446 {
1447 while (__cache->__parent_ != nullptr)
1448 __cache = static_cast<__node_pointer>(__cache->__parent_);
1449 destroy(__cache);
1450 }
1451 }
1452 while (__t.size() != 0)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001453 __insert_multi(__e, _VSTD::move(__t.remove(__t.begin())->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001454 }
1455}
1456
1457template <class _Tp, class _Compare, class _Allocator>
1458__tree<_Tp, _Compare, _Allocator>&
1459__tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t)
Howard Hinnant7686add2011-06-04 14:31:57 +00001460 _NOEXCEPT_(
1461 __node_traits::propagate_on_container_move_assignment::value &&
1462 is_nothrow_move_assignable<value_compare>::value &&
1463 is_nothrow_move_assignable<__node_allocator>::value)
1464
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001465{
1466 __move_assign(__t, integral_constant<bool,
1467 __node_traits::propagate_on_container_move_assignment::value>());
1468 return *this;
1469}
1470
Howard Hinnant73d21a42010-09-04 23:28:19 +00001471#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001472
1473template <class _Tp, class _Compare, class _Allocator>
1474__tree<_Tp, _Compare, _Allocator>::~__tree()
1475{
1476 destroy(__root());
1477}
1478
1479template <class _Tp, class _Compare, class _Allocator>
1480void
Howard Hinnant7686add2011-06-04 14:31:57 +00001481__tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001482{
1483 if (__nd != nullptr)
1484 {
1485 destroy(static_cast<__node_pointer>(__nd->__left_));
1486 destroy(static_cast<__node_pointer>(__nd->__right_));
1487 __node_allocator& __na = __node_alloc();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001488 __node_traits::destroy(__na, _VSTD::addressof(__nd->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001489 __node_traits::deallocate(__na, __nd, 1);
1490 }
1491}
1492
1493template <class _Tp, class _Compare, class _Allocator>
1494void
1495__tree<_Tp, _Compare, _Allocator>::swap(__tree& __t)
Marshall Clow7d914d12015-07-13 20:04:56 +00001496 _NOEXCEPT_(
1497 __is_nothrow_swappable<value_compare>::value
1498#if _LIBCPP_STD_VER <= 11
1499 && (!__node_traits::propagate_on_container_swap::value ||
1500 __is_nothrow_swappable<__node_allocator>::value)
1501#endif
1502 )
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001503{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001504 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001505 swap(__begin_node_, __t.__begin_node_);
1506 swap(__pair1_.first(), __t.__pair1_.first());
Marshall Clow7d914d12015-07-13 20:04:56 +00001507 __swap_allocator(__node_alloc(), __t.__node_alloc());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001508 __pair3_.swap(__t.__pair3_);
1509 if (size() == 0)
1510 __begin_node() = __end_node();
1511 else
Howard Hinnant70342b92013-06-19 21:29:40 +00001512 __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001513 if (__t.size() == 0)
1514 __t.__begin_node() = __t.__end_node();
1515 else
Howard Hinnant70342b92013-06-19 21:29:40 +00001516 __t.__end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__t.__end_node());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001517}
1518
1519template <class _Tp, class _Compare, class _Allocator>
1520void
Howard Hinnant7686add2011-06-04 14:31:57 +00001521__tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001522{
1523 destroy(__root());
1524 size() = 0;
1525 __begin_node() = __end_node();
1526 __end_node()->__left_ = nullptr;
1527}
1528
1529// Find lower_bound place to insert
1530// Set __parent to parent of null leaf
1531// Return reference to null leaf
1532template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantd615e472011-04-03 20:05:29 +00001533typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
1534__tree<_Tp, _Compare, _Allocator>::__find_leaf_low(typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001535 const value_type& __v)
1536{
1537 __node_pointer __nd = __root();
1538 if (__nd != nullptr)
1539 {
1540 while (true)
1541 {
1542 if (value_comp()(__nd->__value_, __v))
1543 {
1544 if (__nd->__right_ != nullptr)
1545 __nd = static_cast<__node_pointer>(__nd->__right_);
1546 else
1547 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001548 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001549 return __parent->__right_;
1550 }
1551 }
1552 else
1553 {
1554 if (__nd->__left_ != nullptr)
1555 __nd = static_cast<__node_pointer>(__nd->__left_);
1556 else
1557 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001558 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001559 return __parent->__left_;
1560 }
1561 }
1562 }
1563 }
Howard Hinnant70342b92013-06-19 21:29:40 +00001564 __parent = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001565 return __parent->__left_;
1566}
1567
1568// Find upper_bound place to insert
1569// Set __parent to parent of null leaf
1570// Return reference to null leaf
1571template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantd615e472011-04-03 20:05:29 +00001572typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
1573__tree<_Tp, _Compare, _Allocator>::__find_leaf_high(typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001574 const value_type& __v)
1575{
1576 __node_pointer __nd = __root();
1577 if (__nd != nullptr)
1578 {
1579 while (true)
1580 {
1581 if (value_comp()(__v, __nd->__value_))
1582 {
1583 if (__nd->__left_ != nullptr)
1584 __nd = static_cast<__node_pointer>(__nd->__left_);
1585 else
1586 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001587 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001588 return __parent->__left_;
1589 }
1590 }
1591 else
1592 {
1593 if (__nd->__right_ != nullptr)
1594 __nd = static_cast<__node_pointer>(__nd->__right_);
1595 else
1596 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001597 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001598 return __parent->__right_;
1599 }
1600 }
1601 }
1602 }
Howard Hinnant70342b92013-06-19 21:29:40 +00001603 __parent = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001604 return __parent->__left_;
1605}
1606
1607// Find leaf place to insert closest to __hint
1608// First check prior to __hint.
1609// Next check after __hint.
1610// Next do O(log N) search.
1611// Set __parent to parent of null leaf
1612// Return reference to null leaf
1613template <class _Tp, class _Compare, class _Allocator>
Howard Hinnantd615e472011-04-03 20:05:29 +00001614typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001615__tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint,
Howard Hinnantd615e472011-04-03 20:05:29 +00001616 typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001617 const value_type& __v)
1618{
1619 if (__hint == end() || !value_comp()(*__hint, __v)) // check before
1620 {
1621 // __v <= *__hint
1622 const_iterator __prior = __hint;
1623 if (__prior == begin() || !value_comp()(__v, *--__prior))
1624 {
1625 // *prev(__hint) <= __v <= *__hint
1626 if (__hint.__ptr_->__left_ == nullptr)
1627 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001628 __parent = static_cast<__node_base_pointer>(__hint.__ptr_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001629 return __parent->__left_;
1630 }
1631 else
1632 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001633 __parent = static_cast<__node_base_pointer>(__prior.__ptr_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001634 return __parent->__right_;
1635 }
1636 }
1637 // __v < *prev(__hint)
1638 return __find_leaf_high(__parent, __v);
1639 }
1640 // else __v > *__hint
1641 return __find_leaf_low(__parent, __v);
1642}
1643
1644// Find place to insert if __v doesn't exist
1645// Set __parent to parent of null leaf
1646// Return reference to null leaf
1647// If __v exists, set parent to node of __v and return reference to node of __v
1648template <class _Tp, class _Compare, class _Allocator>
1649template <class _Key>
Howard Hinnantd615e472011-04-03 20:05:29 +00001650typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
1651__tree<_Tp, _Compare, _Allocator>::__find_equal(typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001652 const _Key& __v)
1653{
1654 __node_pointer __nd = __root();
1655 if (__nd != nullptr)
1656 {
1657 while (true)
1658 {
1659 if (value_comp()(__v, __nd->__value_))
1660 {
1661 if (__nd->__left_ != nullptr)
1662 __nd = static_cast<__node_pointer>(__nd->__left_);
1663 else
1664 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001665 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001666 return __parent->__left_;
1667 }
1668 }
1669 else if (value_comp()(__nd->__value_, __v))
1670 {
1671 if (__nd->__right_ != nullptr)
1672 __nd = static_cast<__node_pointer>(__nd->__right_);
1673 else
1674 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001675 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001676 return __parent->__right_;
1677 }
1678 }
1679 else
1680 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001681 __parent = static_cast<__node_base_pointer>(__nd);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001682 return __parent;
1683 }
1684 }
1685 }
Howard Hinnant70342b92013-06-19 21:29:40 +00001686 __parent = static_cast<__node_base_pointer>(__end_node());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001687 return __parent->__left_;
1688}
1689
1690// Find place to insert if __v doesn't exist
1691// First check prior to __hint.
1692// Next check after __hint.
1693// Next do O(log N) search.
1694// Set __parent to parent of null leaf
1695// Return reference to null leaf
1696// If __v exists, set parent to node of __v and return reference to node of __v
1697template <class _Tp, class _Compare, class _Allocator>
1698template <class _Key>
Howard Hinnantd615e472011-04-03 20:05:29 +00001699typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001700__tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint,
Howard Hinnantd615e472011-04-03 20:05:29 +00001701 typename __node_base::pointer& __parent,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001702 const _Key& __v)
1703{
1704 if (__hint == end() || value_comp()(__v, *__hint)) // check before
1705 {
1706 // __v < *__hint
1707 const_iterator __prior = __hint;
1708 if (__prior == begin() || value_comp()(*--__prior, __v))
1709 {
1710 // *prev(__hint) < __v < *__hint
1711 if (__hint.__ptr_->__left_ == nullptr)
1712 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001713 __parent = static_cast<__node_base_pointer>(__hint.__ptr_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001714 return __parent->__left_;
1715 }
1716 else
1717 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001718 __parent = static_cast<__node_base_pointer>(__prior.__ptr_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001719 return __parent->__right_;
1720 }
1721 }
1722 // __v <= *prev(__hint)
1723 return __find_equal(__parent, __v);
1724 }
1725 else if (value_comp()(*__hint, __v)) // check after
1726 {
1727 // *__hint < __v
Howard Hinnant0949eed2011-06-30 21:18:19 +00001728 const_iterator __next = _VSTD::next(__hint);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001729 if (__next == end() || value_comp()(__v, *__next))
1730 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001731 // *__hint < __v < *_VSTD::next(__hint)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001732 if (__hint.__ptr_->__right_ == nullptr)
1733 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001734 __parent = static_cast<__node_base_pointer>(__hint.__ptr_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001735 return __parent->__right_;
1736 }
1737 else
1738 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001739 __parent = static_cast<__node_base_pointer>(__next.__ptr_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001740 return __parent->__left_;
1741 }
1742 }
1743 // *next(__hint) <= __v
1744 return __find_equal(__parent, __v);
1745 }
1746 // else __v == *__hint
Howard Hinnant70342b92013-06-19 21:29:40 +00001747 __parent = static_cast<__node_base_pointer>(__hint.__ptr_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001748 return __parent;
1749}
1750
1751template <class _Tp, class _Compare, class _Allocator>
1752void
1753__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__node_base_pointer __parent,
1754 __node_base_pointer& __child,
1755 __node_base_pointer __new_node)
1756{
1757 __new_node->__left_ = nullptr;
1758 __new_node->__right_ = nullptr;
1759 __new_node->__parent_ = __parent;
1760 __child = __new_node;
1761 if (__begin_node()->__left_ != nullptr)
1762 __begin_node() = static_cast<__node_pointer>(__begin_node()->__left_);
1763 __tree_balance_after_insert(__end_node()->__left_, __child);
1764 ++size();
1765}
1766
Howard Hinnant73d21a42010-09-04 23:28:19 +00001767#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1768#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001769
1770template <class _Tp, class _Compare, class _Allocator>
1771template <class ..._Args>
1772typename __tree<_Tp, _Compare, _Allocator>::__node_holder
1773__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args)
1774{
1775 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001776 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001777 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001778 __h.get_deleter().__value_constructed = true;
1779 return __h;
1780}
1781
1782template <class _Tp, class _Compare, class _Allocator>
1783template <class... _Args>
1784pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1785__tree<_Tp, _Compare, _Allocator>::__emplace_unique(_Args&&... __args)
1786{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001787 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001788 __node_base_pointer __parent;
1789 __node_base_pointer& __child = __find_equal(__parent, __h->__value_);
1790 __node_pointer __r = static_cast<__node_pointer>(__child);
1791 bool __inserted = false;
1792 if (__child == nullptr)
1793 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001794 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001795 __r = __h.release();
1796 __inserted = true;
1797 }
1798 return pair<iterator, bool>(iterator(__r), __inserted);
1799}
1800
1801template <class _Tp, class _Compare, class _Allocator>
1802template <class... _Args>
1803typename __tree<_Tp, _Compare, _Allocator>::iterator
1804__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique(const_iterator __p, _Args&&... __args)
1805{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001806 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001807 __node_base_pointer __parent;
1808 __node_base_pointer& __child = __find_equal(__p, __parent, __h->__value_);
1809 __node_pointer __r = static_cast<__node_pointer>(__child);
1810 if (__child == nullptr)
1811 {
Howard Hinnant70342b92013-06-19 21:29:40 +00001812 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001813 __r = __h.release();
1814 }
1815 return iterator(__r);
1816}
1817
1818template <class _Tp, class _Compare, class _Allocator>
1819template <class... _Args>
1820typename __tree<_Tp, _Compare, _Allocator>::iterator
1821__tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args)
1822{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001823 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001824 __node_base_pointer __parent;
1825 __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
Howard Hinnant70342b92013-06-19 21:29:40 +00001826 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001827 return iterator(static_cast<__node_pointer>(__h.release()));
1828}
1829
1830template <class _Tp, class _Compare, class _Allocator>
1831template <class... _Args>
1832typename __tree<_Tp, _Compare, _Allocator>::iterator
1833__tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p,
1834 _Args&&... __args)
1835{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001836 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001837 __node_base_pointer __parent;
1838 __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
Howard Hinnant70342b92013-06-19 21:29:40 +00001839 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001840 return iterator(static_cast<__node_pointer>(__h.release()));
1841}
1842
Howard Hinnant73d21a42010-09-04 23:28:19 +00001843#endif // _LIBCPP_HAS_NO_VARIADICS
1844
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001845template <class _Tp, class _Compare, class _Allocator>
Marshall Clow3426a862016-01-05 19:32:41 +00001846pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1847__tree<_Tp, _Compare, _Allocator>::__insert_unique(value_type&& __v)
1848{
1849 __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
1850 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1851 if (__r.second)
1852 __h.release();
1853 return __r;
1854}
1855
1856template <class _Tp, class _Compare, class _Allocator>
1857typename __tree<_Tp, _Compare, _Allocator>::iterator
1858__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, value_type&& __v)
1859{
1860 __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
1861 iterator __r = __node_insert_unique(__p, __h.get());
1862 if (__r.__ptr_ == __h.get())
1863 __h.release();
1864 return __r;
1865}
1866
1867template <class _Tp, class _Compare, class _Allocator>
Howard Hinnant99968442011-11-29 18:15:50 +00001868template <class _Vp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001869pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
Howard Hinnant99968442011-11-29 18:15:50 +00001870__tree<_Tp, _Compare, _Allocator>::__insert_unique(_Vp&& __v)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001871{
Howard Hinnant99968442011-11-29 18:15:50 +00001872 __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001873 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1874 if (__r.second)
1875 __h.release();
1876 return __r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001877}
1878
1879template <class _Tp, class _Compare, class _Allocator>
Howard Hinnant99968442011-11-29 18:15:50 +00001880template <class _Vp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001881typename __tree<_Tp, _Compare, _Allocator>::iterator
Howard Hinnant99968442011-11-29 18:15:50 +00001882__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, _Vp&& __v)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001883{
Howard Hinnant99968442011-11-29 18:15:50 +00001884 __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001885 iterator __r = __node_insert_unique(__p, __h.get());
1886 if (__r.__ptr_ == __h.get())
1887 __h.release();
1888 return __r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001889}
1890
1891template <class _Tp, class _Compare, class _Allocator>
Marshall Clow3426a862016-01-05 19:32:41 +00001892typename __tree<_Tp, _Compare, _Allocator>::iterator
1893__tree<_Tp, _Compare, _Allocator>::__insert_multi(value_type&& __v)
1894{
1895 __node_base_pointer __parent;
1896 __node_base_pointer& __child = __find_leaf_high(__parent, __v);
1897 __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
1898 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
1899 return iterator(__h.release());
1900}
1901
1902template <class _Tp, class _Compare, class _Allocator>
1903typename __tree<_Tp, _Compare, _Allocator>::iterator
1904__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, value_type&& __v)
1905{
1906 __node_base_pointer __parent;
1907 __node_base_pointer& __child = __find_leaf(__p, __parent, __v);
1908 __node_holder __h = __construct_node(_VSTD::forward<value_type>(__v));
1909 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
1910 return iterator(__h.release());
1911}
1912
1913template <class _Tp, class _Compare, class _Allocator>
Howard Hinnant99968442011-11-29 18:15:50 +00001914template <class _Vp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001915typename __tree<_Tp, _Compare, _Allocator>::iterator
Howard Hinnant99968442011-11-29 18:15:50 +00001916__tree<_Tp, _Compare, _Allocator>::__insert_multi(_Vp&& __v)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001917{
Howard Hinnant99968442011-11-29 18:15:50 +00001918 __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001919 __node_base_pointer __parent;
1920 __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
Howard Hinnant70342b92013-06-19 21:29:40 +00001921 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001922 return iterator(__h.release());
1923}
1924
1925template <class _Tp, class _Compare, class _Allocator>
Howard Hinnant99968442011-11-29 18:15:50 +00001926template <class _Vp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001927typename __tree<_Tp, _Compare, _Allocator>::iterator
Howard Hinnant99968442011-11-29 18:15:50 +00001928__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, _Vp&& __v)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001929{
Howard Hinnant99968442011-11-29 18:15:50 +00001930 __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001931 __node_base_pointer __parent;
1932 __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
Howard Hinnant70342b92013-06-19 21:29:40 +00001933 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001934 return iterator(__h.release());
1935}
1936
Howard Hinnant73d21a42010-09-04 23:28:19 +00001937#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001938
1939template <class _Tp, class _Compare, class _Allocator>
1940typename __tree<_Tp, _Compare, _Allocator>::__node_holder
1941__tree<_Tp, _Compare, _Allocator>::__construct_node(const value_type& __v)
1942{
1943 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001944 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001945 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001946 __h.get_deleter().__value_constructed = true;
Dimitry Andric89663502015-08-19 06:43:33 +00001947 return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001948}
1949
Howard Hinnantd0a2fbf2011-03-10 17:27:57 +00001950#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
1951
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001952template <class _Tp, class _Compare, class _Allocator>
1953pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
1954__tree<_Tp, _Compare, _Allocator>::__insert_unique(const value_type& __v)
1955{
1956 __node_base_pointer __parent;
1957 __node_base_pointer& __child = __find_equal(__parent, __v);
1958 __node_pointer __r = static_cast<__node_pointer>(__child);
1959 bool __inserted = false;
1960 if (__child == nullptr)
1961 {
1962 __node_holder __h = __construct_node(__v);
Howard Hinnant70342b92013-06-19 21:29:40 +00001963 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001964 __r = __h.release();
1965 __inserted = true;
1966 }
1967 return pair<iterator, bool>(iterator(__r), __inserted);
1968}
1969
1970template <class _Tp, class _Compare, class _Allocator>
1971typename __tree<_Tp, _Compare, _Allocator>::iterator
1972__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, const value_type& __v)
1973{
1974 __node_base_pointer __parent;
1975 __node_base_pointer& __child = __find_equal(__p, __parent, __v);
1976 __node_pointer __r = static_cast<__node_pointer>(__child);
1977 if (__child == nullptr)
1978 {
1979 __node_holder __h = __construct_node(__v);
Howard Hinnant70342b92013-06-19 21:29:40 +00001980 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001981 __r = __h.release();
1982 }
1983 return iterator(__r);
1984}
1985
1986template <class _Tp, class _Compare, class _Allocator>
1987typename __tree<_Tp, _Compare, _Allocator>::iterator
1988__tree<_Tp, _Compare, _Allocator>::__insert_multi(const value_type& __v)
1989{
1990 __node_base_pointer __parent;
1991 __node_base_pointer& __child = __find_leaf_high(__parent, __v);
1992 __node_holder __h = __construct_node(__v);
Howard Hinnant70342b92013-06-19 21:29:40 +00001993 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001994 return iterator(__h.release());
1995}
1996
1997template <class _Tp, class _Compare, class _Allocator>
1998typename __tree<_Tp, _Compare, _Allocator>::iterator
1999__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const value_type& __v)
2000{
2001 __node_base_pointer __parent;
2002 __node_base_pointer& __child = __find_leaf(__p, __parent, __v);
2003 __node_holder __h = __construct_node(__v);
Howard Hinnant70342b92013-06-19 21:29:40 +00002004 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002005 return iterator(__h.release());
2006}
2007
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002008template <class _Tp, class _Compare, class _Allocator>
2009pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
2010__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd)
2011{
2012 __node_base_pointer __parent;
2013 __node_base_pointer& __child = __find_equal(__parent, __nd->__value_);
2014 __node_pointer __r = static_cast<__node_pointer>(__child);
2015 bool __inserted = false;
2016 if (__child == nullptr)
2017 {
Howard Hinnant70342b92013-06-19 21:29:40 +00002018 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002019 __r = __nd;
2020 __inserted = true;
2021 }
2022 return pair<iterator, bool>(iterator(__r), __inserted);
2023}
2024
2025template <class _Tp, class _Compare, class _Allocator>
2026typename __tree<_Tp, _Compare, _Allocator>::iterator
2027__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p,
2028 __node_pointer __nd)
2029{
2030 __node_base_pointer __parent;
2031 __node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_);
2032 __node_pointer __r = static_cast<__node_pointer>(__child);
2033 if (__child == nullptr)
2034 {
Howard Hinnant70342b92013-06-19 21:29:40 +00002035 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002036 __r = __nd;
2037 }
2038 return iterator(__r);
2039}
2040
2041template <class _Tp, class _Compare, class _Allocator>
2042typename __tree<_Tp, _Compare, _Allocator>::iterator
2043__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd)
2044{
2045 __node_base_pointer __parent;
2046 __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__value_);
Howard Hinnant70342b92013-06-19 21:29:40 +00002047 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002048 return iterator(__nd);
2049}
2050
2051template <class _Tp, class _Compare, class _Allocator>
2052typename __tree<_Tp, _Compare, _Allocator>::iterator
2053__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p,
2054 __node_pointer __nd)
2055{
2056 __node_base_pointer __parent;
2057 __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__value_);
Howard Hinnant70342b92013-06-19 21:29:40 +00002058 __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002059 return iterator(__nd);
2060}
2061
2062template <class _Tp, class _Compare, class _Allocator>
2063typename __tree<_Tp, _Compare, _Allocator>::iterator
2064__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p)
2065{
Howard Hinnant70342b92013-06-19 21:29:40 +00002066 __node_pointer __np = __p.__ptr_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002067 iterator __r(__np);
2068 ++__r;
2069 if (__begin_node() == __np)
2070 __begin_node() = __r.__ptr_;
2071 --size();
2072 __node_allocator& __na = __node_alloc();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002073 __tree_remove(__end_node()->__left_,
2074 static_cast<__node_base_pointer>(__np));
Marshall Clow140e8f52014-04-11 08:22:42 +00002075 __node_traits::destroy(__na, const_cast<value_type*>(_VSTD::addressof(*__p)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002076 __node_traits::deallocate(__na, __np, 1);
2077 return __r;
2078}
2079
2080template <class _Tp, class _Compare, class _Allocator>
2081typename __tree<_Tp, _Compare, _Allocator>::iterator
2082__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l)
2083{
2084 while (__f != __l)
2085 __f = erase(__f);
Howard Hinnant70342b92013-06-19 21:29:40 +00002086 return iterator(__l.__ptr_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002087}
2088
2089template <class _Tp, class _Compare, class _Allocator>
2090template <class _Key>
2091typename __tree<_Tp, _Compare, _Allocator>::size_type
2092__tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k)
2093{
2094 iterator __i = find(__k);
2095 if (__i == end())
2096 return 0;
2097 erase(__i);
2098 return 1;
2099}
2100
2101template <class _Tp, class _Compare, class _Allocator>
2102template <class _Key>
2103typename __tree<_Tp, _Compare, _Allocator>::size_type
2104__tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k)
2105{
2106 pair<iterator, iterator> __p = __equal_range_multi(__k);
2107 size_type __r = 0;
2108 for (; __p.first != __p.second; ++__r)
2109 __p.first = erase(__p.first);
2110 return __r;
2111}
2112
2113template <class _Tp, class _Compare, class _Allocator>
2114template <class _Key>
2115typename __tree<_Tp, _Compare, _Allocator>::iterator
2116__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v)
2117{
2118 iterator __p = __lower_bound(__v, __root(), __end_node());
2119 if (__p != end() && !value_comp()(__v, *__p))
2120 return __p;
2121 return end();
2122}
2123
2124template <class _Tp, class _Compare, class _Allocator>
2125template <class _Key>
2126typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2127__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) const
2128{
2129 const_iterator __p = __lower_bound(__v, __root(), __end_node());
2130 if (__p != end() && !value_comp()(__v, *__p))
2131 return __p;
2132 return end();
2133}
2134
2135template <class _Tp, class _Compare, class _Allocator>
2136template <class _Key>
2137typename __tree<_Tp, _Compare, _Allocator>::size_type
2138__tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const
2139{
Eric Fiselier227b47c2016-02-20 07:12:17 +00002140 __node_pointer __result = __end_node();
2141 __node_pointer __rt = __root();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002142 while (__rt != nullptr)
2143 {
2144 if (value_comp()(__k, __rt->__value_))
2145 {
2146 __result = __rt;
Eric Fiselier227b47c2016-02-20 07:12:17 +00002147 __rt = static_cast<__node_pointer>(__rt->__left_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002148 }
2149 else if (value_comp()(__rt->__value_, __k))
Eric Fiselier227b47c2016-02-20 07:12:17 +00002150 __rt = static_cast<__node_pointer>(__rt->__right_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002151 else
2152 return 1;
2153 }
2154 return 0;
2155}
2156
2157template <class _Tp, class _Compare, class _Allocator>
2158template <class _Key>
2159typename __tree<_Tp, _Compare, _Allocator>::size_type
2160__tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const
2161{
Eric Fiselier227b47c2016-02-20 07:12:17 +00002162 __node_pointer __result = __end_node();
2163 __node_pointer __rt = __root();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002164 while (__rt != nullptr)
2165 {
2166 if (value_comp()(__k, __rt->__value_))
2167 {
2168 __result = __rt;
Eric Fiselier227b47c2016-02-20 07:12:17 +00002169 __rt = static_cast<__node_pointer>(__rt->__left_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002170 }
2171 else if (value_comp()(__rt->__value_, __k))
Eric Fiselier227b47c2016-02-20 07:12:17 +00002172 __rt = static_cast<__node_pointer>(__rt->__right_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002173 else
Howard Hinnant0949eed2011-06-30 21:18:19 +00002174 return _VSTD::distance(
Eric Fiselier227b47c2016-02-20 07:12:17 +00002175 __lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt),
2176 __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002177 );
2178 }
2179 return 0;
2180}
2181
2182template <class _Tp, class _Compare, class _Allocator>
2183template <class _Key>
2184typename __tree<_Tp, _Compare, _Allocator>::iterator
2185__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
2186 __node_pointer __root,
2187 __node_pointer __result)
2188{
2189 while (__root != nullptr)
2190 {
2191 if (!value_comp()(__root->__value_, __v))
2192 {
2193 __result = __root;
2194 __root = static_cast<__node_pointer>(__root->__left_);
2195 }
2196 else
2197 __root = static_cast<__node_pointer>(__root->__right_);
2198 }
2199 return iterator(__result);
2200}
2201
2202template <class _Tp, class _Compare, class _Allocator>
2203template <class _Key>
2204typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2205__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
Eric Fiselier227b47c2016-02-20 07:12:17 +00002206 __node_pointer __root,
2207 __node_pointer __result) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002208{
2209 while (__root != nullptr)
2210 {
2211 if (!value_comp()(__root->__value_, __v))
2212 {
2213 __result = __root;
Eric Fiselier227b47c2016-02-20 07:12:17 +00002214 __root = static_cast<__node_pointer>(__root->__left_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002215 }
2216 else
Eric Fiselier227b47c2016-02-20 07:12:17 +00002217 __root = static_cast<__node_pointer>(__root->__right_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002218 }
2219 return const_iterator(__result);
2220}
2221
2222template <class _Tp, class _Compare, class _Allocator>
2223template <class _Key>
2224typename __tree<_Tp, _Compare, _Allocator>::iterator
2225__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
2226 __node_pointer __root,
2227 __node_pointer __result)
2228{
2229 while (__root != nullptr)
2230 {
2231 if (value_comp()(__v, __root->__value_))
2232 {
2233 __result = __root;
2234 __root = static_cast<__node_pointer>(__root->__left_);
2235 }
2236 else
2237 __root = static_cast<__node_pointer>(__root->__right_);
2238 }
2239 return iterator(__result);
2240}
2241
2242template <class _Tp, class _Compare, class _Allocator>
2243template <class _Key>
2244typename __tree<_Tp, _Compare, _Allocator>::const_iterator
2245__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
Eric Fiselier227b47c2016-02-20 07:12:17 +00002246 __node_pointer __root,
2247 __node_pointer __result) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002248{
2249 while (__root != nullptr)
2250 {
2251 if (value_comp()(__v, __root->__value_))
2252 {
2253 __result = __root;
Eric Fiselier227b47c2016-02-20 07:12:17 +00002254 __root = static_cast<__node_pointer>(__root->__left_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002255 }
2256 else
Eric Fiselier227b47c2016-02-20 07:12:17 +00002257 __root = static_cast<__node_pointer>(__root->__right_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002258 }
2259 return const_iterator(__result);
2260}
2261
2262template <class _Tp, class _Compare, class _Allocator>
2263template <class _Key>
2264pair<typename __tree<_Tp, _Compare, _Allocator>::iterator,
2265 typename __tree<_Tp, _Compare, _Allocator>::iterator>
2266__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k)
2267{
Howard Hinnant99968442011-11-29 18:15:50 +00002268 typedef pair<iterator, iterator> _Pp;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002269 __node_pointer __result = __end_node();
2270 __node_pointer __rt = __root();
2271 while (__rt != nullptr)
2272 {
2273 if (value_comp()(__k, __rt->__value_))
2274 {
2275 __result = __rt;
2276 __rt = static_cast<__node_pointer>(__rt->__left_);
2277 }
2278 else if (value_comp()(__rt->__value_, __k))
2279 __rt = static_cast<__node_pointer>(__rt->__right_);
2280 else
Howard Hinnant99968442011-11-29 18:15:50 +00002281 return _Pp(iterator(__rt),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002282 iterator(
2283 __rt->__right_ != nullptr ?
2284 static_cast<__node_pointer>(__tree_min(__rt->__right_))
2285 : __result));
2286 }
Howard Hinnant99968442011-11-29 18:15:50 +00002287 return _Pp(iterator(__result), iterator(__result));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002288}
2289
2290template <class _Tp, class _Compare, class _Allocator>
2291template <class _Key>
2292pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
2293 typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
2294__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const
2295{
Howard Hinnant99968442011-11-29 18:15:50 +00002296 typedef pair<const_iterator, const_iterator> _Pp;
Eric Fiselier227b47c2016-02-20 07:12:17 +00002297 __node_pointer __result = __end_node();
2298 __node_pointer __rt = __root();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002299 while (__rt != nullptr)
2300 {
2301 if (value_comp()(__k, __rt->__value_))
2302 {
2303 __result = __rt;
Eric Fiselier227b47c2016-02-20 07:12:17 +00002304 __rt = static_cast<__node_pointer>(__rt->__left_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002305 }
2306 else if (value_comp()(__rt->__value_, __k))
Eric Fiselier227b47c2016-02-20 07:12:17 +00002307 __rt = static_cast<__node_pointer>(__rt->__right_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002308 else
Howard Hinnant99968442011-11-29 18:15:50 +00002309 return _Pp(const_iterator(__rt),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002310 const_iterator(
2311 __rt->__right_ != nullptr ?
Eric Fiselier227b47c2016-02-20 07:12:17 +00002312 static_cast<__node_pointer>(__tree_min(__rt->__right_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002313 : __result));
2314 }
Howard Hinnant99968442011-11-29 18:15:50 +00002315 return _Pp(const_iterator(__result), const_iterator(__result));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002316}
2317
2318template <class _Tp, class _Compare, class _Allocator>
2319template <class _Key>
2320pair<typename __tree<_Tp, _Compare, _Allocator>::iterator,
2321 typename __tree<_Tp, _Compare, _Allocator>::iterator>
2322__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k)
2323{
Howard Hinnant99968442011-11-29 18:15:50 +00002324 typedef pair<iterator, iterator> _Pp;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002325 __node_pointer __result = __end_node();
2326 __node_pointer __rt = __root();
2327 while (__rt != nullptr)
2328 {
2329 if (value_comp()(__k, __rt->__value_))
2330 {
2331 __result = __rt;
2332 __rt = static_cast<__node_pointer>(__rt->__left_);
2333 }
2334 else if (value_comp()(__rt->__value_, __k))
2335 __rt = static_cast<__node_pointer>(__rt->__right_);
2336 else
Howard Hinnant99968442011-11-29 18:15:50 +00002337 return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002338 __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
2339 }
Howard Hinnant99968442011-11-29 18:15:50 +00002340 return _Pp(iterator(__result), iterator(__result));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002341}
2342
2343template <class _Tp, class _Compare, class _Allocator>
2344template <class _Key>
2345pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
2346 typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
2347__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const
2348{
Howard Hinnant99968442011-11-29 18:15:50 +00002349 typedef pair<const_iterator, const_iterator> _Pp;
Eric Fiselier227b47c2016-02-20 07:12:17 +00002350 __node_pointer __result = __end_node();
2351 __node_pointer __rt = __root();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002352 while (__rt != nullptr)
2353 {
2354 if (value_comp()(__k, __rt->__value_))
2355 {
2356 __result = __rt;
Eric Fiselier227b47c2016-02-20 07:12:17 +00002357 __rt = static_cast<__node_pointer>(__rt->__left_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002358 }
2359 else if (value_comp()(__rt->__value_, __k))
Eric Fiselier227b47c2016-02-20 07:12:17 +00002360 __rt = static_cast<__node_pointer>(__rt->__right_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002361 else
Eric Fiselier227b47c2016-02-20 07:12:17 +00002362 return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt),
2363 __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002364 }
Howard Hinnant99968442011-11-29 18:15:50 +00002365 return _Pp(const_iterator(__result), const_iterator(__result));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002366}
2367
2368template <class _Tp, class _Compare, class _Allocator>
2369typename __tree<_Tp, _Compare, _Allocator>::__node_holder
Howard Hinnant8b537682011-06-04 17:10:24 +00002370__tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002371{
Howard Hinnant70342b92013-06-19 21:29:40 +00002372 __node_pointer __np = __p.__ptr_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002373 if (__begin_node() == __np)
2374 {
2375 if (__np->__right_ != nullptr)
2376 __begin_node() = static_cast<__node_pointer>(__np->__right_);
2377 else
2378 __begin_node() = static_cast<__node_pointer>(__np->__parent_);
2379 }
2380 --size();
2381 __tree_remove(__end_node()->__left_,
2382 static_cast<__node_base_pointer>(__np));
Marshall Clow01c1c6f2015-01-28 19:54:25 +00002383 return __node_holder(__np, _Dp(__node_alloc(), true));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002384}
2385
Howard Hinnant7686add2011-06-04 14:31:57 +00002386template <class _Tp, class _Compare, class _Allocator>
2387inline _LIBCPP_INLINE_VISIBILITY
2388void
2389swap(__tree<_Tp, _Compare, _Allocator>& __x,
2390 __tree<_Tp, _Compare, _Allocator>& __y)
2391 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
2392{
2393 __x.swap(__y);
2394}
2395
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002396_LIBCPP_END_NAMESPACE_STD
2397
2398#endif // _LIBCPP___TREE