xref: /freebsd-12.1/contrib/libc++/include/__tree (revision b5893f02)
17a984708SDavid Chisnall// -*- C++ -*-
27a984708SDavid Chisnall//===----------------------------------------------------------------------===//
37a984708SDavid Chisnall//
47a984708SDavid Chisnall//                     The LLVM Compiler Infrastructure
57a984708SDavid Chisnall//
67a984708SDavid Chisnall// This file is dual licensed under the MIT and the University of Illinois Open
77a984708SDavid Chisnall// Source Licenses. See LICENSE.TXT for details.
87a984708SDavid Chisnall//
97a984708SDavid Chisnall//===----------------------------------------------------------------------===//
107a984708SDavid Chisnall
117a984708SDavid Chisnall#ifndef _LIBCPP___TREE
127a984708SDavid Chisnall#define _LIBCPP___TREE
137a984708SDavid Chisnall
147a984708SDavid Chisnall#include <__config>
157a984708SDavid Chisnall#include <iterator>
167a984708SDavid Chisnall#include <memory>
177a984708SDavid Chisnall#include <stdexcept>
187a984708SDavid Chisnall#include <algorithm>
197a984708SDavid Chisnall
207a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
217a984708SDavid Chisnall#pragma GCC system_header
227a984708SDavid Chisnall#endif
237a984708SDavid Chisnall
24f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS
25f9448bf3SDimitry Andric#include <__undef_macros>
26f9448bf3SDimitry Andric
27f9448bf3SDimitry Andric
287a984708SDavid Chisnall_LIBCPP_BEGIN_NAMESPACE_STD
297a984708SDavid Chisnall
307a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator> class __tree;
317a984708SDavid Chisnalltemplate <class _Tp, class _NodePtr, class _DiffType>
32aed8d94eSDimitry Andric    class _LIBCPP_TEMPLATE_VIS __tree_iterator;
337a984708SDavid Chisnalltemplate <class _Tp, class _ConstNodePtr, class _DiffType>
34aed8d94eSDimitry Andric    class _LIBCPP_TEMPLATE_VIS __tree_const_iterator;
357a984708SDavid Chisnall
367c82a1ecSDimitry Andrictemplate <class _Pointer> class __tree_end_node;
377c82a1ecSDimitry Andrictemplate <class _VoidPtr> class __tree_node_base;
387c82a1ecSDimitry Andrictemplate <class _Tp, class _VoidPtr> class __tree_node;
397c82a1ecSDimitry Andric
407c82a1ecSDimitry Andrictemplate <class _Key, class _Value>
417c82a1ecSDimitry Andricstruct __value_type;
427c82a1ecSDimitry Andric
437c82a1ecSDimitry Andrictemplate <class _Allocator> class __map_node_destructor;
44aed8d94eSDimitry Andrictemplate <class _TreeIterator> class _LIBCPP_TEMPLATE_VIS __map_iterator;
45aed8d94eSDimitry Andrictemplate <class _TreeIterator> class _LIBCPP_TEMPLATE_VIS __map_const_iterator;
467c82a1ecSDimitry Andric
477a984708SDavid Chisnall/*
487a984708SDavid Chisnall
497a984708SDavid Chisnall_NodePtr algorithms
507a984708SDavid Chisnall
517a984708SDavid ChisnallThe algorithms taking _NodePtr are red black tree algorithms.  Those
527a984708SDavid Chisnallalgorithms taking a parameter named __root should assume that __root
537a984708SDavid Chisnallpoints to a proper red black tree (unless otherwise specified).
547a984708SDavid Chisnall
557a984708SDavid ChisnallEach algorithm herein assumes that __root->__parent_ points to a non-null
567a984708SDavid Chisnallstructure which has a member __left_ which points back to __root.  No other
577a984708SDavid Chisnallmember is read or written to at __root->__parent_.
587a984708SDavid Chisnall
597a984708SDavid Chisnall__root->__parent_ will be referred to below (in comments only) as end_node.
607a984708SDavid Chisnallend_node->__left_ is an externably accessible lvalue for __root, and can be
617a984708SDavid Chisnallchanged by node insertion and removal (without explicit reference to end_node).
627a984708SDavid Chisnall
637a984708SDavid ChisnallAll nodes (with the exception of end_node), even the node referred to as
647a984708SDavid Chisnall__root, have a non-null __parent_ field.
657a984708SDavid Chisnall
667a984708SDavid Chisnall*/
677a984708SDavid Chisnall
687a984708SDavid Chisnall// Returns:  true if __x is a left child of its parent, else false
697a984708SDavid Chisnall// Precondition:  __x != nullptr.
707a984708SDavid Chisnalltemplate <class _NodePtr>
717a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
727a984708SDavid Chisnallbool
737a984708SDavid Chisnall__tree_is_left_child(_NodePtr __x) _NOEXCEPT
747a984708SDavid Chisnall{
757a984708SDavid Chisnall    return __x == __x->__parent_->__left_;
767a984708SDavid Chisnall}
777a984708SDavid Chisnall
78b2c7081bSDimitry Andric// Determines if the subtree rooted at __x is a proper red black subtree.  If
797a984708SDavid Chisnall//    __x is a proper subtree, returns the black height (null counts as 1).  If
807a984708SDavid Chisnall//    __x is an improper subtree, returns 0.
817a984708SDavid Chisnalltemplate <class _NodePtr>
827a984708SDavid Chisnallunsigned
837a984708SDavid Chisnall__tree_sub_invariant(_NodePtr __x)
847a984708SDavid Chisnall{
857a984708SDavid Chisnall    if (__x == nullptr)
867a984708SDavid Chisnall        return 1;
877a984708SDavid Chisnall    // parent consistency checked by caller
887a984708SDavid Chisnall    // check __x->__left_ consistency
897a984708SDavid Chisnall    if (__x->__left_ != nullptr && __x->__left_->__parent_ != __x)
907a984708SDavid Chisnall        return 0;
917a984708SDavid Chisnall    // check __x->__right_ consistency
927a984708SDavid Chisnall    if (__x->__right_ != nullptr && __x->__right_->__parent_ != __x)
937a984708SDavid Chisnall        return 0;
947a984708SDavid Chisnall    // check __x->__left_ != __x->__right_ unless both are nullptr
957a984708SDavid Chisnall    if (__x->__left_ == __x->__right_ && __x->__left_ != nullptr)
967a984708SDavid Chisnall        return 0;
977a984708SDavid Chisnall    // If this is red, neither child can be red
987a984708SDavid Chisnall    if (!__x->__is_black_)
997a984708SDavid Chisnall    {
1007a984708SDavid Chisnall        if (__x->__left_ && !__x->__left_->__is_black_)
1017a984708SDavid Chisnall            return 0;
1027a984708SDavid Chisnall        if (__x->__right_ && !__x->__right_->__is_black_)
1037a984708SDavid Chisnall            return 0;
1047a984708SDavid Chisnall    }
1057a984708SDavid Chisnall    unsigned __h = __tree_sub_invariant(__x->__left_);
1067a984708SDavid Chisnall    if (__h == 0)
1077a984708SDavid Chisnall        return 0;  // invalid left subtree
1087a984708SDavid Chisnall    if (__h != __tree_sub_invariant(__x->__right_))
1097a984708SDavid Chisnall        return 0;  // invalid or different height right subtree
1107a984708SDavid Chisnall    return __h + __x->__is_black_;  // return black height of this node
1117a984708SDavid Chisnall}
1127a984708SDavid Chisnall
113b2c7081bSDimitry Andric// Determines if the red black tree rooted at __root is a proper red black tree.
1147a984708SDavid Chisnall//    __root == nullptr is a proper tree.  Returns true is __root is a proper
1157a984708SDavid Chisnall//    red black tree, else returns false.
1167a984708SDavid Chisnalltemplate <class _NodePtr>
1177a984708SDavid Chisnallbool
1187a984708SDavid Chisnall__tree_invariant(_NodePtr __root)
1197a984708SDavid Chisnall{
1207a984708SDavid Chisnall    if (__root == nullptr)
1217a984708SDavid Chisnall        return true;
1227a984708SDavid Chisnall    // check __x->__parent_ consistency
1237a984708SDavid Chisnall    if (__root->__parent_ == nullptr)
1247a984708SDavid Chisnall        return false;
1257a984708SDavid Chisnall    if (!__tree_is_left_child(__root))
1267a984708SDavid Chisnall        return false;
1277a984708SDavid Chisnall    // root must be black
1287a984708SDavid Chisnall    if (!__root->__is_black_)
1297a984708SDavid Chisnall        return false;
1307a984708SDavid Chisnall    // do normal node checks
1317a984708SDavid Chisnall    return __tree_sub_invariant(__root) != 0;
1327a984708SDavid Chisnall}
1337a984708SDavid Chisnall
1347a984708SDavid Chisnall// Returns:  pointer to the left-most node under __x.
1357a984708SDavid Chisnall// Precondition:  __x != nullptr.
1367a984708SDavid Chisnalltemplate <class _NodePtr>
1377a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
1387a984708SDavid Chisnall_NodePtr
1397a984708SDavid Chisnall__tree_min(_NodePtr __x) _NOEXCEPT
1407a984708SDavid Chisnall{
1417a984708SDavid Chisnall    while (__x->__left_ != nullptr)
1427a984708SDavid Chisnall        __x = __x->__left_;
1437a984708SDavid Chisnall    return __x;
1447a984708SDavid Chisnall}
1457a984708SDavid Chisnall
1467a984708SDavid Chisnall// Returns:  pointer to the right-most node under __x.
1477a984708SDavid Chisnall// Precondition:  __x != nullptr.
1487a984708SDavid Chisnalltemplate <class _NodePtr>
1497a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
1507a984708SDavid Chisnall_NodePtr
1517a984708SDavid Chisnall__tree_max(_NodePtr __x) _NOEXCEPT
1527a984708SDavid Chisnall{
1537a984708SDavid Chisnall    while (__x->__right_ != nullptr)
1547a984708SDavid Chisnall        __x = __x->__right_;
1557a984708SDavid Chisnall    return __x;
1567a984708SDavid Chisnall}
1577a984708SDavid Chisnall
1587a984708SDavid Chisnall// Returns:  pointer to the next in-order node after __x.
1597a984708SDavid Chisnall// Precondition:  __x != nullptr.
1607a984708SDavid Chisnalltemplate <class _NodePtr>
1617a984708SDavid Chisnall_NodePtr
1627a984708SDavid Chisnall__tree_next(_NodePtr __x) _NOEXCEPT
1637a984708SDavid Chisnall{
1647a984708SDavid Chisnall    if (__x->__right_ != nullptr)
1657a984708SDavid Chisnall        return __tree_min(__x->__right_);
1667a984708SDavid Chisnall    while (!__tree_is_left_child(__x))
1677c82a1ecSDimitry Andric        __x = __x->__parent_unsafe();
1687c82a1ecSDimitry Andric    return __x->__parent_unsafe();
1697c82a1ecSDimitry Andric}
1707c82a1ecSDimitry Andric
1717c82a1ecSDimitry Andrictemplate <class _EndNodePtr, class _NodePtr>
1727c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1737c82a1ecSDimitry Andric_EndNodePtr
1747c82a1ecSDimitry Andric__tree_next_iter(_NodePtr __x) _NOEXCEPT
1757c82a1ecSDimitry Andric{
1767c82a1ecSDimitry Andric    if (__x->__right_ != nullptr)
1777c82a1ecSDimitry Andric        return static_cast<_EndNodePtr>(__tree_min(__x->__right_));
1787c82a1ecSDimitry Andric    while (!__tree_is_left_child(__x))
1797c82a1ecSDimitry Andric        __x = __x->__parent_unsafe();
1807c82a1ecSDimitry Andric    return static_cast<_EndNodePtr>(__x->__parent_);
1817a984708SDavid Chisnall}
1827a984708SDavid Chisnall
1837a984708SDavid Chisnall// Returns:  pointer to the previous in-order node before __x.
1847a984708SDavid Chisnall// Precondition:  __x != nullptr.
1857c82a1ecSDimitry Andric// Note: __x may be the end node.
1867c82a1ecSDimitry Andrictemplate <class _NodePtr, class _EndNodePtr>
1877c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1887a984708SDavid Chisnall_NodePtr
1897c82a1ecSDimitry Andric__tree_prev_iter(_EndNodePtr __x) _NOEXCEPT
1907a984708SDavid Chisnall{
1917a984708SDavid Chisnall    if (__x->__left_ != nullptr)
1927a984708SDavid Chisnall        return __tree_max(__x->__left_);
1937c82a1ecSDimitry Andric    _NodePtr __xx = static_cast<_NodePtr>(__x);
1947c82a1ecSDimitry Andric    while (__tree_is_left_child(__xx))
1957c82a1ecSDimitry Andric        __xx = __xx->__parent_unsafe();
1967c82a1ecSDimitry Andric    return __xx->__parent_unsafe();
1977a984708SDavid Chisnall}
1987a984708SDavid Chisnall
1997a984708SDavid Chisnall// Returns:  pointer to a node which has no children
2007a984708SDavid Chisnall// Precondition:  __x != nullptr.
2017a984708SDavid Chisnalltemplate <class _NodePtr>
2027a984708SDavid Chisnall_NodePtr
2037a984708SDavid Chisnall__tree_leaf(_NodePtr __x) _NOEXCEPT
2047a984708SDavid Chisnall{
2057a984708SDavid Chisnall    while (true)
2067a984708SDavid Chisnall    {
2077a984708SDavid Chisnall        if (__x->__left_ != nullptr)
2087a984708SDavid Chisnall        {
2097a984708SDavid Chisnall            __x = __x->__left_;
2107a984708SDavid Chisnall            continue;
2117a984708SDavid Chisnall        }
2127a984708SDavid Chisnall        if (__x->__right_ != nullptr)
2137a984708SDavid Chisnall        {
2147a984708SDavid Chisnall            __x = __x->__right_;
2157a984708SDavid Chisnall            continue;
2167a984708SDavid Chisnall        }
2177a984708SDavid Chisnall        break;
2187a984708SDavid Chisnall    }
2197a984708SDavid Chisnall    return __x;
2207a984708SDavid Chisnall}
2217a984708SDavid Chisnall
2227a984708SDavid Chisnall// Effects:  Makes __x->__right_ the subtree root with __x as its left child
2237a984708SDavid Chisnall//           while preserving in-order order.
2247a984708SDavid Chisnall// Precondition:  __x->__right_ != nullptr
2257a984708SDavid Chisnalltemplate <class _NodePtr>
2267a984708SDavid Chisnallvoid
2277a984708SDavid Chisnall__tree_left_rotate(_NodePtr __x) _NOEXCEPT
2287a984708SDavid Chisnall{
2297a984708SDavid Chisnall    _NodePtr __y = __x->__right_;
2307a984708SDavid Chisnall    __x->__right_ = __y->__left_;
2317a984708SDavid Chisnall    if (__x->__right_ != nullptr)
2327c82a1ecSDimitry Andric        __x->__right_->__set_parent(__x);
2337a984708SDavid Chisnall    __y->__parent_ = __x->__parent_;
2347a984708SDavid Chisnall    if (__tree_is_left_child(__x))
2357a984708SDavid Chisnall        __x->__parent_->__left_ = __y;
2367a984708SDavid Chisnall    else
2377c82a1ecSDimitry Andric        __x->__parent_unsafe()->__right_ = __y;
2387a984708SDavid Chisnall    __y->__left_ = __x;
2397c82a1ecSDimitry Andric    __x->__set_parent(__y);
2407a984708SDavid Chisnall}
2417a984708SDavid Chisnall
2427a984708SDavid Chisnall// Effects:  Makes __x->__left_ the subtree root with __x as its right child
2437a984708SDavid Chisnall//           while preserving in-order order.
2447a984708SDavid Chisnall// Precondition:  __x->__left_ != nullptr
2457a984708SDavid Chisnalltemplate <class _NodePtr>
2467a984708SDavid Chisnallvoid
2477a984708SDavid Chisnall__tree_right_rotate(_NodePtr __x) _NOEXCEPT
2487a984708SDavid Chisnall{
2497a984708SDavid Chisnall    _NodePtr __y = __x->__left_;
2507a984708SDavid Chisnall    __x->__left_ = __y->__right_;
2517a984708SDavid Chisnall    if (__x->__left_ != nullptr)
2527c82a1ecSDimitry Andric        __x->__left_->__set_parent(__x);
2537a984708SDavid Chisnall    __y->__parent_ = __x->__parent_;
2547a984708SDavid Chisnall    if (__tree_is_left_child(__x))
2557a984708SDavid Chisnall        __x->__parent_->__left_ = __y;
2567a984708SDavid Chisnall    else
2577c82a1ecSDimitry Andric        __x->__parent_unsafe()->__right_ = __y;
2587a984708SDavid Chisnall    __y->__right_ = __x;
2597c82a1ecSDimitry Andric    __x->__set_parent(__y);
2607a984708SDavid Chisnall}
2617a984708SDavid Chisnall
2627a984708SDavid Chisnall// Effects:  Rebalances __root after attaching __x to a leaf.
2637a984708SDavid Chisnall// Precondition:  __root != nulptr && __x != nullptr.
2647a984708SDavid Chisnall//                __x has no children.
2657a984708SDavid Chisnall//                __x == __root or == a direct or indirect child of __root.
2667a984708SDavid Chisnall//                If __x were to be unlinked from __root (setting __root to
2677a984708SDavid Chisnall//                  nullptr if __root == __x), __tree_invariant(__root) == true.
2687a984708SDavid Chisnall// Postcondition: __tree_invariant(end_node->__left_) == true.  end_node->__left_
2697a984708SDavid Chisnall//                may be different than the value passed in as __root.
2707a984708SDavid Chisnalltemplate <class _NodePtr>
2717a984708SDavid Chisnallvoid
2727a984708SDavid Chisnall__tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT
2737a984708SDavid Chisnall{
2747a984708SDavid Chisnall    __x->__is_black_ = __x == __root;
2757c82a1ecSDimitry Andric    while (__x != __root && !__x->__parent_unsafe()->__is_black_)
2767a984708SDavid Chisnall    {
2777a984708SDavid Chisnall        // __x->__parent_ != __root because __x->__parent_->__is_black == false
2787c82a1ecSDimitry Andric        if (__tree_is_left_child(__x->__parent_unsafe()))
2797a984708SDavid Chisnall        {
2807c82a1ecSDimitry Andric            _NodePtr __y = __x->__parent_unsafe()->__parent_unsafe()->__right_;
2817a984708SDavid Chisnall            if (__y != nullptr && !__y->__is_black_)
2827a984708SDavid Chisnall            {
2837c82a1ecSDimitry Andric                __x = __x->__parent_unsafe();
2847a984708SDavid Chisnall                __x->__is_black_ = true;
2857c82a1ecSDimitry Andric                __x = __x->__parent_unsafe();
2867a984708SDavid Chisnall                __x->__is_black_ = __x == __root;
2877a984708SDavid Chisnall                __y->__is_black_ = true;
2887a984708SDavid Chisnall            }
2897a984708SDavid Chisnall            else
2907a984708SDavid Chisnall            {
2917a984708SDavid Chisnall                if (!__tree_is_left_child(__x))
2927a984708SDavid Chisnall                {
2937c82a1ecSDimitry Andric                    __x = __x->__parent_unsafe();
2947a984708SDavid Chisnall                    __tree_left_rotate(__x);
2957a984708SDavid Chisnall                }
2967c82a1ecSDimitry Andric                __x = __x->__parent_unsafe();
2977a984708SDavid Chisnall                __x->__is_black_ = true;
2987c82a1ecSDimitry Andric                __x = __x->__parent_unsafe();
2997a984708SDavid Chisnall                __x->__is_black_ = false;
3007a984708SDavid Chisnall                __tree_right_rotate(__x);
3017a984708SDavid Chisnall                break;
3027a984708SDavid Chisnall            }
3037a984708SDavid Chisnall        }
3047a984708SDavid Chisnall        else
3057a984708SDavid Chisnall        {
3067c82a1ecSDimitry Andric            _NodePtr __y = __x->__parent_unsafe()->__parent_->__left_;
3077a984708SDavid Chisnall            if (__y != nullptr && !__y->__is_black_)
3087a984708SDavid Chisnall            {
3097c82a1ecSDimitry Andric                __x = __x->__parent_unsafe();
3107a984708SDavid Chisnall                __x->__is_black_ = true;
3117c82a1ecSDimitry Andric                __x = __x->__parent_unsafe();
3127a984708SDavid Chisnall                __x->__is_black_ = __x == __root;
3137a984708SDavid Chisnall                __y->__is_black_ = true;
3147a984708SDavid Chisnall            }
3157a984708SDavid Chisnall            else
3167a984708SDavid Chisnall            {
3177a984708SDavid Chisnall                if (__tree_is_left_child(__x))
3187a984708SDavid Chisnall                {
3197c82a1ecSDimitry Andric                    __x = __x->__parent_unsafe();
3207a984708SDavid Chisnall                    __tree_right_rotate(__x);
3217a984708SDavid Chisnall                }
3227c82a1ecSDimitry Andric                __x = __x->__parent_unsafe();
3237a984708SDavid Chisnall                __x->__is_black_ = true;
3247c82a1ecSDimitry Andric                __x = __x->__parent_unsafe();
3257a984708SDavid Chisnall                __x->__is_black_ = false;
3267a984708SDavid Chisnall                __tree_left_rotate(__x);
3277a984708SDavid Chisnall                break;
3287a984708SDavid Chisnall            }
3297a984708SDavid Chisnall        }
3307a984708SDavid Chisnall    }
3317a984708SDavid Chisnall}
3327a984708SDavid Chisnall
3337a984708SDavid Chisnall// Precondition:  __root != nullptr && __z != nullptr.
3347a984708SDavid Chisnall//                __tree_invariant(__root) == true.
3357a984708SDavid Chisnall//                __z == __root or == a direct or indirect child of __root.
3367a984708SDavid Chisnall// Effects:  unlinks __z from the tree rooted at __root, rebalancing as needed.
3377a984708SDavid Chisnall// Postcondition: __tree_invariant(end_node->__left_) == true && end_node->__left_
3387a984708SDavid Chisnall//                nor any of its children refer to __z.  end_node->__left_
3397a984708SDavid Chisnall//                may be different than the value passed in as __root.
3407a984708SDavid Chisnalltemplate <class _NodePtr>
3417a984708SDavid Chisnallvoid
3427a984708SDavid Chisnall__tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT
3437a984708SDavid Chisnall{
3447a984708SDavid Chisnall    // __z will be removed from the tree.  Client still needs to destruct/deallocate it
3457a984708SDavid Chisnall    // __y is either __z, or if __z has two children, __tree_next(__z).
3467a984708SDavid Chisnall    // __y will have at most one child.
3477a984708SDavid Chisnall    // __y will be the initial hole in the tree (make the hole at a leaf)
3487a984708SDavid Chisnall    _NodePtr __y = (__z->__left_ == nullptr || __z->__right_ == nullptr) ?
3497a984708SDavid Chisnall                    __z : __tree_next(__z);
3507a984708SDavid Chisnall    // __x is __y's possibly null single child
3517a984708SDavid Chisnall    _NodePtr __x = __y->__left_ != nullptr ? __y->__left_ : __y->__right_;
3527a984708SDavid Chisnall    // __w is __x's possibly null uncle (will become __x's sibling)
3537a984708SDavid Chisnall    _NodePtr __w = nullptr;
3547a984708SDavid Chisnall    // link __x to __y's parent, and find __w
3557a984708SDavid Chisnall    if (__x != nullptr)
3567a984708SDavid Chisnall        __x->__parent_ = __y->__parent_;
3577a984708SDavid Chisnall    if (__tree_is_left_child(__y))
3587a984708SDavid Chisnall    {
3597a984708SDavid Chisnall        __y->__parent_->__left_ = __x;
3607a984708SDavid Chisnall        if (__y != __root)
3617c82a1ecSDimitry Andric            __w = __y->__parent_unsafe()->__right_;
3627a984708SDavid Chisnall        else
3637a984708SDavid Chisnall            __root = __x;  // __w == nullptr
3647a984708SDavid Chisnall    }
3657a984708SDavid Chisnall    else
3667a984708SDavid Chisnall    {
3677c82a1ecSDimitry Andric        __y->__parent_unsafe()->__right_ = __x;
3687a984708SDavid Chisnall        // __y can't be root if it is a right child
3697a984708SDavid Chisnall        __w = __y->__parent_->__left_;
3707a984708SDavid Chisnall    }
3717a984708SDavid Chisnall    bool __removed_black = __y->__is_black_;
3727a984708SDavid Chisnall    // If we didn't remove __z, do so now by splicing in __y for __z,
3737a984708SDavid Chisnall    //    but copy __z's color.  This does not impact __x or __w.
3747a984708SDavid Chisnall    if (__y != __z)
3757a984708SDavid Chisnall    {
3767a984708SDavid Chisnall        // __z->__left_ != nulptr but __z->__right_ might == __x == nullptr
3777a984708SDavid Chisnall        __y->__parent_ = __z->__parent_;
3787a984708SDavid Chisnall        if (__tree_is_left_child(__z))
3797a984708SDavid Chisnall            __y->__parent_->__left_ = __y;
3807a984708SDavid Chisnall        else
3817c82a1ecSDimitry Andric            __y->__parent_unsafe()->__right_ = __y;
3827a984708SDavid Chisnall        __y->__left_ = __z->__left_;
3837c82a1ecSDimitry Andric        __y->__left_->__set_parent(__y);
3847a984708SDavid Chisnall        __y->__right_ = __z->__right_;
3857a984708SDavid Chisnall        if (__y->__right_ != nullptr)
3867c82a1ecSDimitry Andric            __y->__right_->__set_parent(__y);
3877a984708SDavid Chisnall        __y->__is_black_ = __z->__is_black_;
3887a984708SDavid Chisnall        if (__root == __z)
3897a984708SDavid Chisnall            __root = __y;
3907a984708SDavid Chisnall    }
3917a984708SDavid Chisnall    // There is no need to rebalance if we removed a red, or if we removed
3927a984708SDavid Chisnall    //     the last node.
3937a984708SDavid Chisnall    if (__removed_black && __root != nullptr)
3947a984708SDavid Chisnall    {
3957a984708SDavid Chisnall        // Rebalance:
3967a984708SDavid Chisnall        // __x has an implicit black color (transferred from the removed __y)
3977a984708SDavid Chisnall        //    associated with it, no matter what its color is.
3987a984708SDavid Chisnall        // If __x is __root (in which case it can't be null), it is supposed
3997a984708SDavid Chisnall        //    to be black anyway, and if it is doubly black, then the double
4007a984708SDavid Chisnall        //    can just be ignored.
4017a984708SDavid Chisnall        // If __x is red (in which case it can't be null), then it can absorb
4027a984708SDavid Chisnall        //    the implicit black just by setting its color to black.
4037a984708SDavid Chisnall        // Since __y was black and only had one child (which __x points to), __x
4047a984708SDavid Chisnall        //   is either red with no children, else null, otherwise __y would have
4057a984708SDavid Chisnall        //   different black heights under left and right pointers.
4067a984708SDavid Chisnall        // if (__x == __root || __x != nullptr && !__x->__is_black_)
4077a984708SDavid Chisnall        if (__x != nullptr)
4087a984708SDavid Chisnall            __x->__is_black_ = true;
4097a984708SDavid Chisnall        else
4107a984708SDavid Chisnall        {
4117a984708SDavid Chisnall            //  Else __x isn't root, and is "doubly black", even though it may
4127a984708SDavid Chisnall            //     be null.  __w can not be null here, else the parent would
4137a984708SDavid Chisnall            //     see a black height >= 2 on the __x side and a black height
4147a984708SDavid Chisnall            //     of 1 on the __w side (__w must be a non-null black or a red
4157a984708SDavid Chisnall            //     with a non-null black child).
4167a984708SDavid Chisnall            while (true)
4177a984708SDavid Chisnall            {
4187a984708SDavid Chisnall                if (!__tree_is_left_child(__w))  // if x is left child
4197a984708SDavid Chisnall                {
4207a984708SDavid Chisnall                    if (!__w->__is_black_)
4217a984708SDavid Chisnall                    {
4227a984708SDavid Chisnall                        __w->__is_black_ = true;
4237c82a1ecSDimitry Andric                        __w->__parent_unsafe()->__is_black_ = false;
4247c82a1ecSDimitry Andric                        __tree_left_rotate(__w->__parent_unsafe());
4257a984708SDavid Chisnall                        // __x is still valid
4267a984708SDavid Chisnall                        // reset __root only if necessary
4277a984708SDavid Chisnall                        if (__root == __w->__left_)
4287a984708SDavid Chisnall                            __root = __w;
4297a984708SDavid Chisnall                        // reset sibling, and it still can't be null
4307a984708SDavid Chisnall                        __w = __w->__left_->__right_;
4317a984708SDavid Chisnall                    }
4327a984708SDavid Chisnall                    // __w->__is_black_ is now true, __w may have null children
4337a984708SDavid Chisnall                    if ((__w->__left_  == nullptr || __w->__left_->__is_black_) &&
4347a984708SDavid Chisnall                        (__w->__right_ == nullptr || __w->__right_->__is_black_))
4357a984708SDavid Chisnall                    {
4367a984708SDavid Chisnall                        __w->__is_black_ = false;
4377c82a1ecSDimitry Andric                        __x = __w->__parent_unsafe();
4387a984708SDavid Chisnall                        // __x can no longer be null
4397a984708SDavid Chisnall                        if (__x == __root || !__x->__is_black_)
4407a984708SDavid Chisnall                        {
4417a984708SDavid Chisnall                            __x->__is_black_ = true;
4427a984708SDavid Chisnall                            break;
4437a984708SDavid Chisnall                        }
4447a984708SDavid Chisnall                        // reset sibling, and it still can't be null
4457a984708SDavid Chisnall                        __w = __tree_is_left_child(__x) ?
4467c82a1ecSDimitry Andric                                    __x->__parent_unsafe()->__right_ :
4477a984708SDavid Chisnall                                    __x->__parent_->__left_;
4487a984708SDavid Chisnall                        // continue;
4497a984708SDavid Chisnall                    }
4507a984708SDavid Chisnall                    else  // __w has a red child
4517a984708SDavid Chisnall                    {
4527a984708SDavid Chisnall                        if (__w->__right_ == nullptr || __w->__right_->__is_black_)
4537a984708SDavid Chisnall                        {
4547a984708SDavid Chisnall                            // __w left child is non-null and red
4557a984708SDavid Chisnall                            __w->__left_->__is_black_ = true;
4567a984708SDavid Chisnall                            __w->__is_black_ = false;
4577a984708SDavid Chisnall                            __tree_right_rotate(__w);
4587a984708SDavid Chisnall                            // __w is known not to be root, so root hasn't changed
4597a984708SDavid Chisnall                            // reset sibling, and it still can't be null
4607c82a1ecSDimitry Andric                            __w = __w->__parent_unsafe();
4617a984708SDavid Chisnall                        }
4627a984708SDavid Chisnall                        // __w has a right red child, left child may be null
4637c82a1ecSDimitry Andric                        __w->__is_black_ = __w->__parent_unsafe()->__is_black_;
4647c82a1ecSDimitry Andric                        __w->__parent_unsafe()->__is_black_ = true;
4657a984708SDavid Chisnall                        __w->__right_->__is_black_ = true;
4667c82a1ecSDimitry Andric                        __tree_left_rotate(__w->__parent_unsafe());
4677a984708SDavid Chisnall                        break;
4687a984708SDavid Chisnall                    }
4697a984708SDavid Chisnall                }
4707a984708SDavid Chisnall                else
4717a984708SDavid Chisnall                {
4727a984708SDavid Chisnall                    if (!__w->__is_black_)
4737a984708SDavid Chisnall                    {
4747a984708SDavid Chisnall                        __w->__is_black_ = true;
4757c82a1ecSDimitry Andric                        __w->__parent_unsafe()->__is_black_ = false;
4767c82a1ecSDimitry Andric                        __tree_right_rotate(__w->__parent_unsafe());
4777a984708SDavid Chisnall                        // __x is still valid
4787a984708SDavid Chisnall                        // reset __root only if necessary
4797a984708SDavid Chisnall                        if (__root == __w->__right_)
4807a984708SDavid Chisnall                            __root = __w;
4817a984708SDavid Chisnall                        // reset sibling, and it still can't be null
4827a984708SDavid Chisnall                        __w = __w->__right_->__left_;
4837a984708SDavid Chisnall                    }
4847a984708SDavid Chisnall                    // __w->__is_black_ is now true, __w may have null children
4857a984708SDavid Chisnall                    if ((__w->__left_  == nullptr || __w->__left_->__is_black_) &&
4867a984708SDavid Chisnall                        (__w->__right_ == nullptr || __w->__right_->__is_black_))
4877a984708SDavid Chisnall                    {
4887a984708SDavid Chisnall                        __w->__is_black_ = false;
4897c82a1ecSDimitry Andric                        __x = __w->__parent_unsafe();
4907a984708SDavid Chisnall                        // __x can no longer be null
4917a984708SDavid Chisnall                        if (!__x->__is_black_ || __x == __root)
4927a984708SDavid Chisnall                        {
4937a984708SDavid Chisnall                            __x->__is_black_ = true;
4947a984708SDavid Chisnall                            break;
4957a984708SDavid Chisnall                        }
4967a984708SDavid Chisnall                        // reset sibling, and it still can't be null
4977a984708SDavid Chisnall                        __w = __tree_is_left_child(__x) ?
4987c82a1ecSDimitry Andric                                    __x->__parent_unsafe()->__right_ :
4997a984708SDavid Chisnall                                    __x->__parent_->__left_;
5007a984708SDavid Chisnall                        // continue;
5017a984708SDavid Chisnall                    }
5027a984708SDavid Chisnall                    else  // __w has a red child
5037a984708SDavid Chisnall                    {
5047a984708SDavid Chisnall                        if (__w->__left_ == nullptr || __w->__left_->__is_black_)
5057a984708SDavid Chisnall                        {
5067a984708SDavid Chisnall                            // __w right child is non-null and red
5077a984708SDavid Chisnall                            __w->__right_->__is_black_ = true;
5087a984708SDavid Chisnall                            __w->__is_black_ = false;
5097a984708SDavid Chisnall                            __tree_left_rotate(__w);
5107a984708SDavid Chisnall                            // __w is known not to be root, so root hasn't changed
5117a984708SDavid Chisnall                            // reset sibling, and it still can't be null
5127c82a1ecSDimitry Andric                            __w = __w->__parent_unsafe();
5137a984708SDavid Chisnall                        }
5147a984708SDavid Chisnall                        // __w has a left red child, right child may be null
5157c82a1ecSDimitry Andric                        __w->__is_black_ = __w->__parent_unsafe()->__is_black_;
5167c82a1ecSDimitry Andric                        __w->__parent_unsafe()->__is_black_ = true;
5177a984708SDavid Chisnall                        __w->__left_->__is_black_ = true;
5187c82a1ecSDimitry Andric                        __tree_right_rotate(__w->__parent_unsafe());
5197a984708SDavid Chisnall                        break;
5207a984708SDavid Chisnall                    }
5217a984708SDavid Chisnall                }
5227a984708SDavid Chisnall            }
5237a984708SDavid Chisnall        }
5247a984708SDavid Chisnall    }
5257a984708SDavid Chisnall}
5267a984708SDavid Chisnall
5277c82a1ecSDimitry Andric// node traits
5287a984708SDavid Chisnall
5297a984708SDavid Chisnall
5307c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
5317c82a1ecSDimitry Andrictemplate <class _Tp>
5327c82a1ecSDimitry Andricstruct __is_tree_value_type_imp : false_type {};
5337a984708SDavid Chisnall
5347c82a1ecSDimitry Andrictemplate <class _Key, class _Value>
5357c82a1ecSDimitry Andricstruct __is_tree_value_type_imp<__value_type<_Key, _Value>> : true_type {};
5367a984708SDavid Chisnall
5377c82a1ecSDimitry Andrictemplate <class ..._Args>
5387c82a1ecSDimitry Andricstruct __is_tree_value_type : false_type {};
5397c82a1ecSDimitry Andric
5407c82a1ecSDimitry Andrictemplate <class _One>
5417c82a1ecSDimitry Andricstruct __is_tree_value_type<_One> : __is_tree_value_type_imp<typename __uncvref<_One>::type> {};
5427c82a1ecSDimitry Andric#endif
5437c82a1ecSDimitry Andric
5447c82a1ecSDimitry Andrictemplate <class _Tp>
5457c82a1ecSDimitry Andricstruct __tree_key_value_types {
5467c82a1ecSDimitry Andric  typedef _Tp key_type;
5477c82a1ecSDimitry Andric  typedef _Tp __node_value_type;
5487c82a1ecSDimitry Andric  typedef _Tp __container_value_type;
5497c82a1ecSDimitry Andric  static const bool __is_map = false;
5507a984708SDavid Chisnall
5517a984708SDavid Chisnall  _LIBCPP_INLINE_VISIBILITY
5527c82a1ecSDimitry Andric  static key_type const& __get_key(_Tp const& __v) {
5537c82a1ecSDimitry Andric    return __v;
5547c82a1ecSDimitry Andric  }
5557a984708SDavid Chisnall  _LIBCPP_INLINE_VISIBILITY
5567c82a1ecSDimitry Andric  static __container_value_type const& __get_value(__node_value_type const& __v) {
5577c82a1ecSDimitry Andric    return __v;
5587c82a1ecSDimitry Andric  }
5597c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
5607c82a1ecSDimitry Andric  static __container_value_type* __get_ptr(__node_value_type& __n) {
5617c82a1ecSDimitry Andric    return _VSTD::addressof(__n);
5627a984708SDavid Chisnall  }
5637c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
5647c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
5657c82a1ecSDimitry Andric  static __container_value_type&& __move(__node_value_type& __v) {
5667c82a1ecSDimitry Andric    return _VSTD::move(__v);
5677c82a1ecSDimitry Andric  }
5687c82a1ecSDimitry Andric#endif
5697c82a1ecSDimitry Andric};
5707c82a1ecSDimitry Andric
5717c82a1ecSDimitry Andrictemplate <class _Key, class _Tp>
5727c82a1ecSDimitry Andricstruct __tree_key_value_types<__value_type<_Key, _Tp> > {
5737c82a1ecSDimitry Andric  typedef _Key                                         key_type;
5747c82a1ecSDimitry Andric  typedef _Tp                                          mapped_type;
5757c82a1ecSDimitry Andric  typedef __value_type<_Key, _Tp>                      __node_value_type;
5767c82a1ecSDimitry Andric  typedef pair<const _Key, _Tp>                        __container_value_type;
5777c82a1ecSDimitry Andric  typedef __container_value_type                       __map_value_type;
5787c82a1ecSDimitry Andric  static const bool __is_map = true;
5797c82a1ecSDimitry Andric
5807c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
5817c82a1ecSDimitry Andric  static key_type const&
5827c82a1ecSDimitry Andric  __get_key(__node_value_type const& __t) {
5834ba319b5SDimitry Andric    return __t.__get_value().first;
5847c82a1ecSDimitry Andric  }
5857c82a1ecSDimitry Andric
5867c82a1ecSDimitry Andric  template <class _Up>
5877c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
5887c82a1ecSDimitry Andric  static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value,
5897c82a1ecSDimitry Andric      key_type const&>::type
5907c82a1ecSDimitry Andric  __get_key(_Up& __t) {
5917c82a1ecSDimitry Andric    return __t.first;
5927c82a1ecSDimitry Andric  }
5937c82a1ecSDimitry Andric
5947c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
5957c82a1ecSDimitry Andric  static __container_value_type const&
5967c82a1ecSDimitry Andric  __get_value(__node_value_type const& __t) {
5974ba319b5SDimitry Andric    return __t.__get_value();
5987c82a1ecSDimitry Andric  }
5997c82a1ecSDimitry Andric
6007c82a1ecSDimitry Andric  template <class _Up>
6017c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
6027c82a1ecSDimitry Andric  static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value,
6037c82a1ecSDimitry Andric      __container_value_type const&>::type
6047c82a1ecSDimitry Andric  __get_value(_Up& __t) {
6057c82a1ecSDimitry Andric    return __t;
6067c82a1ecSDimitry Andric  }
6077c82a1ecSDimitry Andric
6087c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
6097c82a1ecSDimitry Andric  static __container_value_type* __get_ptr(__node_value_type& __n) {
6104ba319b5SDimitry Andric    return _VSTD::addressof(__n.__get_value());
6117c82a1ecSDimitry Andric  }
6127c82a1ecSDimitry Andric
6137c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
6147c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
6154ba319b5SDimitry Andric  static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) {
6164ba319b5SDimitry Andric    return __v.__move();
6177c82a1ecSDimitry Andric  }
6187c82a1ecSDimitry Andric#endif
6197c82a1ecSDimitry Andric};
6207c82a1ecSDimitry Andric
6217c82a1ecSDimitry Andrictemplate <class _VoidPtr>
6227c82a1ecSDimitry Andricstruct __tree_node_base_types {
6237c82a1ecSDimitry Andric  typedef _VoidPtr                                               __void_pointer;
6247c82a1ecSDimitry Andric
6257c82a1ecSDimitry Andric  typedef __tree_node_base<__void_pointer>                      __node_base_type;
6267c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_VoidPtr, __node_base_type>::type
6277c82a1ecSDimitry Andric                                                             __node_base_pointer;
6287c82a1ecSDimitry Andric
6297c82a1ecSDimitry Andric  typedef __tree_end_node<__node_base_pointer>                  __end_node_type;
6307c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_VoidPtr, __end_node_type>::type
6317c82a1ecSDimitry Andric                                                             __end_node_pointer;
6327c82a1ecSDimitry Andric#if defined(_LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB)
6337c82a1ecSDimitry Andric  typedef __end_node_pointer __parent_pointer;
6347c82a1ecSDimitry Andric#else
6357c82a1ecSDimitry Andric  typedef typename conditional<
6367c82a1ecSDimitry Andric      is_pointer<__end_node_pointer>::value,
6377c82a1ecSDimitry Andric        __end_node_pointer,
6387c82a1ecSDimitry Andric        __node_base_pointer>::type __parent_pointer;
6397c82a1ecSDimitry Andric#endif
6407c82a1ecSDimitry Andric
6417c82a1ecSDimitry Andricprivate:
6427c82a1ecSDimitry Andric  static_assert((is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value),
6437c82a1ecSDimitry Andric                  "_VoidPtr does not point to unqualified void type");
6447c82a1ecSDimitry Andric};
6457c82a1ecSDimitry Andric
6467c82a1ecSDimitry Andrictemplate <class _Tp, class _AllocPtr, class _KVTypes = __tree_key_value_types<_Tp>,
6477c82a1ecSDimitry Andric         bool = _KVTypes::__is_map>
6487c82a1ecSDimitry Andricstruct __tree_map_pointer_types {};
6497c82a1ecSDimitry Andric
6507c82a1ecSDimitry Andrictemplate <class _Tp, class _AllocPtr, class _KVTypes>
6517c82a1ecSDimitry Andricstruct __tree_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
6527c82a1ecSDimitry Andric  typedef typename _KVTypes::__map_value_type   _Mv;
6537c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_AllocPtr, _Mv>::type
6547c82a1ecSDimitry Andric                                                       __map_value_type_pointer;
6557c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type
6567c82a1ecSDimitry Andric                                                 __const_map_value_type_pointer;
6577c82a1ecSDimitry Andric};
6587c82a1ecSDimitry Andric
6597c82a1ecSDimitry Andrictemplate <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
6607c82a1ecSDimitry Andricstruct __tree_node_types;
6617c82a1ecSDimitry Andric
6627c82a1ecSDimitry Andrictemplate <class _NodePtr, class _Tp, class _VoidPtr>
6637c82a1ecSDimitry Andricstruct __tree_node_types<_NodePtr, __tree_node<_Tp, _VoidPtr> >
6647c82a1ecSDimitry Andric    : public __tree_node_base_types<_VoidPtr>,
6657c82a1ecSDimitry Andric             __tree_key_value_types<_Tp>,
6667c82a1ecSDimitry Andric             __tree_map_pointer_types<_Tp, _VoidPtr>
6677c82a1ecSDimitry Andric{
6687c82a1ecSDimitry Andric  typedef __tree_node_base_types<_VoidPtr> __base;
6697c82a1ecSDimitry Andric  typedef __tree_key_value_types<_Tp>      __key_base;
6707c82a1ecSDimitry Andric  typedef __tree_map_pointer_types<_Tp, _VoidPtr> __map_pointer_base;
6717c82a1ecSDimitry Andricpublic:
6727c82a1ecSDimitry Andric
6737c82a1ecSDimitry Andric  typedef typename pointer_traits<_NodePtr>::element_type       __node_type;
6747c82a1ecSDimitry Andric  typedef _NodePtr                                              __node_pointer;
6757c82a1ecSDimitry Andric
6767c82a1ecSDimitry Andric  typedef _Tp                                                 __node_value_type;
6777c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type
6787c82a1ecSDimitry Andric                                                      __node_value_type_pointer;
6797c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type
6807c82a1ecSDimitry Andric                                                __const_node_value_type_pointer;
6817c82a1ecSDimitry Andric#if defined(_LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB)
6827c82a1ecSDimitry Andric  typedef typename __base::__end_node_pointer __iter_pointer;
6837c82a1ecSDimitry Andric#else
6847c82a1ecSDimitry Andric  typedef typename conditional<
6857c82a1ecSDimitry Andric      is_pointer<__node_pointer>::value,
6867c82a1ecSDimitry Andric        typename __base::__end_node_pointer,
6877c82a1ecSDimitry Andric        __node_pointer>::type __iter_pointer;
6887c82a1ecSDimitry Andric#endif
6897c82a1ecSDimitry Andricprivate:
6907c82a1ecSDimitry Andric    static_assert(!is_const<__node_type>::value,
6917c82a1ecSDimitry Andric                "_NodePtr should never be a pointer to const");
6927c82a1ecSDimitry Andric    static_assert((is_same<typename __rebind_pointer<_VoidPtr, __node_type>::type,
6937c82a1ecSDimitry Andric                          _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr.");
6947c82a1ecSDimitry Andric};
6957c82a1ecSDimitry Andric
6967c82a1ecSDimitry Andrictemplate <class _ValueTp, class _VoidPtr>
6977c82a1ecSDimitry Andricstruct __make_tree_node_types {
6987c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_VoidPtr, __tree_node<_ValueTp, _VoidPtr> >::type
6997c82a1ecSDimitry Andric                                                                        _NodePtr;
7007c82a1ecSDimitry Andric  typedef __tree_node_types<_NodePtr> type;
7017a984708SDavid Chisnall};
7027a984708SDavid Chisnall
7037a984708SDavid Chisnall// node
7047a984708SDavid Chisnall
7057a984708SDavid Chisnalltemplate <class _Pointer>
7067a984708SDavid Chisnallclass __tree_end_node
7077a984708SDavid Chisnall{
7087a984708SDavid Chisnallpublic:
7097a984708SDavid Chisnall    typedef _Pointer pointer;
7107a984708SDavid Chisnall    pointer __left_;
7117a984708SDavid Chisnall
7127a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
7137a984708SDavid Chisnall    __tree_end_node() _NOEXCEPT : __left_() {}
7147a984708SDavid Chisnall};
7157a984708SDavid Chisnall
7167a984708SDavid Chisnalltemplate <class _VoidPtr>
7177a984708SDavid Chisnallclass __tree_node_base
7187c82a1ecSDimitry Andric    : public __tree_node_base_types<_VoidPtr>::__end_node_type
7197a984708SDavid Chisnall{
7207c82a1ecSDimitry Andric    typedef __tree_node_base_types<_VoidPtr> _NodeBaseTypes;
7219729cf09SDimitry Andric
7227c82a1ecSDimitry Andricpublic:
7237c82a1ecSDimitry Andric    typedef typename _NodeBaseTypes::__node_base_pointer pointer;
7247c82a1ecSDimitry Andric    typedef typename _NodeBaseTypes::__parent_pointer __parent_pointer;
7257a984708SDavid Chisnall
7267a984708SDavid Chisnall    pointer          __right_;
7277c82a1ecSDimitry Andric    __parent_pointer __parent_;
7287a984708SDavid Chisnall    bool __is_black_;
7297a984708SDavid Chisnall
7307a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
7317c82a1ecSDimitry Andric    pointer __parent_unsafe() const { return static_cast<pointer>(__parent_);}
7327c82a1ecSDimitry Andric
7337c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
7347c82a1ecSDimitry Andric    void __set_parent(pointer __p) {
7357c82a1ecSDimitry Andric        __parent_ = static_cast<__parent_pointer>(__p);
7367c82a1ecSDimitry Andric    }
7377c82a1ecSDimitry Andric
7387c82a1ecSDimitry Andricprivate:
7397c82a1ecSDimitry Andric  ~__tree_node_base() _LIBCPP_EQUAL_DELETE;
7407c82a1ecSDimitry Andric  __tree_node_base(__tree_node_base const&) _LIBCPP_EQUAL_DELETE;
7417c82a1ecSDimitry Andric  __tree_node_base& operator=(__tree_node_base const&) _LIBCPP_EQUAL_DELETE;
7427a984708SDavid Chisnall};
7437a984708SDavid Chisnall
7447a984708SDavid Chisnalltemplate <class _Tp, class _VoidPtr>
7457a984708SDavid Chisnallclass __tree_node
7467a984708SDavid Chisnall    : public __tree_node_base<_VoidPtr>
7477a984708SDavid Chisnall{
7487a984708SDavid Chisnallpublic:
7497c82a1ecSDimitry Andric    typedef _Tp __node_value_type;
7507a984708SDavid Chisnall
7517c82a1ecSDimitry Andric    __node_value_type __value_;
7527a984708SDavid Chisnall
7537c82a1ecSDimitry Andricprivate:
7547c82a1ecSDimitry Andric  ~__tree_node() _LIBCPP_EQUAL_DELETE;
7557c82a1ecSDimitry Andric  __tree_node(__tree_node const&) _LIBCPP_EQUAL_DELETE;
7567c82a1ecSDimitry Andric  __tree_node& operator=(__tree_node const&) _LIBCPP_EQUAL_DELETE;
7577a984708SDavid Chisnall};
7587a984708SDavid Chisnall
7597c82a1ecSDimitry Andric
7607c82a1ecSDimitry Andrictemplate <class _Allocator>
7617c82a1ecSDimitry Andricclass __tree_node_destructor
7627c82a1ecSDimitry Andric{
7637c82a1ecSDimitry Andric    typedef _Allocator                                      allocator_type;
7647c82a1ecSDimitry Andric    typedef allocator_traits<allocator_type>                __alloc_traits;
7657c82a1ecSDimitry Andric
7667c82a1ecSDimitry Andricpublic:
7677c82a1ecSDimitry Andric    typedef typename __alloc_traits::pointer                pointer;
7687c82a1ecSDimitry Andricprivate:
7697c82a1ecSDimitry Andric    typedef __tree_node_types<pointer> _NodeTypes;
7707c82a1ecSDimitry Andric    allocator_type& __na_;
7717c82a1ecSDimitry Andric
7727c82a1ecSDimitry Andric    __tree_node_destructor& operator=(const __tree_node_destructor&);
7737c82a1ecSDimitry Andric
7747c82a1ecSDimitry Andricpublic:
7757c82a1ecSDimitry Andric    bool __value_constructed;
7767c82a1ecSDimitry Andric
7777c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
7787c82a1ecSDimitry Andric    explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT
7797c82a1ecSDimitry Andric        : __na_(__na),
7807c82a1ecSDimitry Andric          __value_constructed(__val)
7817c82a1ecSDimitry Andric        {}
7827c82a1ecSDimitry Andric
7837c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
7847c82a1ecSDimitry Andric    void operator()(pointer __p) _NOEXCEPT
7857c82a1ecSDimitry Andric    {
7867c82a1ecSDimitry Andric        if (__value_constructed)
7877c82a1ecSDimitry Andric            __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_));
7887c82a1ecSDimitry Andric        if (__p)
7897c82a1ecSDimitry Andric            __alloc_traits::deallocate(__na_, __p, 1);
7907c82a1ecSDimitry Andric    }
7917c82a1ecSDimitry Andric
7927c82a1ecSDimitry Andric    template <class> friend class __map_node_destructor;
7937c82a1ecSDimitry Andric};
7947c82a1ecSDimitry Andric
7954ba319b5SDimitry Andric#if _LIBCPP_STD_VER > 14
7964ba319b5SDimitry Andrictemplate <class _NodeType, class _Alloc>
7974ba319b5SDimitry Andricstruct __generic_container_node_destructor;
7984ba319b5SDimitry Andrictemplate <class _Tp, class _VoidPtr, class _Alloc>
7994ba319b5SDimitry Andricstruct __generic_container_node_destructor<__tree_node<_Tp, _VoidPtr>, _Alloc>
8004ba319b5SDimitry Andric    : __tree_node_destructor<_Alloc>
8014ba319b5SDimitry Andric{
8024ba319b5SDimitry Andric    using __tree_node_destructor<_Alloc>::__tree_node_destructor;
8034ba319b5SDimitry Andric};
8044ba319b5SDimitry Andric#endif
8057a984708SDavid Chisnall
8067a984708SDavid Chisnalltemplate <class _Tp, class _NodePtr, class _DiffType>
807aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __tree_iterator
8087a984708SDavid Chisnall{
8097c82a1ecSDimitry Andric    typedef __tree_node_types<_NodePtr>                     _NodeTypes;
8107a984708SDavid Chisnall    typedef _NodePtr                                        __node_pointer;
8117c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_base_pointer        __node_base_pointer;
8127c82a1ecSDimitry Andric    typedef typename _NodeTypes::__end_node_pointer         __end_node_pointer;
8137c82a1ecSDimitry Andric    typedef typename _NodeTypes::__iter_pointer             __iter_pointer;
8147a984708SDavid Chisnall    typedef pointer_traits<__node_pointer> __pointer_traits;
8157c82a1ecSDimitry Andric
8167c82a1ecSDimitry Andric    __iter_pointer __ptr_;
8177c82a1ecSDimitry Andric
8187a984708SDavid Chisnallpublic:
8197a984708SDavid Chisnall    typedef bidirectional_iterator_tag                     iterator_category;
8207a984708SDavid Chisnall    typedef _Tp                                            value_type;
8217a984708SDavid Chisnall    typedef _DiffType                                      difference_type;
8227a984708SDavid Chisnall    typedef value_type&                                    reference;
8237c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_value_type_pointer pointer;
8247a984708SDavid Chisnall
8254f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY __tree_iterator() _NOEXCEPT
8264f7ab58eSDimitry Andric#if _LIBCPP_STD_VER > 11
8274f7ab58eSDimitry Andric    : __ptr_(nullptr)
8284f7ab58eSDimitry Andric#endif
8294f7ab58eSDimitry Andric    {}
8307a984708SDavid Chisnall
8317c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY reference operator*() const
8327c82a1ecSDimitry Andric        {return __get_np()->__value_;}
8334bab9fd9SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY pointer operator->() const
8347c82a1ecSDimitry Andric        {return pointer_traits<pointer>::pointer_to(__get_np()->__value_);}
8357a984708SDavid Chisnall
8367a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
837854fa44bSDimitry Andric    __tree_iterator& operator++() {
8387c82a1ecSDimitry Andric      __ptr_ = static_cast<__iter_pointer>(
8397c82a1ecSDimitry Andric          __tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)));
840854fa44bSDimitry Andric      return *this;
841854fa44bSDimitry Andric    }
8427a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
8437a984708SDavid Chisnall    __tree_iterator operator++(int)
8447a984708SDavid Chisnall        {__tree_iterator __t(*this); ++(*this); return __t;}
8457a984708SDavid Chisnall
8467a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
847854fa44bSDimitry Andric    __tree_iterator& operator--() {
8487c82a1ecSDimitry Andric      __ptr_ = static_cast<__iter_pointer>(__tree_prev_iter<__node_base_pointer>(
8497c82a1ecSDimitry Andric          static_cast<__end_node_pointer>(__ptr_)));
850854fa44bSDimitry Andric      return *this;
851854fa44bSDimitry Andric    }
8527a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
8537a984708SDavid Chisnall    __tree_iterator operator--(int)
8547a984708SDavid Chisnall        {__tree_iterator __t(*this); --(*this); return __t;}
8557a984708SDavid Chisnall
8567a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
8577a984708SDavid Chisnall        bool operator==(const __tree_iterator& __x, const __tree_iterator& __y)
8587a984708SDavid Chisnall        {return __x.__ptr_ == __y.__ptr_;}
8597a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
8607a984708SDavid Chisnall        bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y)
8617a984708SDavid Chisnall        {return !(__x == __y);}
8627a984708SDavid Chisnall
8637a984708SDavid Chisnallprivate:
8647a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
8657a984708SDavid Chisnall    explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {}
8667c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
8677c82a1ecSDimitry Andric    explicit __tree_iterator(__end_node_pointer __p) _NOEXCEPT : __ptr_(__p) {}
8687c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
8697c82a1ecSDimitry Andric    __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); }
8707a984708SDavid Chisnall    template <class, class, class> friend class __tree;
871aed8d94eSDimitry Andric    template <class, class, class> friend class _LIBCPP_TEMPLATE_VIS __tree_const_iterator;
872aed8d94eSDimitry Andric    template <class> friend class _LIBCPP_TEMPLATE_VIS __map_iterator;
873aed8d94eSDimitry Andric    template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS map;
874aed8d94eSDimitry Andric    template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS multimap;
875aed8d94eSDimitry Andric    template <class, class, class> friend class _LIBCPP_TEMPLATE_VIS set;
876aed8d94eSDimitry Andric    template <class, class, class> friend class _LIBCPP_TEMPLATE_VIS multiset;
8777a984708SDavid Chisnall};
8787a984708SDavid Chisnall
8797c82a1ecSDimitry Andrictemplate <class _Tp, class _NodePtr, class _DiffType>
880aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __tree_const_iterator
8817a984708SDavid Chisnall{
8827c82a1ecSDimitry Andric    typedef __tree_node_types<_NodePtr>                     _NodeTypes;
8837c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_pointer             __node_pointer;
8847c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_base_pointer        __node_base_pointer;
8857c82a1ecSDimitry Andric    typedef typename _NodeTypes::__end_node_pointer         __end_node_pointer;
8867c82a1ecSDimitry Andric    typedef typename _NodeTypes::__iter_pointer             __iter_pointer;
8877a984708SDavid Chisnall    typedef pointer_traits<__node_pointer> __pointer_traits;
8887c82a1ecSDimitry Andric
8897c82a1ecSDimitry Andric    __iter_pointer __ptr_;
8907c82a1ecSDimitry Andric
8917a984708SDavid Chisnallpublic:
8927a984708SDavid Chisnall    typedef bidirectional_iterator_tag                           iterator_category;
8937a984708SDavid Chisnall    typedef _Tp                                                  value_type;
8947a984708SDavid Chisnall    typedef _DiffType                                            difference_type;
8957a984708SDavid Chisnall    typedef const value_type&                                    reference;
8967c82a1ecSDimitry Andric    typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
8977a984708SDavid Chisnall
8984f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY __tree_const_iterator() _NOEXCEPT
8994f7ab58eSDimitry Andric#if _LIBCPP_STD_VER > 11
9004f7ab58eSDimitry Andric    : __ptr_(nullptr)
9014f7ab58eSDimitry Andric#endif
9024f7ab58eSDimitry Andric    {}
9034f7ab58eSDimitry Andric
9047a984708SDavid Chisnallprivate:
9057c82a1ecSDimitry Andric    typedef __tree_iterator<value_type, __node_pointer, difference_type>
9067a984708SDavid Chisnall                                                           __non_const_iterator;
9077a984708SDavid Chisnallpublic:
9087a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9097a984708SDavid Chisnall    __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT
9107a984708SDavid Chisnall        : __ptr_(__p.__ptr_) {}
9117a984708SDavid Chisnall
9127c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY reference operator*() const
9137c82a1ecSDimitry Andric        {return __get_np()->__value_;}
9144bab9fd9SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY pointer operator->() const
9157c82a1ecSDimitry Andric        {return pointer_traits<pointer>::pointer_to(__get_np()->__value_);}
9167a984708SDavid Chisnall
9177a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
918854fa44bSDimitry Andric    __tree_const_iterator& operator++() {
9197c82a1ecSDimitry Andric      __ptr_ = static_cast<__iter_pointer>(
9207c82a1ecSDimitry Andric          __tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)));
921854fa44bSDimitry Andric      return *this;
922854fa44bSDimitry Andric    }
923854fa44bSDimitry Andric
9247a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9257a984708SDavid Chisnall    __tree_const_iterator operator++(int)
9267a984708SDavid Chisnall        {__tree_const_iterator __t(*this); ++(*this); return __t;}
9277a984708SDavid Chisnall
9287a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
929854fa44bSDimitry Andric    __tree_const_iterator& operator--() {
9307c82a1ecSDimitry Andric      __ptr_ = static_cast<__iter_pointer>(__tree_prev_iter<__node_base_pointer>(
9317c82a1ecSDimitry Andric          static_cast<__end_node_pointer>(__ptr_)));
932854fa44bSDimitry Andric      return *this;
933854fa44bSDimitry Andric    }
934854fa44bSDimitry Andric
9357a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9367a984708SDavid Chisnall    __tree_const_iterator operator--(int)
9377a984708SDavid Chisnall        {__tree_const_iterator __t(*this); --(*this); return __t;}
9387a984708SDavid Chisnall
9397a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
9407a984708SDavid Chisnall        bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
9417a984708SDavid Chisnall        {return __x.__ptr_ == __y.__ptr_;}
9427a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
9437a984708SDavid Chisnall        bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y)
9447a984708SDavid Chisnall        {return !(__x == __y);}
9457a984708SDavid Chisnall
9467a984708SDavid Chisnallprivate:
9477a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9487a984708SDavid Chisnall    explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT
9497a984708SDavid Chisnall        : __ptr_(__p) {}
9507c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9517c82a1ecSDimitry Andric    explicit __tree_const_iterator(__end_node_pointer __p) _NOEXCEPT
9527c82a1ecSDimitry Andric        : __ptr_(__p) {}
9537c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9547c82a1ecSDimitry Andric    __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); }
9557c82a1ecSDimitry Andric
9567a984708SDavid Chisnall    template <class, class, class> friend class __tree;
957aed8d94eSDimitry Andric    template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS map;
958aed8d94eSDimitry Andric    template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS multimap;
959aed8d94eSDimitry Andric    template <class, class, class> friend class _LIBCPP_TEMPLATE_VIS set;
960aed8d94eSDimitry Andric    template <class, class, class> friend class _LIBCPP_TEMPLATE_VIS multiset;
961aed8d94eSDimitry Andric    template <class> friend class _LIBCPP_TEMPLATE_VIS __map_const_iterator;
9627c82a1ecSDimitry Andric
9637a984708SDavid Chisnall};
9647a984708SDavid Chisnall
965*b5893f02SDimitry Andrictemplate<class _Tp, class _Compare>
966540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
967*b5893f02SDimitry Andric    _LIBCPP_DIAGNOSE_WARNING(!std::__invokable<_Compare const&, _Tp const&, _Tp const&>::value,
968540d2a8bSDimitry Andric        "the specified comparator type does not provide a const call operator")
969*b5893f02SDimitry Andric#endif
970*b5893f02SDimitry Andricint __diagnose_non_const_comparator();
971540d2a8bSDimitry Andric
9727a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
9737a984708SDavid Chisnallclass __tree
9747a984708SDavid Chisnall{
9757a984708SDavid Chisnallpublic:
9767a984708SDavid Chisnall    typedef _Tp                                      value_type;
9777a984708SDavid Chisnall    typedef _Compare                                 value_compare;
9787a984708SDavid Chisnall    typedef _Allocator                               allocator_type;
9797c82a1ecSDimitry Andric
9807c82a1ecSDimitry Andricprivate:
9817a984708SDavid Chisnall    typedef allocator_traits<allocator_type>         __alloc_traits;
9827c82a1ecSDimitry Andric    typedef typename __make_tree_node_types<value_type,
9837c82a1ecSDimitry Andric        typename __alloc_traits::void_pointer>::type
9847c82a1ecSDimitry Andric                                                    _NodeTypes;
9857c82a1ecSDimitry Andric    typedef typename _NodeTypes::key_type           key_type;
9867c82a1ecSDimitry Andricpublic:
9877c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_value_type      __node_value_type;
9887c82a1ecSDimitry Andric    typedef typename _NodeTypes::__container_value_type __container_value_type;
9897c82a1ecSDimitry Andric
9907a984708SDavid Chisnall    typedef typename __alloc_traits::pointer         pointer;
9917a984708SDavid Chisnall    typedef typename __alloc_traits::const_pointer   const_pointer;
9927a984708SDavid Chisnall    typedef typename __alloc_traits::size_type       size_type;
9937a984708SDavid Chisnall    typedef typename __alloc_traits::difference_type difference_type;
9947a984708SDavid Chisnall
9957c82a1ecSDimitry Andricpublic:
9967c82a1ecSDimitry Andric    typedef typename _NodeTypes::__void_pointer        __void_pointer;
9974bab9fd9SDavid Chisnall
9987c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_type           __node;
9997c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_pointer        __node_pointer;
10007c82a1ecSDimitry Andric
10017c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_base_type      __node_base;
10027c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_base_pointer   __node_base_pointer;
10037c82a1ecSDimitry Andric
10047c82a1ecSDimitry Andric    typedef typename _NodeTypes::__end_node_type       __end_node_t;
10057c82a1ecSDimitry Andric    typedef typename _NodeTypes::__end_node_pointer    __end_node_ptr;
10067c82a1ecSDimitry Andric
10077c82a1ecSDimitry Andric    typedef typename _NodeTypes::__parent_pointer      __parent_pointer;
10087c82a1ecSDimitry Andric    typedef typename _NodeTypes::__iter_pointer        __iter_pointer;
10097c82a1ecSDimitry Andric
1010854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator;
10117a984708SDavid Chisnall    typedef allocator_traits<__node_allocator>         __node_traits;
10127a984708SDavid Chisnall
10137c82a1ecSDimitry Andricprivate:
10147c82a1ecSDimitry Andric    // check for sane allocator pointer rebinding semantics. Rebinding the
10157c82a1ecSDimitry Andric    // allocator for a new pointer type should be exactly the same as rebinding
10167c82a1ecSDimitry Andric    // the pointer using 'pointer_traits'.
10177c82a1ecSDimitry Andric    static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value),
10187c82a1ecSDimitry Andric                  "Allocator does not rebind pointers in a sane manner.");
10197c82a1ecSDimitry Andric    typedef typename __rebind_alloc_helper<__node_traits, __node_base>::type
10207c82a1ecSDimitry Andric        __node_base_allocator;
10217c82a1ecSDimitry Andric    typedef allocator_traits<__node_base_allocator> __node_base_traits;
10227c82a1ecSDimitry Andric    static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value),
10237c82a1ecSDimitry Andric                 "Allocator does not rebind pointers in a sane manner.");
10247c82a1ecSDimitry Andric
10257c82a1ecSDimitry Andricprivate:
10267c82a1ecSDimitry Andric    __iter_pointer                                     __begin_node_;
10277a984708SDavid Chisnall    __compressed_pair<__end_node_t, __node_allocator>  __pair1_;
10287a984708SDavid Chisnall    __compressed_pair<size_type, value_compare>        __pair3_;
10297a984708SDavid Chisnall
10307a984708SDavid Chisnallpublic:
10317a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10327c82a1ecSDimitry Andric    __iter_pointer __end_node() _NOEXCEPT
10337a984708SDavid Chisnall    {
10347c82a1ecSDimitry Andric        return static_cast<__iter_pointer>(
10357a984708SDavid Chisnall                pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first())
10367a984708SDavid Chisnall        );
10377a984708SDavid Chisnall    }
10387a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10397c82a1ecSDimitry Andric    __iter_pointer __end_node() const _NOEXCEPT
10407a984708SDavid Chisnall    {
10417c82a1ecSDimitry Andric        return static_cast<__iter_pointer>(
10427c82a1ecSDimitry Andric            pointer_traits<__end_node_ptr>::pointer_to(
10437c82a1ecSDimitry Andric                const_cast<__end_node_t&>(__pair1_.first())
10447c82a1ecSDimitry Andric            )
10457a984708SDavid Chisnall        );
10467a984708SDavid Chisnall    }
10477a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10487a984708SDavid Chisnall          __node_allocator& __node_alloc() _NOEXCEPT {return __pair1_.second();}
10497a984708SDavid Chisnallprivate:
10507a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10517a984708SDavid Chisnall    const __node_allocator& __node_alloc() const _NOEXCEPT
10527a984708SDavid Chisnall        {return __pair1_.second();}
10537a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10547c82a1ecSDimitry Andric          __iter_pointer& __begin_node() _NOEXCEPT {return __begin_node_;}
10557a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10567c82a1ecSDimitry Andric    const __iter_pointer& __begin_node() const _NOEXCEPT {return __begin_node_;}
10577a984708SDavid Chisnallpublic:
10587a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10597a984708SDavid Chisnall    allocator_type __alloc() const _NOEXCEPT
10607a984708SDavid Chisnall        {return allocator_type(__node_alloc());}
10617a984708SDavid Chisnallprivate:
10627a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10637a984708SDavid Chisnall          size_type& size() _NOEXCEPT {return __pair3_.first();}
10647a984708SDavid Chisnallpublic:
10657a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10667a984708SDavid Chisnall    const size_type& size() const _NOEXCEPT {return __pair3_.first();}
10677a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10687a984708SDavid Chisnall          value_compare& value_comp() _NOEXCEPT {return __pair3_.second();}
10697a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10707a984708SDavid Chisnall    const value_compare& value_comp() const _NOEXCEPT
10717a984708SDavid Chisnall        {return __pair3_.second();}
10727a984708SDavid Chisnallpublic:
10737c82a1ecSDimitry Andric
10747a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10757c82a1ecSDimitry Andric    __node_pointer __root() const _NOEXCEPT
10767a984708SDavid Chisnall        {return static_cast<__node_pointer>(__end_node()->__left_);}
10777c82a1ecSDimitry Andric
10787c82a1ecSDimitry Andric    __node_base_pointer* __root_ptr() const _NOEXCEPT {
10797c82a1ecSDimitry Andric        return _VSTD::addressof(__end_node()->__left_);
10807c82a1ecSDimitry Andric    }
10817a984708SDavid Chisnall
10827a984708SDavid Chisnall    typedef __tree_iterator<value_type, __node_pointer, difference_type>             iterator;
10834bab9fd9SDavid Chisnall    typedef __tree_const_iterator<value_type, __node_pointer, difference_type> const_iterator;
10847a984708SDavid Chisnall
10857a984708SDavid Chisnall    explicit __tree(const value_compare& __comp)
10867a984708SDavid Chisnall        _NOEXCEPT_(
10877a984708SDavid Chisnall            is_nothrow_default_constructible<__node_allocator>::value &&
10887a984708SDavid Chisnall            is_nothrow_copy_constructible<value_compare>::value);
10897a984708SDavid Chisnall    explicit __tree(const allocator_type& __a);
10907a984708SDavid Chisnall    __tree(const value_compare& __comp, const allocator_type& __a);
10917a984708SDavid Chisnall    __tree(const __tree& __t);
10927a984708SDavid Chisnall    __tree& operator=(const __tree& __t);
10937a984708SDavid Chisnall    template <class _InputIterator>
10947a984708SDavid Chisnall        void __assign_unique(_InputIterator __first, _InputIterator __last);
10957a984708SDavid Chisnall    template <class _InputIterator>
10967a984708SDavid Chisnall        void __assign_multi(_InputIterator __first, _InputIterator __last);
1097540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
10987a984708SDavid Chisnall    __tree(__tree&& __t)
10997a984708SDavid Chisnall        _NOEXCEPT_(
11007a984708SDavid Chisnall            is_nothrow_move_constructible<__node_allocator>::value &&
11017a984708SDavid Chisnall            is_nothrow_move_constructible<value_compare>::value);
11027a984708SDavid Chisnall    __tree(__tree&& __t, const allocator_type& __a);
11037a984708SDavid Chisnall    __tree& operator=(__tree&& __t)
11047a984708SDavid Chisnall        _NOEXCEPT_(
11057a984708SDavid Chisnall            __node_traits::propagate_on_container_move_assignment::value &&
11067a984708SDavid Chisnall            is_nothrow_move_assignable<value_compare>::value &&
11077a984708SDavid Chisnall            is_nothrow_move_assignable<__node_allocator>::value);
1108540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG
11097a984708SDavid Chisnall
11107a984708SDavid Chisnall    ~__tree();
11117a984708SDavid Chisnall
11127a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
11137a984708SDavid Chisnall          iterator begin()  _NOEXCEPT {return       iterator(__begin_node());}
11147a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
11157a984708SDavid Chisnall    const_iterator begin() const _NOEXCEPT {return const_iterator(__begin_node());}
11167a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
11177a984708SDavid Chisnall          iterator end() _NOEXCEPT {return       iterator(__end_node());}
11187a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
11197a984708SDavid Chisnall    const_iterator end() const _NOEXCEPT {return const_iterator(__end_node());}
11207a984708SDavid Chisnall
11217a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
11227a984708SDavid Chisnall    size_type max_size() const _NOEXCEPT
1123aed8d94eSDimitry Andric        {return std::min<size_type>(
1124aed8d94eSDimitry Andric                __node_traits::max_size(__node_alloc()),
1125aed8d94eSDimitry Andric                numeric_limits<difference_type >::max());}
11267a984708SDavid Chisnall
11277a984708SDavid Chisnall    void clear() _NOEXCEPT;
11287a984708SDavid Chisnall
11297a984708SDavid Chisnall    void swap(__tree& __t)
1130aed8d94eSDimitry Andric#if _LIBCPP_STD_VER <= 11
11317a984708SDavid Chisnall        _NOEXCEPT_(
1132854fa44bSDimitry Andric            __is_nothrow_swappable<value_compare>::value
1133854fa44bSDimitry Andric            && (!__node_traits::propagate_on_container_swap::value ||
1134854fa44bSDimitry Andric                 __is_nothrow_swappable<__node_allocator>::value)
1135854fa44bSDimitry Andric            );
1136aed8d94eSDimitry Andric#else
1137aed8d94eSDimitry Andric        _NOEXCEPT_(__is_nothrow_swappable<value_compare>::value);
1138aed8d94eSDimitry Andric#endif
11397c82a1ecSDimitry Andric
11407c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
11417c82a1ecSDimitry Andric    template <class _Key, class ..._Args>
11427a984708SDavid Chisnall    pair<iterator, bool>
11437c82a1ecSDimitry Andric    __emplace_unique_key_args(_Key const&, _Args&&... __args);
11447c82a1ecSDimitry Andric    template <class _Key, class ..._Args>
11457a984708SDavid Chisnall    iterator
11467c82a1ecSDimitry Andric    __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&&...);
11477a984708SDavid Chisnall
11487a984708SDavid Chisnall    template <class... _Args>
11497c82a1ecSDimitry Andric    pair<iterator, bool> __emplace_unique_impl(_Args&&... __args);
11507c82a1ecSDimitry Andric
11517a984708SDavid Chisnall    template <class... _Args>
11527c82a1ecSDimitry Andric    iterator __emplace_hint_unique_impl(const_iterator __p, _Args&&... __args);
11537c82a1ecSDimitry Andric
11547c82a1ecSDimitry Andric    template <class... _Args>
11557c82a1ecSDimitry Andric    iterator __emplace_multi(_Args&&... __args);
11567c82a1ecSDimitry Andric
11577c82a1ecSDimitry Andric    template <class... _Args>
11587c82a1ecSDimitry Andric    iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
11597c82a1ecSDimitry Andric
11607c82a1ecSDimitry Andric    template <class _Pp>
11617c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11627c82a1ecSDimitry Andric    pair<iterator, bool> __emplace_unique(_Pp&& __x) {
11637c82a1ecSDimitry Andric        return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x),
11647c82a1ecSDimitry Andric                                            __can_extract_key<_Pp, key_type>());
11657c82a1ecSDimitry Andric    }
11667c82a1ecSDimitry Andric
11677c82a1ecSDimitry Andric    template <class _First, class _Second>
11687c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11697c82a1ecSDimitry Andric    typename enable_if<
11707c82a1ecSDimitry Andric        __can_extract_map_key<_First, key_type, __container_value_type>::value,
11717c82a1ecSDimitry Andric        pair<iterator, bool>
11727c82a1ecSDimitry Andric    >::type __emplace_unique(_First&& __f, _Second&& __s) {
11737c82a1ecSDimitry Andric        return __emplace_unique_key_args(__f, _VSTD::forward<_First>(__f),
11747c82a1ecSDimitry Andric                                              _VSTD::forward<_Second>(__s));
11757c82a1ecSDimitry Andric    }
11767c82a1ecSDimitry Andric
11777c82a1ecSDimitry Andric    template <class... _Args>
11787c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11797c82a1ecSDimitry Andric    pair<iterator, bool> __emplace_unique(_Args&&... __args) {
11807c82a1ecSDimitry Andric        return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...);
11817c82a1ecSDimitry Andric    }
11827c82a1ecSDimitry Andric
11837c82a1ecSDimitry Andric    template <class _Pp>
11847c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11857c82a1ecSDimitry Andric    pair<iterator, bool>
11867c82a1ecSDimitry Andric    __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) {
11877c82a1ecSDimitry Andric      return __emplace_unique_impl(_VSTD::forward<_Pp>(__x));
11887c82a1ecSDimitry Andric    }
11897c82a1ecSDimitry Andric
11907c82a1ecSDimitry Andric    template <class _Pp>
11917c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11927c82a1ecSDimitry Andric    pair<iterator, bool>
11937c82a1ecSDimitry Andric    __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) {
11947c82a1ecSDimitry Andric      return __emplace_unique_key_args(__x, _VSTD::forward<_Pp>(__x));
11957c82a1ecSDimitry Andric    }
11967c82a1ecSDimitry Andric
11977c82a1ecSDimitry Andric    template <class _Pp>
11987c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11997c82a1ecSDimitry Andric    pair<iterator, bool>
12007c82a1ecSDimitry Andric    __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) {
12017c82a1ecSDimitry Andric      return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x));
12027c82a1ecSDimitry Andric    }
12037c82a1ecSDimitry Andric
12047c82a1ecSDimitry Andric    template <class _Pp>
12057c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12067c82a1ecSDimitry Andric    iterator __emplace_hint_unique(const_iterator __p, _Pp&& __x) {
12077c82a1ecSDimitry Andric        return __emplace_hint_unique_extract_key(__p, _VSTD::forward<_Pp>(__x),
12087c82a1ecSDimitry Andric                                            __can_extract_key<_Pp, key_type>());
12097c82a1ecSDimitry Andric    }
12107c82a1ecSDimitry Andric
12117c82a1ecSDimitry Andric    template <class _First, class _Second>
12127c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12137c82a1ecSDimitry Andric    typename enable_if<
12147c82a1ecSDimitry Andric        __can_extract_map_key<_First, key_type, __container_value_type>::value,
12157a984708SDavid Chisnall        iterator
12167c82a1ecSDimitry Andric    >::type __emplace_hint_unique(const_iterator __p, _First&& __f, _Second&& __s) {
12177c82a1ecSDimitry Andric        return __emplace_hint_unique_key_args(__p, __f,
12187c82a1ecSDimitry Andric                                              _VSTD::forward<_First>(__f),
12197c82a1ecSDimitry Andric                                              _VSTD::forward<_Second>(__s));
12207c82a1ecSDimitry Andric    }
12217a984708SDavid Chisnall
12227c82a1ecSDimitry Andric    template <class... _Args>
12237c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12247c82a1ecSDimitry Andric    iterator __emplace_hint_unique(const_iterator __p, _Args&&... __args) {
12257c82a1ecSDimitry Andric        return __emplace_hint_unique_impl(__p, _VSTD::forward<_Args>(__args)...);
12267c82a1ecSDimitry Andric    }
12277a984708SDavid Chisnall
12287c82a1ecSDimitry Andric    template <class _Pp>
12297c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12307c82a1ecSDimitry Andric    iterator
12317c82a1ecSDimitry Andric    __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_fail_tag) {
12327c82a1ecSDimitry Andric      return __emplace_hint_unique_impl(__p, _VSTD::forward<_Pp>(__x));
12337c82a1ecSDimitry Andric    }
12347a984708SDavid Chisnall
12357c82a1ecSDimitry Andric    template <class _Pp>
12367c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12377c82a1ecSDimitry Andric    iterator
12387c82a1ecSDimitry Andric    __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_self_tag) {
12397c82a1ecSDimitry Andric      return __emplace_hint_unique_key_args(__p, __x, _VSTD::forward<_Pp>(__x));
12407c82a1ecSDimitry Andric    }
12417c82a1ecSDimitry Andric
12427c82a1ecSDimitry Andric    template <class _Pp>
12437c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12447c82a1ecSDimitry Andric    iterator
12457c82a1ecSDimitry Andric    __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_first_tag) {
12467c82a1ecSDimitry Andric      return __emplace_hint_unique_key_args(__p, __x.first, _VSTD::forward<_Pp>(__x));
12477c82a1ecSDimitry Andric    }
12487c82a1ecSDimitry Andric
12497c82a1ecSDimitry Andric#else
12507c82a1ecSDimitry Andric    template <class _Key, class _Args>
12517c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12527c82a1ecSDimitry Andric    pair<iterator, bool> __emplace_unique_key_args(_Key const&, _Args& __args);
12537c82a1ecSDimitry Andric    template <class _Key, class _Args>
12547c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12557c82a1ecSDimitry Andric    iterator __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&);
12569729cf09SDimitry Andric#endif
12579729cf09SDimitry Andric
12587c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12597c82a1ecSDimitry Andric    pair<iterator, bool> __insert_unique(const __container_value_type& __v) {
12607c82a1ecSDimitry Andric        return __emplace_unique_key_args(_NodeTypes::__get_key(__v), __v);
12617c82a1ecSDimitry Andric    }
12627c82a1ecSDimitry Andric
12637c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12647c82a1ecSDimitry Andric    iterator __insert_unique(const_iterator __p, const __container_value_type& __v) {
12657c82a1ecSDimitry Andric        return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), __v);
12667c82a1ecSDimitry Andric    }
12677c82a1ecSDimitry Andric
12687c82a1ecSDimitry Andric#ifdef _LIBCPP_CXX03_LANG
12697c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12707c82a1ecSDimitry Andric    iterator __insert_multi(const __container_value_type& __v);
12717c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12727c82a1ecSDimitry Andric    iterator __insert_multi(const_iterator __p, const __container_value_type& __v);
12737c82a1ecSDimitry Andric#else
12747c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12757c82a1ecSDimitry Andric    pair<iterator, bool> __insert_unique(__container_value_type&& __v) {
12767c82a1ecSDimitry Andric        return __emplace_unique_key_args(_NodeTypes::__get_key(__v), _VSTD::move(__v));
12777c82a1ecSDimitry Andric    }
12787c82a1ecSDimitry Andric
12797c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12807c82a1ecSDimitry Andric    iterator __insert_unique(const_iterator __p, __container_value_type&& __v) {
12817c82a1ecSDimitry Andric        return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), _VSTD::move(__v));
12827c82a1ecSDimitry Andric    }
12837c82a1ecSDimitry Andric
12847c82a1ecSDimitry Andric    template <class _Vp, class = typename enable_if<
12857c82a1ecSDimitry Andric            !is_same<typename __unconstref<_Vp>::type,
12867c82a1ecSDimitry Andric                     __container_value_type
12877c82a1ecSDimitry Andric            >::value
12887c82a1ecSDimitry Andric        >::type>
12897c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12907c82a1ecSDimitry Andric    pair<iterator, bool> __insert_unique(_Vp&& __v) {
12917c82a1ecSDimitry Andric        return __emplace_unique(_VSTD::forward<_Vp>(__v));
12927c82a1ecSDimitry Andric    }
12937c82a1ecSDimitry Andric
12947c82a1ecSDimitry Andric    template <class _Vp, class = typename enable_if<
12957c82a1ecSDimitry Andric            !is_same<typename __unconstref<_Vp>::type,
12967c82a1ecSDimitry Andric                     __container_value_type
12977c82a1ecSDimitry Andric            >::value
12987c82a1ecSDimitry Andric        >::type>
12997c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13007c82a1ecSDimitry Andric    iterator __insert_unique(const_iterator __p, _Vp&& __v) {
13017c82a1ecSDimitry Andric        return __emplace_hint_unique(__p, _VSTD::forward<_Vp>(__v));
13027c82a1ecSDimitry Andric    }
13037c82a1ecSDimitry Andric
13047c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13057c82a1ecSDimitry Andric    iterator __insert_multi(__container_value_type&& __v) {
13067c82a1ecSDimitry Andric        return __emplace_multi(_VSTD::move(__v));
13077c82a1ecSDimitry Andric    }
13087c82a1ecSDimitry Andric
13097c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13107c82a1ecSDimitry Andric    iterator __insert_multi(const_iterator __p, __container_value_type&& __v) {
13117c82a1ecSDimitry Andric        return __emplace_hint_multi(__p, _VSTD::move(__v));
13127c82a1ecSDimitry Andric    }
13137c82a1ecSDimitry Andric
13147c82a1ecSDimitry Andric    template <class _Vp>
13157c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13167c82a1ecSDimitry Andric    iterator __insert_multi(_Vp&& __v) {
13177c82a1ecSDimitry Andric        return __emplace_multi(_VSTD::forward<_Vp>(__v));
13187c82a1ecSDimitry Andric    }
13197c82a1ecSDimitry Andric
13207c82a1ecSDimitry Andric    template <class _Vp>
13217c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13227c82a1ecSDimitry Andric    iterator __insert_multi(const_iterator __p, _Vp&& __v) {
13237c82a1ecSDimitry Andric        return __emplace_hint_multi(__p, _VSTD::forward<_Vp>(__v));
13247c82a1ecSDimitry Andric    }
13257c82a1ecSDimitry Andric
13267c82a1ecSDimitry Andric#endif // !_LIBCPP_CXX03_LANG
13277c82a1ecSDimitry Andric
1328*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13297a984708SDavid Chisnall    pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
1330*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13317a984708SDavid Chisnall    iterator             __node_insert_unique(const_iterator __p,
13327a984708SDavid Chisnall                                              __node_pointer __nd);
13337a984708SDavid Chisnall
1334*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13357a984708SDavid Chisnall    iterator __node_insert_multi(__node_pointer __nd);
1336*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13377a984708SDavid Chisnall    iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
13387a984708SDavid Chisnall
13394ba319b5SDimitry Andric
1340*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY iterator
1341*b5893f02SDimitry Andric    __remove_node_pointer(__node_pointer) _NOEXCEPT;
13424ba319b5SDimitry Andric
13434ba319b5SDimitry Andric#if _LIBCPP_STD_VER > 14
13444ba319b5SDimitry Andric    template <class _NodeHandle, class _InsertReturnType>
13454ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13464ba319b5SDimitry Andric    _InsertReturnType __node_handle_insert_unique(_NodeHandle&&);
13474ba319b5SDimitry Andric    template <class _NodeHandle>
13484ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13494ba319b5SDimitry Andric    iterator __node_handle_insert_unique(const_iterator, _NodeHandle&&);
1350*b5893f02SDimitry Andric    template <class _Tree>
1351*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1352*b5893f02SDimitry Andric    void __node_handle_merge_unique(_Tree& __source);
13534ba319b5SDimitry Andric
13544ba319b5SDimitry Andric    template <class _NodeHandle>
13554ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13564ba319b5SDimitry Andric    iterator __node_handle_insert_multi(_NodeHandle&&);
13574ba319b5SDimitry Andric    template <class _NodeHandle>
13584ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13594ba319b5SDimitry Andric    iterator __node_handle_insert_multi(const_iterator, _NodeHandle&&);
1360*b5893f02SDimitry Andric    template <class _Tree>
1361*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1362*b5893f02SDimitry Andric    void __node_handle_merge_multi(_Tree& __source);
13634ba319b5SDimitry Andric
13644ba319b5SDimitry Andric
13654ba319b5SDimitry Andric    template <class _NodeHandle>
13664ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13674ba319b5SDimitry Andric    _NodeHandle __node_handle_extract(key_type const&);
13684ba319b5SDimitry Andric    template <class _NodeHandle>
13694ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13704ba319b5SDimitry Andric    _NodeHandle __node_handle_extract(const_iterator);
13714ba319b5SDimitry Andric#endif
13724ba319b5SDimitry Andric
13737a984708SDavid Chisnall    iterator erase(const_iterator __p);
13747a984708SDavid Chisnall    iterator erase(const_iterator __f, const_iterator __l);
13757a984708SDavid Chisnall    template <class _Key>
13767a984708SDavid Chisnall        size_type __erase_unique(const _Key& __k);
13777a984708SDavid Chisnall    template <class _Key>
13787a984708SDavid Chisnall        size_type __erase_multi(const _Key& __k);
13797a984708SDavid Chisnall
13807c82a1ecSDimitry Andric    void __insert_node_at(__parent_pointer     __parent,
13817a984708SDavid Chisnall                          __node_base_pointer& __child,
1382*b5893f02SDimitry Andric                          __node_base_pointer __new_node) _NOEXCEPT;
13837a984708SDavid Chisnall
13847a984708SDavid Chisnall    template <class _Key>
13857a984708SDavid Chisnall        iterator find(const _Key& __v);
13867a984708SDavid Chisnall    template <class _Key>
13877a984708SDavid Chisnall        const_iterator find(const _Key& __v) const;
13887a984708SDavid Chisnall
13897a984708SDavid Chisnall    template <class _Key>
13907a984708SDavid Chisnall        size_type __count_unique(const _Key& __k) const;
13917a984708SDavid Chisnall    template <class _Key>
13927a984708SDavid Chisnall        size_type __count_multi(const _Key& __k) const;
13937a984708SDavid Chisnall
13947a984708SDavid Chisnall    template <class _Key>
13957a984708SDavid Chisnall        _LIBCPP_INLINE_VISIBILITY
13967a984708SDavid Chisnall        iterator lower_bound(const _Key& __v)
13977a984708SDavid Chisnall            {return __lower_bound(__v, __root(), __end_node());}
13987a984708SDavid Chisnall    template <class _Key>
13997a984708SDavid Chisnall        iterator __lower_bound(const _Key& __v,
14007a984708SDavid Chisnall                               __node_pointer __root,
14017c82a1ecSDimitry Andric                               __iter_pointer __result);
14027a984708SDavid Chisnall    template <class _Key>
14037a984708SDavid Chisnall        _LIBCPP_INLINE_VISIBILITY
14047a984708SDavid Chisnall        const_iterator lower_bound(const _Key& __v) const
14057a984708SDavid Chisnall            {return __lower_bound(__v, __root(), __end_node());}
14067a984708SDavid Chisnall    template <class _Key>
14077a984708SDavid Chisnall        const_iterator __lower_bound(const _Key& __v,
14087c82a1ecSDimitry Andric                                     __node_pointer __root,
14097c82a1ecSDimitry Andric                                     __iter_pointer __result) const;
14107a984708SDavid Chisnall    template <class _Key>
14117a984708SDavid Chisnall        _LIBCPP_INLINE_VISIBILITY
14127a984708SDavid Chisnall        iterator upper_bound(const _Key& __v)
14137a984708SDavid Chisnall            {return __upper_bound(__v, __root(), __end_node());}
14147a984708SDavid Chisnall    template <class _Key>
14157a984708SDavid Chisnall        iterator __upper_bound(const _Key& __v,
14167a984708SDavid Chisnall                               __node_pointer __root,
14177c82a1ecSDimitry Andric                               __iter_pointer __result);
14187a984708SDavid Chisnall    template <class _Key>
14197a984708SDavid Chisnall        _LIBCPP_INLINE_VISIBILITY
14207a984708SDavid Chisnall        const_iterator upper_bound(const _Key& __v) const
14217a984708SDavid Chisnall            {return __upper_bound(__v, __root(), __end_node());}
14227a984708SDavid Chisnall    template <class _Key>
14237a984708SDavid Chisnall        const_iterator __upper_bound(const _Key& __v,
14247c82a1ecSDimitry Andric                                     __node_pointer __root,
14257c82a1ecSDimitry Andric                                     __iter_pointer __result) const;
14267a984708SDavid Chisnall    template <class _Key>
14277a984708SDavid Chisnall        pair<iterator, iterator>
14287a984708SDavid Chisnall        __equal_range_unique(const _Key& __k);
14297a984708SDavid Chisnall    template <class _Key>
14307a984708SDavid Chisnall        pair<const_iterator, const_iterator>
14317a984708SDavid Chisnall        __equal_range_unique(const _Key& __k) const;
14327a984708SDavid Chisnall
14337a984708SDavid Chisnall    template <class _Key>
14347a984708SDavid Chisnall        pair<iterator, iterator>
14357a984708SDavid Chisnall        __equal_range_multi(const _Key& __k);
14367a984708SDavid Chisnall    template <class _Key>
14377a984708SDavid Chisnall        pair<const_iterator, const_iterator>
14387a984708SDavid Chisnall        __equal_range_multi(const _Key& __k) const;
14397a984708SDavid Chisnall
144094e3ee44SDavid Chisnall    typedef __tree_node_destructor<__node_allocator> _Dp;
144194e3ee44SDavid Chisnall    typedef unique_ptr<__node, _Dp> __node_holder;
14427a984708SDavid Chisnall
14437a984708SDavid Chisnall    __node_holder remove(const_iterator __p) _NOEXCEPT;
14447a984708SDavid Chisnallprivate:
14457c82a1ecSDimitry Andric    __node_base_pointer&
14467c82a1ecSDimitry Andric        __find_leaf_low(__parent_pointer& __parent, const key_type& __v);
14477c82a1ecSDimitry Andric    __node_base_pointer&
14487c82a1ecSDimitry Andric        __find_leaf_high(__parent_pointer& __parent, const key_type& __v);
14497c82a1ecSDimitry Andric    __node_base_pointer&
14507a984708SDavid Chisnall        __find_leaf(const_iterator __hint,
14517c82a1ecSDimitry Andric                    __parent_pointer& __parent, const key_type& __v);
1452aed8d94eSDimitry Andric    // FIXME: Make this function const qualified. Unfortunetly doing so
1453aed8d94eSDimitry Andric    // breaks existing code which uses non-const callable comparators.
14547a984708SDavid Chisnall    template <class _Key>
14557c82a1ecSDimitry Andric    __node_base_pointer&
14567c82a1ecSDimitry Andric        __find_equal(__parent_pointer& __parent, const _Key& __v);
14577a984708SDavid Chisnall    template <class _Key>
1458aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY __node_base_pointer&
1459aed8d94eSDimitry Andric    __find_equal(__parent_pointer& __parent, const _Key& __v) const {
1460aed8d94eSDimitry Andric      return const_cast<__tree*>(this)->__find_equal(__parent, __v);
1461aed8d94eSDimitry Andric    }
1462aed8d94eSDimitry Andric    template <class _Key>
14637c82a1ecSDimitry Andric    __node_base_pointer&
14647c82a1ecSDimitry Andric        __find_equal(const_iterator __hint, __parent_pointer& __parent,
14657c82a1ecSDimitry Andric                     __node_base_pointer& __dummy,
14667a984708SDavid Chisnall                     const _Key& __v);
14677a984708SDavid Chisnall
14687c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
14697a984708SDavid Chisnall    template <class ..._Args>
14707a984708SDavid Chisnall    __node_holder __construct_node(_Args&& ...__args);
14717c82a1ecSDimitry Andric#else
14727c82a1ecSDimitry Andric    __node_holder __construct_node(const __container_value_type& __v);
14737a984708SDavid Chisnall#endif
14747a984708SDavid Chisnall
14757a984708SDavid Chisnall    void destroy(__node_pointer __nd) _NOEXCEPT;
14767a984708SDavid Chisnall
14777a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
14787a984708SDavid Chisnall    void __copy_assign_alloc(const __tree& __t)
14797a984708SDavid Chisnall        {__copy_assign_alloc(__t, integral_constant<bool,
14807a984708SDavid Chisnall             __node_traits::propagate_on_container_copy_assignment::value>());}
14817a984708SDavid Chisnall
14827a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
14837a984708SDavid Chisnall    void __copy_assign_alloc(const __tree& __t, true_type)
14847c82a1ecSDimitry Andric        {
14857c82a1ecSDimitry Andric        if (__node_alloc() != __t.__node_alloc())
14867c82a1ecSDimitry Andric            clear();
14877c82a1ecSDimitry Andric        __node_alloc() = __t.__node_alloc();
14887c82a1ecSDimitry Andric        }
14897a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1490aed8d94eSDimitry Andric    void __copy_assign_alloc(const __tree&, false_type) {}
14917a984708SDavid Chisnall
14927a984708SDavid Chisnall    void __move_assign(__tree& __t, false_type);
14937a984708SDavid Chisnall    void __move_assign(__tree& __t, true_type)
14947a984708SDavid Chisnall        _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value &&
14957a984708SDavid Chisnall                   is_nothrow_move_assignable<__node_allocator>::value);
14967a984708SDavid Chisnall
14977a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
14987a984708SDavid Chisnall    void __move_assign_alloc(__tree& __t)
14997a984708SDavid Chisnall        _NOEXCEPT_(
15007a984708SDavid Chisnall            !__node_traits::propagate_on_container_move_assignment::value ||
15017a984708SDavid Chisnall            is_nothrow_move_assignable<__node_allocator>::value)
15027a984708SDavid Chisnall        {__move_assign_alloc(__t, integral_constant<bool,
15037a984708SDavid Chisnall             __node_traits::propagate_on_container_move_assignment::value>());}
15047a984708SDavid Chisnall
15057a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
15067a984708SDavid Chisnall    void __move_assign_alloc(__tree& __t, true_type)
15077a984708SDavid Chisnall        _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value)
15087a984708SDavid Chisnall        {__node_alloc() = _VSTD::move(__t.__node_alloc());}
15097a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1510aed8d94eSDimitry Andric    void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {}
15117a984708SDavid Chisnall
15127a984708SDavid Chisnall    __node_pointer __detach();
15137a984708SDavid Chisnall    static __node_pointer __detach(__node_pointer);
15144bab9fd9SDavid Chisnall
1515aed8d94eSDimitry Andric    template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS map;
1516aed8d94eSDimitry Andric    template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS multimap;
15177a984708SDavid Chisnall};
15187a984708SDavid Chisnall
15197a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
15207a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp)
15217a984708SDavid Chisnall        _NOEXCEPT_(
15227a984708SDavid Chisnall            is_nothrow_default_constructible<__node_allocator>::value &&
15237a984708SDavid Chisnall            is_nothrow_copy_constructible<value_compare>::value)
15247a984708SDavid Chisnall    : __pair3_(0, __comp)
15257a984708SDavid Chisnall{
15267a984708SDavid Chisnall    __begin_node() = __end_node();
15277a984708SDavid Chisnall}
15287a984708SDavid Chisnall
15297a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
15307a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a)
15317c82a1ecSDimitry Andric    : __begin_node_(__iter_pointer()),
1532540d2a8bSDimitry Andric      __pair1_(__second_tag(), __node_allocator(__a)),
15337a984708SDavid Chisnall      __pair3_(0)
15347a984708SDavid Chisnall{
15357a984708SDavid Chisnall    __begin_node() = __end_node();
15367a984708SDavid Chisnall}
15377a984708SDavid Chisnall
15387a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
15397a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp,
15407a984708SDavid Chisnall                                           const allocator_type& __a)
15417c82a1ecSDimitry Andric    : __begin_node_(__iter_pointer()),
1542540d2a8bSDimitry Andric      __pair1_(__second_tag(), __node_allocator(__a)),
15437a984708SDavid Chisnall      __pair3_(0, __comp)
15447a984708SDavid Chisnall{
15457a984708SDavid Chisnall    __begin_node() = __end_node();
15467a984708SDavid Chisnall}
15477a984708SDavid Chisnall
15487a984708SDavid Chisnall// Precondition:  size() != 0
15497a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
15507a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::__node_pointer
15517a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__detach()
15527a984708SDavid Chisnall{
15537c82a1ecSDimitry Andric    __node_pointer __cache = static_cast<__node_pointer>(__begin_node());
15547a984708SDavid Chisnall    __begin_node() = __end_node();
15557a984708SDavid Chisnall    __end_node()->__left_->__parent_ = nullptr;
15567a984708SDavid Chisnall    __end_node()->__left_ = nullptr;
15577a984708SDavid Chisnall    size() = 0;
15587a984708SDavid Chisnall    // __cache->__left_ == nullptr
15597a984708SDavid Chisnall    if (__cache->__right_ != nullptr)
15607a984708SDavid Chisnall        __cache = static_cast<__node_pointer>(__cache->__right_);
15617a984708SDavid Chisnall    // __cache->__left_ == nullptr
15627a984708SDavid Chisnall    // __cache->__right_ == nullptr
15637a984708SDavid Chisnall    return __cache;
15647a984708SDavid Chisnall}
15657a984708SDavid Chisnall
15667a984708SDavid Chisnall// Precondition:  __cache != nullptr
15677a984708SDavid Chisnall//    __cache->left_ == nullptr
15687a984708SDavid Chisnall//    __cache->right_ == nullptr
15697a984708SDavid Chisnall//    This is no longer a red-black tree
15707a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
15717a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::__node_pointer
15727a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache)
15737a984708SDavid Chisnall{
15747a984708SDavid Chisnall    if (__cache->__parent_ == nullptr)
15757a984708SDavid Chisnall        return nullptr;
15764bab9fd9SDavid Chisnall    if (__tree_is_left_child(static_cast<__node_base_pointer>(__cache)))
15777a984708SDavid Chisnall    {
15787a984708SDavid Chisnall        __cache->__parent_->__left_ = nullptr;
15797a984708SDavid Chisnall        __cache = static_cast<__node_pointer>(__cache->__parent_);
15807a984708SDavid Chisnall        if (__cache->__right_ == nullptr)
15817a984708SDavid Chisnall            return __cache;
15827a984708SDavid Chisnall        return static_cast<__node_pointer>(__tree_leaf(__cache->__right_));
15837a984708SDavid Chisnall    }
15847a984708SDavid Chisnall    // __cache is right child
15857c82a1ecSDimitry Andric    __cache->__parent_unsafe()->__right_ = nullptr;
15867a984708SDavid Chisnall    __cache = static_cast<__node_pointer>(__cache->__parent_);
15877a984708SDavid Chisnall    if (__cache->__left_ == nullptr)
15887a984708SDavid Chisnall        return __cache;
15897a984708SDavid Chisnall    return static_cast<__node_pointer>(__tree_leaf(__cache->__left_));
15907a984708SDavid Chisnall}
15917a984708SDavid Chisnall
15927a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
15937a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>&
15947a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t)
15957a984708SDavid Chisnall{
15967a984708SDavid Chisnall    if (this != &__t)
15977a984708SDavid Chisnall    {
15987a984708SDavid Chisnall        value_comp() = __t.value_comp();
15997a984708SDavid Chisnall        __copy_assign_alloc(__t);
16007a984708SDavid Chisnall        __assign_multi(__t.begin(), __t.end());
16017a984708SDavid Chisnall    }
16027a984708SDavid Chisnall    return *this;
16037a984708SDavid Chisnall}
16047a984708SDavid Chisnall
16057a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
16067a984708SDavid Chisnalltemplate <class _InputIterator>
16077a984708SDavid Chisnallvoid
16087a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last)
16097a984708SDavid Chisnall{
16107c82a1ecSDimitry Andric    typedef iterator_traits<_InputIterator> _ITraits;
16117c82a1ecSDimitry Andric    typedef typename _ITraits::value_type _ItValueType;
16127c82a1ecSDimitry Andric    static_assert((is_same<_ItValueType, __container_value_type>::value),
16137c82a1ecSDimitry Andric                  "__assign_unique may only be called with the containers value type");
16147c82a1ecSDimitry Andric
16157a984708SDavid Chisnall    if (size() != 0)
16167a984708SDavid Chisnall    {
16177a984708SDavid Chisnall        __node_pointer __cache = __detach();
16187a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
16197a984708SDavid Chisnall        try
16207a984708SDavid Chisnall        {
16217a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
16227a984708SDavid Chisnall            for (; __cache != nullptr && __first != __last; ++__first)
16237a984708SDavid Chisnall            {
16247a984708SDavid Chisnall                __cache->__value_ = *__first;
16257a984708SDavid Chisnall                __node_pointer __next = __detach(__cache);
16267a984708SDavid Chisnall                __node_insert_unique(__cache);
16277a984708SDavid Chisnall                __cache = __next;
16287a984708SDavid Chisnall            }
16297a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
16307a984708SDavid Chisnall        }
16317a984708SDavid Chisnall        catch (...)
16327a984708SDavid Chisnall        {
16337a984708SDavid Chisnall            while (__cache->__parent_ != nullptr)
16347a984708SDavid Chisnall                __cache = static_cast<__node_pointer>(__cache->__parent_);
16357a984708SDavid Chisnall            destroy(__cache);
16367a984708SDavid Chisnall            throw;
16377a984708SDavid Chisnall        }
16387a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
16397a984708SDavid Chisnall        if (__cache != nullptr)
16407a984708SDavid Chisnall        {
16417a984708SDavid Chisnall            while (__cache->__parent_ != nullptr)
16427a984708SDavid Chisnall                __cache = static_cast<__node_pointer>(__cache->__parent_);
16437a984708SDavid Chisnall            destroy(__cache);
16447a984708SDavid Chisnall        }
16457a984708SDavid Chisnall    }
16467a984708SDavid Chisnall    for (; __first != __last; ++__first)
16477a984708SDavid Chisnall        __insert_unique(*__first);
16487a984708SDavid Chisnall}
16497a984708SDavid Chisnall
16507a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
16517a984708SDavid Chisnalltemplate <class _InputIterator>
16527a984708SDavid Chisnallvoid
16537a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last)
16547a984708SDavid Chisnall{
16557c82a1ecSDimitry Andric    typedef iterator_traits<_InputIterator> _ITraits;
16567c82a1ecSDimitry Andric    typedef typename _ITraits::value_type _ItValueType;
16577c82a1ecSDimitry Andric    static_assert((is_same<_ItValueType, __container_value_type>::value ||
16587c82a1ecSDimitry Andric                  is_same<_ItValueType, __node_value_type>::value),
16597c82a1ecSDimitry Andric                  "__assign_multi may only be called with the containers value type"
16607c82a1ecSDimitry Andric                  " or the nodes value type");
16617a984708SDavid Chisnall    if (size() != 0)
16627a984708SDavid Chisnall    {
16637a984708SDavid Chisnall        __node_pointer __cache = __detach();
16647a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
16657a984708SDavid Chisnall        try
16667a984708SDavid Chisnall        {
16677a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
16687a984708SDavid Chisnall            for (; __cache != nullptr && __first != __last; ++__first)
16697a984708SDavid Chisnall            {
16707a984708SDavid Chisnall                __cache->__value_ = *__first;
16717a984708SDavid Chisnall                __node_pointer __next = __detach(__cache);
16727a984708SDavid Chisnall                __node_insert_multi(__cache);
16737a984708SDavid Chisnall                __cache = __next;
16747a984708SDavid Chisnall            }
16757a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
16767a984708SDavid Chisnall        }
16777a984708SDavid Chisnall        catch (...)
16787a984708SDavid Chisnall        {
16797a984708SDavid Chisnall            while (__cache->__parent_ != nullptr)
16807a984708SDavid Chisnall                __cache = static_cast<__node_pointer>(__cache->__parent_);
16817a984708SDavid Chisnall            destroy(__cache);
16827a984708SDavid Chisnall            throw;
16837a984708SDavid Chisnall        }
16847a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
16857a984708SDavid Chisnall        if (__cache != nullptr)
16867a984708SDavid Chisnall        {
16877a984708SDavid Chisnall            while (__cache->__parent_ != nullptr)
16887a984708SDavid Chisnall                __cache = static_cast<__node_pointer>(__cache->__parent_);
16897a984708SDavid Chisnall            destroy(__cache);
16907a984708SDavid Chisnall        }
16917a984708SDavid Chisnall    }
16927a984708SDavid Chisnall    for (; __first != __last; ++__first)
16937c82a1ecSDimitry Andric        __insert_multi(_NodeTypes::__get_value(*__first));
16947a984708SDavid Chisnall}
16957a984708SDavid Chisnall
16967a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
16977a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
16987c82a1ecSDimitry Andric    : __begin_node_(__iter_pointer()),
1699540d2a8bSDimitry Andric      __pair1_(__second_tag(), __node_traits::select_on_container_copy_construction(__t.__node_alloc())),
17007a984708SDavid Chisnall      __pair3_(0, __t.value_comp())
17017a984708SDavid Chisnall{
17027a984708SDavid Chisnall    __begin_node() = __end_node();
17037a984708SDavid Chisnall}
17047a984708SDavid Chisnall
1705540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
17067a984708SDavid Chisnall
17077a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
17087a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t)
17097a984708SDavid Chisnall    _NOEXCEPT_(
17107a984708SDavid Chisnall        is_nothrow_move_constructible<__node_allocator>::value &&
17117a984708SDavid Chisnall        is_nothrow_move_constructible<value_compare>::value)
17127a984708SDavid Chisnall    : __begin_node_(_VSTD::move(__t.__begin_node_)),
17137a984708SDavid Chisnall      __pair1_(_VSTD::move(__t.__pair1_)),
17147a984708SDavid Chisnall      __pair3_(_VSTD::move(__t.__pair3_))
17157a984708SDavid Chisnall{
17167a984708SDavid Chisnall    if (size() == 0)
17177a984708SDavid Chisnall        __begin_node() = __end_node();
17187a984708SDavid Chisnall    else
17197a984708SDavid Chisnall    {
17207c82a1ecSDimitry Andric        __end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__end_node());
17217a984708SDavid Chisnall        __t.__begin_node() = __t.__end_node();
17227a984708SDavid Chisnall        __t.__end_node()->__left_ = nullptr;
17237a984708SDavid Chisnall        __t.size() = 0;
17247a984708SDavid Chisnall    }
17257a984708SDavid Chisnall}
17267a984708SDavid Chisnall
17277a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
17287a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a)
1729540d2a8bSDimitry Andric    : __pair1_(__second_tag(), __node_allocator(__a)),
17307a984708SDavid Chisnall      __pair3_(0, _VSTD::move(__t.value_comp()))
17317a984708SDavid Chisnall{
17327a984708SDavid Chisnall    if (__a == __t.__alloc())
17337a984708SDavid Chisnall    {
17347a984708SDavid Chisnall        if (__t.size() == 0)
17357a984708SDavid Chisnall            __begin_node() = __end_node();
17367a984708SDavid Chisnall        else
17377a984708SDavid Chisnall        {
17387a984708SDavid Chisnall            __begin_node() = __t.__begin_node();
17397a984708SDavid Chisnall            __end_node()->__left_ = __t.__end_node()->__left_;
17407c82a1ecSDimitry Andric            __end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__end_node());
17417a984708SDavid Chisnall            size() = __t.size();
17427a984708SDavid Chisnall            __t.__begin_node() = __t.__end_node();
17437a984708SDavid Chisnall            __t.__end_node()->__left_ = nullptr;
17447a984708SDavid Chisnall            __t.size() = 0;
17457a984708SDavid Chisnall        }
17467a984708SDavid Chisnall    }
17477a984708SDavid Chisnall    else
17487a984708SDavid Chisnall    {
17497a984708SDavid Chisnall        __begin_node() = __end_node();
17507a984708SDavid Chisnall    }
17517a984708SDavid Chisnall}
17527a984708SDavid Chisnall
17537a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
17547a984708SDavid Chisnallvoid
17557a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type)
17567a984708SDavid Chisnall    _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value &&
17577a984708SDavid Chisnall               is_nothrow_move_assignable<__node_allocator>::value)
17587a984708SDavid Chisnall{
17597a984708SDavid Chisnall    destroy(static_cast<__node_pointer>(__end_node()->__left_));
17607a984708SDavid Chisnall    __begin_node_ = __t.__begin_node_;
17617a984708SDavid Chisnall    __pair1_.first() = __t.__pair1_.first();
17627a984708SDavid Chisnall    __move_assign_alloc(__t);
17637a984708SDavid Chisnall    __pair3_ = _VSTD::move(__t.__pair3_);
17647a984708SDavid Chisnall    if (size() == 0)
17657a984708SDavid Chisnall        __begin_node() = __end_node();
17667a984708SDavid Chisnall    else
17677a984708SDavid Chisnall    {
17687c82a1ecSDimitry Andric        __end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__end_node());
17697a984708SDavid Chisnall        __t.__begin_node() = __t.__end_node();
17707a984708SDavid Chisnall        __t.__end_node()->__left_ = nullptr;
17717a984708SDavid Chisnall        __t.size() = 0;
17727a984708SDavid Chisnall    }
17737a984708SDavid Chisnall}
17747a984708SDavid Chisnall
17757a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
17767a984708SDavid Chisnallvoid
17777a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type)
17787a984708SDavid Chisnall{
17797a984708SDavid Chisnall    if (__node_alloc() == __t.__node_alloc())
17807a984708SDavid Chisnall        __move_assign(__t, true_type());
17817a984708SDavid Chisnall    else
17827a984708SDavid Chisnall    {
17837a984708SDavid Chisnall        value_comp() = _VSTD::move(__t.value_comp());
17847a984708SDavid Chisnall        const_iterator __e = end();
17857a984708SDavid Chisnall        if (size() != 0)
17867a984708SDavid Chisnall        {
17877a984708SDavid Chisnall            __node_pointer __cache = __detach();
17887a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
17897a984708SDavid Chisnall            try
17907a984708SDavid Chisnall            {
17917a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
17927a984708SDavid Chisnall                while (__cache != nullptr && __t.size() != 0)
17937a984708SDavid Chisnall                {
17947a984708SDavid Chisnall                    __cache->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_);
17957a984708SDavid Chisnall                    __node_pointer __next = __detach(__cache);
17967a984708SDavid Chisnall                    __node_insert_multi(__cache);
17977a984708SDavid Chisnall                    __cache = __next;
17987a984708SDavid Chisnall                }
17997a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
18007a984708SDavid Chisnall            }
18017a984708SDavid Chisnall            catch (...)
18027a984708SDavid Chisnall            {
18037a984708SDavid Chisnall                while (__cache->__parent_ != nullptr)
18047a984708SDavid Chisnall                    __cache = static_cast<__node_pointer>(__cache->__parent_);
18057a984708SDavid Chisnall                destroy(__cache);
18067a984708SDavid Chisnall                throw;
18077a984708SDavid Chisnall            }
18087a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
18097a984708SDavid Chisnall            if (__cache != nullptr)
18107a984708SDavid Chisnall            {
18117a984708SDavid Chisnall                while (__cache->__parent_ != nullptr)
18127a984708SDavid Chisnall                    __cache = static_cast<__node_pointer>(__cache->__parent_);
18137a984708SDavid Chisnall                destroy(__cache);
18147a984708SDavid Chisnall            }
18157a984708SDavid Chisnall        }
18167a984708SDavid Chisnall        while (__t.size() != 0)
18177c82a1ecSDimitry Andric            __insert_multi(__e, _NodeTypes::__move(__t.remove(__t.begin())->__value_));
18187a984708SDavid Chisnall    }
18197a984708SDavid Chisnall}
18207a984708SDavid Chisnall
18217a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
18227a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>&
18237a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t)
18247a984708SDavid Chisnall    _NOEXCEPT_(
18257a984708SDavid Chisnall        __node_traits::propagate_on_container_move_assignment::value &&
18267a984708SDavid Chisnall        is_nothrow_move_assignable<value_compare>::value &&
18277a984708SDavid Chisnall        is_nothrow_move_assignable<__node_allocator>::value)
18287a984708SDavid Chisnall
18297a984708SDavid Chisnall{
18307a984708SDavid Chisnall    __move_assign(__t, integral_constant<bool,
18317a984708SDavid Chisnall                  __node_traits::propagate_on_container_move_assignment::value>());
18327a984708SDavid Chisnall    return *this;
18337a984708SDavid Chisnall}
18347a984708SDavid Chisnall
1835540d2a8bSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
18367a984708SDavid Chisnall
18377a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
18387a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::~__tree()
18397a984708SDavid Chisnall{
18407c82a1ecSDimitry Andric    static_assert((is_copy_constructible<value_compare>::value),
18417c82a1ecSDimitry Andric                 "Comparator must be copy-constructible.");
18427a984708SDavid Chisnall  destroy(__root());
18437a984708SDavid Chisnall}
18447a984708SDavid Chisnall
18457a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
18467a984708SDavid Chisnallvoid
18477a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT
18487a984708SDavid Chisnall{
18497a984708SDavid Chisnall    if (__nd != nullptr)
18507a984708SDavid Chisnall    {
18517a984708SDavid Chisnall        destroy(static_cast<__node_pointer>(__nd->__left_));
18527a984708SDavid Chisnall        destroy(static_cast<__node_pointer>(__nd->__right_));
18537a984708SDavid Chisnall        __node_allocator& __na = __node_alloc();
18547c82a1ecSDimitry Andric        __node_traits::destroy(__na, _NodeTypes::__get_ptr(__nd->__value_));
18557a984708SDavid Chisnall        __node_traits::deallocate(__na, __nd, 1);
18567a984708SDavid Chisnall    }
18577a984708SDavid Chisnall}
18587a984708SDavid Chisnall
18597a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
18607a984708SDavid Chisnallvoid
18617a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::swap(__tree& __t)
1862aed8d94eSDimitry Andric#if _LIBCPP_STD_VER <= 11
18637a984708SDavid Chisnall        _NOEXCEPT_(
1864854fa44bSDimitry Andric            __is_nothrow_swappable<value_compare>::value
1865854fa44bSDimitry Andric            && (!__node_traits::propagate_on_container_swap::value ||
1866854fa44bSDimitry Andric                 __is_nothrow_swappable<__node_allocator>::value)
1867854fa44bSDimitry Andric            )
1868aed8d94eSDimitry Andric#else
1869aed8d94eSDimitry Andric        _NOEXCEPT_(__is_nothrow_swappable<value_compare>::value)
1870aed8d94eSDimitry Andric#endif
18717a984708SDavid Chisnall{
18727a984708SDavid Chisnall    using _VSTD::swap;
18737a984708SDavid Chisnall    swap(__begin_node_, __t.__begin_node_);
18747a984708SDavid Chisnall    swap(__pair1_.first(), __t.__pair1_.first());
1875854fa44bSDimitry Andric    __swap_allocator(__node_alloc(), __t.__node_alloc());
18767a984708SDavid Chisnall    __pair3_.swap(__t.__pair3_);
18777a984708SDavid Chisnall    if (size() == 0)
18787a984708SDavid Chisnall        __begin_node() = __end_node();
18797a984708SDavid Chisnall    else
18807c82a1ecSDimitry Andric        __end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__end_node());
18817a984708SDavid Chisnall    if (__t.size() == 0)
18827a984708SDavid Chisnall        __t.__begin_node() = __t.__end_node();
18837a984708SDavid Chisnall    else
18847c82a1ecSDimitry Andric        __t.__end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__t.__end_node());
18857a984708SDavid Chisnall}
18867a984708SDavid Chisnall
18877a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
18887a984708SDavid Chisnallvoid
18897a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT
18907a984708SDavid Chisnall{
18917a984708SDavid Chisnall    destroy(__root());
18927a984708SDavid Chisnall    size() = 0;
18937a984708SDavid Chisnall    __begin_node() = __end_node();
18947a984708SDavid Chisnall    __end_node()->__left_ = nullptr;
18957a984708SDavid Chisnall}
18967a984708SDavid Chisnall
18977a984708SDavid Chisnall// Find lower_bound place to insert
18987a984708SDavid Chisnall// Set __parent to parent of null leaf
18997a984708SDavid Chisnall// Return reference to null leaf
19007a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
19017c82a1ecSDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
19027c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__parent_pointer& __parent,
19037c82a1ecSDimitry Andric                                                   const key_type& __v)
19047a984708SDavid Chisnall{
19057a984708SDavid Chisnall    __node_pointer __nd = __root();
19067a984708SDavid Chisnall    if (__nd != nullptr)
19077a984708SDavid Chisnall    {
19087a984708SDavid Chisnall        while (true)
19097a984708SDavid Chisnall        {
19107a984708SDavid Chisnall            if (value_comp()(__nd->__value_, __v))
19117a984708SDavid Chisnall            {
19127a984708SDavid Chisnall                if (__nd->__right_ != nullptr)
19137a984708SDavid Chisnall                    __nd = static_cast<__node_pointer>(__nd->__right_);
19147a984708SDavid Chisnall                else
19157a984708SDavid Chisnall                {
19167c82a1ecSDimitry Andric                    __parent = static_cast<__parent_pointer>(__nd);
19177c82a1ecSDimitry Andric                    return __nd->__right_;
19187a984708SDavid Chisnall                }
19197a984708SDavid Chisnall            }
19207a984708SDavid Chisnall            else
19217a984708SDavid Chisnall            {
19227a984708SDavid Chisnall                if (__nd->__left_ != nullptr)
19237a984708SDavid Chisnall                    __nd = static_cast<__node_pointer>(__nd->__left_);
19247a984708SDavid Chisnall                else
19257a984708SDavid Chisnall                {
19267c82a1ecSDimitry Andric                    __parent = static_cast<__parent_pointer>(__nd);
19277a984708SDavid Chisnall                    return __parent->__left_;
19287a984708SDavid Chisnall                }
19297a984708SDavid Chisnall            }
19307a984708SDavid Chisnall        }
19317a984708SDavid Chisnall    }
19327c82a1ecSDimitry Andric    __parent = static_cast<__parent_pointer>(__end_node());
19337a984708SDavid Chisnall    return __parent->__left_;
19347a984708SDavid Chisnall}
19357a984708SDavid Chisnall
19367a984708SDavid Chisnall// Find upper_bound place to insert
19377a984708SDavid Chisnall// Set __parent to parent of null leaf
19387a984708SDavid Chisnall// Return reference to null leaf
19397a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
19407c82a1ecSDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
19417c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__parent_pointer& __parent,
19427c82a1ecSDimitry Andric                                                    const key_type& __v)
19437a984708SDavid Chisnall{
19447a984708SDavid Chisnall    __node_pointer __nd = __root();
19457a984708SDavid Chisnall    if (__nd != nullptr)
19467a984708SDavid Chisnall    {
19477a984708SDavid Chisnall        while (true)
19487a984708SDavid Chisnall        {
19497a984708SDavid Chisnall            if (value_comp()(__v, __nd->__value_))
19507a984708SDavid Chisnall            {
19517a984708SDavid Chisnall                if (__nd->__left_ != nullptr)
19527a984708SDavid Chisnall                    __nd = static_cast<__node_pointer>(__nd->__left_);
19537a984708SDavid Chisnall                else
19547a984708SDavid Chisnall                {
19557c82a1ecSDimitry Andric                    __parent = static_cast<__parent_pointer>(__nd);
19567a984708SDavid Chisnall                    return __parent->__left_;
19577a984708SDavid Chisnall                }
19587a984708SDavid Chisnall            }
19597a984708SDavid Chisnall            else
19607a984708SDavid Chisnall            {
19617a984708SDavid Chisnall                if (__nd->__right_ != nullptr)
19627a984708SDavid Chisnall                    __nd = static_cast<__node_pointer>(__nd->__right_);
19637a984708SDavid Chisnall                else
19647a984708SDavid Chisnall                {
19657c82a1ecSDimitry Andric                    __parent = static_cast<__parent_pointer>(__nd);
19667c82a1ecSDimitry Andric                    return __nd->__right_;
19677a984708SDavid Chisnall                }
19687a984708SDavid Chisnall            }
19697a984708SDavid Chisnall        }
19707a984708SDavid Chisnall    }
19717c82a1ecSDimitry Andric    __parent = static_cast<__parent_pointer>(__end_node());
19727a984708SDavid Chisnall    return __parent->__left_;
19737a984708SDavid Chisnall}
19747a984708SDavid Chisnall
19757a984708SDavid Chisnall// Find leaf place to insert closest to __hint
19767a984708SDavid Chisnall// First check prior to __hint.
19777a984708SDavid Chisnall// Next check after __hint.
19787a984708SDavid Chisnall// Next do O(log N) search.
19797a984708SDavid Chisnall// Set __parent to parent of null leaf
19807a984708SDavid Chisnall// Return reference to null leaf
19817a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
19827c82a1ecSDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
19837a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint,
19847c82a1ecSDimitry Andric                                               __parent_pointer& __parent,
19857c82a1ecSDimitry Andric                                               const key_type& __v)
19867a984708SDavid Chisnall{
19877a984708SDavid Chisnall    if (__hint == end() || !value_comp()(*__hint, __v))  // check before
19887a984708SDavid Chisnall    {
19897a984708SDavid Chisnall        // __v <= *__hint
19907a984708SDavid Chisnall        const_iterator __prior = __hint;
19917a984708SDavid Chisnall        if (__prior == begin() || !value_comp()(__v, *--__prior))
19927a984708SDavid Chisnall        {
19937a984708SDavid Chisnall            // *prev(__hint) <= __v <= *__hint
19947a984708SDavid Chisnall            if (__hint.__ptr_->__left_ == nullptr)
19957a984708SDavid Chisnall            {
19967c82a1ecSDimitry Andric                __parent = static_cast<__parent_pointer>(__hint.__ptr_);
19977a984708SDavid Chisnall                return __parent->__left_;
19987a984708SDavid Chisnall            }
19997a984708SDavid Chisnall            else
20007a984708SDavid Chisnall            {
20017c82a1ecSDimitry Andric                __parent = static_cast<__parent_pointer>(__prior.__ptr_);
20027c82a1ecSDimitry Andric                return static_cast<__node_base_pointer>(__prior.__ptr_)->__right_;
20037a984708SDavid Chisnall            }
20047a984708SDavid Chisnall        }
20057a984708SDavid Chisnall        // __v < *prev(__hint)
20067a984708SDavid Chisnall        return __find_leaf_high(__parent, __v);
20077a984708SDavid Chisnall    }
20087a984708SDavid Chisnall    // else __v > *__hint
20097a984708SDavid Chisnall    return __find_leaf_low(__parent, __v);
20107a984708SDavid Chisnall}
20117a984708SDavid Chisnall
20127a984708SDavid Chisnall// Find place to insert if __v doesn't exist
20137a984708SDavid Chisnall// Set __parent to parent of null leaf
20147a984708SDavid Chisnall// Return reference to null leaf
20157a984708SDavid Chisnall// If __v exists, set parent to node of __v and return reference to node of __v
20167a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
20177a984708SDavid Chisnalltemplate <class _Key>
20187c82a1ecSDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
20197c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__find_equal(__parent_pointer& __parent,
20207a984708SDavid Chisnall                                                const _Key& __v)
20217a984708SDavid Chisnall{
20227a984708SDavid Chisnall    __node_pointer __nd = __root();
20237c82a1ecSDimitry Andric    __node_base_pointer* __nd_ptr = __root_ptr();
20247a984708SDavid Chisnall    if (__nd != nullptr)
20257a984708SDavid Chisnall    {
20267a984708SDavid Chisnall        while (true)
20277a984708SDavid Chisnall        {
20287a984708SDavid Chisnall            if (value_comp()(__v, __nd->__value_))
20297a984708SDavid Chisnall            {
20307c82a1ecSDimitry Andric                if (__nd->__left_ != nullptr) {
20317c82a1ecSDimitry Andric                    __nd_ptr = _VSTD::addressof(__nd->__left_);
20327a984708SDavid Chisnall                    __nd = static_cast<__node_pointer>(__nd->__left_);
20337c82a1ecSDimitry Andric                } else {
20347c82a1ecSDimitry Andric                    __parent = static_cast<__parent_pointer>(__nd);
20357a984708SDavid Chisnall                    return __parent->__left_;
20367a984708SDavid Chisnall                }
20377a984708SDavid Chisnall            }
20387a984708SDavid Chisnall            else if (value_comp()(__nd->__value_, __v))
20397a984708SDavid Chisnall            {
20407c82a1ecSDimitry Andric                if (__nd->__right_ != nullptr) {
20417c82a1ecSDimitry Andric                    __nd_ptr = _VSTD::addressof(__nd->__right_);
20427a984708SDavid Chisnall                    __nd = static_cast<__node_pointer>(__nd->__right_);
20437c82a1ecSDimitry Andric                } else {
20447c82a1ecSDimitry Andric                    __parent = static_cast<__parent_pointer>(__nd);
20457c82a1ecSDimitry Andric                    return __nd->__right_;
20467a984708SDavid Chisnall                }
20477a984708SDavid Chisnall            }
20487a984708SDavid Chisnall            else
20497a984708SDavid Chisnall            {
20507c82a1ecSDimitry Andric                __parent = static_cast<__parent_pointer>(__nd);
20517c82a1ecSDimitry Andric                return *__nd_ptr;
20527a984708SDavid Chisnall            }
20537a984708SDavid Chisnall        }
20547a984708SDavid Chisnall    }
20557c82a1ecSDimitry Andric    __parent = static_cast<__parent_pointer>(__end_node());
20567a984708SDavid Chisnall    return __parent->__left_;
20577a984708SDavid Chisnall}
20587a984708SDavid Chisnall
20597a984708SDavid Chisnall// Find place to insert if __v doesn't exist
20607a984708SDavid Chisnall// First check prior to __hint.
20617a984708SDavid Chisnall// Next check after __hint.
20627a984708SDavid Chisnall// Next do O(log N) search.
20637a984708SDavid Chisnall// Set __parent to parent of null leaf
20647a984708SDavid Chisnall// Return reference to null leaf
20657a984708SDavid Chisnall// If __v exists, set parent to node of __v and return reference to node of __v
20667a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
20677a984708SDavid Chisnalltemplate <class _Key>
20687c82a1ecSDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
20697a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint,
20707c82a1ecSDimitry Andric                                                __parent_pointer& __parent,
20717c82a1ecSDimitry Andric                                                __node_base_pointer& __dummy,
20727a984708SDavid Chisnall                                                const _Key& __v)
20737a984708SDavid Chisnall{
20747a984708SDavid Chisnall    if (__hint == end() || value_comp()(__v, *__hint))  // check before
20757a984708SDavid Chisnall    {
20767a984708SDavid Chisnall        // __v < *__hint
20777a984708SDavid Chisnall        const_iterator __prior = __hint;
20787a984708SDavid Chisnall        if (__prior == begin() || value_comp()(*--__prior, __v))
20797a984708SDavid Chisnall        {
20807a984708SDavid Chisnall            // *prev(__hint) < __v < *__hint
20817a984708SDavid Chisnall            if (__hint.__ptr_->__left_ == nullptr)
20827a984708SDavid Chisnall            {
20837c82a1ecSDimitry Andric                __parent = static_cast<__parent_pointer>(__hint.__ptr_);
20847a984708SDavid Chisnall                return __parent->__left_;
20857a984708SDavid Chisnall            }
20867a984708SDavid Chisnall            else
20877a984708SDavid Chisnall            {
20887c82a1ecSDimitry Andric                __parent = static_cast<__parent_pointer>(__prior.__ptr_);
20897c82a1ecSDimitry Andric                return static_cast<__node_base_pointer>(__prior.__ptr_)->__right_;
20907a984708SDavid Chisnall            }
20917a984708SDavid Chisnall        }
20927a984708SDavid Chisnall        // __v <= *prev(__hint)
20937a984708SDavid Chisnall        return __find_equal(__parent, __v);
20947a984708SDavid Chisnall    }
20957a984708SDavid Chisnall    else if (value_comp()(*__hint, __v))  // check after
20967a984708SDavid Chisnall    {
20977a984708SDavid Chisnall        // *__hint < __v
20987a984708SDavid Chisnall        const_iterator __next = _VSTD::next(__hint);
20997a984708SDavid Chisnall        if (__next == end() || value_comp()(__v, *__next))
21007a984708SDavid Chisnall        {
21017a984708SDavid Chisnall            // *__hint < __v < *_VSTD::next(__hint)
21027c82a1ecSDimitry Andric            if (__hint.__get_np()->__right_ == nullptr)
21037a984708SDavid Chisnall            {
21047c82a1ecSDimitry Andric                __parent = static_cast<__parent_pointer>(__hint.__ptr_);
21057c82a1ecSDimitry Andric                return static_cast<__node_base_pointer>(__hint.__ptr_)->__right_;
21067a984708SDavid Chisnall            }
21077a984708SDavid Chisnall            else
21087a984708SDavid Chisnall            {
21097c82a1ecSDimitry Andric                __parent = static_cast<__parent_pointer>(__next.__ptr_);
21107a984708SDavid Chisnall                return __parent->__left_;
21117a984708SDavid Chisnall            }
21127a984708SDavid Chisnall        }
21137a984708SDavid Chisnall        // *next(__hint) <= __v
21147a984708SDavid Chisnall        return __find_equal(__parent, __v);
21157a984708SDavid Chisnall    }
21167a984708SDavid Chisnall    // else __v == *__hint
21177c82a1ecSDimitry Andric    __parent = static_cast<__parent_pointer>(__hint.__ptr_);
21187c82a1ecSDimitry Andric    __dummy = static_cast<__node_base_pointer>(__hint.__ptr_);
21197c82a1ecSDimitry Andric    return __dummy;
21207a984708SDavid Chisnall}
21217a984708SDavid Chisnall
21227a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
2123*b5893f02SDimitry Andricvoid __tree<_Tp, _Compare, _Allocator>::__insert_node_at(
2124*b5893f02SDimitry Andric    __parent_pointer __parent, __node_base_pointer& __child,
2125*b5893f02SDimitry Andric    __node_base_pointer __new_node) _NOEXCEPT
21267a984708SDavid Chisnall{
21277a984708SDavid Chisnall    __new_node->__left_   = nullptr;
21287a984708SDavid Chisnall    __new_node->__right_  = nullptr;
21297a984708SDavid Chisnall    __new_node->__parent_ = __parent;
21307c82a1ecSDimitry Andric    // __new_node->__is_black_ is initialized in __tree_balance_after_insert
21317a984708SDavid Chisnall    __child = __new_node;
21327a984708SDavid Chisnall    if (__begin_node()->__left_ != nullptr)
21337c82a1ecSDimitry Andric        __begin_node() = static_cast<__iter_pointer>(__begin_node()->__left_);
21347a984708SDavid Chisnall    __tree_balance_after_insert(__end_node()->__left_, __child);
21357a984708SDavid Chisnall    ++size();
21367a984708SDavid Chisnall}
21377a984708SDavid Chisnall
21387c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
21397c82a1ecSDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
21407c82a1ecSDimitry Andrictemplate <class _Key, class... _Args>
21417c82a1ecSDimitry Andricpair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
21427c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args)
21437c82a1ecSDimitry Andric#else
21447c82a1ecSDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
21457c82a1ecSDimitry Andrictemplate <class _Key, class _Args>
21467c82a1ecSDimitry Andricpair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
21477c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args& __args)
21487c82a1ecSDimitry Andric#endif
21497c82a1ecSDimitry Andric{
21507c82a1ecSDimitry Andric    __parent_pointer __parent;
21517c82a1ecSDimitry Andric    __node_base_pointer& __child = __find_equal(__parent, __k);
21527c82a1ecSDimitry Andric    __node_pointer __r = static_cast<__node_pointer>(__child);
21537c82a1ecSDimitry Andric    bool __inserted = false;
21547c82a1ecSDimitry Andric    if (__child == nullptr)
21557c82a1ecSDimitry Andric    {
21567c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
21577c82a1ecSDimitry Andric        __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
21587c82a1ecSDimitry Andric#else
21597c82a1ecSDimitry Andric        __node_holder __h = __construct_node(__args);
21607c82a1ecSDimitry Andric#endif
21617c82a1ecSDimitry Andric        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
21627c82a1ecSDimitry Andric        __r = __h.release();
21637c82a1ecSDimitry Andric        __inserted = true;
21647c82a1ecSDimitry Andric    }
21657c82a1ecSDimitry Andric    return pair<iterator, bool>(iterator(__r), __inserted);
21667c82a1ecSDimitry Andric}
21677c82a1ecSDimitry Andric
21687c82a1ecSDimitry Andric
21697c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
21707c82a1ecSDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
21717c82a1ecSDimitry Andrictemplate <class _Key, class... _Args>
21727c82a1ecSDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::iterator
21737c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args(
21747c82a1ecSDimitry Andric    const_iterator __p, _Key const& __k, _Args&&... __args)
21757c82a1ecSDimitry Andric#else
21767c82a1ecSDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
21777c82a1ecSDimitry Andrictemplate <class _Key, class _Args>
21787c82a1ecSDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::iterator
21797c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args(
21807c82a1ecSDimitry Andric    const_iterator __p, _Key const& __k, _Args& __args)
21817c82a1ecSDimitry Andric#endif
21827c82a1ecSDimitry Andric{
21837c82a1ecSDimitry Andric    __parent_pointer __parent;
21847c82a1ecSDimitry Andric    __node_base_pointer __dummy;
21857c82a1ecSDimitry Andric    __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __k);
21867c82a1ecSDimitry Andric    __node_pointer __r = static_cast<__node_pointer>(__child);
21877c82a1ecSDimitry Andric    if (__child == nullptr)
21887c82a1ecSDimitry Andric    {
21897c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
21907c82a1ecSDimitry Andric        __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
21917c82a1ecSDimitry Andric#else
21927c82a1ecSDimitry Andric        __node_holder __h = __construct_node(__args);
21937c82a1ecSDimitry Andric#endif
21947c82a1ecSDimitry Andric        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
21957c82a1ecSDimitry Andric        __r = __h.release();
21967c82a1ecSDimitry Andric    }
21977c82a1ecSDimitry Andric    return iterator(__r);
21987c82a1ecSDimitry Andric}
21997c82a1ecSDimitry Andric
22007c82a1ecSDimitry Andric
22017c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
22027a984708SDavid Chisnall
22037a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
22047a984708SDavid Chisnalltemplate <class ..._Args>
22057a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::__node_holder
22067a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args)
22077a984708SDavid Chisnall{
22087c82a1ecSDimitry Andric    static_assert(!__is_tree_value_type<_Args...>::value,
22097c82a1ecSDimitry Andric                  "Cannot construct from __value_type");
22107a984708SDavid Chisnall    __node_allocator& __na = __node_alloc();
221194e3ee44SDavid Chisnall    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
22127c82a1ecSDimitry Andric    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...);
22137a984708SDavid Chisnall    __h.get_deleter().__value_constructed = true;
22147a984708SDavid Chisnall    return __h;
22157a984708SDavid Chisnall}
22167a984708SDavid Chisnall
22177c82a1ecSDimitry Andric
22187a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
22197a984708SDavid Chisnalltemplate <class... _Args>
22207a984708SDavid Chisnallpair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
22217c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_Args&&... __args)
22227a984708SDavid Chisnall{
22237a984708SDavid Chisnall    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
22247c82a1ecSDimitry Andric    __parent_pointer __parent;
22257a984708SDavid Chisnall    __node_base_pointer& __child = __find_equal(__parent, __h->__value_);
22267a984708SDavid Chisnall    __node_pointer __r = static_cast<__node_pointer>(__child);
22277a984708SDavid Chisnall    bool __inserted = false;
22287a984708SDavid Chisnall    if (__child == nullptr)
22297a984708SDavid Chisnall    {
22304bab9fd9SDavid Chisnall        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
22317a984708SDavid Chisnall        __r = __h.release();
22327a984708SDavid Chisnall        __inserted = true;
22337a984708SDavid Chisnall    }
22347a984708SDavid Chisnall    return pair<iterator, bool>(iterator(__r), __inserted);
22357a984708SDavid Chisnall}
22367a984708SDavid Chisnall
22377a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
22387a984708SDavid Chisnalltemplate <class... _Args>
22397a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
22407c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_impl(const_iterator __p, _Args&&... __args)
22417a984708SDavid Chisnall{
22427a984708SDavid Chisnall    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
22437c82a1ecSDimitry Andric    __parent_pointer __parent;
22447c82a1ecSDimitry Andric    __node_base_pointer __dummy;
22457c82a1ecSDimitry Andric    __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __h->__value_);
22467a984708SDavid Chisnall    __node_pointer __r = static_cast<__node_pointer>(__child);
22477a984708SDavid Chisnall    if (__child == nullptr)
22487a984708SDavid Chisnall    {
22494bab9fd9SDavid Chisnall        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
22507a984708SDavid Chisnall        __r = __h.release();
22517a984708SDavid Chisnall    }
22527a984708SDavid Chisnall    return iterator(__r);
22537a984708SDavid Chisnall}
22547a984708SDavid Chisnall
22557a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
22567a984708SDavid Chisnalltemplate <class... _Args>
22577a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
22587a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args)
22597a984708SDavid Chisnall{
22607a984708SDavid Chisnall    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
22617c82a1ecSDimitry Andric    __parent_pointer __parent;
22627c82a1ecSDimitry Andric    __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__h->__value_));
22634bab9fd9SDavid Chisnall    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
22647a984708SDavid Chisnall    return iterator(static_cast<__node_pointer>(__h.release()));
22657a984708SDavid Chisnall}
22667a984708SDavid Chisnall
22677a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
22687a984708SDavid Chisnalltemplate <class... _Args>
22697a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
22707a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p,
22717a984708SDavid Chisnall                                                        _Args&&... __args)
22727a984708SDavid Chisnall{
22737a984708SDavid Chisnall    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
22747c82a1ecSDimitry Andric    __parent_pointer __parent;
22757c82a1ecSDimitry Andric    __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__h->__value_));
22764bab9fd9SDavid Chisnall    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
22777a984708SDavid Chisnall    return iterator(static_cast<__node_pointer>(__h.release()));
22787a984708SDavid Chisnall}
22797a984708SDavid Chisnall
22807a984708SDavid Chisnall
22817c82a1ecSDimitry Andric#else  // _LIBCPP_CXX03_LANG
22827a984708SDavid Chisnall
22837a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
22847a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::__node_holder
22857c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__construct_node(const __container_value_type& __v)
22867a984708SDavid Chisnall{
22877a984708SDavid Chisnall    __node_allocator& __na = __node_alloc();
228894e3ee44SDavid Chisnall    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
22897c82a1ecSDimitry Andric    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v);
22907a984708SDavid Chisnall    __h.get_deleter().__value_constructed = true;
22919729cf09SDimitry Andric    return _LIBCPP_EXPLICIT_MOVE(__h);  // explicitly moved for C++03
22927a984708SDavid Chisnall}
22937a984708SDavid Chisnall
22947c82a1ecSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
22957a984708SDavid Chisnall
22967c82a1ecSDimitry Andric#ifdef _LIBCPP_CXX03_LANG
22977a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
22987a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
22997c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__insert_multi(const __container_value_type& __v)
23007a984708SDavid Chisnall{
23017c82a1ecSDimitry Andric    __parent_pointer __parent;
23027c82a1ecSDimitry Andric    __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__v));
23037a984708SDavid Chisnall    __node_holder __h = __construct_node(__v);
23044bab9fd9SDavid Chisnall    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
23057a984708SDavid Chisnall    return iterator(__h.release());
23067a984708SDavid Chisnall}
23077a984708SDavid Chisnall
23087a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
23097a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
23107c82a1ecSDimitry Andric__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const __container_value_type& __v)
23117a984708SDavid Chisnall{
23127c82a1ecSDimitry Andric    __parent_pointer __parent;
23137c82a1ecSDimitry Andric    __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__v));
23147a984708SDavid Chisnall    __node_holder __h = __construct_node(__v);
23154bab9fd9SDavid Chisnall    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
23167a984708SDavid Chisnall    return iterator(__h.release());
23177a984708SDavid Chisnall}
23187c82a1ecSDimitry Andric#endif
23197a984708SDavid Chisnall
23207a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
23217a984708SDavid Chisnallpair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
23227a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd)
23237a984708SDavid Chisnall{
23247c82a1ecSDimitry Andric    __parent_pointer __parent;
23257a984708SDavid Chisnall    __node_base_pointer& __child = __find_equal(__parent, __nd->__value_);
23267a984708SDavid Chisnall    __node_pointer __r = static_cast<__node_pointer>(__child);
23277a984708SDavid Chisnall    bool __inserted = false;
23287a984708SDavid Chisnall    if (__child == nullptr)
23297a984708SDavid Chisnall    {
23304bab9fd9SDavid Chisnall        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
23317a984708SDavid Chisnall        __r = __nd;
23327a984708SDavid Chisnall        __inserted = true;
23337a984708SDavid Chisnall    }
23347a984708SDavid Chisnall    return pair<iterator, bool>(iterator(__r), __inserted);
23357a984708SDavid Chisnall}
23367a984708SDavid Chisnall
23377a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
23387a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
23397a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p,
23407a984708SDavid Chisnall                                                        __node_pointer __nd)
23417a984708SDavid Chisnall{
23427c82a1ecSDimitry Andric    __parent_pointer __parent;
23437c82a1ecSDimitry Andric    __node_base_pointer __dummy;
23447a984708SDavid Chisnall    __node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_);
23457a984708SDavid Chisnall    __node_pointer __r = static_cast<__node_pointer>(__child);
23467a984708SDavid Chisnall    if (__child == nullptr)
23477a984708SDavid Chisnall    {
23484bab9fd9SDavid Chisnall        __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
23497a984708SDavid Chisnall        __r = __nd;
23507a984708SDavid Chisnall    }
23517a984708SDavid Chisnall    return iterator(__r);
23527a984708SDavid Chisnall}
23537a984708SDavid Chisnall
23547a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
23557a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
23567a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd)
23577a984708SDavid Chisnall{
23587c82a1ecSDimitry Andric    __parent_pointer __parent;
23597c82a1ecSDimitry Andric    __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__nd->__value_));
23604bab9fd9SDavid Chisnall    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
23617a984708SDavid Chisnall    return iterator(__nd);
23627a984708SDavid Chisnall}
23637a984708SDavid Chisnall
23647a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
23657a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
23667a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p,
23677a984708SDavid Chisnall                                                       __node_pointer __nd)
23687a984708SDavid Chisnall{
23697c82a1ecSDimitry Andric    __parent_pointer __parent;
23707c82a1ecSDimitry Andric    __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__nd->__value_));
23714bab9fd9SDavid Chisnall    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
23727a984708SDavid Chisnall    return iterator(__nd);
23737a984708SDavid Chisnall}
23747a984708SDavid Chisnall
23757a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
23767a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
2377*b5893f02SDimitry Andric__tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr) _NOEXCEPT
23784ba319b5SDimitry Andric{
23794ba319b5SDimitry Andric    iterator __r(__ptr);
23804ba319b5SDimitry Andric    ++__r;
23814ba319b5SDimitry Andric    if (__begin_node() == __ptr)
23824ba319b5SDimitry Andric        __begin_node() = __r.__ptr_;
23834ba319b5SDimitry Andric    --size();
23844ba319b5SDimitry Andric    __tree_remove(__end_node()->__left_,
23854ba319b5SDimitry Andric                  static_cast<__node_base_pointer>(__ptr));
23864ba319b5SDimitry Andric    return __r;
23874ba319b5SDimitry Andric}
23884ba319b5SDimitry Andric
23894ba319b5SDimitry Andric#if _LIBCPP_STD_VER > 14
23904ba319b5SDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
23914ba319b5SDimitry Andrictemplate <class _NodeHandle, class _InsertReturnType>
23924ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
23934ba319b5SDimitry Andric_InsertReturnType
23944ba319b5SDimitry Andric__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(
23954ba319b5SDimitry Andric    _NodeHandle&& __nh)
23964ba319b5SDimitry Andric{
23974ba319b5SDimitry Andric    if (__nh.empty())
23984ba319b5SDimitry Andric        return _InsertReturnType{end(), false, _NodeHandle()};
23994ba319b5SDimitry Andric
24004ba319b5SDimitry Andric    __node_pointer __ptr = __nh.__ptr_;
24014ba319b5SDimitry Andric    __parent_pointer __parent;
24024ba319b5SDimitry Andric    __node_base_pointer& __child = __find_equal(__parent,
24034ba319b5SDimitry Andric                                                __ptr->__value_);
24044ba319b5SDimitry Andric    if (__child != nullptr)
24054ba319b5SDimitry Andric        return _InsertReturnType{
24064ba319b5SDimitry Andric            iterator(static_cast<__node_pointer>(__child)),
24074ba319b5SDimitry Andric            false, _VSTD::move(__nh)};
24084ba319b5SDimitry Andric
24094ba319b5SDimitry Andric    __insert_node_at(__parent, __child,
24104ba319b5SDimitry Andric                     static_cast<__node_base_pointer>(__ptr));
24114ba319b5SDimitry Andric    __nh.__release();
24124ba319b5SDimitry Andric    return _InsertReturnType{iterator(__ptr), true, _NodeHandle()};
24134ba319b5SDimitry Andric}
24144ba319b5SDimitry Andric
24154ba319b5SDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
24164ba319b5SDimitry Andrictemplate <class _NodeHandle>
24174ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
24184ba319b5SDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::iterator
24194ba319b5SDimitry Andric__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(
24204ba319b5SDimitry Andric    const_iterator __hint, _NodeHandle&& __nh)
24214ba319b5SDimitry Andric{
24224ba319b5SDimitry Andric    if (__nh.empty())
24234ba319b5SDimitry Andric        return end();
24244ba319b5SDimitry Andric
24254ba319b5SDimitry Andric    __node_pointer __ptr = __nh.__ptr_;
24264ba319b5SDimitry Andric    __parent_pointer __parent;
24274ba319b5SDimitry Andric    __node_base_pointer __dummy;
24284ba319b5SDimitry Andric    __node_base_pointer& __child = __find_equal(__hint, __parent, __dummy,
24294ba319b5SDimitry Andric                                                __ptr->__value_);
24304ba319b5SDimitry Andric    __node_pointer __r = static_cast<__node_pointer>(__child);
24314ba319b5SDimitry Andric    if (__child == nullptr)
24324ba319b5SDimitry Andric    {
24334ba319b5SDimitry Andric        __insert_node_at(__parent, __child,
24344ba319b5SDimitry Andric                         static_cast<__node_base_pointer>(__ptr));
24354ba319b5SDimitry Andric        __r = __ptr;
24364ba319b5SDimitry Andric        __nh.__release();
24374ba319b5SDimitry Andric    }
24384ba319b5SDimitry Andric    return iterator(__r);
24394ba319b5SDimitry Andric}
24404ba319b5SDimitry Andric
24414ba319b5SDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
24424ba319b5SDimitry Andrictemplate <class _NodeHandle>
24434ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
24444ba319b5SDimitry Andric_NodeHandle
24454ba319b5SDimitry Andric__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key)
24464ba319b5SDimitry Andric{
24474ba319b5SDimitry Andric    iterator __it = find(__key);
24484ba319b5SDimitry Andric    if (__it == end())
24494ba319b5SDimitry Andric        return _NodeHandle();
24504ba319b5SDimitry Andric    return __node_handle_extract<_NodeHandle>(__it);
24514ba319b5SDimitry Andric}
24524ba319b5SDimitry Andric
24534ba319b5SDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
24544ba319b5SDimitry Andrictemplate <class _NodeHandle>
24554ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
24564ba319b5SDimitry Andric_NodeHandle
24574ba319b5SDimitry Andric__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const_iterator __p)
24584ba319b5SDimitry Andric{
24594ba319b5SDimitry Andric    __node_pointer __np = __p.__get_np();
24604ba319b5SDimitry Andric    __remove_node_pointer(__np);
24614ba319b5SDimitry Andric    return _NodeHandle(__np, __alloc());
24624ba319b5SDimitry Andric}
24634ba319b5SDimitry Andric
24644ba319b5SDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
2465*b5893f02SDimitry Andrictemplate <class _Tree>
2466*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY
2467*b5893f02SDimitry Andricvoid
2468*b5893f02SDimitry Andric__tree<_Tp, _Compare, _Allocator>::__node_handle_merge_unique(_Tree& __source)
2469*b5893f02SDimitry Andric{
2470*b5893f02SDimitry Andric    static_assert(is_same<typename _Tree::__node_pointer, __node_pointer>::value, "");
2471*b5893f02SDimitry Andric
2472*b5893f02SDimitry Andric    for (typename _Tree::iterator __i = __source.begin();
2473*b5893f02SDimitry Andric         __i != __source.end();)
2474*b5893f02SDimitry Andric    {
2475*b5893f02SDimitry Andric        __node_pointer __src_ptr = __i.__get_np();
2476*b5893f02SDimitry Andric        __parent_pointer __parent;
2477*b5893f02SDimitry Andric        __node_base_pointer& __child =
2478*b5893f02SDimitry Andric            __find_equal(__parent, _NodeTypes::__get_key(__src_ptr->__value_));
2479*b5893f02SDimitry Andric        ++__i;
2480*b5893f02SDimitry Andric        if (__child != nullptr)
2481*b5893f02SDimitry Andric            continue;
2482*b5893f02SDimitry Andric        __source.__remove_node_pointer(__src_ptr);
2483*b5893f02SDimitry Andric        __insert_node_at(__parent, __child,
2484*b5893f02SDimitry Andric                         static_cast<__node_base_pointer>(__src_ptr));
2485*b5893f02SDimitry Andric    }
2486*b5893f02SDimitry Andric}
2487*b5893f02SDimitry Andric
2488*b5893f02SDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
24894ba319b5SDimitry Andrictemplate <class _NodeHandle>
24904ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
24914ba319b5SDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::iterator
24924ba319b5SDimitry Andric__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(_NodeHandle&& __nh)
24934ba319b5SDimitry Andric{
24944ba319b5SDimitry Andric    if (__nh.empty())
24954ba319b5SDimitry Andric        return end();
24964ba319b5SDimitry Andric    __node_pointer __ptr = __nh.__ptr_;
24974ba319b5SDimitry Andric    __parent_pointer __parent;
24984ba319b5SDimitry Andric    __node_base_pointer& __child = __find_leaf_high(
24994ba319b5SDimitry Andric        __parent, _NodeTypes::__get_key(__ptr->__value_));
25004ba319b5SDimitry Andric    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
25014ba319b5SDimitry Andric    __nh.__release();
25024ba319b5SDimitry Andric    return iterator(__ptr);
25034ba319b5SDimitry Andric}
25044ba319b5SDimitry Andric
25054ba319b5SDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
25064ba319b5SDimitry Andrictemplate <class _NodeHandle>
25074ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
25084ba319b5SDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::iterator
25094ba319b5SDimitry Andric__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(
25104ba319b5SDimitry Andric    const_iterator __hint, _NodeHandle&& __nh)
25114ba319b5SDimitry Andric{
25124ba319b5SDimitry Andric    if (__nh.empty())
25134ba319b5SDimitry Andric        return end();
25144ba319b5SDimitry Andric
25154ba319b5SDimitry Andric    __node_pointer __ptr = __nh.__ptr_;
25164ba319b5SDimitry Andric    __parent_pointer __parent;
25174ba319b5SDimitry Andric    __node_base_pointer& __child = __find_leaf(__hint, __parent,
25184ba319b5SDimitry Andric                                               _NodeTypes::__get_key(__ptr->__value_));
25194ba319b5SDimitry Andric    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
25204ba319b5SDimitry Andric    __nh.__release();
25214ba319b5SDimitry Andric    return iterator(__ptr);
25224ba319b5SDimitry Andric}
25234ba319b5SDimitry Andric
2524*b5893f02SDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
2525*b5893f02SDimitry Andrictemplate <class _Tree>
2526*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY
2527*b5893f02SDimitry Andricvoid
2528*b5893f02SDimitry Andric__tree<_Tp, _Compare, _Allocator>::__node_handle_merge_multi(_Tree& __source)
2529*b5893f02SDimitry Andric{
2530*b5893f02SDimitry Andric    static_assert(is_same<typename _Tree::__node_pointer, __node_pointer>::value, "");
2531*b5893f02SDimitry Andric
2532*b5893f02SDimitry Andric    for (typename _Tree::iterator __i = __source.begin();
2533*b5893f02SDimitry Andric         __i != __source.end();)
2534*b5893f02SDimitry Andric    {
2535*b5893f02SDimitry Andric        __node_pointer __src_ptr = __i.__get_np();
2536*b5893f02SDimitry Andric        __parent_pointer __parent;
2537*b5893f02SDimitry Andric        __node_base_pointer& __child = __find_leaf_high(
2538*b5893f02SDimitry Andric            __parent, _NodeTypes::__get_key(__src_ptr->__value_));
2539*b5893f02SDimitry Andric        ++__i;
2540*b5893f02SDimitry Andric        __source.__remove_node_pointer(__src_ptr);
2541*b5893f02SDimitry Andric        __insert_node_at(__parent, __child,
2542*b5893f02SDimitry Andric                         static_cast<__node_base_pointer>(__src_ptr));
2543*b5893f02SDimitry Andric    }
2544*b5893f02SDimitry Andric}
2545*b5893f02SDimitry Andric
25464ba319b5SDimitry Andric#endif  // _LIBCPP_STD_VER > 14
25474ba319b5SDimitry Andric
25484ba319b5SDimitry Andrictemplate <class _Tp, class _Compare, class _Allocator>
25494ba319b5SDimitry Andrictypename __tree<_Tp, _Compare, _Allocator>::iterator
25507a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p)
25517a984708SDavid Chisnall{
25527c82a1ecSDimitry Andric    __node_pointer __np = __p.__get_np();
25534ba319b5SDimitry Andric    iterator __r = __remove_node_pointer(__np);
25547a984708SDavid Chisnall    __node_allocator& __na = __node_alloc();
25557c82a1ecSDimitry Andric    __node_traits::destroy(__na, _NodeTypes::__get_ptr(
25567c82a1ecSDimitry Andric        const_cast<__node_value_type&>(*__p)));
25577a984708SDavid Chisnall    __node_traits::deallocate(__na, __np, 1);
25587a984708SDavid Chisnall    return __r;
25597a984708SDavid Chisnall}
25607a984708SDavid Chisnall
25617a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
25627a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
25637a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l)
25647a984708SDavid Chisnall{
25657a984708SDavid Chisnall    while (__f != __l)
25667a984708SDavid Chisnall        __f = erase(__f);
25674bab9fd9SDavid Chisnall    return iterator(__l.__ptr_);
25687a984708SDavid Chisnall}
25697a984708SDavid Chisnall
25707a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
25717a984708SDavid Chisnalltemplate <class _Key>
25727a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::size_type
25737a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k)
25747a984708SDavid Chisnall{
25757a984708SDavid Chisnall    iterator __i = find(__k);
25767a984708SDavid Chisnall    if (__i == end())
25777a984708SDavid Chisnall        return 0;
25787a984708SDavid Chisnall    erase(__i);
25797a984708SDavid Chisnall    return 1;
25807a984708SDavid Chisnall}
25817a984708SDavid Chisnall
25827a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
25837a984708SDavid Chisnalltemplate <class _Key>
25847a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::size_type
25857a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k)
25867a984708SDavid Chisnall{
25877a984708SDavid Chisnall    pair<iterator, iterator> __p = __equal_range_multi(__k);
25887a984708SDavid Chisnall    size_type __r = 0;
25897a984708SDavid Chisnall    for (; __p.first != __p.second; ++__r)
25907a984708SDavid Chisnall        __p.first = erase(__p.first);
25917a984708SDavid Chisnall    return __r;
25927a984708SDavid Chisnall}
25937a984708SDavid Chisnall
25947a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
25957a984708SDavid Chisnalltemplate <class _Key>
25967a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
25977a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v)
25987a984708SDavid Chisnall{
25997a984708SDavid Chisnall    iterator __p = __lower_bound(__v, __root(), __end_node());
26007a984708SDavid Chisnall    if (__p != end() && !value_comp()(__v, *__p))
26017a984708SDavid Chisnall        return __p;
26027a984708SDavid Chisnall    return end();
26037a984708SDavid Chisnall}
26047a984708SDavid Chisnall
26057a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
26067a984708SDavid Chisnalltemplate <class _Key>
26077a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::const_iterator
26087a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) const
26097a984708SDavid Chisnall{
26107a984708SDavid Chisnall    const_iterator __p = __lower_bound(__v, __root(), __end_node());
26117a984708SDavid Chisnall    if (__p != end() && !value_comp()(__v, *__p))
26127a984708SDavid Chisnall        return __p;
26137a984708SDavid Chisnall    return end();
26147a984708SDavid Chisnall}
26157a984708SDavid Chisnall
26167a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
26177a984708SDavid Chisnalltemplate <class _Key>
26187a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::size_type
26197a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const
26207a984708SDavid Chisnall{
26217c82a1ecSDimitry Andric    __node_pointer __rt = __root();
26227a984708SDavid Chisnall    while (__rt != nullptr)
26237a984708SDavid Chisnall    {
26247a984708SDavid Chisnall        if (value_comp()(__k, __rt->__value_))
26257a984708SDavid Chisnall        {
26267c82a1ecSDimitry Andric            __rt = static_cast<__node_pointer>(__rt->__left_);
26277a984708SDavid Chisnall        }
26287a984708SDavid Chisnall        else if (value_comp()(__rt->__value_, __k))
26297c82a1ecSDimitry Andric            __rt = static_cast<__node_pointer>(__rt->__right_);
26307a984708SDavid Chisnall        else
26317a984708SDavid Chisnall            return 1;
26327a984708SDavid Chisnall    }
26337a984708SDavid Chisnall    return 0;
26347a984708SDavid Chisnall}
26357a984708SDavid Chisnall
26367a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
26377a984708SDavid Chisnalltemplate <class _Key>
26387a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::size_type
26397a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const
26407a984708SDavid Chisnall{
26417c82a1ecSDimitry Andric    __iter_pointer __result = __end_node();
26427c82a1ecSDimitry Andric    __node_pointer __rt = __root();
26437a984708SDavid Chisnall    while (__rt != nullptr)
26447a984708SDavid Chisnall    {
26457a984708SDavid Chisnall        if (value_comp()(__k, __rt->__value_))
26467a984708SDavid Chisnall        {
26477c82a1ecSDimitry Andric            __result = static_cast<__iter_pointer>(__rt);
26487c82a1ecSDimitry Andric            __rt = static_cast<__node_pointer>(__rt->__left_);
26497a984708SDavid Chisnall        }
26507a984708SDavid Chisnall        else if (value_comp()(__rt->__value_, __k))
26517c82a1ecSDimitry Andric            __rt = static_cast<__node_pointer>(__rt->__right_);
26527a984708SDavid Chisnall        else
26537a984708SDavid Chisnall            return _VSTD::distance(
26547c82a1ecSDimitry Andric                __lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__iter_pointer>(__rt)),
26557c82a1ecSDimitry Andric                __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result)
26567a984708SDavid Chisnall            );
26577a984708SDavid Chisnall    }
26587a984708SDavid Chisnall    return 0;
26597a984708SDavid Chisnall}
26607a984708SDavid Chisnall
26617a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
26627a984708SDavid Chisnalltemplate <class _Key>
26637a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
26647a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
26657a984708SDavid Chisnall                                                 __node_pointer __root,
26667c82a1ecSDimitry Andric                                                 __iter_pointer __result)
26677a984708SDavid Chisnall{
26687a984708SDavid Chisnall    while (__root != nullptr)
26697a984708SDavid Chisnall    {
26707a984708SDavid Chisnall        if (!value_comp()(__root->__value_, __v))
26717a984708SDavid Chisnall        {
26727c82a1ecSDimitry Andric            __result = static_cast<__iter_pointer>(__root);
26737a984708SDavid Chisnall            __root = static_cast<__node_pointer>(__root->__left_);
26747a984708SDavid Chisnall        }
26757a984708SDavid Chisnall        else
26767a984708SDavid Chisnall            __root = static_cast<__node_pointer>(__root->__right_);
26777a984708SDavid Chisnall    }
26787a984708SDavid Chisnall    return iterator(__result);
26797a984708SDavid Chisnall}
26807a984708SDavid Chisnall
26817a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
26827a984708SDavid Chisnalltemplate <class _Key>
26837a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::const_iterator
26847a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
26857c82a1ecSDimitry Andric                                                 __node_pointer __root,
26867c82a1ecSDimitry Andric                                                 __iter_pointer __result) const
26877a984708SDavid Chisnall{
26887a984708SDavid Chisnall    while (__root != nullptr)
26897a984708SDavid Chisnall    {
26907a984708SDavid Chisnall        if (!value_comp()(__root->__value_, __v))
26917a984708SDavid Chisnall        {
26927c82a1ecSDimitry Andric            __result = static_cast<__iter_pointer>(__root);
26937c82a1ecSDimitry Andric            __root = static_cast<__node_pointer>(__root->__left_);
26947a984708SDavid Chisnall        }
26957a984708SDavid Chisnall        else
26967c82a1ecSDimitry Andric            __root = static_cast<__node_pointer>(__root->__right_);
26977a984708SDavid Chisnall    }
26987a984708SDavid Chisnall    return const_iterator(__result);
26997a984708SDavid Chisnall}
27007a984708SDavid Chisnall
27017a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
27027a984708SDavid Chisnalltemplate <class _Key>
27037a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::iterator
27047a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
27057a984708SDavid Chisnall                                                 __node_pointer __root,
27067c82a1ecSDimitry Andric                                                 __iter_pointer __result)
27077a984708SDavid Chisnall{
27087a984708SDavid Chisnall    while (__root != nullptr)
27097a984708SDavid Chisnall    {
27107a984708SDavid Chisnall        if (value_comp()(__v, __root->__value_))
27117a984708SDavid Chisnall        {
27127c82a1ecSDimitry Andric            __result = static_cast<__iter_pointer>(__root);
27137a984708SDavid Chisnall            __root = static_cast<__node_pointer>(__root->__left_);
27147a984708SDavid Chisnall        }
27157a984708SDavid Chisnall        else
27167a984708SDavid Chisnall            __root = static_cast<__node_pointer>(__root->__right_);
27177a984708SDavid Chisnall    }
27187a984708SDavid Chisnall    return iterator(__result);
27197a984708SDavid Chisnall}
27207a984708SDavid Chisnall
27217a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
27227a984708SDavid Chisnalltemplate <class _Key>
27237a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::const_iterator
27247a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
27257c82a1ecSDimitry Andric                                                 __node_pointer __root,
27267c82a1ecSDimitry Andric                                                 __iter_pointer __result) const
27277a984708SDavid Chisnall{
27287a984708SDavid Chisnall    while (__root != nullptr)
27297a984708SDavid Chisnall    {
27307a984708SDavid Chisnall        if (value_comp()(__v, __root->__value_))
27317a984708SDavid Chisnall        {
27327c82a1ecSDimitry Andric            __result = static_cast<__iter_pointer>(__root);
27337c82a1ecSDimitry Andric            __root = static_cast<__node_pointer>(__root->__left_);
27347a984708SDavid Chisnall        }
27357a984708SDavid Chisnall        else
27367c82a1ecSDimitry Andric            __root = static_cast<__node_pointer>(__root->__right_);
27377a984708SDavid Chisnall    }
27387a984708SDavid Chisnall    return const_iterator(__result);
27397a984708SDavid Chisnall}
27407a984708SDavid Chisnall
27417a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
27427a984708SDavid Chisnalltemplate <class _Key>
27437a984708SDavid Chisnallpair<typename __tree<_Tp, _Compare, _Allocator>::iterator,
27447a984708SDavid Chisnall     typename __tree<_Tp, _Compare, _Allocator>::iterator>
27457a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k)
27467a984708SDavid Chisnall{
274794e3ee44SDavid Chisnall    typedef pair<iterator, iterator> _Pp;
27487c82a1ecSDimitry Andric    __iter_pointer __result = __end_node();
27497a984708SDavid Chisnall    __node_pointer __rt = __root();
27507a984708SDavid Chisnall    while (__rt != nullptr)
27517a984708SDavid Chisnall    {
27527a984708SDavid Chisnall        if (value_comp()(__k, __rt->__value_))
27537a984708SDavid Chisnall        {
27547c82a1ecSDimitry Andric            __result = static_cast<__iter_pointer>(__rt);
27557a984708SDavid Chisnall            __rt = static_cast<__node_pointer>(__rt->__left_);
27567a984708SDavid Chisnall        }
27577a984708SDavid Chisnall        else if (value_comp()(__rt->__value_, __k))
27587a984708SDavid Chisnall            __rt = static_cast<__node_pointer>(__rt->__right_);
27597a984708SDavid Chisnall        else
276094e3ee44SDavid Chisnall            return _Pp(iterator(__rt),
27617a984708SDavid Chisnall                      iterator(
27627a984708SDavid Chisnall                          __rt->__right_ != nullptr ?
27637c82a1ecSDimitry Andric                              static_cast<__iter_pointer>(__tree_min(__rt->__right_))
27647a984708SDavid Chisnall                            : __result));
27657a984708SDavid Chisnall    }
276694e3ee44SDavid Chisnall    return _Pp(iterator(__result), iterator(__result));
27677a984708SDavid Chisnall}
27687a984708SDavid Chisnall
27697a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
27707a984708SDavid Chisnalltemplate <class _Key>
27717a984708SDavid Chisnallpair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
27727a984708SDavid Chisnall     typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
27737a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const
27747a984708SDavid Chisnall{
277594e3ee44SDavid Chisnall    typedef pair<const_iterator, const_iterator> _Pp;
27767c82a1ecSDimitry Andric    __iter_pointer __result = __end_node();
27777c82a1ecSDimitry Andric    __node_pointer __rt = __root();
27787a984708SDavid Chisnall    while (__rt != nullptr)
27797a984708SDavid Chisnall    {
27807a984708SDavid Chisnall        if (value_comp()(__k, __rt->__value_))
27817a984708SDavid Chisnall        {
27827c82a1ecSDimitry Andric            __result = static_cast<__iter_pointer>(__rt);
27837c82a1ecSDimitry Andric            __rt = static_cast<__node_pointer>(__rt->__left_);
27847a984708SDavid Chisnall        }
27857a984708SDavid Chisnall        else if (value_comp()(__rt->__value_, __k))
27867c82a1ecSDimitry Andric            __rt = static_cast<__node_pointer>(__rt->__right_);
27877a984708SDavid Chisnall        else
278894e3ee44SDavid Chisnall            return _Pp(const_iterator(__rt),
27897a984708SDavid Chisnall                      const_iterator(
27907a984708SDavid Chisnall                          __rt->__right_ != nullptr ?
27917c82a1ecSDimitry Andric                              static_cast<__iter_pointer>(__tree_min(__rt->__right_))
27927a984708SDavid Chisnall                            : __result));
27937a984708SDavid Chisnall    }
279494e3ee44SDavid Chisnall    return _Pp(const_iterator(__result), const_iterator(__result));
27957a984708SDavid Chisnall}
27967a984708SDavid Chisnall
27977a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
27987a984708SDavid Chisnalltemplate <class _Key>
27997a984708SDavid Chisnallpair<typename __tree<_Tp, _Compare, _Allocator>::iterator,
28007a984708SDavid Chisnall     typename __tree<_Tp, _Compare, _Allocator>::iterator>
28017a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k)
28027a984708SDavid Chisnall{
280394e3ee44SDavid Chisnall    typedef pair<iterator, iterator> _Pp;
28047c82a1ecSDimitry Andric    __iter_pointer __result = __end_node();
28057a984708SDavid Chisnall    __node_pointer __rt = __root();
28067a984708SDavid Chisnall    while (__rt != nullptr)
28077a984708SDavid Chisnall    {
28087a984708SDavid Chisnall        if (value_comp()(__k, __rt->__value_))
28097a984708SDavid Chisnall        {
28107c82a1ecSDimitry Andric            __result = static_cast<__iter_pointer>(__rt);
28117a984708SDavid Chisnall            __rt = static_cast<__node_pointer>(__rt->__left_);
28127a984708SDavid Chisnall        }
28137a984708SDavid Chisnall        else if (value_comp()(__rt->__value_, __k))
28147a984708SDavid Chisnall            __rt = static_cast<__node_pointer>(__rt->__right_);
28157a984708SDavid Chisnall        else
28167c82a1ecSDimitry Andric            return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__iter_pointer>(__rt)),
28177a984708SDavid Chisnall                      __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
28187a984708SDavid Chisnall    }
281994e3ee44SDavid Chisnall    return _Pp(iterator(__result), iterator(__result));
28207a984708SDavid Chisnall}
28217a984708SDavid Chisnall
28227a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
28237a984708SDavid Chisnalltemplate <class _Key>
28247a984708SDavid Chisnallpair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator,
28257a984708SDavid Chisnall     typename __tree<_Tp, _Compare, _Allocator>::const_iterator>
28267a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const
28277a984708SDavid Chisnall{
282894e3ee44SDavid Chisnall    typedef pair<const_iterator, const_iterator> _Pp;
28297c82a1ecSDimitry Andric    __iter_pointer __result = __end_node();
28307c82a1ecSDimitry Andric    __node_pointer __rt = __root();
28317a984708SDavid Chisnall    while (__rt != nullptr)
28327a984708SDavid Chisnall    {
28337a984708SDavid Chisnall        if (value_comp()(__k, __rt->__value_))
28347a984708SDavid Chisnall        {
28357c82a1ecSDimitry Andric            __result = static_cast<__iter_pointer>(__rt);
28367c82a1ecSDimitry Andric            __rt = static_cast<__node_pointer>(__rt->__left_);
28377a984708SDavid Chisnall        }
28387a984708SDavid Chisnall        else if (value_comp()(__rt->__value_, __k))
28397c82a1ecSDimitry Andric            __rt = static_cast<__node_pointer>(__rt->__right_);
28407a984708SDavid Chisnall        else
28417c82a1ecSDimitry Andric            return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__iter_pointer>(__rt)),
28427c82a1ecSDimitry Andric                      __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
28437a984708SDavid Chisnall    }
284494e3ee44SDavid Chisnall    return _Pp(const_iterator(__result), const_iterator(__result));
28457a984708SDavid Chisnall}
28467a984708SDavid Chisnall
28477a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
28487a984708SDavid Chisnalltypename __tree<_Tp, _Compare, _Allocator>::__node_holder
28497a984708SDavid Chisnall__tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT
28507a984708SDavid Chisnall{
28517c82a1ecSDimitry Andric    __node_pointer __np = __p.__get_np();
28527c82a1ecSDimitry Andric    if (__begin_node() == __p.__ptr_)
28537a984708SDavid Chisnall    {
28547a984708SDavid Chisnall        if (__np->__right_ != nullptr)
28557c82a1ecSDimitry Andric            __begin_node() = static_cast<__iter_pointer>(__np->__right_);
28567a984708SDavid Chisnall        else
28577c82a1ecSDimitry Andric            __begin_node() = static_cast<__iter_pointer>(__np->__parent_);
28587a984708SDavid Chisnall    }
28597a984708SDavid Chisnall    --size();
28607a984708SDavid Chisnall    __tree_remove(__end_node()->__left_,
28617a984708SDavid Chisnall                  static_cast<__node_base_pointer>(__np));
2862854fa44bSDimitry Andric    return __node_holder(__np, _Dp(__node_alloc(), true));
28637a984708SDavid Chisnall}
28647a984708SDavid Chisnall
28657a984708SDavid Chisnalltemplate <class _Tp, class _Compare, class _Allocator>
28667a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
28677a984708SDavid Chisnallvoid
28687a984708SDavid Chisnallswap(__tree<_Tp, _Compare, _Allocator>& __x,
28697a984708SDavid Chisnall     __tree<_Tp, _Compare, _Allocator>& __y)
28707a984708SDavid Chisnall    _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
28717a984708SDavid Chisnall{
28727a984708SDavid Chisnall    __x.swap(__y);
28737a984708SDavid Chisnall}
28747a984708SDavid Chisnall
28757a984708SDavid Chisnall_LIBCPP_END_NAMESPACE_STD
28767a984708SDavid Chisnall
2877f9448bf3SDimitry Andric_LIBCPP_POP_MACROS
2878f9448bf3SDimitry Andric
28797a984708SDavid Chisnall#endif  // _LIBCPP___TREE
2880