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__HASH_TABLE
127a984708SDavid Chisnall#define _LIBCPP__HASH_TABLE
137a984708SDavid Chisnall
147a984708SDavid Chisnall#include <__config>
157a984708SDavid Chisnall#include <initializer_list>
167a984708SDavid Chisnall#include <memory>
177a984708SDavid Chisnall#include <iterator>
187a984708SDavid Chisnall#include <algorithm>
197a984708SDavid Chisnall#include <cmath>
207c82a1ecSDimitry Andric#include <utility>
21540d2a8bSDimitry Andric#include <type_traits>
227a984708SDavid Chisnall
234f7ab58eSDimitry Andric#include <__debug>
244f7ab58eSDimitry Andric
257a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
267a984708SDavid Chisnall#pragma GCC system_header
277a984708SDavid Chisnall#endif
287a984708SDavid Chisnall
29f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS
30f9448bf3SDimitry Andric#include <__undef_macros>
317a984708SDavid Chisnall
327c82a1ecSDimitry Andric
33f9448bf3SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
34f9448bf3SDimitry Andric
357c82a1ecSDimitry Andrictemplate <class _Key, class _Tp>
367c82a1ecSDimitry Andricstruct __hash_value_type;
377c82a1ecSDimitry Andric
387c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
397c82a1ecSDimitry Andrictemplate <class _Tp>
407c82a1ecSDimitry Andricstruct __is_hash_value_type_imp : false_type {};
417c82a1ecSDimitry Andric
427c82a1ecSDimitry Andrictemplate <class _Key, class _Value>
437c82a1ecSDimitry Andricstruct __is_hash_value_type_imp<__hash_value_type<_Key, _Value>> : true_type {};
447c82a1ecSDimitry Andric
457c82a1ecSDimitry Andrictemplate <class ..._Args>
467c82a1ecSDimitry Andricstruct __is_hash_value_type : false_type {};
477c82a1ecSDimitry Andric
487c82a1ecSDimitry Andrictemplate <class _One>
497c82a1ecSDimitry Andricstruct __is_hash_value_type<_One> : __is_hash_value_type_imp<typename __uncvref<_One>::type> {};
507c82a1ecSDimitry Andric#endif
517c82a1ecSDimitry Andric
521bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS
537a984708SDavid Chisnallsize_t __next_prime(size_t __n);
547a984708SDavid Chisnall
557a984708SDavid Chisnalltemplate <class _NodePtr>
567a984708SDavid Chisnallstruct __hash_node_base
577a984708SDavid Chisnall{
58aed8d94eSDimitry Andric    typedef typename pointer_traits<_NodePtr>::element_type __node_type;
597a984708SDavid Chisnall    typedef __hash_node_base __first_node;
60aed8d94eSDimitry Andric    typedef typename __rebind_pointer<_NodePtr, __first_node>::type __node_base_pointer;
61aed8d94eSDimitry Andric    typedef _NodePtr __node_pointer;
627a984708SDavid Chisnall
63aed8d94eSDimitry Andric#if defined(_LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB)
64aed8d94eSDimitry Andric  typedef __node_base_pointer __next_pointer;
65aed8d94eSDimitry Andric#else
66aed8d94eSDimitry Andric  typedef typename conditional<
67aed8d94eSDimitry Andric      is_pointer<__node_pointer>::value,
68aed8d94eSDimitry Andric      __node_base_pointer,
69aed8d94eSDimitry Andric      __node_pointer>::type   __next_pointer;
70aed8d94eSDimitry Andric#endif
71aed8d94eSDimitry Andric
72aed8d94eSDimitry Andric    __next_pointer    __next_;
73aed8d94eSDimitry Andric
74aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
75aed8d94eSDimitry Andric    __next_pointer __ptr() _NOEXCEPT {
76aed8d94eSDimitry Andric        return static_cast<__next_pointer>(
77aed8d94eSDimitry Andric            pointer_traits<__node_base_pointer>::pointer_to(*this));
78aed8d94eSDimitry Andric    }
79aed8d94eSDimitry Andric
80aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
81aed8d94eSDimitry Andric    __node_pointer __upcast() _NOEXCEPT {
82aed8d94eSDimitry Andric        return static_cast<__node_pointer>(
83aed8d94eSDimitry Andric            pointer_traits<__node_base_pointer>::pointer_to(*this));
84aed8d94eSDimitry Andric    }
85aed8d94eSDimitry Andric
86aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
87aed8d94eSDimitry Andric    size_t __hash() const _NOEXCEPT {
88aed8d94eSDimitry Andric        return static_cast<__node_type const&>(*this).__hash_;
89aed8d94eSDimitry Andric    }
907a984708SDavid Chisnall
917a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
927a984708SDavid Chisnall};
937a984708SDavid Chisnall
947a984708SDavid Chisnalltemplate <class _Tp, class _VoidPtr>
957a984708SDavid Chisnallstruct __hash_node
967a984708SDavid Chisnall    : public __hash_node_base
977a984708SDavid Chisnall             <
989729cf09SDimitry Andric                 typename __rebind_pointer<_VoidPtr, __hash_node<_Tp, _VoidPtr> >::type
997a984708SDavid Chisnall             >
1007a984708SDavid Chisnall{
1017c82a1ecSDimitry Andric    typedef _Tp __node_value_type;
1027a984708SDavid Chisnall
1037a984708SDavid Chisnall    size_t            __hash_;
1047c82a1ecSDimitry Andric    __node_value_type __value_;
1057a984708SDavid Chisnall};
1067a984708SDavid Chisnall
107936e9439SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
108936e9439SDimitry Andricbool
109854fa44bSDimitry Andric__is_hash_power2(size_t __bc)
110936e9439SDimitry Andric{
111936e9439SDimitry Andric    return __bc > 2 && !(__bc & (__bc - 1));
112936e9439SDimitry Andric}
113936e9439SDimitry Andric
114936e9439SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
115936e9439SDimitry Andricsize_t
116936e9439SDimitry Andric__constrain_hash(size_t __h, size_t __bc)
117936e9439SDimitry Andric{
1187c82a1ecSDimitry Andric    return !(__bc & (__bc - 1)) ? __h & (__bc - 1) :
1197c82a1ecSDimitry Andric        (__h < __bc ? __h : __h % __bc);
120936e9439SDimitry Andric}
121936e9439SDimitry Andric
122936e9439SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
123936e9439SDimitry Andricsize_t
124854fa44bSDimitry Andric__next_hash_pow2(size_t __n)
125936e9439SDimitry Andric{
1266d97bb29SDimitry Andric    return __n < 2 ? __n : (size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1)));
127936e9439SDimitry Andric}
128936e9439SDimitry Andric
1297c82a1ecSDimitry Andric
1307a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
1317c82a1ecSDimitry Andric
132aed8d94eSDimitry Andrictemplate <class _NodePtr>      class _LIBCPP_TEMPLATE_VIS __hash_iterator;
133aed8d94eSDimitry Andrictemplate <class _ConstNodePtr> class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
134aed8d94eSDimitry Andrictemplate <class _NodePtr>      class _LIBCPP_TEMPLATE_VIS __hash_local_iterator;
135aed8d94eSDimitry Andrictemplate <class _ConstNodePtr> class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
136aed8d94eSDimitry Andrictemplate <class _HashIterator> class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
137aed8d94eSDimitry Andrictemplate <class _HashIterator> class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
1387a984708SDavid Chisnall
1397c82a1ecSDimitry Andrictemplate <class _Tp>
1407c82a1ecSDimitry Andricstruct __hash_key_value_types {
1417c82a1ecSDimitry Andric  static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, "");
1427c82a1ecSDimitry Andric  typedef _Tp key_type;
1437c82a1ecSDimitry Andric  typedef _Tp __node_value_type;
1447c82a1ecSDimitry Andric  typedef _Tp __container_value_type;
1457c82a1ecSDimitry Andric  static const bool __is_map = false;
1467c82a1ecSDimitry Andric
1477c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
1487c82a1ecSDimitry Andric  static key_type const& __get_key(_Tp const& __v) {
1497c82a1ecSDimitry Andric    return __v;
1507c82a1ecSDimitry Andric  }
1517c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
1527c82a1ecSDimitry Andric  static __container_value_type const& __get_value(__node_value_type const& __v) {
1537c82a1ecSDimitry Andric    return __v;
1547c82a1ecSDimitry Andric  }
1557c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
1567c82a1ecSDimitry Andric  static __container_value_type* __get_ptr(__node_value_type& __n) {
1577c82a1ecSDimitry Andric    return _VSTD::addressof(__n);
1587c82a1ecSDimitry Andric  }
1597c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
1607c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
1617c82a1ecSDimitry Andric  static __container_value_type&& __move(__node_value_type& __v) {
1627c82a1ecSDimitry Andric    return _VSTD::move(__v);
1637c82a1ecSDimitry Andric  }
1647c82a1ecSDimitry Andric#endif
1657c82a1ecSDimitry Andric};
1667c82a1ecSDimitry Andric
1677c82a1ecSDimitry Andrictemplate <class _Key, class _Tp>
1687c82a1ecSDimitry Andricstruct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
1697c82a1ecSDimitry Andric  typedef _Key                                         key_type;
1707c82a1ecSDimitry Andric  typedef _Tp                                          mapped_type;
1717c82a1ecSDimitry Andric  typedef __hash_value_type<_Key, _Tp>                 __node_value_type;
1727c82a1ecSDimitry Andric  typedef pair<const _Key, _Tp>                        __container_value_type;
1737c82a1ecSDimitry Andric  typedef __container_value_type                       __map_value_type;
1747c82a1ecSDimitry Andric  static const bool __is_map = true;
1757c82a1ecSDimitry Andric
1767c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
1777c82a1ecSDimitry Andric  static key_type const& __get_key(__container_value_type const& __v) {
1787c82a1ecSDimitry Andric    return __v.first;
1797c82a1ecSDimitry Andric  }
1807c82a1ecSDimitry Andric
1817c82a1ecSDimitry Andric  template <class _Up>
1827c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
1837c82a1ecSDimitry Andric  static typename enable_if<__is_same_uncvref<_Up, __node_value_type>::value,
1847c82a1ecSDimitry Andric      __container_value_type const&>::type
1857c82a1ecSDimitry Andric  __get_value(_Up& __t) {
1864ba319b5SDimitry Andric    return __t.__get_value();
1877c82a1ecSDimitry Andric  }
1887c82a1ecSDimitry Andric
1897c82a1ecSDimitry Andric  template <class _Up>
1907c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
1917c82a1ecSDimitry Andric  static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value,
1927c82a1ecSDimitry Andric      __container_value_type const&>::type
1937c82a1ecSDimitry Andric  __get_value(_Up& __t) {
1947c82a1ecSDimitry Andric    return __t;
1957c82a1ecSDimitry Andric  }
1967c82a1ecSDimitry Andric
1977c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
1987c82a1ecSDimitry Andric  static __container_value_type* __get_ptr(__node_value_type& __n) {
1994ba319b5SDimitry Andric    return _VSTD::addressof(__n.__get_value());
2007c82a1ecSDimitry Andric  }
2017c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
2027c82a1ecSDimitry Andric  _LIBCPP_INLINE_VISIBILITY
2034ba319b5SDimitry Andric  static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) {
2044ba319b5SDimitry Andric    return __v.__move();
2057c82a1ecSDimitry Andric  }
2067c82a1ecSDimitry Andric#endif
2077c82a1ecSDimitry Andric
2087c82a1ecSDimitry Andric};
2097c82a1ecSDimitry Andric
2107c82a1ecSDimitry Andrictemplate <class _Tp, class _AllocPtr, class _KVTypes = __hash_key_value_types<_Tp>,
2117c82a1ecSDimitry Andric          bool = _KVTypes::__is_map>
2127c82a1ecSDimitry Andricstruct __hash_map_pointer_types {};
2137c82a1ecSDimitry Andric
2147c82a1ecSDimitry Andrictemplate <class _Tp, class _AllocPtr, class _KVTypes>
2157c82a1ecSDimitry Andricstruct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
2167c82a1ecSDimitry Andric  typedef typename _KVTypes::__map_value_type   _Mv;
2177c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_AllocPtr, _Mv>::type
2187c82a1ecSDimitry Andric                                                       __map_value_type_pointer;
2197c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type
2207c82a1ecSDimitry Andric                                                 __const_map_value_type_pointer;
2217c82a1ecSDimitry Andric};
2227c82a1ecSDimitry Andric
2237c82a1ecSDimitry Andrictemplate <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
2247c82a1ecSDimitry Andricstruct __hash_node_types;
2257c82a1ecSDimitry Andric
2267c82a1ecSDimitry Andrictemplate <class _NodePtr, class _Tp, class _VoidPtr>
2277c82a1ecSDimitry Andricstruct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> >
2287c82a1ecSDimitry Andric    : public __hash_key_value_types<_Tp>, __hash_map_pointer_types<_Tp, _VoidPtr>
2297c82a1ecSDimitry Andric
2307c82a1ecSDimitry Andric{
2317c82a1ecSDimitry Andric  typedef __hash_key_value_types<_Tp>           __base;
2327c82a1ecSDimitry Andric
2337c82a1ecSDimitry Andricpublic:
2347c82a1ecSDimitry Andric  typedef ptrdiff_t difference_type;
2357c82a1ecSDimitry Andric  typedef size_t size_type;
2367c82a1ecSDimitry Andric
2377c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_NodePtr, void>::type       __void_pointer;
2387c82a1ecSDimitry Andric
2397c82a1ecSDimitry Andric  typedef typename pointer_traits<_NodePtr>::element_type       __node_type;
2407c82a1ecSDimitry Andric  typedef _NodePtr                                              __node_pointer;
2417c82a1ecSDimitry Andric
2427c82a1ecSDimitry Andric  typedef __hash_node_base<__node_pointer>                      __node_base_type;
2437c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_NodePtr, __node_base_type>::type
2447c82a1ecSDimitry Andric                                                             __node_base_pointer;
2457c82a1ecSDimitry Andric
246aed8d94eSDimitry Andric  typedef typename __node_base_type::__next_pointer          __next_pointer;
247aed8d94eSDimitry Andric
2487c82a1ecSDimitry Andric  typedef _Tp                                                 __node_value_type;
2497c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type
2507c82a1ecSDimitry Andric                                                      __node_value_type_pointer;
2517c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type
2527c82a1ecSDimitry Andric                                                __const_node_value_type_pointer;
253aed8d94eSDimitry Andric
2547c82a1ecSDimitry Andricprivate:
2557c82a1ecSDimitry Andric    static_assert(!is_const<__node_type>::value,
2567c82a1ecSDimitry Andric                "_NodePtr should never be a pointer to const");
2577c82a1ecSDimitry Andric    static_assert((is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value),
2587c82a1ecSDimitry Andric                  "_VoidPtr does not point to unqualified void type");
2597c82a1ecSDimitry Andric    static_assert((is_same<typename __rebind_pointer<_VoidPtr, __node_type>::type,
2607c82a1ecSDimitry Andric                          _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr.");
2617c82a1ecSDimitry Andric};
2627c82a1ecSDimitry Andric
2637c82a1ecSDimitry Andrictemplate <class _HashIterator>
2647c82a1ecSDimitry Andricstruct __hash_node_types_from_iterator;
2657c82a1ecSDimitry Andrictemplate <class _NodePtr>
2667c82a1ecSDimitry Andricstruct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
2677c82a1ecSDimitry Andrictemplate <class _NodePtr>
2687c82a1ecSDimitry Andricstruct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
2697c82a1ecSDimitry Andrictemplate <class _NodePtr>
2707c82a1ecSDimitry Andricstruct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
2717c82a1ecSDimitry Andrictemplate <class _NodePtr>
2727c82a1ecSDimitry Andricstruct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
2737c82a1ecSDimitry Andric
2747c82a1ecSDimitry Andric
2757c82a1ecSDimitry Andrictemplate <class _NodeValueTp, class _VoidPtr>
2767c82a1ecSDimitry Andricstruct __make_hash_node_types {
2777c82a1ecSDimitry Andric  typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp;
2787c82a1ecSDimitry Andric  typedef typename __rebind_pointer<_VoidPtr, _NodeTp>::type _NodePtr;
2797c82a1ecSDimitry Andric  typedef __hash_node_types<_NodePtr> type;
2807c82a1ecSDimitry Andric};
2817c82a1ecSDimitry Andric
2827a984708SDavid Chisnalltemplate <class _NodePtr>
283aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_iterator
2847a984708SDavid Chisnall{
2857c82a1ecSDimitry Andric    typedef __hash_node_types<_NodePtr> _NodeTypes;
2867a984708SDavid Chisnall    typedef _NodePtr                            __node_pointer;
287aed8d94eSDimitry Andric    typedef typename _NodeTypes::__next_pointer __next_pointer;
2887a984708SDavid Chisnall
289aed8d94eSDimitry Andric    __next_pointer            __node_;
2907a984708SDavid Chisnall
2917a984708SDavid Chisnallpublic:
2927a984708SDavid Chisnall    typedef forward_iterator_tag                           iterator_category;
2937c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_value_type         value_type;
2947c82a1ecSDimitry Andric    typedef typename _NodeTypes::difference_type           difference_type;
2957a984708SDavid Chisnall    typedef value_type&                                    reference;
2967c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_value_type_pointer pointer;
2977a984708SDavid Chisnall
298aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT : __node_(nullptr) {
299aed8d94eSDimitry Andric        _LIBCPP_DEBUG_MODE(__get_db()->__insert_i(this));
3004f7ab58eSDimitry Andric    }
3014f7ab58eSDimitry Andric
3024f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
3037a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
3044f7ab58eSDimitry Andric    __hash_iterator(const __hash_iterator& __i)
3054f7ab58eSDimitry Andric        : __node_(__i.__node_)
3064f7ab58eSDimitry Andric    {
3074f7ab58eSDimitry Andric        __get_db()->__iterator_copy(this, &__i);
3084f7ab58eSDimitry Andric    }
3094f7ab58eSDimitry Andric
3107a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
3114f7ab58eSDimitry Andric    ~__hash_iterator()
3124f7ab58eSDimitry Andric    {
3134f7ab58eSDimitry Andric        __get_db()->__erase_i(this);
3144f7ab58eSDimitry Andric    }
3154f7ab58eSDimitry Andric
3164f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3174f7ab58eSDimitry Andric    __hash_iterator& operator=(const __hash_iterator& __i)
3184f7ab58eSDimitry Andric    {
3194f7ab58eSDimitry Andric        if (this != &__i)
3204f7ab58eSDimitry Andric        {
3214f7ab58eSDimitry Andric            __get_db()->__iterator_copy(this, &__i);
3224f7ab58eSDimitry Andric            __node_ = __i.__node_;
3234f7ab58eSDimitry Andric        }
3244f7ab58eSDimitry Andric        return *this;
3254f7ab58eSDimitry Andric    }
3264f7ab58eSDimitry Andric#endif  // _LIBCPP_DEBUG_LEVEL >= 2
3274f7ab58eSDimitry Andric
3284f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
329aed8d94eSDimitry Andric    reference operator*() const {
330aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
3314f7ab58eSDimitry Andric                             "Attempted to dereference a non-dereferenceable unordered container iterator");
332aed8d94eSDimitry Andric        return __node_->__upcast()->__value_;
3334f7ab58eSDimitry Andric    }
3347a984708SDavid Chisnall
3357a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
336aed8d94eSDimitry Andric    pointer operator->() const {
337aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
338aed8d94eSDimitry Andric                           "Attempted to dereference a non-dereferenceable unordered container iterator");
339aed8d94eSDimitry Andric        return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_);
340aed8d94eSDimitry Andric    }
341aed8d94eSDimitry Andric
342aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
343aed8d94eSDimitry Andric    __hash_iterator& operator++() {
344aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
3454f7ab58eSDimitry Andric                       "Attempted to increment non-incrementable unordered container iterator");
3467a984708SDavid Chisnall        __node_ = __node_->__next_;
3477a984708SDavid Chisnall        return *this;
3487a984708SDavid Chisnall    }
3497a984708SDavid Chisnall
3507a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
3517a984708SDavid Chisnall    __hash_iterator operator++(int)
3527a984708SDavid Chisnall    {
3537a984708SDavid Chisnall        __hash_iterator __t(*this);
3547a984708SDavid Chisnall        ++(*this);
3557a984708SDavid Chisnall        return __t;
3567a984708SDavid Chisnall    }
3577a984708SDavid Chisnall
3587a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
3597a984708SDavid Chisnall    bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
3604f7ab58eSDimitry Andric    {
3614f7ab58eSDimitry Andric        return __x.__node_ == __y.__node_;
3624f7ab58eSDimitry Andric    }
3637a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
3647a984708SDavid Chisnall    bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
3654f7ab58eSDimitry Andric        {return !(__x == __y);}
3667a984708SDavid Chisnall
3677a984708SDavid Chisnallprivate:
3684f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
3694f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
370aed8d94eSDimitry Andric    __hash_iterator(__next_pointer __node, const void* __c) _NOEXCEPT
3714f7ab58eSDimitry Andric        : __node_(__node)
3724f7ab58eSDimitry Andric        {
3734f7ab58eSDimitry Andric            __get_db()->__insert_ic(this, __c);
3744f7ab58eSDimitry Andric        }
3754f7ab58eSDimitry Andric#else
3767a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
377aed8d94eSDimitry Andric    __hash_iterator(__next_pointer __node) _NOEXCEPT
3787a984708SDavid Chisnall        : __node_(__node)
3797a984708SDavid Chisnall        {}
3804f7ab58eSDimitry Andric#endif
3817a984708SDavid Chisnall    template <class, class, class, class> friend class __hash_table;
382aed8d94eSDimitry Andric    template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
383aed8d94eSDimitry Andric    template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
384aed8d94eSDimitry Andric    template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map;
385aed8d94eSDimitry Andric    template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
3867a984708SDavid Chisnall};
3877a984708SDavid Chisnall
3887c82a1ecSDimitry Andrictemplate <class _NodePtr>
389aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_const_iterator
3907a984708SDavid Chisnall{
3917c82a1ecSDimitry Andric    static_assert(!is_const<typename pointer_traits<_NodePtr>::element_type>::value, "");
3927c82a1ecSDimitry Andric    typedef __hash_node_types<_NodePtr> _NodeTypes;
3937c82a1ecSDimitry Andric    typedef _NodePtr                            __node_pointer;
394aed8d94eSDimitry Andric    typedef typename _NodeTypes::__next_pointer __next_pointer;
3957a984708SDavid Chisnall
396aed8d94eSDimitry Andric    __next_pointer __node_;
3977a984708SDavid Chisnall
3987a984708SDavid Chisnallpublic:
3997c82a1ecSDimitry Andric    typedef __hash_iterator<_NodePtr> __non_const_iterator;
4007c82a1ecSDimitry Andric
4017a984708SDavid Chisnall    typedef forward_iterator_tag                                 iterator_category;
4027c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_value_type               value_type;
4037c82a1ecSDimitry Andric    typedef typename _NodeTypes::difference_type                 difference_type;
4047a984708SDavid Chisnall    typedef const value_type&                                    reference;
4057c82a1ecSDimitry Andric    typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
4067c82a1ecSDimitry Andric
4077a984708SDavid Chisnall
408aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT : __node_(nullptr) {
409aed8d94eSDimitry Andric        _LIBCPP_DEBUG_MODE(__get_db()->__insert_i(this));
4104f7ab58eSDimitry Andric    }
411aed8d94eSDimitry Andric
4127a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
4137a984708SDavid Chisnall    __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
4147a984708SDavid Chisnall        : __node_(__x.__node_)
4154f7ab58eSDimitry Andric    {
416aed8d94eSDimitry Andric        _LIBCPP_DEBUG_MODE(__get_db()->__iterator_copy(this, &__x));
4174f7ab58eSDimitry Andric    }
4184f7ab58eSDimitry Andric
4194f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
4207a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
4214f7ab58eSDimitry Andric    __hash_const_iterator(const __hash_const_iterator& __i)
4224f7ab58eSDimitry Andric        : __node_(__i.__node_)
4234f7ab58eSDimitry Andric    {
4244f7ab58eSDimitry Andric        __get_db()->__iterator_copy(this, &__i);
4254f7ab58eSDimitry Andric    }
4264f7ab58eSDimitry Andric
4277a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
4284f7ab58eSDimitry Andric    ~__hash_const_iterator()
4294f7ab58eSDimitry Andric    {
4304f7ab58eSDimitry Andric        __get_db()->__erase_i(this);
4314f7ab58eSDimitry Andric    }
4324f7ab58eSDimitry Andric
4334f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4344f7ab58eSDimitry Andric    __hash_const_iterator& operator=(const __hash_const_iterator& __i)
4354f7ab58eSDimitry Andric    {
4364f7ab58eSDimitry Andric        if (this != &__i)
4374f7ab58eSDimitry Andric        {
4384f7ab58eSDimitry Andric            __get_db()->__iterator_copy(this, &__i);
4394f7ab58eSDimitry Andric            __node_ = __i.__node_;
4404f7ab58eSDimitry Andric        }
4414f7ab58eSDimitry Andric        return *this;
4424f7ab58eSDimitry Andric    }
4434f7ab58eSDimitry Andric#endif  // _LIBCPP_DEBUG_LEVEL >= 2
4444f7ab58eSDimitry Andric
4454f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
446aed8d94eSDimitry Andric    reference operator*() const {
447aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
4484f7ab58eSDimitry Andric                           "Attempted to dereference a non-dereferenceable unordered container const_iterator");
449aed8d94eSDimitry Andric        return __node_->__upcast()->__value_;
4504f7ab58eSDimitry Andric    }
4514f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
452aed8d94eSDimitry Andric    pointer operator->() const {
453aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
4544f7ab58eSDimitry Andric                           "Attempted to dereference a non-dereferenceable unordered container const_iterator");
455aed8d94eSDimitry Andric        return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_);
4564f7ab58eSDimitry Andric    }
4577a984708SDavid Chisnall
4587a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
459aed8d94eSDimitry Andric    __hash_const_iterator& operator++() {
460aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
4614f7ab58eSDimitry Andric                             "Attempted to increment non-incrementable unordered container const_iterator");
4627a984708SDavid Chisnall        __node_ = __node_->__next_;
4637a984708SDavid Chisnall        return *this;
4647a984708SDavid Chisnall    }
4657a984708SDavid Chisnall
4667a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
4677a984708SDavid Chisnall    __hash_const_iterator operator++(int)
4687a984708SDavid Chisnall    {
4697a984708SDavid Chisnall        __hash_const_iterator __t(*this);
4707a984708SDavid Chisnall        ++(*this);
4717a984708SDavid Chisnall        return __t;
4727a984708SDavid Chisnall    }
4737a984708SDavid Chisnall
4747a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
4757a984708SDavid Chisnall    bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
4764f7ab58eSDimitry Andric    {
4774f7ab58eSDimitry Andric        return __x.__node_ == __y.__node_;
4784f7ab58eSDimitry Andric    }
4797a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
4807a984708SDavid Chisnall    bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
4814f7ab58eSDimitry Andric        {return !(__x == __y);}
4827a984708SDavid Chisnall
4837a984708SDavid Chisnallprivate:
4844f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
4854f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
486aed8d94eSDimitry Andric    __hash_const_iterator(__next_pointer __node, const void* __c) _NOEXCEPT
4874f7ab58eSDimitry Andric        : __node_(__node)
4884f7ab58eSDimitry Andric        {
4894f7ab58eSDimitry Andric            __get_db()->__insert_ic(this, __c);
4904f7ab58eSDimitry Andric        }
4914f7ab58eSDimitry Andric#else
4927a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
493aed8d94eSDimitry Andric    __hash_const_iterator(__next_pointer __node) _NOEXCEPT
4947a984708SDavid Chisnall        : __node_(__node)
4957a984708SDavid Chisnall        {}
4964f7ab58eSDimitry Andric#endif
4977a984708SDavid Chisnall    template <class, class, class, class> friend class __hash_table;
498aed8d94eSDimitry Andric    template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
499aed8d94eSDimitry Andric    template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map;
500aed8d94eSDimitry Andric    template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
5017a984708SDavid Chisnall};
5027a984708SDavid Chisnall
5037a984708SDavid Chisnalltemplate <class _NodePtr>
504aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_local_iterator
5057a984708SDavid Chisnall{
5067c82a1ecSDimitry Andric    typedef __hash_node_types<_NodePtr> _NodeTypes;
5077a984708SDavid Chisnall    typedef _NodePtr                            __node_pointer;
508aed8d94eSDimitry Andric    typedef typename _NodeTypes::__next_pointer __next_pointer;
5097a984708SDavid Chisnall
510aed8d94eSDimitry Andric    __next_pointer         __node_;
5117a984708SDavid Chisnall    size_t                 __bucket_;
5127a984708SDavid Chisnall    size_t                 __bucket_count_;
5137a984708SDavid Chisnall
5147a984708SDavid Chisnallpublic:
5157a984708SDavid Chisnall    typedef forward_iterator_tag                                iterator_category;
5167c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_value_type              value_type;
5177c82a1ecSDimitry Andric    typedef typename _NodeTypes::difference_type                difference_type;
5187a984708SDavid Chisnall    typedef value_type&                                         reference;
5197c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_value_type_pointer      pointer;
5207a984708SDavid Chisnall
521aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT : __node_(nullptr) {
522aed8d94eSDimitry Andric        _LIBCPP_DEBUG_MODE(__get_db()->__insert_i(this));
5234f7ab58eSDimitry Andric    }
5244f7ab58eSDimitry Andric
5254f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
5267a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
5274f7ab58eSDimitry Andric    __hash_local_iterator(const __hash_local_iterator& __i)
5284f7ab58eSDimitry Andric        : __node_(__i.__node_),
5294f7ab58eSDimitry Andric          __bucket_(__i.__bucket_),
5304f7ab58eSDimitry Andric          __bucket_count_(__i.__bucket_count_)
5314f7ab58eSDimitry Andric    {
5324f7ab58eSDimitry Andric        __get_db()->__iterator_copy(this, &__i);
5334f7ab58eSDimitry Andric    }
5344f7ab58eSDimitry Andric
5357a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
5364f7ab58eSDimitry Andric    ~__hash_local_iterator()
5374f7ab58eSDimitry Andric    {
5384f7ab58eSDimitry Andric        __get_db()->__erase_i(this);
5394f7ab58eSDimitry Andric    }
5404f7ab58eSDimitry Andric
5414f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5424f7ab58eSDimitry Andric    __hash_local_iterator& operator=(const __hash_local_iterator& __i)
5434f7ab58eSDimitry Andric    {
5444f7ab58eSDimitry Andric        if (this != &__i)
5454f7ab58eSDimitry Andric        {
5464f7ab58eSDimitry Andric            __get_db()->__iterator_copy(this, &__i);
5474f7ab58eSDimitry Andric            __node_ = __i.__node_;
5484f7ab58eSDimitry Andric            __bucket_ = __i.__bucket_;
5494f7ab58eSDimitry Andric            __bucket_count_ = __i.__bucket_count_;
5504f7ab58eSDimitry Andric        }
5514f7ab58eSDimitry Andric        return *this;
5524f7ab58eSDimitry Andric    }
5534f7ab58eSDimitry Andric#endif  // _LIBCPP_DEBUG_LEVEL >= 2
5544f7ab58eSDimitry Andric
5554f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
556aed8d94eSDimitry Andric    reference operator*() const {
557aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
5584f7ab58eSDimitry Andric                           "Attempted to dereference a non-dereferenceable unordered container local_iterator");
559aed8d94eSDimitry Andric        return __node_->__upcast()->__value_;
5604f7ab58eSDimitry Andric    }
5617a984708SDavid Chisnall
5627a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
563aed8d94eSDimitry Andric    pointer operator->() const {
564aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
565aed8d94eSDimitry Andric                             "Attempted to dereference a non-dereferenceable unordered container local_iterator");
566aed8d94eSDimitry Andric        return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_);
567aed8d94eSDimitry Andric    }
568aed8d94eSDimitry Andric
569aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
570aed8d94eSDimitry Andric    __hash_local_iterator& operator++() {
571aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
5724f7ab58eSDimitry Andric                       "Attempted to increment non-incrementable unordered container local_iterator");
5737a984708SDavid Chisnall        __node_ = __node_->__next_;
574aed8d94eSDimitry Andric        if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
5757a984708SDavid Chisnall            __node_ = nullptr;
5767a984708SDavid Chisnall        return *this;
5777a984708SDavid Chisnall    }
5787a984708SDavid Chisnall
5797a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
5807a984708SDavid Chisnall    __hash_local_iterator operator++(int)
5817a984708SDavid Chisnall    {
5827a984708SDavid Chisnall        __hash_local_iterator __t(*this);
5837a984708SDavid Chisnall        ++(*this);
5847a984708SDavid Chisnall        return __t;
5857a984708SDavid Chisnall    }
5867a984708SDavid Chisnall
5877a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
5887a984708SDavid Chisnall    bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
5894f7ab58eSDimitry Andric    {
5904f7ab58eSDimitry Andric        return __x.__node_ == __y.__node_;
5914f7ab58eSDimitry Andric    }
5927a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
5937a984708SDavid Chisnall    bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
5944f7ab58eSDimitry Andric        {return !(__x == __y);}
5957a984708SDavid Chisnall
5967a984708SDavid Chisnallprivate:
5974f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
5984f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
599aed8d94eSDimitry Andric    __hash_local_iterator(__next_pointer __node, size_t __bucket,
6004f7ab58eSDimitry Andric                          size_t __bucket_count, const void* __c) _NOEXCEPT
6014f7ab58eSDimitry Andric        : __node_(__node),
6024f7ab58eSDimitry Andric          __bucket_(__bucket),
6034f7ab58eSDimitry Andric          __bucket_count_(__bucket_count)
6044f7ab58eSDimitry Andric        {
6054f7ab58eSDimitry Andric            __get_db()->__insert_ic(this, __c);
6064f7ab58eSDimitry Andric            if (__node_ != nullptr)
6074f7ab58eSDimitry Andric                __node_ = __node_->__next_;
6084f7ab58eSDimitry Andric        }
6094f7ab58eSDimitry Andric#else
6107a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
611aed8d94eSDimitry Andric    __hash_local_iterator(__next_pointer __node, size_t __bucket,
6127a984708SDavid Chisnall                          size_t __bucket_count) _NOEXCEPT
6137a984708SDavid Chisnall        : __node_(__node),
6147a984708SDavid Chisnall          __bucket_(__bucket),
6157a984708SDavid Chisnall          __bucket_count_(__bucket_count)
6167a984708SDavid Chisnall        {
6177a984708SDavid Chisnall            if (__node_ != nullptr)
6187a984708SDavid Chisnall                __node_ = __node_->__next_;
6197a984708SDavid Chisnall        }
6204f7ab58eSDimitry Andric#endif
6217a984708SDavid Chisnall    template <class, class, class, class> friend class __hash_table;
622aed8d94eSDimitry Andric    template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
623aed8d94eSDimitry Andric    template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
6247a984708SDavid Chisnall};
6257a984708SDavid Chisnall
6267a984708SDavid Chisnalltemplate <class _ConstNodePtr>
627aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator
6287a984708SDavid Chisnall{
6297c82a1ecSDimitry Andric    typedef __hash_node_types<_ConstNodePtr> _NodeTypes;
6307a984708SDavid Chisnall    typedef _ConstNodePtr                       __node_pointer;
631aed8d94eSDimitry Andric    typedef typename _NodeTypes::__next_pointer __next_pointer;
6327a984708SDavid Chisnall
633aed8d94eSDimitry Andric    __next_pointer         __node_;
6347a984708SDavid Chisnall    size_t                 __bucket_;
6357a984708SDavid Chisnall    size_t                 __bucket_count_;
6367a984708SDavid Chisnall
6377a984708SDavid Chisnall    typedef pointer_traits<__node_pointer>          __pointer_traits;
6387a984708SDavid Chisnall    typedef typename __pointer_traits::element_type __node;
6397a984708SDavid Chisnall    typedef typename remove_const<__node>::type     __non_const_node;
6409729cf09SDimitry Andric    typedef typename __rebind_pointer<__node_pointer, __non_const_node>::type
6417a984708SDavid Chisnall        __non_const_node_pointer;
6427c82a1ecSDimitry Andricpublic:
6437a984708SDavid Chisnall    typedef __hash_local_iterator<__non_const_node_pointer>
6447a984708SDavid Chisnall                                                    __non_const_iterator;
6457c82a1ecSDimitry Andric
6467a984708SDavid Chisnall    typedef forward_iterator_tag                                 iterator_category;
6477c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_value_type               value_type;
6487c82a1ecSDimitry Andric    typedef typename _NodeTypes::difference_type                 difference_type;
6497a984708SDavid Chisnall    typedef const value_type&                                    reference;
6507c82a1ecSDimitry Andric    typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
6517a984708SDavid Chisnall
6529729cf09SDimitry Andric
653aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) {
654aed8d94eSDimitry Andric        _LIBCPP_DEBUG_MODE(__get_db()->__insert_i(this));
6554f7ab58eSDimitry Andric    }
6564f7ab58eSDimitry Andric
6577a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
6587a984708SDavid Chisnall    __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
6597a984708SDavid Chisnall        : __node_(__x.__node_),
6607a984708SDavid Chisnall          __bucket_(__x.__bucket_),
6617a984708SDavid Chisnall          __bucket_count_(__x.__bucket_count_)
6624f7ab58eSDimitry Andric    {
663aed8d94eSDimitry Andric        _LIBCPP_DEBUG_MODE(__get_db()->__iterator_copy(this, &__x));
6644f7ab58eSDimitry Andric    }
6654f7ab58eSDimitry Andric
6664f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
6677a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
6684f7ab58eSDimitry Andric    __hash_const_local_iterator(const __hash_const_local_iterator& __i)
6694f7ab58eSDimitry Andric        : __node_(__i.__node_),
6704f7ab58eSDimitry Andric          __bucket_(__i.__bucket_),
6714f7ab58eSDimitry Andric          __bucket_count_(__i.__bucket_count_)
6724f7ab58eSDimitry Andric    {
6734f7ab58eSDimitry Andric        __get_db()->__iterator_copy(this, &__i);
6744f7ab58eSDimitry Andric    }
6754f7ab58eSDimitry Andric
6767a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
6774f7ab58eSDimitry Andric    ~__hash_const_local_iterator()
6784f7ab58eSDimitry Andric    {
6794f7ab58eSDimitry Andric        __get_db()->__erase_i(this);
6804f7ab58eSDimitry Andric    }
6814f7ab58eSDimitry Andric
6824f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6834f7ab58eSDimitry Andric    __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i)
6844f7ab58eSDimitry Andric    {
6854f7ab58eSDimitry Andric        if (this != &__i)
6864f7ab58eSDimitry Andric        {
6874f7ab58eSDimitry Andric            __get_db()->__iterator_copy(this, &__i);
6884f7ab58eSDimitry Andric            __node_ = __i.__node_;
6894f7ab58eSDimitry Andric            __bucket_ = __i.__bucket_;
6904f7ab58eSDimitry Andric            __bucket_count_ = __i.__bucket_count_;
6914f7ab58eSDimitry Andric        }
6924f7ab58eSDimitry Andric        return *this;
6934f7ab58eSDimitry Andric    }
6944f7ab58eSDimitry Andric#endif  // _LIBCPP_DEBUG_LEVEL >= 2
6954f7ab58eSDimitry Andric
6964f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
697aed8d94eSDimitry Andric    reference operator*() const {
698aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
6994f7ab58eSDimitry Andric                           "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
700aed8d94eSDimitry Andric        return __node_->__upcast()->__value_;
7014f7ab58eSDimitry Andric    }
7027a984708SDavid Chisnall
7037a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
704aed8d94eSDimitry Andric    pointer operator->() const {
705aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
706aed8d94eSDimitry Andric                           "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
707aed8d94eSDimitry Andric        return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_);
708aed8d94eSDimitry Andric    }
709aed8d94eSDimitry Andric
710aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
711aed8d94eSDimitry Andric    __hash_const_local_iterator& operator++() {
712aed8d94eSDimitry Andric        _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
7134f7ab58eSDimitry Andric                       "Attempted to increment non-incrementable unordered container const_local_iterator");
7147a984708SDavid Chisnall        __node_ = __node_->__next_;
715aed8d94eSDimitry Andric        if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
7167a984708SDavid Chisnall            __node_ = nullptr;
7177a984708SDavid Chisnall        return *this;
7187a984708SDavid Chisnall    }
7197a984708SDavid Chisnall
7207a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
7217a984708SDavid Chisnall    __hash_const_local_iterator operator++(int)
7227a984708SDavid Chisnall    {
7237a984708SDavid Chisnall        __hash_const_local_iterator __t(*this);
7247a984708SDavid Chisnall        ++(*this);
7257a984708SDavid Chisnall        return __t;
7267a984708SDavid Chisnall    }
7277a984708SDavid Chisnall
7287a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
7297a984708SDavid Chisnall    bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
7304f7ab58eSDimitry Andric    {
7314f7ab58eSDimitry Andric        return __x.__node_ == __y.__node_;
7324f7ab58eSDimitry Andric    }
7337a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
7347a984708SDavid Chisnall    bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
7354f7ab58eSDimitry Andric        {return !(__x == __y);}
7367a984708SDavid Chisnall
7377a984708SDavid Chisnallprivate:
7384f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
7394f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
740aed8d94eSDimitry Andric    __hash_const_local_iterator(__next_pointer __node, size_t __bucket,
7414f7ab58eSDimitry Andric                                size_t __bucket_count, const void* __c) _NOEXCEPT
7424f7ab58eSDimitry Andric        : __node_(__node),
7434f7ab58eSDimitry Andric          __bucket_(__bucket),
7444f7ab58eSDimitry Andric          __bucket_count_(__bucket_count)
7454f7ab58eSDimitry Andric        {
7464f7ab58eSDimitry Andric            __get_db()->__insert_ic(this, __c);
7474f7ab58eSDimitry Andric            if (__node_ != nullptr)
7484f7ab58eSDimitry Andric                __node_ = __node_->__next_;
7494f7ab58eSDimitry Andric        }
7504f7ab58eSDimitry Andric#else
7517a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
752aed8d94eSDimitry Andric    __hash_const_local_iterator(__next_pointer __node, size_t __bucket,
7537a984708SDavid Chisnall                                size_t __bucket_count) _NOEXCEPT
7547a984708SDavid Chisnall        : __node_(__node),
7557a984708SDavid Chisnall          __bucket_(__bucket),
7567a984708SDavid Chisnall          __bucket_count_(__bucket_count)
7577a984708SDavid Chisnall        {
7587a984708SDavid Chisnall            if (__node_ != nullptr)
7597a984708SDavid Chisnall                __node_ = __node_->__next_;
7607a984708SDavid Chisnall        }
7614f7ab58eSDimitry Andric#endif
7627a984708SDavid Chisnall    template <class, class, class, class> friend class __hash_table;
763aed8d94eSDimitry Andric    template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
7647a984708SDavid Chisnall};
7657a984708SDavid Chisnall
7667a984708SDavid Chisnalltemplate <class _Alloc>
7677a984708SDavid Chisnallclass __bucket_list_deallocator
7687a984708SDavid Chisnall{
7697a984708SDavid Chisnall    typedef _Alloc                                          allocator_type;
7707a984708SDavid Chisnall    typedef allocator_traits<allocator_type>                __alloc_traits;
7717a984708SDavid Chisnall    typedef typename __alloc_traits::size_type              size_type;
7727a984708SDavid Chisnall
7737a984708SDavid Chisnall    __compressed_pair<size_type, allocator_type> __data_;
7747a984708SDavid Chisnallpublic:
7757a984708SDavid Chisnall    typedef typename __alloc_traits::pointer pointer;
7767a984708SDavid Chisnall
7777a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
7787a984708SDavid Chisnall    __bucket_list_deallocator()
7797a984708SDavid Chisnall        _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
7807a984708SDavid Chisnall        : __data_(0) {}
7817a984708SDavid Chisnall
7827a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
7837a984708SDavid Chisnall    __bucket_list_deallocator(const allocator_type& __a, size_type __size)
7847a984708SDavid Chisnall        _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
7857a984708SDavid Chisnall        : __data_(__size, __a) {}
7867a984708SDavid Chisnall
787540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
7887a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
7897a984708SDavid Chisnall    __bucket_list_deallocator(__bucket_list_deallocator&& __x)
7907a984708SDavid Chisnall        _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
7917a984708SDavid Chisnall        : __data_(_VSTD::move(__x.__data_))
7927a984708SDavid Chisnall    {
7937a984708SDavid Chisnall        __x.size() = 0;
7947a984708SDavid Chisnall    }
795540d2a8bSDimitry Andric#endif
7967a984708SDavid Chisnall
7977a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
7987a984708SDavid Chisnall    size_type& size() _NOEXCEPT {return __data_.first();}
7997a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
8007a984708SDavid Chisnall    size_type  size() const _NOEXCEPT {return __data_.first();}
8017a984708SDavid Chisnall
8027a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
8037a984708SDavid Chisnall    allocator_type& __alloc() _NOEXCEPT {return __data_.second();}
8047a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
8057a984708SDavid Chisnall    const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();}
8067a984708SDavid Chisnall
8077a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
8087a984708SDavid Chisnall    void operator()(pointer __p) _NOEXCEPT
8097a984708SDavid Chisnall    {
8107a984708SDavid Chisnall        __alloc_traits::deallocate(__alloc(), __p, size());
8117a984708SDavid Chisnall    }
8127a984708SDavid Chisnall};
8137a984708SDavid Chisnall
8147a984708SDavid Chisnalltemplate <class _Alloc> class __hash_map_node_destructor;
8157a984708SDavid Chisnall
8167a984708SDavid Chisnalltemplate <class _Alloc>
8177a984708SDavid Chisnallclass __hash_node_destructor
8187a984708SDavid Chisnall{
8197a984708SDavid Chisnall    typedef _Alloc                                          allocator_type;
8207a984708SDavid Chisnall    typedef allocator_traits<allocator_type>                __alloc_traits;
8217c82a1ecSDimitry Andric
8227a984708SDavid Chisnallpublic:
8237a984708SDavid Chisnall    typedef typename __alloc_traits::pointer                pointer;
8247a984708SDavid Chisnallprivate:
8257c82a1ecSDimitry Andric    typedef __hash_node_types<pointer> _NodeTypes;
8267a984708SDavid Chisnall
8277a984708SDavid Chisnall    allocator_type& __na_;
8287a984708SDavid Chisnall
8297a984708SDavid Chisnall    __hash_node_destructor& operator=(const __hash_node_destructor&);
8307a984708SDavid Chisnall
8317a984708SDavid Chisnallpublic:
8327a984708SDavid Chisnall    bool __value_constructed;
8337a984708SDavid Chisnall
8347a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
8357a984708SDavid Chisnall    explicit __hash_node_destructor(allocator_type& __na,
8367a984708SDavid Chisnall                                    bool __constructed = false) _NOEXCEPT
8377a984708SDavid Chisnall        : __na_(__na),
8387a984708SDavid Chisnall          __value_constructed(__constructed)
8397a984708SDavid Chisnall        {}
8407a984708SDavid Chisnall
8417a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
8427a984708SDavid Chisnall    void operator()(pointer __p) _NOEXCEPT
8437a984708SDavid Chisnall    {
8447a984708SDavid Chisnall        if (__value_constructed)
8457c82a1ecSDimitry Andric            __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_));
8467a984708SDavid Chisnall        if (__p)
8477a984708SDavid Chisnall            __alloc_traits::deallocate(__na_, __p, 1);
8487a984708SDavid Chisnall    }
8497a984708SDavid Chisnall
8507a984708SDavid Chisnall    template <class> friend class __hash_map_node_destructor;
8517a984708SDavid Chisnall};
8527a984708SDavid Chisnall
8534ba319b5SDimitry Andric#if _LIBCPP_STD_VER > 14
8544ba319b5SDimitry Andrictemplate <class _NodeType, class _Alloc>
8554ba319b5SDimitry Andricstruct __generic_container_node_destructor;
8564ba319b5SDimitry Andric
8574ba319b5SDimitry Andrictemplate <class _Tp, class _VoidPtr, class _Alloc>
8584ba319b5SDimitry Andricstruct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc>
8594ba319b5SDimitry Andric    : __hash_node_destructor<_Alloc>
8604ba319b5SDimitry Andric{
8614ba319b5SDimitry Andric    using __hash_node_destructor<_Alloc>::__hash_node_destructor;
8624ba319b5SDimitry Andric};
8634ba319b5SDimitry Andric#endif
864540d2a8bSDimitry Andric
865*b5893f02SDimitry Andrictemplate <class _Key, class _Hash, class _Equal>
866*b5893f02SDimitry Andricstruct __enforce_unordered_container_requirements {
867540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
868540d2a8bSDimitry Andric    static_assert(__check_hash_requirements<_Key, _Hash>::value,
869540d2a8bSDimitry Andric    "the specified hash does not meet the Hash requirements");
870540d2a8bSDimitry Andric    static_assert(is_copy_constructible<_Equal>::value,
871540d2a8bSDimitry Andric    "the specified comparator is required to be copy constructible");
872*b5893f02SDimitry Andric#endif
873*b5893f02SDimitry Andric    typedef int type;
874540d2a8bSDimitry Andric};
875540d2a8bSDimitry Andric
876*b5893f02SDimitry Andrictemplate <class _Key, class _Hash, class _Equal>
877*b5893f02SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
878*b5893f02SDimitry Andric    _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value,
879*b5893f02SDimitry Andric    "the specified comparator type does not provide a const call operator")
880*b5893f02SDimitry Andric    _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
881*b5893f02SDimitry Andric    "the specified hash functor does not provide a const call operator")
882*b5893f02SDimitry Andric#endif
883*b5893f02SDimitry Andrictypename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
884*b5893f02SDimitry Andric__diagnose_unordered_container_requirements(int);
885*b5893f02SDimitry Andric
886*b5893f02SDimitry Andric// This dummy overload is used so that the compiler won't emit a spurious
887*b5893f02SDimitry Andric// "no matching function for call to __diagnose_unordered_xxx" diagnostic
888*b5893f02SDimitry Andric// when the overload above causes a hard error.
889*b5893f02SDimitry Andrictemplate <class _Key, class _Hash, class _Equal>
890*b5893f02SDimitry Andricint __diagnose_unordered_container_requirements(void*);
891540d2a8bSDimitry Andric
8927a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
8937a984708SDavid Chisnallclass __hash_table
8947a984708SDavid Chisnall{
8957a984708SDavid Chisnallpublic:
8967a984708SDavid Chisnall    typedef _Tp    value_type;
8977a984708SDavid Chisnall    typedef _Hash  hasher;
8987a984708SDavid Chisnall    typedef _Equal key_equal;
8997a984708SDavid Chisnall    typedef _Alloc allocator_type;
9007a984708SDavid Chisnall
9017a984708SDavid Chisnallprivate:
9027a984708SDavid Chisnall    typedef allocator_traits<allocator_type> __alloc_traits;
9037c82a1ecSDimitry Andric    typedef typename
9047c82a1ecSDimitry Andric      __make_hash_node_types<value_type, typename __alloc_traits::void_pointer>::type
9057c82a1ecSDimitry Andric                                                                     _NodeTypes;
9067a984708SDavid Chisnallpublic:
9077c82a1ecSDimitry Andric
9087c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_value_type           __node_value_type;
9097c82a1ecSDimitry Andric    typedef typename _NodeTypes::__container_value_type      __container_value_type;
9107c82a1ecSDimitry Andric    typedef typename _NodeTypes::key_type                    key_type;
9117a984708SDavid Chisnall    typedef value_type&                              reference;
9127a984708SDavid Chisnall    typedef const value_type&                        const_reference;
9137a984708SDavid Chisnall    typedef typename __alloc_traits::pointer         pointer;
9147a984708SDavid Chisnall    typedef typename __alloc_traits::const_pointer   const_pointer;
9157c82a1ecSDimitry Andric#ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
9167a984708SDavid Chisnall    typedef typename __alloc_traits::size_type       size_type;
9177c82a1ecSDimitry Andric#else
9187c82a1ecSDimitry Andric    typedef typename _NodeTypes::size_type           size_type;
9197c82a1ecSDimitry Andric#endif
9207c82a1ecSDimitry Andric    typedef typename _NodeTypes::difference_type     difference_type;
9217a984708SDavid Chisnallpublic:
9227a984708SDavid Chisnall    // Create __node
9237c82a1ecSDimitry Andric
9247c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_type __node;
925854fa44bSDimitry Andric    typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator;
9267a984708SDavid Chisnall    typedef allocator_traits<__node_allocator>       __node_traits;
9277c82a1ecSDimitry Andric    typedef typename _NodeTypes::__void_pointer      __void_pointer;
9287c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_pointer      __node_pointer;
9297c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_pointer      __node_const_pointer;
9307c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_base_type    __first_node;
9317c82a1ecSDimitry Andric    typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
932aed8d94eSDimitry Andric    typedef typename _NodeTypes::__next_pointer      __next_pointer;
9337c82a1ecSDimitry Andric
9347c82a1ecSDimitry Andricprivate:
9357c82a1ecSDimitry Andric    // check for sane allocator pointer rebinding semantics. Rebinding the
9367c82a1ecSDimitry Andric    // allocator for a new pointer type should be exactly the same as rebinding
9377c82a1ecSDimitry Andric    // the pointer using 'pointer_traits'.
9387c82a1ecSDimitry Andric    static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value),
9397c82a1ecSDimitry Andric                  "Allocator does not rebind pointers in a sane manner.");
9407c82a1ecSDimitry Andric    typedef typename __rebind_alloc_helper<__node_traits, __first_node>::type
9417c82a1ecSDimitry Andric        __node_base_allocator;
9427c82a1ecSDimitry Andric    typedef allocator_traits<__node_base_allocator> __node_base_traits;
9437c82a1ecSDimitry Andric    static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value),
9447c82a1ecSDimitry Andric                 "Allocator does not rebind pointers in a sane manner.");
9457a984708SDavid Chisnall
9467a984708SDavid Chisnallprivate:
9477a984708SDavid Chisnall
948aed8d94eSDimitry Andric    typedef typename __rebind_alloc_helper<__node_traits, __next_pointer>::type __pointer_allocator;
9497a984708SDavid Chisnall    typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
950aed8d94eSDimitry Andric    typedef unique_ptr<__next_pointer[], __bucket_list_deleter> __bucket_list;
9517a984708SDavid Chisnall    typedef allocator_traits<__pointer_allocator>          __pointer_alloc_traits;
9527a984708SDavid Chisnall    typedef typename __bucket_list_deleter::pointer       __node_pointer_pointer;
9537a984708SDavid Chisnall
9547a984708SDavid Chisnall    // --- Member data begin ---
9557a984708SDavid Chisnall    __bucket_list                                         __bucket_list_;
9567a984708SDavid Chisnall    __compressed_pair<__first_node, __node_allocator>     __p1_;
9577a984708SDavid Chisnall    __compressed_pair<size_type, hasher>                  __p2_;
9587a984708SDavid Chisnall    __compressed_pair<float, key_equal>                   __p3_;
9597a984708SDavid Chisnall    // --- Member data end ---
9607a984708SDavid Chisnall
9617a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9627a984708SDavid Chisnall    size_type& size() _NOEXCEPT {return __p2_.first();}
9637a984708SDavid Chisnallpublic:
9647a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9657a984708SDavid Chisnall    size_type  size() const _NOEXCEPT {return __p2_.first();}
9667a984708SDavid Chisnall
9677a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9687a984708SDavid Chisnall    hasher& hash_function() _NOEXCEPT {return __p2_.second();}
9697a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9707a984708SDavid Chisnall    const hasher& hash_function() const _NOEXCEPT {return __p2_.second();}
9717a984708SDavid Chisnall
9727a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9737a984708SDavid Chisnall    float& max_load_factor() _NOEXCEPT {return __p3_.first();}
9747a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9757a984708SDavid Chisnall    float  max_load_factor() const _NOEXCEPT {return __p3_.first();}
9767a984708SDavid Chisnall
9777a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9787a984708SDavid Chisnall    key_equal& key_eq() _NOEXCEPT {return __p3_.second();}
9797a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9807a984708SDavid Chisnall    const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();}
9817a984708SDavid Chisnall
9827a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9837a984708SDavid Chisnall    __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();}
9847a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
9857a984708SDavid Chisnall    const __node_allocator& __node_alloc() const _NOEXCEPT
9867a984708SDavid Chisnall        {return __p1_.second();}
9877a984708SDavid Chisnall
9887a984708SDavid Chisnallpublic:
9897a984708SDavid Chisnall    typedef __hash_iterator<__node_pointer>                   iterator;
9904bab9fd9SDavid Chisnall    typedef __hash_const_iterator<__node_pointer>             const_iterator;
9917a984708SDavid Chisnall    typedef __hash_local_iterator<__node_pointer>             local_iterator;
9924bab9fd9SDavid Chisnall    typedef __hash_const_local_iterator<__node_pointer>       const_local_iterator;
9937a984708SDavid Chisnall
9949729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9957a984708SDavid Chisnall    __hash_table()
9967a984708SDavid Chisnall        _NOEXCEPT_(
9977a984708SDavid Chisnall            is_nothrow_default_constructible<__bucket_list>::value &&
9987a984708SDavid Chisnall            is_nothrow_default_constructible<__first_node>::value &&
9997a984708SDavid Chisnall            is_nothrow_default_constructible<__node_allocator>::value &&
10007a984708SDavid Chisnall            is_nothrow_default_constructible<hasher>::value &&
10017a984708SDavid Chisnall            is_nothrow_default_constructible<key_equal>::value);
10029729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10037a984708SDavid Chisnall    __hash_table(const hasher& __hf, const key_equal& __eql);
10047a984708SDavid Chisnall    __hash_table(const hasher& __hf, const key_equal& __eql,
10057a984708SDavid Chisnall                 const allocator_type& __a);
10067a984708SDavid Chisnall    explicit __hash_table(const allocator_type& __a);
10077a984708SDavid Chisnall    __hash_table(const __hash_table& __u);
10087a984708SDavid Chisnall    __hash_table(const __hash_table& __u, const allocator_type& __a);
10097c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
10107a984708SDavid Chisnall    __hash_table(__hash_table&& __u)
10117a984708SDavid Chisnall        _NOEXCEPT_(
10127a984708SDavid Chisnall            is_nothrow_move_constructible<__bucket_list>::value &&
10137a984708SDavid Chisnall            is_nothrow_move_constructible<__first_node>::value &&
10147a984708SDavid Chisnall            is_nothrow_move_constructible<__node_allocator>::value &&
10157a984708SDavid Chisnall            is_nothrow_move_constructible<hasher>::value &&
10167a984708SDavid Chisnall            is_nothrow_move_constructible<key_equal>::value);
10177a984708SDavid Chisnall    __hash_table(__hash_table&& __u, const allocator_type& __a);
10187c82a1ecSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
10197a984708SDavid Chisnall    ~__hash_table();
10207a984708SDavid Chisnall
10217a984708SDavid Chisnall    __hash_table& operator=(const __hash_table& __u);
10227c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
10239729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10247a984708SDavid Chisnall    __hash_table& operator=(__hash_table&& __u)
10257a984708SDavid Chisnall        _NOEXCEPT_(
10267a984708SDavid Chisnall            __node_traits::propagate_on_container_move_assignment::value &&
10277a984708SDavid Chisnall            is_nothrow_move_assignable<__node_allocator>::value &&
10287a984708SDavid Chisnall            is_nothrow_move_assignable<hasher>::value &&
10297a984708SDavid Chisnall            is_nothrow_move_assignable<key_equal>::value);
10307a984708SDavid Chisnall#endif
10317a984708SDavid Chisnall    template <class _InputIterator>
10327a984708SDavid Chisnall        void __assign_unique(_InputIterator __first, _InputIterator __last);
10337a984708SDavid Chisnall    template <class _InputIterator>
10347a984708SDavid Chisnall        void __assign_multi(_InputIterator __first, _InputIterator __last);
10357a984708SDavid Chisnall
10367a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
10377a984708SDavid Chisnall    size_type max_size() const _NOEXCEPT
10387a984708SDavid Chisnall    {
1039aed8d94eSDimitry Andric        return std::min<size_type>(
1040aed8d94eSDimitry Andric            __node_traits::max_size(__node_alloc()),
1041aed8d94eSDimitry Andric            numeric_limits<difference_type >::max()
1042aed8d94eSDimitry Andric        );
10437a984708SDavid Chisnall    }
10447a984708SDavid Chisnall
1045*b5893f02SDimitry Andricprivate:
1046*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1047*b5893f02SDimitry Andric    __next_pointer __node_insert_multi_prepare(size_t __cp_hash,
1048*b5893f02SDimitry Andric                                               value_type& __cp_val);
1049*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1050*b5893f02SDimitry Andric    void __node_insert_multi_perform(__node_pointer __cp,
1051*b5893f02SDimitry Andric                                     __next_pointer __pn) _NOEXCEPT;
1052*b5893f02SDimitry Andric
1053*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1054*b5893f02SDimitry Andric    __next_pointer __node_insert_unique_prepare(size_t __nd_hash,
1055*b5893f02SDimitry Andric                                                value_type& __nd_val);
1056*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1057*b5893f02SDimitry Andric    void __node_insert_unique_perform(__node_pointer __ptr) _NOEXCEPT;
1058*b5893f02SDimitry Andric
1059*b5893f02SDimitry Andricpublic:
1060*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10617a984708SDavid Chisnall    pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
1062*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10637a984708SDavid Chisnall    iterator             __node_insert_multi(__node_pointer __nd);
1064*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10657a984708SDavid Chisnall    iterator             __node_insert_multi(const_iterator __p,
10667a984708SDavid Chisnall                                             __node_pointer __nd);
10677a984708SDavid Chisnall
10687c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
10697c82a1ecSDimitry Andric    template <class _Key, class ..._Args>
10707c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10717c82a1ecSDimitry Andric    pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args);
10727c82a1ecSDimitry Andric
10737a984708SDavid Chisnall    template <class... _Args>
10747c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10757c82a1ecSDimitry Andric    pair<iterator, bool> __emplace_unique_impl(_Args&&... __args);
10767c82a1ecSDimitry Andric
10777c82a1ecSDimitry Andric    template <class _Pp>
10787c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10797c82a1ecSDimitry Andric    pair<iterator, bool> __emplace_unique(_Pp&& __x) {
10807c82a1ecSDimitry Andric      return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x),
10817c82a1ecSDimitry Andric                                          __can_extract_key<_Pp, key_type>());
10827c82a1ecSDimitry Andric    }
10837c82a1ecSDimitry Andric
10847c82a1ecSDimitry Andric    template <class _First, class _Second>
10857c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10867c82a1ecSDimitry Andric    typename enable_if<
10877c82a1ecSDimitry Andric        __can_extract_map_key<_First, key_type, __container_value_type>::value,
10887c82a1ecSDimitry Andric        pair<iterator, bool>
10897c82a1ecSDimitry Andric    >::type __emplace_unique(_First&& __f, _Second&& __s) {
10907c82a1ecSDimitry Andric        return __emplace_unique_key_args(__f, _VSTD::forward<_First>(__f),
10917c82a1ecSDimitry Andric                                              _VSTD::forward<_Second>(__s));
10927c82a1ecSDimitry Andric    }
10937c82a1ecSDimitry Andric
10947a984708SDavid Chisnall    template <class... _Args>
10957c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10967c82a1ecSDimitry Andric    pair<iterator, bool> __emplace_unique(_Args&&... __args) {
10977c82a1ecSDimitry Andric      return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...);
10987c82a1ecSDimitry Andric    }
10997c82a1ecSDimitry Andric
11007c82a1ecSDimitry Andric    template <class _Pp>
11017c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11027c82a1ecSDimitry Andric    pair<iterator, bool>
11037c82a1ecSDimitry Andric    __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) {
11047c82a1ecSDimitry Andric      return __emplace_unique_impl(_VSTD::forward<_Pp>(__x));
11057c82a1ecSDimitry Andric    }
11067c82a1ecSDimitry Andric    template <class _Pp>
11077c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11087c82a1ecSDimitry Andric    pair<iterator, bool>
11097c82a1ecSDimitry Andric    __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) {
11107c82a1ecSDimitry Andric      return __emplace_unique_key_args(__x, _VSTD::forward<_Pp>(__x));
11117c82a1ecSDimitry Andric    }
11127c82a1ecSDimitry Andric    template <class _Pp>
11137c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11147c82a1ecSDimitry Andric    pair<iterator, bool>
11157c82a1ecSDimitry Andric    __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) {
11167c82a1ecSDimitry Andric      return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x));
11177c82a1ecSDimitry Andric    }
11187c82a1ecSDimitry Andric
11197c82a1ecSDimitry Andric    template <class... _Args>
11207c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11217a984708SDavid Chisnall    iterator __emplace_multi(_Args&&... __args);
11227a984708SDavid Chisnall    template <class... _Args>
11237c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11247a984708SDavid Chisnall    iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
11257a984708SDavid Chisnall
11267c82a1ecSDimitry Andric
1127854fa44bSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11287c82a1ecSDimitry Andric    pair<iterator, bool>
11297c82a1ecSDimitry Andric    __insert_unique(__container_value_type&& __x) {
11307c82a1ecSDimitry Andric      return __emplace_unique_key_args(_NodeTypes::__get_key(__x), _VSTD::move(__x));
11317c82a1ecSDimitry Andric    }
11327c82a1ecSDimitry Andric
11337c82a1ecSDimitry Andric    template <class _Pp, class = typename enable_if<
11347c82a1ecSDimitry Andric            !__is_same_uncvref<_Pp, __container_value_type>::value
11357c82a1ecSDimitry Andric        >::type>
1136854fa44bSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11377c82a1ecSDimitry Andric    pair<iterator, bool> __insert_unique(_Pp&& __x) {
11387c82a1ecSDimitry Andric      return __emplace_unique(_VSTD::forward<_Pp>(__x));
11397c82a1ecSDimitry Andric    }
11407c82a1ecSDimitry Andric
11417c82a1ecSDimitry Andric    template <class _Pp>
11427c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11437c82a1ecSDimitry Andric    iterator __insert_multi(_Pp&& __x) {
11447c82a1ecSDimitry Andric      return __emplace_multi(_VSTD::forward<_Pp>(__x));
11457c82a1ecSDimitry Andric    }
11467c82a1ecSDimitry Andric
11477c82a1ecSDimitry Andric    template <class _Pp>
11487c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11497c82a1ecSDimitry Andric    iterator __insert_multi(const_iterator __p, _Pp&& __x) {
11507c82a1ecSDimitry Andric        return __emplace_hint_multi(__p, _VSTD::forward<_Pp>(__x));
11517c82a1ecSDimitry Andric    }
11527c82a1ecSDimitry Andric
11537c82a1ecSDimitry Andric#else  // !defined(_LIBCPP_CXX03_LANG)
11547c82a1ecSDimitry Andric    template <class _Key, class _Args>
1155aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11567c82a1ecSDimitry Andric    pair<iterator, bool> __emplace_unique_key_args(_Key const&, _Args& __args);
11577c82a1ecSDimitry Andric
11587c82a1ecSDimitry Andric    iterator __insert_multi(const __container_value_type& __x);
11597c82a1ecSDimitry Andric    iterator __insert_multi(const_iterator __p, const __container_value_type& __x);
1160854fa44bSDimitry Andric#endif
1161854fa44bSDimitry Andric
11627c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11637c82a1ecSDimitry Andric    pair<iterator, bool> __insert_unique(const __container_value_type& __x) {
11647c82a1ecSDimitry Andric        return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x);
11657c82a1ecSDimitry Andric    }
11667a984708SDavid Chisnall
11674ba319b5SDimitry Andric#if _LIBCPP_STD_VER > 14
11684ba319b5SDimitry Andric    template <class _NodeHandle, class _InsertReturnType>
11694ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11704ba319b5SDimitry Andric    _InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh);
11714ba319b5SDimitry Andric    template <class _NodeHandle>
11724ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11734ba319b5SDimitry Andric    iterator __node_handle_insert_unique(const_iterator __hint,
11744ba319b5SDimitry Andric                                         _NodeHandle&& __nh);
1175*b5893f02SDimitry Andric    template <class _Table>
1176*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1177*b5893f02SDimitry Andric    void __node_handle_merge_unique(_Table& __source);
11784ba319b5SDimitry Andric
11794ba319b5SDimitry Andric    template <class _NodeHandle>
11804ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11814ba319b5SDimitry Andric    iterator __node_handle_insert_multi(_NodeHandle&& __nh);
11824ba319b5SDimitry Andric    template <class _NodeHandle>
11834ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11844ba319b5SDimitry Andric    iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh);
1185*b5893f02SDimitry Andric    template <class _Table>
1186*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1187*b5893f02SDimitry Andric    void __node_handle_merge_multi(_Table& __source);
11884ba319b5SDimitry Andric
11894ba319b5SDimitry Andric    template <class _NodeHandle>
11904ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11914ba319b5SDimitry Andric    _NodeHandle __node_handle_extract(key_type const& __key);
11924ba319b5SDimitry Andric    template <class _NodeHandle>
11934ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11944ba319b5SDimitry Andric    _NodeHandle __node_handle_extract(const_iterator __it);
11954ba319b5SDimitry Andric#endif
11964ba319b5SDimitry Andric
11977a984708SDavid Chisnall    void clear() _NOEXCEPT;
11987a984708SDavid Chisnall    void rehash(size_type __n);
11997a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
12007a984708SDavid Chisnall        {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
12017a984708SDavid Chisnall
12027a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
12037a984708SDavid Chisnall    size_type bucket_count() const _NOEXCEPT
12047a984708SDavid Chisnall    {
12057a984708SDavid Chisnall        return __bucket_list_.get_deleter().size();
12067a984708SDavid Chisnall    }
12077a984708SDavid Chisnall
12089729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12097a984708SDavid Chisnall    iterator       begin() _NOEXCEPT;
12109729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12117a984708SDavid Chisnall    iterator       end() _NOEXCEPT;
12129729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12137a984708SDavid Chisnall    const_iterator begin() const _NOEXCEPT;
12149729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12157a984708SDavid Chisnall    const_iterator end() const _NOEXCEPT;
12167a984708SDavid Chisnall
12177a984708SDavid Chisnall    template <class _Key>
12187a984708SDavid Chisnall        _LIBCPP_INLINE_VISIBILITY
12197a984708SDavid Chisnall        size_type bucket(const _Key& __k) const
12204f7ab58eSDimitry Andric        {
12214f7ab58eSDimitry Andric            _LIBCPP_ASSERT(bucket_count() > 0,
12224f7ab58eSDimitry Andric                "unordered container::bucket(key) called when bucket_count() == 0");
12234f7ab58eSDimitry Andric            return __constrain_hash(hash_function()(__k), bucket_count());
12244f7ab58eSDimitry Andric        }
12257a984708SDavid Chisnall
12267a984708SDavid Chisnall    template <class _Key>
12277a984708SDavid Chisnall        iterator       find(const _Key& __x);
12287a984708SDavid Chisnall    template <class _Key>
12297a984708SDavid Chisnall        const_iterator find(const _Key& __x) const;
12307a984708SDavid Chisnall
123194e3ee44SDavid Chisnall    typedef __hash_node_destructor<__node_allocator> _Dp;
123294e3ee44SDavid Chisnall    typedef unique_ptr<__node, _Dp> __node_holder;
12337a984708SDavid Chisnall
12347a984708SDavid Chisnall    iterator erase(const_iterator __p);
12357a984708SDavid Chisnall    iterator erase(const_iterator __first, const_iterator __last);
12367a984708SDavid Chisnall    template <class _Key>
12377a984708SDavid Chisnall        size_type __erase_unique(const _Key& __k);
12387a984708SDavid Chisnall    template <class _Key>
12397a984708SDavid Chisnall        size_type __erase_multi(const _Key& __k);
12407a984708SDavid Chisnall    __node_holder remove(const_iterator __p) _NOEXCEPT;
12417a984708SDavid Chisnall
12427a984708SDavid Chisnall    template <class _Key>
12439729cf09SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
12447a984708SDavid Chisnall        size_type __count_unique(const _Key& __k) const;
12457a984708SDavid Chisnall    template <class _Key>
12467a984708SDavid Chisnall        size_type __count_multi(const _Key& __k) const;
12477a984708SDavid Chisnall
12487a984708SDavid Chisnall    template <class _Key>
12497a984708SDavid Chisnall        pair<iterator, iterator>
12507a984708SDavid Chisnall        __equal_range_unique(const _Key& __k);
12517a984708SDavid Chisnall    template <class _Key>
12527a984708SDavid Chisnall        pair<const_iterator, const_iterator>
12537a984708SDavid Chisnall        __equal_range_unique(const _Key& __k) const;
12547a984708SDavid Chisnall
12557a984708SDavid Chisnall    template <class _Key>
12567a984708SDavid Chisnall        pair<iterator, iterator>
12577a984708SDavid Chisnall        __equal_range_multi(const _Key& __k);
12587a984708SDavid Chisnall    template <class _Key>
12597a984708SDavid Chisnall        pair<const_iterator, const_iterator>
12607a984708SDavid Chisnall        __equal_range_multi(const _Key& __k) const;
12617a984708SDavid Chisnall
12627a984708SDavid Chisnall    void swap(__hash_table& __u)
1263fe9390e7SDimitry Andric#if _LIBCPP_STD_VER <= 11
1264aed8d94eSDimitry Andric        _NOEXCEPT_DEBUG_(
1265854fa44bSDimitry Andric            __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
1266854fa44bSDimitry Andric            && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
1267854fa44bSDimitry Andric                  || __is_nothrow_swappable<__pointer_allocator>::value)
1268854fa44bSDimitry Andric            && (!__node_traits::propagate_on_container_swap::value
1269854fa44bSDimitry Andric                  || __is_nothrow_swappable<__node_allocator>::value)
1270854fa44bSDimitry Andric            );
1271fe9390e7SDimitry Andric#else
1272aed8d94eSDimitry Andric     _NOEXCEPT_DEBUG_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value);
1273fe9390e7SDimitry Andric#endif
12747a984708SDavid Chisnall
12757a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
12767a984708SDavid Chisnall    size_type max_bucket_count() const _NOEXCEPT
1277aed8d94eSDimitry Andric        {return max_size(); }
12787a984708SDavid Chisnall    size_type bucket_size(size_type __n) const;
12797a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
12807a984708SDavid Chisnall    {
12817a984708SDavid Chisnall        size_type __bc = bucket_count();
12827a984708SDavid Chisnall        return __bc != 0 ? (float)size() / __bc : 0.f;
12837a984708SDavid Chisnall    }
12847a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
12854f7ab58eSDimitry Andric    {
12864f7ab58eSDimitry Andric        _LIBCPP_ASSERT(__mlf > 0,
12874f7ab58eSDimitry Andric            "unordered container::max_load_factor(lf) called with lf <= 0");
12884f7ab58eSDimitry Andric        max_load_factor() = _VSTD::max(__mlf, load_factor());
12894f7ab58eSDimitry Andric    }
12907a984708SDavid Chisnall
12914f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12924f7ab58eSDimitry Andric    local_iterator
12934f7ab58eSDimitry Andric    begin(size_type __n)
12944f7ab58eSDimitry Andric    {
12954f7ab58eSDimitry Andric        _LIBCPP_ASSERT(__n < bucket_count(),
12964f7ab58eSDimitry Andric            "unordered container::begin(n) called with n >= bucket_count()");
12974f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
12984f7ab58eSDimitry Andric        return local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
12994f7ab58eSDimitry Andric#else
13004f7ab58eSDimitry Andric        return local_iterator(__bucket_list_[__n], __n, bucket_count());
13014f7ab58eSDimitry Andric#endif
13024f7ab58eSDimitry Andric    }
13034f7ab58eSDimitry Andric
13044f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13054f7ab58eSDimitry Andric    local_iterator
13064f7ab58eSDimitry Andric    end(size_type __n)
13074f7ab58eSDimitry Andric    {
13084f7ab58eSDimitry Andric        _LIBCPP_ASSERT(__n < bucket_count(),
13094f7ab58eSDimitry Andric            "unordered container::end(n) called with n >= bucket_count()");
13104f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
13114f7ab58eSDimitry Andric        return local_iterator(nullptr, __n, bucket_count(), this);
13124f7ab58eSDimitry Andric#else
13134f7ab58eSDimitry Andric        return local_iterator(nullptr, __n, bucket_count());
13144f7ab58eSDimitry Andric#endif
13154f7ab58eSDimitry Andric    }
13164f7ab58eSDimitry Andric
13174f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13184f7ab58eSDimitry Andric    const_local_iterator
13194f7ab58eSDimitry Andric    cbegin(size_type __n) const
13204f7ab58eSDimitry Andric    {
13214f7ab58eSDimitry Andric        _LIBCPP_ASSERT(__n < bucket_count(),
13224f7ab58eSDimitry Andric            "unordered container::cbegin(n) called with n >= bucket_count()");
13234f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
13244f7ab58eSDimitry Andric        return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
13254f7ab58eSDimitry Andric#else
13264f7ab58eSDimitry Andric        return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
13274f7ab58eSDimitry Andric#endif
13284f7ab58eSDimitry Andric    }
13294f7ab58eSDimitry Andric
13304f7ab58eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13314f7ab58eSDimitry Andric    const_local_iterator
13324f7ab58eSDimitry Andric    cend(size_type __n) const
13334f7ab58eSDimitry Andric    {
13344f7ab58eSDimitry Andric        _LIBCPP_ASSERT(__n < bucket_count(),
13354f7ab58eSDimitry Andric            "unordered container::cend(n) called with n >= bucket_count()");
13364f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
13374f7ab58eSDimitry Andric        return const_local_iterator(nullptr, __n, bucket_count(), this);
13384f7ab58eSDimitry Andric#else
13394f7ab58eSDimitry Andric        return const_local_iterator(nullptr, __n, bucket_count());
13404f7ab58eSDimitry Andric#endif
13414f7ab58eSDimitry Andric    }
13424f7ab58eSDimitry Andric
13434f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
13444f7ab58eSDimitry Andric
13454f7ab58eSDimitry Andric    bool __dereferenceable(const const_iterator* __i) const;
13464f7ab58eSDimitry Andric    bool __decrementable(const const_iterator* __i) const;
13474f7ab58eSDimitry Andric    bool __addable(const const_iterator* __i, ptrdiff_t __n) const;
13484f7ab58eSDimitry Andric    bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const;
13494f7ab58eSDimitry Andric
13504f7ab58eSDimitry Andric#endif  // _LIBCPP_DEBUG_LEVEL >= 2
13514f7ab58eSDimitry Andric
13527a984708SDavid Chisnallprivate:
13537a984708SDavid Chisnall    void __rehash(size_type __n);
13547a984708SDavid Chisnall
13557c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
13567a984708SDavid Chisnall    template <class ..._Args>
13577a984708SDavid Chisnall    __node_holder __construct_node(_Args&& ...__args);
13587c82a1ecSDimitry Andric
13597c82a1ecSDimitry Andric    template <class _First, class ..._Rest>
13607c82a1ecSDimitry Andric    __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest);
13617c82a1ecSDimitry Andric#else // _LIBCPP_CXX03_LANG
13627c82a1ecSDimitry Andric    __node_holder __construct_node(const __container_value_type& __v);
13637c82a1ecSDimitry Andric    __node_holder __construct_node_hash(size_t __hash, const __container_value_type& __v);
13647a984708SDavid Chisnall#endif
13657c82a1ecSDimitry Andric
13667a984708SDavid Chisnall
13677a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
13687a984708SDavid Chisnall    void __copy_assign_alloc(const __hash_table& __u)
13697a984708SDavid Chisnall        {__copy_assign_alloc(__u, integral_constant<bool,
13707a984708SDavid Chisnall             __node_traits::propagate_on_container_copy_assignment::value>());}
13717a984708SDavid Chisnall    void __copy_assign_alloc(const __hash_table& __u, true_type);
13727a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
137394e3ee44SDavid Chisnall        void __copy_assign_alloc(const __hash_table&, false_type) {}
13747a984708SDavid Chisnall
13757c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
13767a984708SDavid Chisnall    void __move_assign(__hash_table& __u, false_type);
13777a984708SDavid Chisnall    void __move_assign(__hash_table& __u, true_type)
13787a984708SDavid Chisnall        _NOEXCEPT_(
13797a984708SDavid Chisnall            is_nothrow_move_assignable<__node_allocator>::value &&
13807a984708SDavid Chisnall            is_nothrow_move_assignable<hasher>::value &&
13817a984708SDavid Chisnall            is_nothrow_move_assignable<key_equal>::value);
13827a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
13837a984708SDavid Chisnall    void __move_assign_alloc(__hash_table& __u)
13847a984708SDavid Chisnall        _NOEXCEPT_(
13857a984708SDavid Chisnall            !__node_traits::propagate_on_container_move_assignment::value ||
13867a984708SDavid Chisnall            (is_nothrow_move_assignable<__pointer_allocator>::value &&
13877a984708SDavid Chisnall             is_nothrow_move_assignable<__node_allocator>::value))
13887a984708SDavid Chisnall        {__move_assign_alloc(__u, integral_constant<bool,
13897a984708SDavid Chisnall             __node_traits::propagate_on_container_move_assignment::value>());}
13907a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
13917a984708SDavid Chisnall    void __move_assign_alloc(__hash_table& __u, true_type)
13927a984708SDavid Chisnall        _NOEXCEPT_(
13937a984708SDavid Chisnall            is_nothrow_move_assignable<__pointer_allocator>::value &&
13947a984708SDavid Chisnall            is_nothrow_move_assignable<__node_allocator>::value)
13957a984708SDavid Chisnall    {
13967a984708SDavid Chisnall        __bucket_list_.get_deleter().__alloc() =
13977a984708SDavid Chisnall                _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
13987a984708SDavid Chisnall        __node_alloc() = _VSTD::move(__u.__node_alloc());
13997a984708SDavid Chisnall    }
14007a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
14017a984708SDavid Chisnall        void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
14027c82a1ecSDimitry Andric#endif // _LIBCPP_CXX03_LANG
14037a984708SDavid Chisnall
140480779b37SDimitry Andric    void __deallocate_node(__next_pointer __np) _NOEXCEPT;
1405aed8d94eSDimitry Andric    __next_pointer __detach() _NOEXCEPT;
14064bab9fd9SDavid Chisnall
1407aed8d94eSDimitry Andric    template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map;
1408aed8d94eSDimitry Andric    template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
14097a984708SDavid Chisnall};
14107a984708SDavid Chisnall
14117a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14129729cf09SDimitry Andricinline
14137a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
14147a984708SDavid Chisnall    _NOEXCEPT_(
14157a984708SDavid Chisnall        is_nothrow_default_constructible<__bucket_list>::value &&
14167a984708SDavid Chisnall        is_nothrow_default_constructible<__first_node>::value &&
14179729cf09SDimitry Andric        is_nothrow_default_constructible<__node_allocator>::value &&
14187a984708SDavid Chisnall        is_nothrow_default_constructible<hasher>::value &&
14197a984708SDavid Chisnall        is_nothrow_default_constructible<key_equal>::value)
14207a984708SDavid Chisnall    : __p2_(0),
14217a984708SDavid Chisnall      __p3_(1.0f)
14227a984708SDavid Chisnall{
14237a984708SDavid Chisnall}
14247a984708SDavid Chisnall
14257a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14269729cf09SDimitry Andricinline
14277a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
14287a984708SDavid Chisnall                                                       const key_equal& __eql)
14297a984708SDavid Chisnall    : __bucket_list_(nullptr, __bucket_list_deleter()),
14307a984708SDavid Chisnall      __p1_(),
14317a984708SDavid Chisnall      __p2_(0, __hf),
14327a984708SDavid Chisnall      __p3_(1.0f, __eql)
14337a984708SDavid Chisnall{
14347a984708SDavid Chisnall}
14357a984708SDavid Chisnall
14367a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14377a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
14387a984708SDavid Chisnall                                                       const key_equal& __eql,
14397a984708SDavid Chisnall                                                       const allocator_type& __a)
14407a984708SDavid Chisnall    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1441540d2a8bSDimitry Andric      __p1_(__second_tag(), __node_allocator(__a)),
14427a984708SDavid Chisnall      __p2_(0, __hf),
14437a984708SDavid Chisnall      __p3_(1.0f, __eql)
14447a984708SDavid Chisnall{
14457a984708SDavid Chisnall}
14467a984708SDavid Chisnall
14477a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14487a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
14497a984708SDavid Chisnall    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1450540d2a8bSDimitry Andric      __p1_(__second_tag(), __node_allocator(__a)),
14517a984708SDavid Chisnall      __p2_(0),
14527a984708SDavid Chisnall      __p3_(1.0f)
14537a984708SDavid Chisnall{
14547a984708SDavid Chisnall}
14557a984708SDavid Chisnall
14567a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14577a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
14587a984708SDavid Chisnall    : __bucket_list_(nullptr,
14597a984708SDavid Chisnall          __bucket_list_deleter(allocator_traits<__pointer_allocator>::
14607a984708SDavid Chisnall              select_on_container_copy_construction(
14617a984708SDavid Chisnall                  __u.__bucket_list_.get_deleter().__alloc()), 0)),
1462540d2a8bSDimitry Andric      __p1_(__second_tag(), allocator_traits<__node_allocator>::
14637a984708SDavid Chisnall          select_on_container_copy_construction(__u.__node_alloc())),
14647a984708SDavid Chisnall      __p2_(0, __u.hash_function()),
14657a984708SDavid Chisnall      __p3_(__u.__p3_)
14667a984708SDavid Chisnall{
14677a984708SDavid Chisnall}
14687a984708SDavid Chisnall
14697a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14707a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
14717a984708SDavid Chisnall                                                       const allocator_type& __a)
14727a984708SDavid Chisnall    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1473540d2a8bSDimitry Andric      __p1_(__second_tag(), __node_allocator(__a)),
14747a984708SDavid Chisnall      __p2_(0, __u.hash_function()),
14757a984708SDavid Chisnall      __p3_(__u.__p3_)
14767a984708SDavid Chisnall{
14777a984708SDavid Chisnall}
14787a984708SDavid Chisnall
14797c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
14807a984708SDavid Chisnall
14817a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14827a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
14837a984708SDavid Chisnall        _NOEXCEPT_(
14847a984708SDavid Chisnall            is_nothrow_move_constructible<__bucket_list>::value &&
14857a984708SDavid Chisnall            is_nothrow_move_constructible<__first_node>::value &&
14869729cf09SDimitry Andric            is_nothrow_move_constructible<__node_allocator>::value &&
14877a984708SDavid Chisnall            is_nothrow_move_constructible<hasher>::value &&
14887a984708SDavid Chisnall            is_nothrow_move_constructible<key_equal>::value)
14897a984708SDavid Chisnall    : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
14907a984708SDavid Chisnall      __p1_(_VSTD::move(__u.__p1_)),
14917a984708SDavid Chisnall      __p2_(_VSTD::move(__u.__p2_)),
14927a984708SDavid Chisnall      __p3_(_VSTD::move(__u.__p3_))
14937a984708SDavid Chisnall{
14947a984708SDavid Chisnall    if (size() > 0)
14957a984708SDavid Chisnall    {
1496aed8d94eSDimitry Andric        __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] =
1497aed8d94eSDimitry Andric            __p1_.first().__ptr();
14987a984708SDavid Chisnall        __u.__p1_.first().__next_ = nullptr;
14997a984708SDavid Chisnall        __u.size() = 0;
15007a984708SDavid Chisnall    }
15017a984708SDavid Chisnall}
15027a984708SDavid Chisnall
15037a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15047a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
15057a984708SDavid Chisnall                                                       const allocator_type& __a)
15067a984708SDavid Chisnall    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1507540d2a8bSDimitry Andric      __p1_(__second_tag(), __node_allocator(__a)),
15087a984708SDavid Chisnall      __p2_(0, _VSTD::move(__u.hash_function())),
15097a984708SDavid Chisnall      __p3_(_VSTD::move(__u.__p3_))
15107a984708SDavid Chisnall{
15117a984708SDavid Chisnall    if (__a == allocator_type(__u.__node_alloc()))
15127a984708SDavid Chisnall    {
15137a984708SDavid Chisnall        __bucket_list_.reset(__u.__bucket_list_.release());
15147a984708SDavid Chisnall        __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
15157a984708SDavid Chisnall        __u.__bucket_list_.get_deleter().size() = 0;
15167a984708SDavid Chisnall        if (__u.size() > 0)
15177a984708SDavid Chisnall        {
15187a984708SDavid Chisnall            __p1_.first().__next_ = __u.__p1_.first().__next_;
15197a984708SDavid Chisnall            __u.__p1_.first().__next_ = nullptr;
1520aed8d94eSDimitry Andric            __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] =
1521aed8d94eSDimitry Andric                __p1_.first().__ptr();
15227a984708SDavid Chisnall            size() = __u.size();
15237a984708SDavid Chisnall            __u.size() = 0;
15247a984708SDavid Chisnall        }
15257a984708SDavid Chisnall    }
15267a984708SDavid Chisnall}
15277a984708SDavid Chisnall
15287c82a1ecSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
15297a984708SDavid Chisnall
15307a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15317a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
15327a984708SDavid Chisnall{
1533540d2a8bSDimitry Andric#if defined(_LIBCPP_CXX03_LANG)
15347c82a1ecSDimitry Andric    static_assert((is_copy_constructible<key_equal>::value),
15357c82a1ecSDimitry Andric                 "Predicate must be copy-constructible.");
15367c82a1ecSDimitry Andric    static_assert((is_copy_constructible<hasher>::value),
15377c82a1ecSDimitry Andric                 "Hasher must be copy-constructible.");
1538540d2a8bSDimitry Andric#endif
1539540d2a8bSDimitry Andric
154080779b37SDimitry Andric    __deallocate_node(__p1_.first().__next_);
15414f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
15424f7ab58eSDimitry Andric    __get_db()->__erase_c(this);
15434f7ab58eSDimitry Andric#endif
15447a984708SDavid Chisnall}
15457a984708SDavid Chisnall
15467a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15477a984708SDavid Chisnallvoid
15487a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
15497a984708SDavid Chisnall        const __hash_table& __u, true_type)
15507a984708SDavid Chisnall{
15517a984708SDavid Chisnall    if (__node_alloc() != __u.__node_alloc())
15527a984708SDavid Chisnall    {
15537a984708SDavid Chisnall        clear();
15547a984708SDavid Chisnall        __bucket_list_.reset();
15557a984708SDavid Chisnall        __bucket_list_.get_deleter().size() = 0;
15567a984708SDavid Chisnall    }
15577a984708SDavid Chisnall    __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
15587a984708SDavid Chisnall    __node_alloc() = __u.__node_alloc();
15597a984708SDavid Chisnall}
15607a984708SDavid Chisnall
15617a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15627a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>&
15637a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
15647a984708SDavid Chisnall{
15657a984708SDavid Chisnall    if (this != &__u)
15667a984708SDavid Chisnall    {
15677a984708SDavid Chisnall        __copy_assign_alloc(__u);
15687a984708SDavid Chisnall        hash_function() = __u.hash_function();
15697a984708SDavid Chisnall        key_eq() = __u.key_eq();
15707a984708SDavid Chisnall        max_load_factor() = __u.max_load_factor();
15717a984708SDavid Chisnall        __assign_multi(__u.begin(), __u.end());
15727a984708SDavid Chisnall    }
15737a984708SDavid Chisnall    return *this;
15747a984708SDavid Chisnall}
15757a984708SDavid Chisnall
15767a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15777a984708SDavid Chisnallvoid
157880779b37SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np)
15797a984708SDavid Chisnall    _NOEXCEPT
15807a984708SDavid Chisnall{
15817a984708SDavid Chisnall    __node_allocator& __na = __node_alloc();
15827a984708SDavid Chisnall    while (__np != nullptr)
15837a984708SDavid Chisnall    {
1584aed8d94eSDimitry Andric        __next_pointer __next = __np->__next_;
15854f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
15864f7ab58eSDimitry Andric        __c_node* __c = __get_db()->__find_c_and_lock(this);
15874f7ab58eSDimitry Andric        for (__i_node** __p = __c->end_; __p != __c->beg_; )
15884f7ab58eSDimitry Andric        {
15894f7ab58eSDimitry Andric            --__p;
15904f7ab58eSDimitry Andric            iterator* __i = static_cast<iterator*>((*__p)->__i_);
15914f7ab58eSDimitry Andric            if (__i->__node_ == __np)
15924f7ab58eSDimitry Andric            {
15934f7ab58eSDimitry Andric                (*__p)->__c_ = nullptr;
15944f7ab58eSDimitry Andric                if (--__c->end_ != __p)
15954f7ab58eSDimitry Andric                    memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
15964f7ab58eSDimitry Andric            }
15974f7ab58eSDimitry Andric        }
15984f7ab58eSDimitry Andric        __get_db()->unlock();
15994f7ab58eSDimitry Andric#endif
1600aed8d94eSDimitry Andric        __node_pointer __real_np = __np->__upcast();
1601aed8d94eSDimitry Andric        __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__value_));
1602aed8d94eSDimitry Andric        __node_traits::deallocate(__na, __real_np, 1);
16037a984708SDavid Chisnall        __np = __next;
16047a984708SDavid Chisnall    }
16057a984708SDavid Chisnall}
16067a984708SDavid Chisnall
16077a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1608aed8d94eSDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
16097a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
16107a984708SDavid Chisnall{
16117a984708SDavid Chisnall    size_type __bc = bucket_count();
16127a984708SDavid Chisnall    for (size_type __i = 0; __i < __bc; ++__i)
16137a984708SDavid Chisnall        __bucket_list_[__i] = nullptr;
16147a984708SDavid Chisnall    size() = 0;
1615aed8d94eSDimitry Andric    __next_pointer __cache = __p1_.first().__next_;
16167a984708SDavid Chisnall    __p1_.first().__next_ = nullptr;
16177a984708SDavid Chisnall    return __cache;
16187a984708SDavid Chisnall}
16197a984708SDavid Chisnall
16207c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
16217a984708SDavid Chisnall
16227a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
16237a984708SDavid Chisnallvoid
16247a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
16257a984708SDavid Chisnall        __hash_table& __u, true_type)
16267a984708SDavid Chisnall    _NOEXCEPT_(
16277a984708SDavid Chisnall        is_nothrow_move_assignable<__node_allocator>::value &&
16287a984708SDavid Chisnall        is_nothrow_move_assignable<hasher>::value &&
16297a984708SDavid Chisnall        is_nothrow_move_assignable<key_equal>::value)
16307a984708SDavid Chisnall{
16317a984708SDavid Chisnall    clear();
16327a984708SDavid Chisnall    __bucket_list_.reset(__u.__bucket_list_.release());
16337a984708SDavid Chisnall    __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
16347a984708SDavid Chisnall    __u.__bucket_list_.get_deleter().size() = 0;
16357a984708SDavid Chisnall    __move_assign_alloc(__u);
16367a984708SDavid Chisnall    size() = __u.size();
16377a984708SDavid Chisnall    hash_function() = _VSTD::move(__u.hash_function());
16387a984708SDavid Chisnall    max_load_factor() = __u.max_load_factor();
16397a984708SDavid Chisnall    key_eq() = _VSTD::move(__u.key_eq());
16407a984708SDavid Chisnall    __p1_.first().__next_ = __u.__p1_.first().__next_;
16417a984708SDavid Chisnall    if (size() > 0)
16427a984708SDavid Chisnall    {
1643aed8d94eSDimitry Andric        __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] =
1644aed8d94eSDimitry Andric            __p1_.first().__ptr();
16457a984708SDavid Chisnall        __u.__p1_.first().__next_ = nullptr;
16467a984708SDavid Chisnall        __u.size() = 0;
16477a984708SDavid Chisnall    }
16484f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
16494f7ab58eSDimitry Andric    __get_db()->swap(this, &__u);
16504f7ab58eSDimitry Andric#endif
16517a984708SDavid Chisnall}
16527a984708SDavid Chisnall
16537a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
16547a984708SDavid Chisnallvoid
16557a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
16567a984708SDavid Chisnall        __hash_table& __u, false_type)
16577a984708SDavid Chisnall{
16587a984708SDavid Chisnall    if (__node_alloc() == __u.__node_alloc())
16597a984708SDavid Chisnall        __move_assign(__u, true_type());
16607a984708SDavid Chisnall    else
16617a984708SDavid Chisnall    {
16627a984708SDavid Chisnall        hash_function() = _VSTD::move(__u.hash_function());
16637a984708SDavid Chisnall        key_eq() = _VSTD::move(__u.key_eq());
16647a984708SDavid Chisnall        max_load_factor() = __u.max_load_factor();
16657a984708SDavid Chisnall        if (bucket_count() != 0)
16667a984708SDavid Chisnall        {
1667aed8d94eSDimitry Andric            __next_pointer __cache = __detach();
16687a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
16697a984708SDavid Chisnall            try
16707a984708SDavid Chisnall            {
16717a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
16727a984708SDavid Chisnall                const_iterator __i = __u.begin();
16737a984708SDavid Chisnall                while (__cache != nullptr && __u.size() != 0)
16747a984708SDavid Chisnall                {
1675aed8d94eSDimitry Andric                    __cache->__upcast()->__value_ =
1676aed8d94eSDimitry Andric                        _VSTD::move(__u.remove(__i++)->__value_);
1677aed8d94eSDimitry Andric                    __next_pointer __next = __cache->__next_;
1678aed8d94eSDimitry Andric                    __node_insert_multi(__cache->__upcast());
16797a984708SDavid Chisnall                    __cache = __next;
16807a984708SDavid Chisnall                }
16817a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
16827a984708SDavid Chisnall            }
16837a984708SDavid Chisnall            catch (...)
16847a984708SDavid Chisnall            {
168580779b37SDimitry Andric                __deallocate_node(__cache);
16867a984708SDavid Chisnall                throw;
16877a984708SDavid Chisnall            }
16887a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
168980779b37SDimitry Andric            __deallocate_node(__cache);
16907a984708SDavid Chisnall        }
16917a984708SDavid Chisnall        const_iterator __i = __u.begin();
16927a984708SDavid Chisnall        while (__u.size() != 0)
16937a984708SDavid Chisnall        {
16947c82a1ecSDimitry Andric            __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__value_));
16957a984708SDavid Chisnall            __node_insert_multi(__h.get());
16967a984708SDavid Chisnall            __h.release();
16977a984708SDavid Chisnall        }
16987a984708SDavid Chisnall    }
16997a984708SDavid Chisnall}
17007a984708SDavid Chisnall
17017a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
17029729cf09SDimitry Andricinline
17037a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>&
17047a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
17057a984708SDavid Chisnall    _NOEXCEPT_(
17067a984708SDavid Chisnall        __node_traits::propagate_on_container_move_assignment::value &&
17077a984708SDavid Chisnall        is_nothrow_move_assignable<__node_allocator>::value &&
17087a984708SDavid Chisnall        is_nothrow_move_assignable<hasher>::value &&
17097a984708SDavid Chisnall        is_nothrow_move_assignable<key_equal>::value)
17107a984708SDavid Chisnall{
17117a984708SDavid Chisnall    __move_assign(__u, integral_constant<bool,
17127a984708SDavid Chisnall                  __node_traits::propagate_on_container_move_assignment::value>());
17137a984708SDavid Chisnall    return *this;
17147a984708SDavid Chisnall}
17157a984708SDavid Chisnall
17167c82a1ecSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
17177a984708SDavid Chisnall
17187a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
17197a984708SDavid Chisnalltemplate <class _InputIterator>
17207a984708SDavid Chisnallvoid
17217a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
17227a984708SDavid Chisnall                                                          _InputIterator __last)
17237a984708SDavid Chisnall{
17247c82a1ecSDimitry Andric    typedef iterator_traits<_InputIterator> _ITraits;
17257c82a1ecSDimitry Andric    typedef typename _ITraits::value_type _ItValueType;
17267c82a1ecSDimitry Andric    static_assert((is_same<_ItValueType, __container_value_type>::value),
17277c82a1ecSDimitry Andric                  "__assign_unique may only be called with the containers value type");
17287c82a1ecSDimitry Andric
17297a984708SDavid Chisnall    if (bucket_count() != 0)
17307a984708SDavid Chisnall    {
1731aed8d94eSDimitry Andric        __next_pointer __cache = __detach();
17327a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
17337a984708SDavid Chisnall        try
17347a984708SDavid Chisnall        {
17357a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
17367a984708SDavid Chisnall            for (; __cache != nullptr && __first != __last; ++__first)
17377a984708SDavid Chisnall            {
1738aed8d94eSDimitry Andric                __cache->__upcast()->__value_ = *__first;
1739aed8d94eSDimitry Andric                __next_pointer __next = __cache->__next_;
1740aed8d94eSDimitry Andric                __node_insert_unique(__cache->__upcast());
17417a984708SDavid Chisnall                __cache = __next;
17427a984708SDavid Chisnall            }
17437a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
17447a984708SDavid Chisnall        }
17457a984708SDavid Chisnall        catch (...)
17467a984708SDavid Chisnall        {
174780779b37SDimitry Andric            __deallocate_node(__cache);
17487a984708SDavid Chisnall            throw;
17497a984708SDavid Chisnall        }
17507a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
175180779b37SDimitry Andric        __deallocate_node(__cache);
17527a984708SDavid Chisnall    }
17537a984708SDavid Chisnall    for (; __first != __last; ++__first)
17547a984708SDavid Chisnall        __insert_unique(*__first);
17557a984708SDavid Chisnall}
17567a984708SDavid Chisnall
17577a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
17587a984708SDavid Chisnalltemplate <class _InputIterator>
17597a984708SDavid Chisnallvoid
17607a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
17617a984708SDavid Chisnall                                                         _InputIterator __last)
17627a984708SDavid Chisnall{
17637c82a1ecSDimitry Andric    typedef iterator_traits<_InputIterator> _ITraits;
17647c82a1ecSDimitry Andric    typedef typename _ITraits::value_type _ItValueType;
17657c82a1ecSDimitry Andric    static_assert((is_same<_ItValueType, __container_value_type>::value ||
17667c82a1ecSDimitry Andric                  is_same<_ItValueType, __node_value_type>::value),
17677c82a1ecSDimitry Andric                  "__assign_multi may only be called with the containers value type"
17687c82a1ecSDimitry Andric                  " or the nodes value type");
17697a984708SDavid Chisnall    if (bucket_count() != 0)
17707a984708SDavid Chisnall    {
1771aed8d94eSDimitry Andric        __next_pointer __cache = __detach();
17727a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
17737a984708SDavid Chisnall        try
17747a984708SDavid Chisnall        {
17757a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
17767a984708SDavid Chisnall            for (; __cache != nullptr && __first != __last; ++__first)
17777a984708SDavid Chisnall            {
1778aed8d94eSDimitry Andric                __cache->__upcast()->__value_ = *__first;
1779aed8d94eSDimitry Andric                __next_pointer __next = __cache->__next_;
1780aed8d94eSDimitry Andric                __node_insert_multi(__cache->__upcast());
17817a984708SDavid Chisnall                __cache = __next;
17827a984708SDavid Chisnall            }
17837a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
17847a984708SDavid Chisnall        }
17857a984708SDavid Chisnall        catch (...)
17867a984708SDavid Chisnall        {
178780779b37SDimitry Andric            __deallocate_node(__cache);
17887a984708SDavid Chisnall            throw;
17897a984708SDavid Chisnall        }
17907a984708SDavid Chisnall#endif  // _LIBCPP_NO_EXCEPTIONS
179180779b37SDimitry Andric        __deallocate_node(__cache);
17927a984708SDavid Chisnall    }
17937a984708SDavid Chisnall    for (; __first != __last; ++__first)
17947c82a1ecSDimitry Andric        __insert_multi(_NodeTypes::__get_value(*__first));
17957a984708SDavid Chisnall}
17967a984708SDavid Chisnall
17977a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
17989729cf09SDimitry Andricinline
17997a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
18007a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
18017a984708SDavid Chisnall{
18024f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
18034f7ab58eSDimitry Andric    return iterator(__p1_.first().__next_, this);
18044f7ab58eSDimitry Andric#else
18057a984708SDavid Chisnall    return iterator(__p1_.first().__next_);
18064f7ab58eSDimitry Andric#endif
18077a984708SDavid Chisnall}
18087a984708SDavid Chisnall
18097a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18109729cf09SDimitry Andricinline
18117a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
18127a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
18137a984708SDavid Chisnall{
18144f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
18154f7ab58eSDimitry Andric    return iterator(nullptr, this);
18164f7ab58eSDimitry Andric#else
18177a984708SDavid Chisnall    return iterator(nullptr);
18184f7ab58eSDimitry Andric#endif
18197a984708SDavid Chisnall}
18207a984708SDavid Chisnall
18217a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18229729cf09SDimitry Andricinline
18237a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
18247a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
18257a984708SDavid Chisnall{
18264f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
18274f7ab58eSDimitry Andric    return const_iterator(__p1_.first().__next_, this);
18284f7ab58eSDimitry Andric#else
18297a984708SDavid Chisnall    return const_iterator(__p1_.first().__next_);
18304f7ab58eSDimitry Andric#endif
18317a984708SDavid Chisnall}
18327a984708SDavid Chisnall
18337a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18349729cf09SDimitry Andricinline
18357a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
18367a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
18377a984708SDavid Chisnall{
18384f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
18394f7ab58eSDimitry Andric    return const_iterator(nullptr, this);
18404f7ab58eSDimitry Andric#else
18417a984708SDavid Chisnall    return const_iterator(nullptr);
18424f7ab58eSDimitry Andric#endif
18437a984708SDavid Chisnall}
18447a984708SDavid Chisnall
18457a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18467a984708SDavid Chisnallvoid
18477a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
18487a984708SDavid Chisnall{
18497a984708SDavid Chisnall    if (size() > 0)
18507a984708SDavid Chisnall    {
185180779b37SDimitry Andric        __deallocate_node(__p1_.first().__next_);
18527a984708SDavid Chisnall        __p1_.first().__next_ = nullptr;
18537a984708SDavid Chisnall        size_type __bc = bucket_count();
18547a984708SDavid Chisnall        for (size_type __i = 0; __i < __bc; ++__i)
18557a984708SDavid Chisnall            __bucket_list_[__i] = nullptr;
18567a984708SDavid Chisnall        size() = 0;
18577a984708SDavid Chisnall    }
18587a984708SDavid Chisnall}
18597a984708SDavid Chisnall
1860*b5893f02SDimitry Andric
1861*b5893f02SDimitry Andric// Prepare the container for an insertion of the value __value with the hash
1862*b5893f02SDimitry Andric// __hash. This does a lookup into the container to see if __value is already
1863*b5893f02SDimitry Andric// present, and performs a rehash if necessary. Returns a pointer to the
1864*b5893f02SDimitry Andric// existing element if it exists, otherwise nullptr.
1865*b5893f02SDimitry Andric//
1866*b5893f02SDimitry Andric// Note that this function does forward exceptions if key_eq() throws, and never
1867*b5893f02SDimitry Andric// mutates __value or actually inserts into the map.
18687a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1869*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY
1870*b5893f02SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1871*b5893f02SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare(
1872*b5893f02SDimitry Andric    size_t __hash, value_type& __value)
18737a984708SDavid Chisnall{
18747a984708SDavid Chisnall    size_type __bc = bucket_count();
1875*b5893f02SDimitry Andric
18767a984708SDavid Chisnall    if (__bc != 0)
18777a984708SDavid Chisnall    {
1878*b5893f02SDimitry Andric        size_t __chash = __constrain_hash(__hash, __bc);
1879*b5893f02SDimitry Andric        __next_pointer __ndptr = __bucket_list_[__chash];
18807a984708SDavid Chisnall        if (__ndptr != nullptr)
18817a984708SDavid Chisnall        {
18827a984708SDavid Chisnall            for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
1883aed8d94eSDimitry Andric                                             __constrain_hash(__ndptr->__hash(), __bc) == __chash;
18847a984708SDavid Chisnall                                                     __ndptr = __ndptr->__next_)
18857a984708SDavid Chisnall            {
1886*b5893f02SDimitry Andric                if (key_eq()(__ndptr->__upcast()->__value_, __value))
1887*b5893f02SDimitry Andric                    return __ndptr;
18887a984708SDavid Chisnall            }
18897a984708SDavid Chisnall        }
18907a984708SDavid Chisnall    }
18917a984708SDavid Chisnall    if (size()+1 > __bc * max_load_factor() || __bc == 0)
18927a984708SDavid Chisnall    {
1893854fa44bSDimitry Andric        rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
18947a984708SDavid Chisnall                                     size_type(ceil(float(size() + 1) / max_load_factor()))));
18957a984708SDavid Chisnall    }
1896*b5893f02SDimitry Andric    return nullptr;
1897*b5893f02SDimitry Andric}
1898*b5893f02SDimitry Andric
1899*b5893f02SDimitry Andric// Insert the node __nd into the container by pushing it into the right bucket,
1900*b5893f02SDimitry Andric// and updating size(). Assumes that __nd->__hash is up-to-date, and that
1901*b5893f02SDimitry Andric// rehashing has already occurred and that no element with the same key exists
1902*b5893f02SDimitry Andric// in the map.
1903*b5893f02SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1904*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY
1905*b5893f02SDimitry Andricvoid
1906*b5893f02SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_perform(
1907*b5893f02SDimitry Andric    __node_pointer __nd) _NOEXCEPT
1908*b5893f02SDimitry Andric{
1909*b5893f02SDimitry Andric    size_type __bc = bucket_count();
1910*b5893f02SDimitry Andric    size_t __chash = __constrain_hash(__nd->__hash(), __bc);
19117a984708SDavid Chisnall    // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1912aed8d94eSDimitry Andric    __next_pointer __pn = __bucket_list_[__chash];
19137a984708SDavid Chisnall    if (__pn == nullptr)
19147a984708SDavid Chisnall    {
1915aed8d94eSDimitry Andric        __pn =__p1_.first().__ptr();
19167a984708SDavid Chisnall        __nd->__next_ = __pn->__next_;
1917aed8d94eSDimitry Andric        __pn->__next_ = __nd->__ptr();
19187a984708SDavid Chisnall        // fix up __bucket_list_
19197a984708SDavid Chisnall        __bucket_list_[__chash] = __pn;
19207a984708SDavid Chisnall        if (__nd->__next_ != nullptr)
1921aed8d94eSDimitry Andric            __bucket_list_[__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr();
19227a984708SDavid Chisnall    }
19237a984708SDavid Chisnall    else
19247a984708SDavid Chisnall    {
19257a984708SDavid Chisnall        __nd->__next_ = __pn->__next_;
1926aed8d94eSDimitry Andric        __pn->__next_ = __nd->__ptr();
19277a984708SDavid Chisnall    }
19287a984708SDavid Chisnall    ++size();
19297a984708SDavid Chisnall}
19307a984708SDavid Chisnall
19317a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1932*b5893f02SDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1933*b5893f02SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
19347a984708SDavid Chisnall{
1935*b5893f02SDimitry Andric    __nd->__hash_ = hash_function()(__nd->__value_);
1936*b5893f02SDimitry Andric    __next_pointer __existing_node =
1937*b5893f02SDimitry Andric        __node_insert_unique_prepare(__nd->__hash(), __nd->__value_);
1938*b5893f02SDimitry Andric
1939*b5893f02SDimitry Andric    // Insert the node, unless it already exists in the container.
1940*b5893f02SDimitry Andric    bool __inserted = false;
1941*b5893f02SDimitry Andric    if (__existing_node == nullptr)
1942*b5893f02SDimitry Andric    {
1943*b5893f02SDimitry Andric        __node_insert_unique_perform(__nd);
1944*b5893f02SDimitry Andric        __existing_node = __nd->__ptr();
1945*b5893f02SDimitry Andric        __inserted = true;
1946*b5893f02SDimitry Andric    }
1947*b5893f02SDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
1948*b5893f02SDimitry Andric    return pair<iterator, bool>(iterator(__existing_node, this), __inserted);
1949*b5893f02SDimitry Andric#else
1950*b5893f02SDimitry Andric    return pair<iterator, bool>(iterator(__existing_node), __inserted);
1951*b5893f02SDimitry Andric#endif
1952*b5893f02SDimitry Andric}
1953*b5893f02SDimitry Andric
1954*b5893f02SDimitry Andric// Prepare the container for an insertion of the value __cp_val with the hash
1955*b5893f02SDimitry Andric// __cp_hash. This does a lookup into the container to see if __cp_value is
1956*b5893f02SDimitry Andric// already present, and performs a rehash if necessary. Returns a pointer to the
1957*b5893f02SDimitry Andric// last occurance of __cp_val in the map.
1958*b5893f02SDimitry Andric//
1959*b5893f02SDimitry Andric// Note that this function does forward exceptions if key_eq() throws, and never
1960*b5893f02SDimitry Andric// mutates __value or actually inserts into the map.
1961*b5893f02SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1962*b5893f02SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1963*b5893f02SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_prepare(
1964*b5893f02SDimitry Andric    size_t __cp_hash, value_type& __cp_val)
1965*b5893f02SDimitry Andric{
19667a984708SDavid Chisnall    size_type __bc = bucket_count();
19677a984708SDavid Chisnall    if (size()+1 > __bc * max_load_factor() || __bc == 0)
19687a984708SDavid Chisnall    {
1969854fa44bSDimitry Andric        rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
19707a984708SDavid Chisnall                       size_type(ceil(float(size() + 1) / max_load_factor()))));
19717a984708SDavid Chisnall        __bc = bucket_count();
19727a984708SDavid Chisnall    }
1973*b5893f02SDimitry Andric    size_t __chash = __constrain_hash(__cp_hash, __bc);
1974aed8d94eSDimitry Andric    __next_pointer __pn = __bucket_list_[__chash];
1975*b5893f02SDimitry Andric    if (__pn != nullptr)
1976*b5893f02SDimitry Andric    {
1977*b5893f02SDimitry Andric        for (bool __found = false; __pn->__next_ != nullptr &&
1978*b5893f02SDimitry Andric                                   __constrain_hash(__pn->__next_->__hash(), __bc) == __chash;
1979*b5893f02SDimitry Andric                                                           __pn = __pn->__next_)
1980*b5893f02SDimitry Andric        {
1981*b5893f02SDimitry Andric            //      __found    key_eq()     action
1982*b5893f02SDimitry Andric            //      false       false       loop
1983*b5893f02SDimitry Andric            //      true        true        loop
1984*b5893f02SDimitry Andric            //      false       true        set __found to true
1985*b5893f02SDimitry Andric            //      true        false       break
1986*b5893f02SDimitry Andric            if (__found != (__pn->__next_->__hash() == __cp_hash &&
1987*b5893f02SDimitry Andric                            key_eq()(__pn->__next_->__upcast()->__value_, __cp_val)))
1988*b5893f02SDimitry Andric            {
1989*b5893f02SDimitry Andric                if (!__found)
1990*b5893f02SDimitry Andric                    __found = true;
1991*b5893f02SDimitry Andric                else
1992*b5893f02SDimitry Andric                    break;
1993*b5893f02SDimitry Andric            }
1994*b5893f02SDimitry Andric        }
1995*b5893f02SDimitry Andric    }
1996*b5893f02SDimitry Andric    return __pn;
1997*b5893f02SDimitry Andric}
1998*b5893f02SDimitry Andric
1999*b5893f02SDimitry Andric// Insert the node __cp into the container after __pn (which is the last node in
2000*b5893f02SDimitry Andric// the bucket that compares equal to __cp). Rehashing, and checking for
2001*b5893f02SDimitry Andric// uniqueness has already been performed (in __node_insert_multi_prepare), so
2002*b5893f02SDimitry Andric// all we need to do is update the bucket and size(). Assumes that __cp->__hash
2003*b5893f02SDimitry Andric// is up-to-date.
2004*b5893f02SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
2005*b5893f02SDimitry Andricvoid
2006*b5893f02SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform(
2007*b5893f02SDimitry Andric    __node_pointer __cp, __next_pointer __pn) _NOEXCEPT
2008*b5893f02SDimitry Andric{
2009*b5893f02SDimitry Andric    size_type __bc = bucket_count();
2010*b5893f02SDimitry Andric    size_t __chash = __constrain_hash(__cp->__hash_, __bc);
20117a984708SDavid Chisnall    if (__pn == nullptr)
20127a984708SDavid Chisnall    {
2013aed8d94eSDimitry Andric        __pn =__p1_.first().__ptr();
20147a984708SDavid Chisnall        __cp->__next_ = __pn->__next_;
2015aed8d94eSDimitry Andric        __pn->__next_ = __cp->__ptr();
20167a984708SDavid Chisnall        // fix up __bucket_list_
20177a984708SDavid Chisnall        __bucket_list_[__chash] = __pn;
20187a984708SDavid Chisnall        if (__cp->__next_ != nullptr)
2019aed8d94eSDimitry Andric            __bucket_list_[__constrain_hash(__cp->__next_->__hash(), __bc)]
2020aed8d94eSDimitry Andric                = __cp->__ptr();
20217a984708SDavid Chisnall    }
20227a984708SDavid Chisnall    else
20237a984708SDavid Chisnall    {
20247a984708SDavid Chisnall        __cp->__next_ = __pn->__next_;
2025aed8d94eSDimitry Andric        __pn->__next_ = __cp->__ptr();
20267a984708SDavid Chisnall        if (__cp->__next_ != nullptr)
20277a984708SDavid Chisnall        {
2028aed8d94eSDimitry Andric            size_t __nhash = __constrain_hash(__cp->__next_->__hash(), __bc);
20297a984708SDavid Chisnall            if (__nhash != __chash)
2030aed8d94eSDimitry Andric                __bucket_list_[__nhash] = __cp->__ptr();
20317a984708SDavid Chisnall        }
20327a984708SDavid Chisnall    }
20337a984708SDavid Chisnall    ++size();
2034*b5893f02SDimitry Andric}
2035*b5893f02SDimitry Andric
2036*b5893f02SDimitry Andric
2037*b5893f02SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
2038*b5893f02SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2039*b5893f02SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
2040*b5893f02SDimitry Andric{
2041*b5893f02SDimitry Andric    __cp->__hash_ = hash_function()(__cp->__value_);
2042*b5893f02SDimitry Andric    __next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__value_);
2043*b5893f02SDimitry Andric    __node_insert_multi_perform(__cp, __pn);
2044*b5893f02SDimitry Andric
20454f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
2046aed8d94eSDimitry Andric    return iterator(__cp->__ptr(), this);
20474f7ab58eSDimitry Andric#else
2048aed8d94eSDimitry Andric    return iterator(__cp->__ptr());
20494f7ab58eSDimitry Andric#endif
20507a984708SDavid Chisnall}
20517a984708SDavid Chisnall
20527a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
20537a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
20547a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
20557a984708SDavid Chisnall        const_iterator __p, __node_pointer __cp)
20567a984708SDavid Chisnall{
20574f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
20584f7ab58eSDimitry Andric    _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
20594f7ab58eSDimitry Andric        "unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
20604f7ab58eSDimitry Andric        " referring to this unordered container");
20614f7ab58eSDimitry Andric#endif
20627a984708SDavid Chisnall    if (__p != end() && key_eq()(*__p, __cp->__value_))
20637a984708SDavid Chisnall    {
2064aed8d94eSDimitry Andric        __next_pointer __np = __p.__node_;
2065aed8d94eSDimitry Andric        __cp->__hash_ = __np->__hash();
20667a984708SDavid Chisnall        size_type __bc = bucket_count();
20677a984708SDavid Chisnall        if (size()+1 > __bc * max_load_factor() || __bc == 0)
20687a984708SDavid Chisnall        {
2069854fa44bSDimitry Andric            rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
20707a984708SDavid Chisnall                           size_type(ceil(float(size() + 1) / max_load_factor()))));
20717a984708SDavid Chisnall            __bc = bucket_count();
20727a984708SDavid Chisnall        }
2073936e9439SDimitry Andric        size_t __chash = __constrain_hash(__cp->__hash_, __bc);
2074aed8d94eSDimitry Andric        __next_pointer __pp = __bucket_list_[__chash];
20757a984708SDavid Chisnall        while (__pp->__next_ != __np)
20767a984708SDavid Chisnall            __pp = __pp->__next_;
20777a984708SDavid Chisnall        __cp->__next_ = __np;
2078aed8d94eSDimitry Andric        __pp->__next_ = static_cast<__next_pointer>(__cp);
20797a984708SDavid Chisnall        ++size();
20804f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
2081aed8d94eSDimitry Andric        return iterator(static_cast<__next_pointer>(__cp), this);
20824f7ab58eSDimitry Andric#else
2083aed8d94eSDimitry Andric        return iterator(static_cast<__next_pointer>(__cp));
20844f7ab58eSDimitry Andric#endif
20857a984708SDavid Chisnall    }
20867a984708SDavid Chisnall    return __node_insert_multi(__cp);
20877a984708SDavid Chisnall}
20887a984708SDavid Chisnall
2089854fa44bSDimitry Andric
2090854fa44bSDimitry Andric
20917c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
2092854fa44bSDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
20937c82a1ecSDimitry Andrictemplate <class _Key, class ..._Args>
2094854fa44bSDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
20957c82a1ecSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args)
2096854fa44bSDimitry Andric#else
2097854fa44bSDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
20987c82a1ecSDimitry Andrictemplate <class _Key, class _Args>
2099854fa44bSDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
21007c82a1ecSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args& __args)
2101854fa44bSDimitry Andric#endif
2102854fa44bSDimitry Andric{
21037c82a1ecSDimitry Andric
21047c82a1ecSDimitry Andric    size_t __hash = hash_function()(__k);
21057a984708SDavid Chisnall    size_type __bc = bucket_count();
21067a984708SDavid Chisnall    bool __inserted = false;
2107aed8d94eSDimitry Andric    __next_pointer __nd;
21087a984708SDavid Chisnall    size_t __chash;
21097a984708SDavid Chisnall    if (__bc != 0)
21107a984708SDavid Chisnall    {
2111936e9439SDimitry Andric        __chash = __constrain_hash(__hash, __bc);
21127a984708SDavid Chisnall        __nd = __bucket_list_[__chash];
21137a984708SDavid Chisnall        if (__nd != nullptr)
21147a984708SDavid Chisnall        {
21157a984708SDavid Chisnall            for (__nd = __nd->__next_; __nd != nullptr &&
2116aed8d94eSDimitry Andric                (__nd->__hash() == __hash || __constrain_hash(__nd->__hash(), __bc) == __chash);
21177a984708SDavid Chisnall                                                           __nd = __nd->__next_)
21187a984708SDavid Chisnall            {
2119aed8d94eSDimitry Andric                if (key_eq()(__nd->__upcast()->__value_, __k))
21207a984708SDavid Chisnall                    goto __done;
21217a984708SDavid Chisnall            }
21227a984708SDavid Chisnall        }
21237a984708SDavid Chisnall    }
21247a984708SDavid Chisnall    {
21257c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
21267c82a1ecSDimitry Andric        __node_holder __h = __construct_node_hash(__hash, _VSTD::forward<_Args>(__args)...);
21277c82a1ecSDimitry Andric#else
21287c82a1ecSDimitry Andric        __node_holder __h = __construct_node_hash(__hash, __args);
21297c82a1ecSDimitry Andric#endif
21307a984708SDavid Chisnall        if (size()+1 > __bc * max_load_factor() || __bc == 0)
21317a984708SDavid Chisnall        {
2132854fa44bSDimitry Andric            rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
21337a984708SDavid Chisnall                           size_type(ceil(float(size() + 1) / max_load_factor()))));
21347a984708SDavid Chisnall            __bc = bucket_count();
2135936e9439SDimitry Andric            __chash = __constrain_hash(__hash, __bc);
21367a984708SDavid Chisnall        }
21377a984708SDavid Chisnall        // insert_after __bucket_list_[__chash], or __first_node if bucket is null
2138aed8d94eSDimitry Andric        __next_pointer __pn = __bucket_list_[__chash];
21397a984708SDavid Chisnall        if (__pn == nullptr)
21407a984708SDavid Chisnall        {
2141aed8d94eSDimitry Andric            __pn = __p1_.first().__ptr();
21427a984708SDavid Chisnall            __h->__next_ = __pn->__next_;
2143aed8d94eSDimitry Andric            __pn->__next_ = __h.get()->__ptr();
21447a984708SDavid Chisnall            // fix up __bucket_list_
21457a984708SDavid Chisnall            __bucket_list_[__chash] = __pn;
21467a984708SDavid Chisnall            if (__h->__next_ != nullptr)
2147aed8d94eSDimitry Andric                __bucket_list_[__constrain_hash(__h->__next_->__hash(), __bc)]
2148aed8d94eSDimitry Andric                    = __h.get()->__ptr();
21497a984708SDavid Chisnall        }
21507a984708SDavid Chisnall        else
21517a984708SDavid Chisnall        {
21527a984708SDavid Chisnall            __h->__next_ = __pn->__next_;
2153aed8d94eSDimitry Andric            __pn->__next_ = static_cast<__next_pointer>(__h.get());
21547a984708SDavid Chisnall        }
2155aed8d94eSDimitry Andric        __nd = static_cast<__next_pointer>(__h.release());
21567a984708SDavid Chisnall        // increment size
21577a984708SDavid Chisnall        ++size();
21587a984708SDavid Chisnall        __inserted = true;
21597a984708SDavid Chisnall    }
21607a984708SDavid Chisnall__done:
21614f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
21624f7ab58eSDimitry Andric    return pair<iterator, bool>(iterator(__nd, this), __inserted);
21634f7ab58eSDimitry Andric#else
21647a984708SDavid Chisnall    return pair<iterator, bool>(iterator(__nd), __inserted);
21654f7ab58eSDimitry Andric#endif
21667a984708SDavid Chisnall}
21677a984708SDavid Chisnall
21687c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
21697a984708SDavid Chisnall
21707a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
21717a984708SDavid Chisnalltemplate <class... _Args>
21727a984708SDavid Chisnallpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
21737c82a1ecSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args)
21747a984708SDavid Chisnall{
21757a984708SDavid Chisnall    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
21767a984708SDavid Chisnall    pair<iterator, bool> __r = __node_insert_unique(__h.get());
21777a984708SDavid Chisnall    if (__r.second)
21787a984708SDavid Chisnall        __h.release();
21797a984708SDavid Chisnall    return __r;
21807a984708SDavid Chisnall}
21817a984708SDavid Chisnall
21827a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
21837a984708SDavid Chisnalltemplate <class... _Args>
21847a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
21857a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
21867a984708SDavid Chisnall{
21877a984708SDavid Chisnall    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
21887a984708SDavid Chisnall    iterator __r = __node_insert_multi(__h.get());
21897a984708SDavid Chisnall    __h.release();
21907a984708SDavid Chisnall    return __r;
21917a984708SDavid Chisnall}
21927a984708SDavid Chisnall
21937a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
21947a984708SDavid Chisnalltemplate <class... _Args>
21957a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
21967a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
21977a984708SDavid Chisnall        const_iterator __p, _Args&&... __args)
21987a984708SDavid Chisnall{
21994f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
22004f7ab58eSDimitry Andric    _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
22014f7ab58eSDimitry Andric        "unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
22024f7ab58eSDimitry Andric        " referring to this unordered container");
22034f7ab58eSDimitry Andric#endif
22047a984708SDavid Chisnall    __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
22057a984708SDavid Chisnall    iterator __r = __node_insert_multi(__p, __h.get());
22067a984708SDavid Chisnall    __h.release();
22077a984708SDavid Chisnall    return __r;
22087a984708SDavid Chisnall}
22097a984708SDavid Chisnall
22107c82a1ecSDimitry Andric#else // _LIBCPP_CXX03_LANG
22117a984708SDavid Chisnall
22127a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
22137a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
22147c82a1ecSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const __container_value_type& __x)
22157a984708SDavid Chisnall{
22167a984708SDavid Chisnall    __node_holder __h = __construct_node(__x);
22177a984708SDavid Chisnall    iterator __r = __node_insert_multi(__h.get());
22187a984708SDavid Chisnall    __h.release();
22197a984708SDavid Chisnall    return __r;
22207a984708SDavid Chisnall}
22217a984708SDavid Chisnall
22227a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
22237a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
22247a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
22257c82a1ecSDimitry Andric                                                         const __container_value_type& __x)
22267a984708SDavid Chisnall{
22274f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
22284f7ab58eSDimitry Andric    _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
22294f7ab58eSDimitry Andric        "unordered container::insert(const_iterator, lvalue) called with an iterator not"
22304f7ab58eSDimitry Andric        " referring to this unordered container");
22314f7ab58eSDimitry Andric#endif
22327a984708SDavid Chisnall    __node_holder __h = __construct_node(__x);
22337a984708SDavid Chisnall    iterator __r = __node_insert_multi(__p, __h.get());
22347a984708SDavid Chisnall    __h.release();
22357a984708SDavid Chisnall    return __r;
22367a984708SDavid Chisnall}
22377a984708SDavid Chisnall
22387c82a1ecSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
22397a984708SDavid Chisnall
22404ba319b5SDimitry Andric#if _LIBCPP_STD_VER > 14
22414ba319b5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
22424ba319b5SDimitry Andrictemplate <class _NodeHandle, class _InsertReturnType>
22434ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
22444ba319b5SDimitry Andric_InsertReturnType
22454ba319b5SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
22464ba319b5SDimitry Andric    _NodeHandle&& __nh)
22474ba319b5SDimitry Andric{
22484ba319b5SDimitry Andric    if (__nh.empty())
22494ba319b5SDimitry Andric        return _InsertReturnType{end(), false, _NodeHandle()};
22504ba319b5SDimitry Andric    pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
22514ba319b5SDimitry Andric    if (__result.second)
22524ba319b5SDimitry Andric        __nh.__release();
22534ba319b5SDimitry Andric    return _InsertReturnType{__result.first, __result.second, _VSTD::move(__nh)};
22544ba319b5SDimitry Andric}
22554ba319b5SDimitry Andric
22564ba319b5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
22574ba319b5SDimitry Andrictemplate <class _NodeHandle>
22584ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
22594ba319b5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
22604ba319b5SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
22614ba319b5SDimitry Andric    const_iterator, _NodeHandle&& __nh)
22624ba319b5SDimitry Andric{
22634ba319b5SDimitry Andric    if (__nh.empty())
22644ba319b5SDimitry Andric        return end();
22654ba319b5SDimitry Andric    pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
22664ba319b5SDimitry Andric    if (__result.second)
22674ba319b5SDimitry Andric        __nh.__release();
22684ba319b5SDimitry Andric    return __result.first;
22694ba319b5SDimitry Andric}
22704ba319b5SDimitry Andric
22714ba319b5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
22724ba319b5SDimitry Andrictemplate <class _NodeHandle>
22734ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
22744ba319b5SDimitry Andric_NodeHandle
22754ba319b5SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
22764ba319b5SDimitry Andric    key_type const& __key)
22774ba319b5SDimitry Andric{
22784ba319b5SDimitry Andric    iterator __i = find(__key);
22794ba319b5SDimitry Andric    if (__i == end())
22804ba319b5SDimitry Andric        return _NodeHandle();
22814ba319b5SDimitry Andric    return __node_handle_extract<_NodeHandle>(__i);
22824ba319b5SDimitry Andric}
22834ba319b5SDimitry Andric
22844ba319b5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
22854ba319b5SDimitry Andrictemplate <class _NodeHandle>
22864ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
22874ba319b5SDimitry Andric_NodeHandle
22884ba319b5SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
22894ba319b5SDimitry Andric    const_iterator __p)
22904ba319b5SDimitry Andric{
22914ba319b5SDimitry Andric    allocator_type __alloc(__node_alloc());
22924ba319b5SDimitry Andric    return _NodeHandle(remove(__p).release(), __alloc);
22934ba319b5SDimitry Andric}
22944ba319b5SDimitry Andric
22954ba319b5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
2296*b5893f02SDimitry Andrictemplate <class _Table>
2297*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY
2298*b5893f02SDimitry Andricvoid
2299*b5893f02SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_unique(
2300*b5893f02SDimitry Andric    _Table& __source)
2301*b5893f02SDimitry Andric{
2302*b5893f02SDimitry Andric    static_assert(is_same<__node, typename _Table::__node>::value, "");
2303*b5893f02SDimitry Andric
2304*b5893f02SDimitry Andric    for (typename _Table::iterator __it = __source.begin();
2305*b5893f02SDimitry Andric         __it != __source.end();)
2306*b5893f02SDimitry Andric    {
2307*b5893f02SDimitry Andric        __node_pointer __src_ptr = __it.__node_->__upcast();
2308*b5893f02SDimitry Andric        size_t __hash = hash_function()(__src_ptr->__value_);
2309*b5893f02SDimitry Andric        __next_pointer __existing_node =
2310*b5893f02SDimitry Andric            __node_insert_unique_prepare(__hash, __src_ptr->__value_);
2311*b5893f02SDimitry Andric        auto __prev_iter = __it++;
2312*b5893f02SDimitry Andric        if (__existing_node == nullptr)
2313*b5893f02SDimitry Andric        {
2314*b5893f02SDimitry Andric            (void)__source.remove(__prev_iter).release();
2315*b5893f02SDimitry Andric            __src_ptr->__hash_ = __hash;
2316*b5893f02SDimitry Andric            __node_insert_unique_perform(__src_ptr);
2317*b5893f02SDimitry Andric        }
2318*b5893f02SDimitry Andric    }
2319*b5893f02SDimitry Andric}
2320*b5893f02SDimitry Andric
2321*b5893f02SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
23224ba319b5SDimitry Andrictemplate <class _NodeHandle>
23234ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
23244ba319b5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
23254ba319b5SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
23264ba319b5SDimitry Andric    _NodeHandle&& __nh)
23274ba319b5SDimitry Andric{
23284ba319b5SDimitry Andric    if (__nh.empty())
23294ba319b5SDimitry Andric        return end();
23304ba319b5SDimitry Andric    iterator __result = __node_insert_multi(__nh.__ptr_);
23314ba319b5SDimitry Andric    __nh.__release();
23324ba319b5SDimitry Andric    return __result;
23334ba319b5SDimitry Andric}
23344ba319b5SDimitry Andric
23354ba319b5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
23364ba319b5SDimitry Andrictemplate <class _NodeHandle>
23374ba319b5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
23384ba319b5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
23394ba319b5SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
23404ba319b5SDimitry Andric    const_iterator __hint, _NodeHandle&& __nh)
23414ba319b5SDimitry Andric{
23424ba319b5SDimitry Andric    if (__nh.empty())
23434ba319b5SDimitry Andric        return end();
23444ba319b5SDimitry Andric    iterator __result = __node_insert_multi(__hint, __nh.__ptr_);
23454ba319b5SDimitry Andric    __nh.__release();
23464ba319b5SDimitry Andric    return __result;
23474ba319b5SDimitry Andric}
23484ba319b5SDimitry Andric
2349*b5893f02SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
2350*b5893f02SDimitry Andrictemplate <class _Table>
2351*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY
2352*b5893f02SDimitry Andricvoid
2353*b5893f02SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi(
2354*b5893f02SDimitry Andric    _Table& __source)
2355*b5893f02SDimitry Andric{
2356*b5893f02SDimitry Andric    static_assert(is_same<typename _Table::__node, __node>::value, "");
2357*b5893f02SDimitry Andric
2358*b5893f02SDimitry Andric    for (typename _Table::iterator __it = __source.begin();
2359*b5893f02SDimitry Andric         __it != __source.end();)
2360*b5893f02SDimitry Andric    {
2361*b5893f02SDimitry Andric        __node_pointer __src_ptr = __it.__node_->__upcast();
2362*b5893f02SDimitry Andric        size_t __src_hash = hash_function()(__src_ptr->__value_);
2363*b5893f02SDimitry Andric        __next_pointer __pn =
2364*b5893f02SDimitry Andric            __node_insert_multi_prepare(__src_hash, __src_ptr->__value_);
2365*b5893f02SDimitry Andric        (void)__source.remove(__it++).release();
2366*b5893f02SDimitry Andric        __src_ptr->__hash_ = __src_hash;
2367*b5893f02SDimitry Andric        __node_insert_multi_perform(__src_ptr, __pn);
2368*b5893f02SDimitry Andric    }
2369*b5893f02SDimitry Andric}
23704ba319b5SDimitry Andric#endif  // _LIBCPP_STD_VER > 14
23714ba319b5SDimitry Andric
23727a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
23737a984708SDavid Chisnallvoid
23747a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
23757a984708SDavid Chisnall{
2376936e9439SDimitry Andric    if (__n == 1)
2377936e9439SDimitry Andric        __n = 2;
2378936e9439SDimitry Andric    else if (__n & (__n - 1))
2379936e9439SDimitry Andric        __n = __next_prime(__n);
23807a984708SDavid Chisnall    size_type __bc = bucket_count();
23817a984708SDavid Chisnall    if (__n > __bc)
23827a984708SDavid Chisnall        __rehash(__n);
2383936e9439SDimitry Andric    else if (__n < __bc)
23847a984708SDavid Chisnall    {
23857a984708SDavid Chisnall        __n = _VSTD::max<size_type>
23867a984708SDavid Chisnall              (
23877a984708SDavid Chisnall                  __n,
2388854fa44bSDimitry Andric                  __is_hash_power2(__bc) ? __next_hash_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
23897a984708SDavid Chisnall                                           __next_prime(size_t(ceil(float(size()) / max_load_factor())))
23907a984708SDavid Chisnall              );
23917a984708SDavid Chisnall        if (__n < __bc)
23927a984708SDavid Chisnall            __rehash(__n);
23937a984708SDavid Chisnall    }
23947a984708SDavid Chisnall}
23957a984708SDavid Chisnall
23967a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
23977a984708SDavid Chisnallvoid
23987a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
23997a984708SDavid Chisnall{
24004f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
24014f7ab58eSDimitry Andric    __get_db()->__invalidate_all(this);
24024f7ab58eSDimitry Andric#endif  // _LIBCPP_DEBUG_LEVEL >= 2
24037a984708SDavid Chisnall    __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
24047a984708SDavid Chisnall    __bucket_list_.reset(__nbc > 0 ?
24057a984708SDavid Chisnall                      __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
24067a984708SDavid Chisnall    __bucket_list_.get_deleter().size() = __nbc;
24077a984708SDavid Chisnall    if (__nbc > 0)
24087a984708SDavid Chisnall    {
24097a984708SDavid Chisnall        for (size_type __i = 0; __i < __nbc; ++__i)
24107a984708SDavid Chisnall            __bucket_list_[__i] = nullptr;
2411aed8d94eSDimitry Andric        __next_pointer __pp = __p1_.first().__ptr();
2412aed8d94eSDimitry Andric        __next_pointer __cp = __pp->__next_;
24137a984708SDavid Chisnall        if (__cp != nullptr)
24147a984708SDavid Chisnall        {
2415aed8d94eSDimitry Andric            size_type __chash = __constrain_hash(__cp->__hash(), __nbc);
24167a984708SDavid Chisnall            __bucket_list_[__chash] = __pp;
24177a984708SDavid Chisnall            size_type __phash = __chash;
24187a984708SDavid Chisnall            for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
24197a984708SDavid Chisnall                                                           __cp = __pp->__next_)
24207a984708SDavid Chisnall            {
2421aed8d94eSDimitry Andric                __chash = __constrain_hash(__cp->__hash(), __nbc);
24227a984708SDavid Chisnall                if (__chash == __phash)
24237a984708SDavid Chisnall                    __pp = __cp;
24247a984708SDavid Chisnall                else
24257a984708SDavid Chisnall                {
24267a984708SDavid Chisnall                    if (__bucket_list_[__chash] == nullptr)
24277a984708SDavid Chisnall                    {
24287a984708SDavid Chisnall                        __bucket_list_[__chash] = __pp;
24297a984708SDavid Chisnall                        __pp = __cp;
24307a984708SDavid Chisnall                        __phash = __chash;
24317a984708SDavid Chisnall                    }
24327a984708SDavid Chisnall                    else
24337a984708SDavid Chisnall                    {
2434aed8d94eSDimitry Andric                        __next_pointer __np = __cp;
24357a984708SDavid Chisnall                        for (; __np->__next_ != nullptr &&
2436aed8d94eSDimitry Andric                               key_eq()(__cp->__upcast()->__value_,
2437aed8d94eSDimitry Andric                                        __np->__next_->__upcast()->__value_);
24387a984708SDavid Chisnall                                                           __np = __np->__next_)
24397a984708SDavid Chisnall                            ;
24407a984708SDavid Chisnall                        __pp->__next_ = __np->__next_;
24417a984708SDavid Chisnall                        __np->__next_ = __bucket_list_[__chash]->__next_;
24427a984708SDavid Chisnall                        __bucket_list_[__chash]->__next_ = __cp;
24437a984708SDavid Chisnall
24447a984708SDavid Chisnall                    }
24457a984708SDavid Chisnall                }
24467a984708SDavid Chisnall            }
24477a984708SDavid Chisnall        }
24487a984708SDavid Chisnall    }
24497a984708SDavid Chisnall}
24507a984708SDavid Chisnall
24517a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
24527a984708SDavid Chisnalltemplate <class _Key>
24537a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
24547a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
24557a984708SDavid Chisnall{
24567a984708SDavid Chisnall    size_t __hash = hash_function()(__k);
24577a984708SDavid Chisnall    size_type __bc = bucket_count();
24587a984708SDavid Chisnall    if (__bc != 0)
24597a984708SDavid Chisnall    {
2460936e9439SDimitry Andric        size_t __chash = __constrain_hash(__hash, __bc);
2461aed8d94eSDimitry Andric        __next_pointer __nd = __bucket_list_[__chash];
24627a984708SDavid Chisnall        if (__nd != nullptr)
24637a984708SDavid Chisnall        {
24647a984708SDavid Chisnall            for (__nd = __nd->__next_; __nd != nullptr &&
2465aed8d94eSDimitry Andric                (__nd->__hash() == __hash
2466aed8d94eSDimitry Andric                  || __constrain_hash(__nd->__hash(), __bc) == __chash);
24677a984708SDavid Chisnall                                                           __nd = __nd->__next_)
24687a984708SDavid Chisnall            {
2469aed8d94eSDimitry Andric                if ((__nd->__hash() == __hash)
2470aed8d94eSDimitry Andric                    && key_eq()(__nd->__upcast()->__value_, __k))
24714f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
24724f7ab58eSDimitry Andric                    return iterator(__nd, this);
24734f7ab58eSDimitry Andric#else
24747a984708SDavid Chisnall                    return iterator(__nd);
24754f7ab58eSDimitry Andric#endif
24767a984708SDavid Chisnall            }
24777a984708SDavid Chisnall        }
24787a984708SDavid Chisnall    }
24797a984708SDavid Chisnall    return end();
24807a984708SDavid Chisnall}
24817a984708SDavid Chisnall
24827a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
24837a984708SDavid Chisnalltemplate <class _Key>
24847a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
24857a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
24867a984708SDavid Chisnall{
24877a984708SDavid Chisnall    size_t __hash = hash_function()(__k);
24887a984708SDavid Chisnall    size_type __bc = bucket_count();
24897a984708SDavid Chisnall    if (__bc != 0)
24907a984708SDavid Chisnall    {
2491936e9439SDimitry Andric        size_t __chash = __constrain_hash(__hash, __bc);
2492aed8d94eSDimitry Andric        __next_pointer __nd = __bucket_list_[__chash];
24937a984708SDavid Chisnall        if (__nd != nullptr)
24947a984708SDavid Chisnall        {
24957a984708SDavid Chisnall            for (__nd = __nd->__next_; __nd != nullptr &&
2496aed8d94eSDimitry Andric                (__hash == __nd->__hash()
2497aed8d94eSDimitry Andric                    || __constrain_hash(__nd->__hash(), __bc) == __chash);
24987a984708SDavid Chisnall                                                           __nd = __nd->__next_)
24997a984708SDavid Chisnall            {
2500aed8d94eSDimitry Andric                if ((__nd->__hash() == __hash)
2501aed8d94eSDimitry Andric                    && key_eq()(__nd->__upcast()->__value_, __k))
25024f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
25034f7ab58eSDimitry Andric                    return const_iterator(__nd, this);
25044f7ab58eSDimitry Andric#else
25057a984708SDavid Chisnall                    return const_iterator(__nd);
25064f7ab58eSDimitry Andric#endif
25077a984708SDavid Chisnall            }
25087a984708SDavid Chisnall        }
25097a984708SDavid Chisnall
25107a984708SDavid Chisnall    }
25117a984708SDavid Chisnall    return end();
25127a984708SDavid Chisnall}
25137a984708SDavid Chisnall
25147c82a1ecSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
25157a984708SDavid Chisnall
25167a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
25177a984708SDavid Chisnalltemplate <class ..._Args>
25187a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
25197a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
25207a984708SDavid Chisnall{
25217c82a1ecSDimitry Andric    static_assert(!__is_hash_value_type<_Args...>::value,
25227c82a1ecSDimitry Andric                  "Construct cannot be called with a hash value type");
25237a984708SDavid Chisnall    __node_allocator& __na = __node_alloc();
252494e3ee44SDavid Chisnall    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
25257c82a1ecSDimitry Andric    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...);
25267a984708SDavid Chisnall    __h.get_deleter().__value_constructed = true;
25277a984708SDavid Chisnall    __h->__hash_ = hash_function()(__h->__value_);
25287a984708SDavid Chisnall    __h->__next_ = nullptr;
25297a984708SDavid Chisnall    return __h;
25307a984708SDavid Chisnall}
25317a984708SDavid Chisnall
25327a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
25337c82a1ecSDimitry Andrictemplate <class _First, class ..._Rest>
25347a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
25357c82a1ecSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(
25367c82a1ecSDimitry Andric    size_t __hash, _First&& __f, _Rest&& ...__rest)
25377a984708SDavid Chisnall{
25387c82a1ecSDimitry Andric    static_assert(!__is_hash_value_type<_First, _Rest...>::value,
25397c82a1ecSDimitry Andric                  "Construct cannot be called with a hash value type");
25407a984708SDavid Chisnall    __node_allocator& __na = __node_alloc();
254194e3ee44SDavid Chisnall    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
25427c82a1ecSDimitry Andric    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_),
25437c82a1ecSDimitry Andric                             _VSTD::forward<_First>(__f),
25447c82a1ecSDimitry Andric                             _VSTD::forward<_Rest>(__rest)...);
25457a984708SDavid Chisnall    __h.get_deleter().__value_constructed = true;
25467a984708SDavid Chisnall    __h->__hash_ = __hash;
25477a984708SDavid Chisnall    __h->__next_ = nullptr;
25484f7ab58eSDimitry Andric    return __h;
25497a984708SDavid Chisnall}
25507a984708SDavid Chisnall
25517c82a1ecSDimitry Andric#else  // _LIBCPP_CXX03_LANG
25527a984708SDavid Chisnall
25537a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
25547a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
25557c82a1ecSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const __container_value_type& __v)
25567a984708SDavid Chisnall{
25577a984708SDavid Chisnall    __node_allocator& __na = __node_alloc();
255894e3ee44SDavid Chisnall    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
25597c82a1ecSDimitry Andric    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v);
25607a984708SDavid Chisnall    __h.get_deleter().__value_constructed = true;
25617a984708SDavid Chisnall    __h->__hash_ = hash_function()(__h->__value_);
25627a984708SDavid Chisnall    __h->__next_ = nullptr;
25639729cf09SDimitry Andric    return _LIBCPP_EXPLICIT_MOVE(__h);  // explicitly moved for C++03
25647a984708SDavid Chisnall}
25657a984708SDavid Chisnall
25667a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
25677a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
25687c82a1ecSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash,
25697c82a1ecSDimitry Andric                                                                const __container_value_type& __v)
25707a984708SDavid Chisnall{
25717a984708SDavid Chisnall    __node_allocator& __na = __node_alloc();
257294e3ee44SDavid Chisnall    __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
25737c82a1ecSDimitry Andric    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v);
25747a984708SDavid Chisnall    __h.get_deleter().__value_constructed = true;
25757a984708SDavid Chisnall    __h->__hash_ = __hash;
25767a984708SDavid Chisnall    __h->__next_ = nullptr;
25779729cf09SDimitry Andric    return _LIBCPP_EXPLICIT_MOVE(__h);  // explicitly moved for C++03
25787a984708SDavid Chisnall}
25797a984708SDavid Chisnall
25807c82a1ecSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
25817c82a1ecSDimitry Andric
25827a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
25837a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
25847a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
25857a984708SDavid Chisnall{
2586aed8d94eSDimitry Andric    __next_pointer __np = __p.__node_;
25874f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
25884f7ab58eSDimitry Andric    _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
25894f7ab58eSDimitry Andric        "unordered container erase(iterator) called with an iterator not"
25904f7ab58eSDimitry Andric        " referring to this container");
25914f7ab58eSDimitry Andric    _LIBCPP_ASSERT(__p != end(),
25924f7ab58eSDimitry Andric        "unordered container erase(iterator) called with a non-dereferenceable iterator");
25934f7ab58eSDimitry Andric    iterator __r(__np, this);
25944f7ab58eSDimitry Andric#else
25957a984708SDavid Chisnall    iterator __r(__np);
25964f7ab58eSDimitry Andric#endif
25977a984708SDavid Chisnall    ++__r;
25987a984708SDavid Chisnall    remove(__p);
25997a984708SDavid Chisnall    return __r;
26007a984708SDavid Chisnall}
26017a984708SDavid Chisnall
26027a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
26037a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
26047a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
26057a984708SDavid Chisnall                                                const_iterator __last)
26067a984708SDavid Chisnall{
26074f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
26084f7ab58eSDimitry Andric    _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this,
26094f7ab58eSDimitry Andric        "unodered container::erase(iterator, iterator) called with an iterator not"
26104f7ab58eSDimitry Andric        " referring to this unodered container");
26114f7ab58eSDimitry Andric    _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this,
26124f7ab58eSDimitry Andric        "unodered container::erase(iterator, iterator) called with an iterator not"
26134f7ab58eSDimitry Andric        " referring to this unodered container");
26144f7ab58eSDimitry Andric#endif
26157a984708SDavid Chisnall    for (const_iterator __p = __first; __first != __last; __p = __first)
26167a984708SDavid Chisnall    {
26177a984708SDavid Chisnall        ++__first;
26187a984708SDavid Chisnall        erase(__p);
26197a984708SDavid Chisnall    }
2620aed8d94eSDimitry Andric    __next_pointer __np = __last.__node_;
26214f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
26224f7ab58eSDimitry Andric    return iterator (__np, this);
26234f7ab58eSDimitry Andric#else
26247a984708SDavid Chisnall    return iterator (__np);
26254f7ab58eSDimitry Andric#endif
26267a984708SDavid Chisnall}
26277a984708SDavid Chisnall
26287a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
26297a984708SDavid Chisnalltemplate <class _Key>
26307a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
26317a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
26327a984708SDavid Chisnall{
26337a984708SDavid Chisnall    iterator __i = find(__k);
26347a984708SDavid Chisnall    if (__i == end())
26357a984708SDavid Chisnall        return 0;
26367a984708SDavid Chisnall    erase(__i);
26377a984708SDavid Chisnall    return 1;
26387a984708SDavid Chisnall}
26397a984708SDavid Chisnall
26407a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
26417a984708SDavid Chisnalltemplate <class _Key>
26427a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
26437a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
26447a984708SDavid Chisnall{
26457a984708SDavid Chisnall    size_type __r = 0;
26467a984708SDavid Chisnall    iterator __i = find(__k);
26477a984708SDavid Chisnall    if (__i != end())
26487a984708SDavid Chisnall    {
26497a984708SDavid Chisnall        iterator __e = end();
26507a984708SDavid Chisnall        do
26517a984708SDavid Chisnall        {
26527a984708SDavid Chisnall            erase(__i++);
26537a984708SDavid Chisnall            ++__r;
26547a984708SDavid Chisnall        } while (__i != __e && key_eq()(*__i, __k));
26557a984708SDavid Chisnall    }
26567a984708SDavid Chisnall    return __r;
26577a984708SDavid Chisnall}
26587a984708SDavid Chisnall
26597a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
26607a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
26617a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
26627a984708SDavid Chisnall{
26637a984708SDavid Chisnall    // current node
2664aed8d94eSDimitry Andric    __next_pointer __cn = __p.__node_;
26657a984708SDavid Chisnall    size_type __bc = bucket_count();
2666aed8d94eSDimitry Andric    size_t __chash = __constrain_hash(__cn->__hash(), __bc);
26677a984708SDavid Chisnall    // find previous node
2668aed8d94eSDimitry Andric    __next_pointer __pn = __bucket_list_[__chash];
26697a984708SDavid Chisnall    for (; __pn->__next_ != __cn; __pn = __pn->__next_)
26707a984708SDavid Chisnall        ;
26717a984708SDavid Chisnall    // Fix up __bucket_list_
26727a984708SDavid Chisnall        // if __pn is not in same bucket (before begin is not in same bucket) &&
26737a984708SDavid Chisnall        //    if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
2674aed8d94eSDimitry Andric    if (__pn == __p1_.first().__ptr()
2675aed8d94eSDimitry Andric            || __constrain_hash(__pn->__hash(), __bc) != __chash)
26767a984708SDavid Chisnall    {
2677aed8d94eSDimitry Andric        if (__cn->__next_ == nullptr
2678aed8d94eSDimitry Andric            || __constrain_hash(__cn->__next_->__hash(), __bc) != __chash)
26797a984708SDavid Chisnall            __bucket_list_[__chash] = nullptr;
26807a984708SDavid Chisnall    }
26817a984708SDavid Chisnall        // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
26827a984708SDavid Chisnall    if (__cn->__next_ != nullptr)
26837a984708SDavid Chisnall    {
2684aed8d94eSDimitry Andric        size_t __nhash = __constrain_hash(__cn->__next_->__hash(), __bc);
26857a984708SDavid Chisnall        if (__nhash != __chash)
26867a984708SDavid Chisnall            __bucket_list_[__nhash] = __pn;
26877a984708SDavid Chisnall    }
26887a984708SDavid Chisnall    // remove __cn
26897a984708SDavid Chisnall    __pn->__next_ = __cn->__next_;
26907a984708SDavid Chisnall    __cn->__next_ = nullptr;
26917a984708SDavid Chisnall    --size();
26924f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
26934f7ab58eSDimitry Andric    __c_node* __c = __get_db()->__find_c_and_lock(this);
2694aed8d94eSDimitry Andric    for (__i_node** __dp = __c->end_; __dp != __c->beg_; )
26954f7ab58eSDimitry Andric    {
2696aed8d94eSDimitry Andric        --__dp;
2697aed8d94eSDimitry Andric        iterator* __i = static_cast<iterator*>((*__dp)->__i_);
26984f7ab58eSDimitry Andric        if (__i->__node_ == __cn)
26994f7ab58eSDimitry Andric        {
2700aed8d94eSDimitry Andric            (*__dp)->__c_ = nullptr;
2701aed8d94eSDimitry Andric            if (--__c->end_ != __dp)
2702aed8d94eSDimitry Andric                memmove(__dp, __dp+1, (__c->end_ - __dp)*sizeof(__i_node*));
27034f7ab58eSDimitry Andric        }
27044f7ab58eSDimitry Andric    }
27054f7ab58eSDimitry Andric    __get_db()->unlock();
27064f7ab58eSDimitry Andric#endif
2707aed8d94eSDimitry Andric    return __node_holder(__cn->__upcast(), _Dp(__node_alloc(), true));
27087a984708SDavid Chisnall}
27097a984708SDavid Chisnall
27107a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
27117a984708SDavid Chisnalltemplate <class _Key>
27129729cf09SDimitry Andricinline
27137a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
27147a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
27157a984708SDavid Chisnall{
27167a984708SDavid Chisnall    return static_cast<size_type>(find(__k) != end());
27177a984708SDavid Chisnall}
27187a984708SDavid Chisnall
27197a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
27207a984708SDavid Chisnalltemplate <class _Key>
27217a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
27227a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
27237a984708SDavid Chisnall{
27247a984708SDavid Chisnall    size_type __r = 0;
27257a984708SDavid Chisnall    const_iterator __i = find(__k);
27267a984708SDavid Chisnall    if (__i != end())
27277a984708SDavid Chisnall    {
27287a984708SDavid Chisnall        const_iterator __e = end();
27297a984708SDavid Chisnall        do
27307a984708SDavid Chisnall        {
27317a984708SDavid Chisnall            ++__i;
27327a984708SDavid Chisnall            ++__r;
27337a984708SDavid Chisnall        } while (__i != __e && key_eq()(*__i, __k));
27347a984708SDavid Chisnall    }
27357a984708SDavid Chisnall    return __r;
27367a984708SDavid Chisnall}
27377a984708SDavid Chisnall
27387a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
27397a984708SDavid Chisnalltemplate <class _Key>
27407a984708SDavid Chisnallpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
27417a984708SDavid Chisnall     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
27427a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
27437a984708SDavid Chisnall        const _Key& __k)
27447a984708SDavid Chisnall{
27457a984708SDavid Chisnall    iterator __i = find(__k);
27467a984708SDavid Chisnall    iterator __j = __i;
27477a984708SDavid Chisnall    if (__i != end())
27487a984708SDavid Chisnall        ++__j;
27497a984708SDavid Chisnall    return pair<iterator, iterator>(__i, __j);
27507a984708SDavid Chisnall}
27517a984708SDavid Chisnall
27527a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
27537a984708SDavid Chisnalltemplate <class _Key>
27547a984708SDavid Chisnallpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
27557a984708SDavid Chisnall     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
27567a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
27577a984708SDavid Chisnall        const _Key& __k) const
27587a984708SDavid Chisnall{
27597a984708SDavid Chisnall    const_iterator __i = find(__k);
27607a984708SDavid Chisnall    const_iterator __j = __i;
27617a984708SDavid Chisnall    if (__i != end())
27627a984708SDavid Chisnall        ++__j;
27637a984708SDavid Chisnall    return pair<const_iterator, const_iterator>(__i, __j);
27647a984708SDavid Chisnall}
27657a984708SDavid Chisnall
27667a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
27677a984708SDavid Chisnalltemplate <class _Key>
27687a984708SDavid Chisnallpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
27697a984708SDavid Chisnall     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
27707a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
27717a984708SDavid Chisnall        const _Key& __k)
27727a984708SDavid Chisnall{
27737a984708SDavid Chisnall    iterator __i = find(__k);
27747a984708SDavid Chisnall    iterator __j = __i;
27757a984708SDavid Chisnall    if (__i != end())
27767a984708SDavid Chisnall    {
27777a984708SDavid Chisnall        iterator __e = end();
27787a984708SDavid Chisnall        do
27797a984708SDavid Chisnall        {
27807a984708SDavid Chisnall            ++__j;
27817a984708SDavid Chisnall        } while (__j != __e && key_eq()(*__j, __k));
27827a984708SDavid Chisnall    }
27837a984708SDavid Chisnall    return pair<iterator, iterator>(__i, __j);
27847a984708SDavid Chisnall}
27857a984708SDavid Chisnall
27867a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
27877a984708SDavid Chisnalltemplate <class _Key>
27887a984708SDavid Chisnallpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
27897a984708SDavid Chisnall     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
27907a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
27917a984708SDavid Chisnall        const _Key& __k) const
27927a984708SDavid Chisnall{
27937a984708SDavid Chisnall    const_iterator __i = find(__k);
27947a984708SDavid Chisnall    const_iterator __j = __i;
27957a984708SDavid Chisnall    if (__i != end())
27967a984708SDavid Chisnall    {
27977a984708SDavid Chisnall        const_iterator __e = end();
27987a984708SDavid Chisnall        do
27997a984708SDavid Chisnall        {
28007a984708SDavid Chisnall            ++__j;
28017a984708SDavid Chisnall        } while (__j != __e && key_eq()(*__j, __k));
28027a984708SDavid Chisnall    }
28037a984708SDavid Chisnall    return pair<const_iterator, const_iterator>(__i, __j);
28047a984708SDavid Chisnall}
28057a984708SDavid Chisnall
28067a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
28077a984708SDavid Chisnallvoid
28087a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
2809fe9390e7SDimitry Andric#if _LIBCPP_STD_VER <= 11
2810aed8d94eSDimitry Andric    _NOEXCEPT_DEBUG_(
2811854fa44bSDimitry Andric        __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
2812854fa44bSDimitry Andric        && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
2813854fa44bSDimitry Andric              || __is_nothrow_swappable<__pointer_allocator>::value)
2814854fa44bSDimitry Andric        && (!__node_traits::propagate_on_container_swap::value
2815854fa44bSDimitry Andric              || __is_nothrow_swappable<__node_allocator>::value)
2816854fa44bSDimitry Andric            )
2817fe9390e7SDimitry Andric#else
2818aed8d94eSDimitry Andric  _NOEXCEPT_DEBUG_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value)
2819fe9390e7SDimitry Andric#endif
28207a984708SDavid Chisnall{
2821aed8d94eSDimitry Andric    _LIBCPP_ASSERT(__node_traits::propagate_on_container_swap::value ||
2822aed8d94eSDimitry Andric                   this->__node_alloc() == __u.__node_alloc(),
2823aed8d94eSDimitry Andric                   "list::swap: Either propagate_on_container_swap must be true"
2824aed8d94eSDimitry Andric                   " or the allocators must compare equal");
28257a984708SDavid Chisnall    {
28267a984708SDavid Chisnall    __node_pointer_pointer __npp = __bucket_list_.release();
28277a984708SDavid Chisnall    __bucket_list_.reset(__u.__bucket_list_.release());
28287a984708SDavid Chisnall    __u.__bucket_list_.reset(__npp);
28297a984708SDavid Chisnall    }
28307a984708SDavid Chisnall    _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
2831854fa44bSDimitry Andric    __swap_allocator(__bucket_list_.get_deleter().__alloc(),
28327a984708SDavid Chisnall             __u.__bucket_list_.get_deleter().__alloc());
2833854fa44bSDimitry Andric    __swap_allocator(__node_alloc(), __u.__node_alloc());
28347a984708SDavid Chisnall    _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
28357a984708SDavid Chisnall    __p2_.swap(__u.__p2_);
28367a984708SDavid Chisnall    __p3_.swap(__u.__p3_);
28377a984708SDavid Chisnall    if (size() > 0)
2838aed8d94eSDimitry Andric        __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] =
2839aed8d94eSDimitry Andric            __p1_.first().__ptr();
28407a984708SDavid Chisnall    if (__u.size() > 0)
2841aed8d94eSDimitry Andric        __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] =
2842aed8d94eSDimitry Andric            __u.__p1_.first().__ptr();
28434f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
28444f7ab58eSDimitry Andric    __get_db()->swap(this, &__u);
28454f7ab58eSDimitry Andric#endif
28467a984708SDavid Chisnall}
28477a984708SDavid Chisnall
28487a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
28497a984708SDavid Chisnalltypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
28507a984708SDavid Chisnall__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
28517a984708SDavid Chisnall{
28524f7ab58eSDimitry Andric    _LIBCPP_ASSERT(__n < bucket_count(),
28534f7ab58eSDimitry Andric        "unordered container::bucket_size(n) called with n >= bucket_count()");
2854aed8d94eSDimitry Andric    __next_pointer __np = __bucket_list_[__n];
28557a984708SDavid Chisnall    size_type __bc = bucket_count();
28567a984708SDavid Chisnall    size_type __r = 0;
28577a984708SDavid Chisnall    if (__np != nullptr)
28587a984708SDavid Chisnall    {
28597a984708SDavid Chisnall        for (__np = __np->__next_; __np != nullptr &&
2860aed8d94eSDimitry Andric                                   __constrain_hash(__np->__hash(), __bc) == __n;
28617a984708SDavid Chisnall                                                    __np = __np->__next_, ++__r)
28627a984708SDavid Chisnall            ;
28637a984708SDavid Chisnall    }
28647a984708SDavid Chisnall    return __r;
28657a984708SDavid Chisnall}
28667a984708SDavid Chisnall
28677a984708SDavid Chisnalltemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
28687a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
28697a984708SDavid Chisnallvoid
28707a984708SDavid Chisnallswap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
28717a984708SDavid Chisnall     __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
28727a984708SDavid Chisnall    _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
28737a984708SDavid Chisnall{
28747a984708SDavid Chisnall    __x.swap(__y);
28757a984708SDavid Chisnall}
28767a984708SDavid Chisnall
28774f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
28784f7ab58eSDimitry Andric
28794f7ab58eSDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
28804f7ab58eSDimitry Andricbool
28814f7ab58eSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const
28824f7ab58eSDimitry Andric{
28834f7ab58eSDimitry Andric    return __i->__node_ != nullptr;
28844f7ab58eSDimitry Andric}
28854f7ab58eSDimitry Andric
28864f7ab58eSDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
28874f7ab58eSDimitry Andricbool
28884f7ab58eSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const
28894f7ab58eSDimitry Andric{
28904f7ab58eSDimitry Andric    return false;
28914f7ab58eSDimitry Andric}
28924f7ab58eSDimitry Andric
28934f7ab58eSDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
28944f7ab58eSDimitry Andricbool
28954f7ab58eSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const
28964f7ab58eSDimitry Andric{
28974f7ab58eSDimitry Andric    return false;
28984f7ab58eSDimitry Andric}
28994f7ab58eSDimitry Andric
29004f7ab58eSDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
29014f7ab58eSDimitry Andricbool
29024f7ab58eSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const
29034f7ab58eSDimitry Andric{
29044f7ab58eSDimitry Andric    return false;
29054f7ab58eSDimitry Andric}
29064f7ab58eSDimitry Andric
29074f7ab58eSDimitry Andric#endif  // _LIBCPP_DEBUG_LEVEL >= 2
2908f9448bf3SDimitry Andric
29097a984708SDavid Chisnall_LIBCPP_END_NAMESPACE_STD
29107a984708SDavid Chisnall
2911f9448bf3SDimitry Andric_LIBCPP_POP_MACROS
2912f9448bf3SDimitry Andric
29137a984708SDavid Chisnall#endif  // _LIBCPP__HASH_TABLE
2914