xref: /freebsd/contrib/llvm-project/libcxx/include/__hash_table (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric// -*- C++ -*-
20b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
1081ad6265SDimitry Andric#ifndef _LIBCPP___HASH_TABLE
1181ad6265SDimitry Andric#define _LIBCPP___HASH_TABLE
120b57cec5SDimitry Andric
1381ad6265SDimitry Andric#include <__algorithm/max.h>
1481ad6265SDimitry Andric#include <__algorithm/min.h>
1581ad6265SDimitry Andric#include <__assert>
16bdd1243dSDimitry Andric#include <__bit/countl.h>
170b57cec5SDimitry Andric#include <__config>
1881ad6265SDimitry Andric#include <__functional/hash.h>
1906c3fb27SDimitry Andric#include <__functional/invoke.h>
2081ad6265SDimitry Andric#include <__iterator/iterator_traits.h>
21bdd1243dSDimitry Andric#include <__memory/addressof.h>
22bdd1243dSDimitry Andric#include <__memory/allocator_traits.h>
23bdd1243dSDimitry Andric#include <__memory/compressed_pair.h>
245f757f3fSDimitry Andric#include <__memory/construct_at.h>
25bdd1243dSDimitry Andric#include <__memory/pointer_traits.h>
26972a253aSDimitry Andric#include <__memory/swap_allocator.h>
27bdd1243dSDimitry Andric#include <__memory/unique_ptr.h>
28bdd1243dSDimitry Andric#include <__type_traits/can_extract_key.h>
2906c3fb27SDimitry Andric#include <__type_traits/conditional.h>
3006c3fb27SDimitry Andric#include <__type_traits/is_const.h>
31*0fca6ea1SDimitry Andric#include <__type_traits/is_constructible.h>
32*0fca6ea1SDimitry Andric#include <__type_traits/is_nothrow_assignable.h>
3306c3fb27SDimitry Andric#include <__type_traits/is_nothrow_constructible.h>
3406c3fb27SDimitry Andric#include <__type_traits/is_pointer.h>
3506c3fb27SDimitry Andric#include <__type_traits/is_reference.h>
3606c3fb27SDimitry Andric#include <__type_traits/is_swappable.h>
3706c3fb27SDimitry Andric#include <__type_traits/remove_const.h>
3806c3fb27SDimitry Andric#include <__type_traits/remove_cvref.h>
39bdd1243dSDimitry Andric#include <__utility/forward.h>
40bdd1243dSDimitry Andric#include <__utility/move.h>
41bdd1243dSDimitry Andric#include <__utility/pair.h>
4281ad6265SDimitry Andric#include <__utility/swap.h>
430b57cec5SDimitry Andric#include <cmath>
44bdd1243dSDimitry Andric#include <cstring>
45fe6060f1SDimitry Andric#include <initializer_list>
465f757f3fSDimitry Andric#include <new> // __launder
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
490b57cec5SDimitry Andric#  pragma GCC system_header
500b57cec5SDimitry Andric#endif
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric_LIBCPP_PUSH_MACROS
530b57cec5SDimitry Andric#include <__undef_macros>
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
560b57cec5SDimitry Andric
570b57cec5SDimitry Andrictemplate <class _Key, class _Tp>
580b57cec5SDimitry Andricstruct __hash_value_type;
590b57cec5SDimitry Andric
600b57cec5SDimitry Andrictemplate <class _Tp>
610b57cec5SDimitry Andricstruct __is_hash_value_type_imp : false_type {};
620b57cec5SDimitry Andric
630b57cec5SDimitry Andrictemplate <class _Key, class _Value>
640b57cec5SDimitry Andricstruct __is_hash_value_type_imp<__hash_value_type<_Key, _Value> > : true_type {};
650b57cec5SDimitry Andric
660b57cec5SDimitry Andrictemplate <class... _Args>
670b57cec5SDimitry Andricstruct __is_hash_value_type : false_type {};
680b57cec5SDimitry Andric
690b57cec5SDimitry Andrictemplate <class _One>
70bdd1243dSDimitry Andricstruct __is_hash_value_type<_One> : __is_hash_value_type_imp<__remove_cvref_t<_One> > {};
710b57cec5SDimitry Andric
7206c3fb27SDimitry Andric_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t __n);
730b57cec5SDimitry Andric
740b57cec5SDimitry Andrictemplate <class _NodePtr>
75cb14a3feSDimitry Andricstruct __hash_node_base {
760b57cec5SDimitry Andric  typedef typename pointer_traits<_NodePtr>::element_type __node_type;
770b57cec5SDimitry Andric  typedef __hash_node_base __first_node;
78bdd1243dSDimitry Andric  typedef __rebind_pointer_t<_NodePtr, __first_node> __node_base_pointer;
790b57cec5SDimitry Andric  typedef _NodePtr __node_pointer;
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric#if defined(_LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB)
820b57cec5SDimitry Andric  typedef __node_base_pointer __next_pointer;
830b57cec5SDimitry Andric#else
84bdd1243dSDimitry Andric  typedef __conditional_t<is_pointer<__node_pointer>::value, __node_base_pointer, __node_pointer> __next_pointer;
850b57cec5SDimitry Andric#endif
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric  __next_pointer __next_;
880b57cec5SDimitry Andric
89cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __next_pointer __ptr() _NOEXCEPT {
90cb14a3feSDimitry Andric    return static_cast<__next_pointer>(pointer_traits<__node_base_pointer>::pointer_to(*this));
910b57cec5SDimitry Andric  }
920b57cec5SDimitry Andric
93cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __node_pointer __upcast() _NOEXCEPT {
94cb14a3feSDimitry Andric    return static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(*this));
950b57cec5SDimitry Andric  }
960b57cec5SDimitry Andric
97cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_t __hash() const _NOEXCEPT { return static_cast<__node_type const&>(*this).__hash_; }
980b57cec5SDimitry Andric
995f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
1005f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit __hash_node_base(__next_pointer __next) _NOEXCEPT : __next_(__next) {}
1010b57cec5SDimitry Andric};
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andrictemplate <class _Tp, class _VoidPtr>
104cb14a3feSDimitry Andricstruct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > {
1050b57cec5SDimitry Andric  typedef _Tp __node_value_type;
1065f757f3fSDimitry Andric  using _Base          = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >;
1075f757f3fSDimitry Andric  using __next_pointer = typename _Base::__next_pointer;
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andric  size_t __hash_;
1105f757f3fSDimitry Andric
1115f757f3fSDimitry Andric  // We allow starting the lifetime of nodes without initializing the value held by the node,
1125f757f3fSDimitry Andric  // since that is handled by the hash table itself in order to be allocator-aware.
1135f757f3fSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
114cb14a3feSDimitry Andric
1155f757f3fSDimitry Andricprivate:
1165f757f3fSDimitry Andric  union {
1175f757f3fSDimitry Andric    _Tp __value_;
1180b57cec5SDimitry Andric  };
1190b57cec5SDimitry Andric
1205f757f3fSDimitry Andricpublic:
1215f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; }
1225f757f3fSDimitry Andric#else
123cb14a3feSDimitry Andric
1245f757f3fSDimitry Andricprivate:
1255f757f3fSDimitry Andric  _ALIGNAS_TYPE(_Tp) char __buffer_[sizeof(_Tp)];
1265f757f3fSDimitry Andric
1275f757f3fSDimitry Andricpublic:
128cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); }
1295f757f3fSDimitry Andric#endif
1305f757f3fSDimitry Andric
1315f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash) : _Base(__next), __hash_(__hash) {}
1325f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI ~__hash_node() {}
1335f757f3fSDimitry Andric};
1345f757f3fSDimitry Andric
135cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI bool __is_hash_power2(size_t __bc) { return __bc > 2 && !(__bc & (__bc - 1)); }
136cb14a3feSDimitry Andric
137cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI size_t __constrain_hash(size_t __h, size_t __bc) {
138cb14a3feSDimitry Andric  return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : (__h < __bc ? __h : __h % __bc);
1390b57cec5SDimitry Andric}
1400b57cec5SDimitry Andric
141cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI size_t __next_hash_pow2(size_t __n) {
142e8d8bef9SDimitry Andric  return __n < 2 ? __n : (size_t(1) << (numeric_limits<size_t>::digits - __libcpp_clz(__n - 1)));
1430b57cec5SDimitry Andric}
1440b57cec5SDimitry Andric
145cb14a3feSDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
146cb14a3feSDimitry Andricclass __hash_table;
1470b57cec5SDimitry Andric
148cb14a3feSDimitry Andrictemplate <class _NodePtr>
149cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_iterator;
150cb14a3feSDimitry Andrictemplate <class _ConstNodePtr>
151cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
152cb14a3feSDimitry Andrictemplate <class _NodePtr>
153cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_local_iterator;
154cb14a3feSDimitry Andrictemplate <class _ConstNodePtr>
155cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
156cb14a3feSDimitry Andrictemplate <class _HashIterator>
157cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
158cb14a3feSDimitry Andrictemplate <class _HashIterator>
159cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andrictemplate <class _Tp>
1620b57cec5SDimitry Andricstruct __hash_key_value_types {
1630b57cec5SDimitry Andric  static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, "");
1640b57cec5SDimitry Andric  typedef _Tp key_type;
1650b57cec5SDimitry Andric  typedef _Tp __node_value_type;
1660b57cec5SDimitry Andric  typedef _Tp __container_value_type;
1670b57cec5SDimitry Andric  static const bool __is_map = false;
1680b57cec5SDimitry Andric
169cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Tp const& __v) { return __v; }
170cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __v) { return __v; }
171cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { return std::addressof(__n); }
172cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI static __container_value_type&& __move(__node_value_type& __v) { return std::move(__v); }
1730b57cec5SDimitry Andric};
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andrictemplate <class _Key, class _Tp>
1760b57cec5SDimitry Andricstruct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
1770b57cec5SDimitry Andric  typedef _Key key_type;
1780b57cec5SDimitry Andric  typedef _Tp mapped_type;
1790b57cec5SDimitry Andric  typedef __hash_value_type<_Key, _Tp> __node_value_type;
1800b57cec5SDimitry Andric  typedef pair<const _Key, _Tp> __container_value_type;
1810b57cec5SDimitry Andric  typedef __container_value_type __map_value_type;
1820b57cec5SDimitry Andric  static const bool __is_map = true;
1830b57cec5SDimitry Andric
184cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__container_value_type const& __v) { return __v.first; }
1850b57cec5SDimitry Andric
1865f757f3fSDimitry Andric  template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __node_value_type>::value, int> = 0>
187cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
1880b57cec5SDimitry Andric    return __t.__get_value();
1890b57cec5SDimitry Andric  }
1900b57cec5SDimitry Andric
1915f757f3fSDimitry Andric  template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
192cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
1930b57cec5SDimitry Andric    return __t;
1940b57cec5SDimitry Andric  }
1950b57cec5SDimitry Andric
196cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) {
1975f757f3fSDimitry Andric    return std::addressof(__n.__get_value());
1980b57cec5SDimitry Andric  }
199cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
2000b57cec5SDimitry Andric};
2010b57cec5SDimitry Andric
202cb14a3feSDimitry Andrictemplate <class _Tp, class _AllocPtr, class _KVTypes = __hash_key_value_types<_Tp>, bool = _KVTypes::__is_map>
2030b57cec5SDimitry Andricstruct __hash_map_pointer_types {};
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andrictemplate <class _Tp, class _AllocPtr, class _KVTypes>
2060b57cec5SDimitry Andricstruct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
2070b57cec5SDimitry Andric  typedef typename _KVTypes::__map_value_type _Mv;
208cb14a3feSDimitry Andric  typedef __rebind_pointer_t<_AllocPtr, _Mv> __map_value_type_pointer;
209cb14a3feSDimitry Andric  typedef __rebind_pointer_t<_AllocPtr, const _Mv> __const_map_value_type_pointer;
2100b57cec5SDimitry Andric};
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andrictemplate <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
2130b57cec5SDimitry Andricstruct __hash_node_types;
2140b57cec5SDimitry Andric
2150b57cec5SDimitry Andrictemplate <class _NodePtr, class _Tp, class _VoidPtr>
2160b57cec5SDimitry Andricstruct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> >
217cb14a3feSDimitry Andric    : public __hash_key_value_types<_Tp>,
218cb14a3feSDimitry Andric      __hash_map_pointer_types<_Tp, _VoidPtr>
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric{
2210b57cec5SDimitry Andric  typedef __hash_key_value_types<_Tp> __base;
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andricpublic:
2240b57cec5SDimitry Andric  typedef ptrdiff_t difference_type;
2250b57cec5SDimitry Andric  typedef size_t size_type;
2260b57cec5SDimitry Andric
227bdd1243dSDimitry Andric  typedef __rebind_pointer_t<_NodePtr, void> __void_pointer;
2280b57cec5SDimitry Andric
2290b57cec5SDimitry Andric  typedef typename pointer_traits<_NodePtr>::element_type __node_type;
2300b57cec5SDimitry Andric  typedef _NodePtr __node_pointer;
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric  typedef __hash_node_base<__node_pointer> __node_base_type;
233cb14a3feSDimitry Andric  typedef __rebind_pointer_t<_NodePtr, __node_base_type> __node_base_pointer;
2340b57cec5SDimitry Andric
2350b57cec5SDimitry Andric  typedef typename __node_base_type::__next_pointer __next_pointer;
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric  typedef _Tp __node_value_type;
238cb14a3feSDimitry Andric  typedef __rebind_pointer_t<_VoidPtr, __node_value_type> __node_value_type_pointer;
239cb14a3feSDimitry Andric  typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> __const_node_value_type_pointer;
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andricprivate:
242cb14a3feSDimitry Andric  static_assert(!is_const<__node_type>::value, "_NodePtr should never be a pointer to const");
243*0fca6ea1SDimitry Andric  static_assert(is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value,
2440b57cec5SDimitry Andric                "_VoidPtr does not point to unqualified void type");
245*0fca6ea1SDimitry Andric  static_assert(is_same<__rebind_pointer_t<_VoidPtr, __node_type>, _NodePtr>::value,
246cb14a3feSDimitry Andric                "_VoidPtr does not rebind to _NodePtr.");
2470b57cec5SDimitry Andric};
2480b57cec5SDimitry Andric
2490b57cec5SDimitry Andrictemplate <class _HashIterator>
2500b57cec5SDimitry Andricstruct __hash_node_types_from_iterator;
2510b57cec5SDimitry Andrictemplate <class _NodePtr>
2520b57cec5SDimitry Andricstruct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
2530b57cec5SDimitry Andrictemplate <class _NodePtr>
2540b57cec5SDimitry Andricstruct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
2550b57cec5SDimitry Andrictemplate <class _NodePtr>
2560b57cec5SDimitry Andricstruct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
2570b57cec5SDimitry Andrictemplate <class _NodePtr>
2580b57cec5SDimitry Andricstruct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andrictemplate <class _NodeValueTp, class _VoidPtr>
2610b57cec5SDimitry Andricstruct __make_hash_node_types {
2620b57cec5SDimitry Andric  typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp;
263bdd1243dSDimitry Andric  typedef __rebind_pointer_t<_VoidPtr, _NodeTp> _NodePtr;
2640b57cec5SDimitry Andric  typedef __hash_node_types<_NodePtr> type;
2650b57cec5SDimitry Andric};
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andrictemplate <class _NodePtr>
268cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_iterator {
2690b57cec5SDimitry Andric  typedef __hash_node_types<_NodePtr> _NodeTypes;
2700b57cec5SDimitry Andric  typedef _NodePtr __node_pointer;
2710b57cec5SDimitry Andric  typedef typename _NodeTypes::__next_pointer __next_pointer;
2720b57cec5SDimitry Andric
2730b57cec5SDimitry Andric  __next_pointer __node_;
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andricpublic:
2760b57cec5SDimitry Andric  typedef forward_iterator_tag iterator_category;
2770b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_value_type value_type;
2780b57cec5SDimitry Andric  typedef typename _NodeTypes::difference_type difference_type;
2790b57cec5SDimitry Andric  typedef value_type& reference;
2800b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_value_type_pointer pointer;
2810b57cec5SDimitry Andric
282cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_iterator() _NOEXCEPT : __node_(nullptr) {}
2830b57cec5SDimitry Andric
284*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
285*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
286*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator");
287*0fca6ea1SDimitry Andric    return __node_->__upcast()->__get_value();
288*0fca6ea1SDimitry Andric  }
2890b57cec5SDimitry Andric
290cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
291*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
292*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator");
2935f757f3fSDimitry Andric    return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
2940b57cec5SDimitry Andric  }
2950b57cec5SDimitry Andric
296cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_iterator& operator++() {
297*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
298*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container iterator");
2990b57cec5SDimitry Andric    __node_ = __node_->__next_;
3000b57cec5SDimitry Andric    return *this;
3010b57cec5SDimitry Andric  }
3020b57cec5SDimitry Andric
303cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_iterator operator++(int) {
3040b57cec5SDimitry Andric    __hash_iterator __t(*this);
3050b57cec5SDimitry Andric    ++(*this);
3060b57cec5SDimitry Andric    return __t;
3070b57cec5SDimitry Andric  }
3080b57cec5SDimitry Andric
309cb14a3feSDimitry Andric  friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_iterator& __x, const __hash_iterator& __y) {
3100b57cec5SDimitry Andric    return __x.__node_ == __y.__node_;
3110b57cec5SDimitry Andric  }
312cb14a3feSDimitry Andric  friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y) {
313cb14a3feSDimitry Andric    return !(__x == __y);
31481ad6265SDimitry Andric  }
31506c3fb27SDimitry Andric
316cb14a3feSDimitry Andricprivate:
317cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit __hash_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) {}
318cb14a3feSDimitry Andric
319cb14a3feSDimitry Andric  template <class, class, class, class>
320cb14a3feSDimitry Andric  friend class __hash_table;
321cb14a3feSDimitry Andric  template <class>
322cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
323cb14a3feSDimitry Andric  template <class>
324cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
325cb14a3feSDimitry Andric  template <class, class, class, class, class>
326cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS unordered_map;
327cb14a3feSDimitry Andric  template <class, class, class, class, class>
328cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
3290b57cec5SDimitry Andric};
3300b57cec5SDimitry Andric
3310b57cec5SDimitry Andrictemplate <class _NodePtr>
332cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_const_iterator {
3330b57cec5SDimitry Andric  static_assert(!is_const<typename pointer_traits<_NodePtr>::element_type>::value, "");
3340b57cec5SDimitry Andric  typedef __hash_node_types<_NodePtr> _NodeTypes;
3350b57cec5SDimitry Andric  typedef _NodePtr __node_pointer;
3360b57cec5SDimitry Andric  typedef typename _NodeTypes::__next_pointer __next_pointer;
3370b57cec5SDimitry Andric
3380b57cec5SDimitry Andric  __next_pointer __node_;
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andricpublic:
3410b57cec5SDimitry Andric  typedef __hash_iterator<_NodePtr> __non_const_iterator;
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric  typedef forward_iterator_tag iterator_category;
3440b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_value_type value_type;
3450b57cec5SDimitry Andric  typedef typename _NodeTypes::difference_type difference_type;
3460b57cec5SDimitry Andric  typedef const value_type& reference;
3470b57cec5SDimitry Andric  typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
3480b57cec5SDimitry Andric
349cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_const_iterator() _NOEXCEPT : __node_(nullptr) {}
3500b57cec5SDimitry Andric
351cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_) {}
3520b57cec5SDimitry Andric
353*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
354*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
355*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
356*0fca6ea1SDimitry Andric    return __node_->__upcast()->__get_value();
357*0fca6ea1SDimitry Andric  }
358cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
359*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
360*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
3615f757f3fSDimitry Andric    return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
3620b57cec5SDimitry Andric  }
3630b57cec5SDimitry Andric
364cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_const_iterator& operator++() {
365*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
366*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_iterator");
3670b57cec5SDimitry Andric    __node_ = __node_->__next_;
3680b57cec5SDimitry Andric    return *this;
3690b57cec5SDimitry Andric  }
3700b57cec5SDimitry Andric
371cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_const_iterator operator++(int) {
3720b57cec5SDimitry Andric    __hash_const_iterator __t(*this);
3730b57cec5SDimitry Andric    ++(*this);
3740b57cec5SDimitry Andric    return __t;
3750b57cec5SDimitry Andric  }
3760b57cec5SDimitry Andric
377cb14a3feSDimitry Andric  friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y) {
3780b57cec5SDimitry Andric    return __x.__node_ == __y.__node_;
3790b57cec5SDimitry Andric  }
380cb14a3feSDimitry Andric  friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y) {
381cb14a3feSDimitry Andric    return !(__x == __y);
38281ad6265SDimitry Andric  }
38306c3fb27SDimitry Andric
384cb14a3feSDimitry Andricprivate:
385cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit __hash_const_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) {}
386cb14a3feSDimitry Andric
387cb14a3feSDimitry Andric  template <class, class, class, class>
388cb14a3feSDimitry Andric  friend class __hash_table;
389cb14a3feSDimitry Andric  template <class>
390cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
391cb14a3feSDimitry Andric  template <class, class, class, class, class>
392cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS unordered_map;
393cb14a3feSDimitry Andric  template <class, class, class, class, class>
394cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
3950b57cec5SDimitry Andric};
3960b57cec5SDimitry Andric
3970b57cec5SDimitry Andrictemplate <class _NodePtr>
398cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_local_iterator {
3990b57cec5SDimitry Andric  typedef __hash_node_types<_NodePtr> _NodeTypes;
4000b57cec5SDimitry Andric  typedef _NodePtr __node_pointer;
4010b57cec5SDimitry Andric  typedef typename _NodeTypes::__next_pointer __next_pointer;
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric  __next_pointer __node_;
4040b57cec5SDimitry Andric  size_t __bucket_;
4050b57cec5SDimitry Andric  size_t __bucket_count_;
4060b57cec5SDimitry Andric
4070b57cec5SDimitry Andricpublic:
4080b57cec5SDimitry Andric  typedef forward_iterator_tag iterator_category;
4090b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_value_type value_type;
4100b57cec5SDimitry Andric  typedef typename _NodeTypes::difference_type difference_type;
4110b57cec5SDimitry Andric  typedef value_type& reference;
4120b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_value_type_pointer pointer;
4130b57cec5SDimitry Andric
414cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_local_iterator() _NOEXCEPT : __node_(nullptr) {}
4150b57cec5SDimitry Andric
416*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
417*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
418*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
419*0fca6ea1SDimitry Andric    return __node_->__upcast()->__get_value();
420*0fca6ea1SDimitry Andric  }
4210b57cec5SDimitry Andric
422cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
423*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
424*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
4255f757f3fSDimitry Andric    return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
4260b57cec5SDimitry Andric  }
4270b57cec5SDimitry Andric
428cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_local_iterator& operator++() {
429*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
430*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container local_iterator");
4310b57cec5SDimitry Andric    __node_ = __node_->__next_;
432bdd1243dSDimitry Andric    if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
4330b57cec5SDimitry Andric      __node_ = nullptr;
4340b57cec5SDimitry Andric    return *this;
4350b57cec5SDimitry Andric  }
4360b57cec5SDimitry Andric
437cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_local_iterator operator++(int) {
4380b57cec5SDimitry Andric    __hash_local_iterator __t(*this);
4390b57cec5SDimitry Andric    ++(*this);
4400b57cec5SDimitry Andric    return __t;
4410b57cec5SDimitry Andric  }
4420b57cec5SDimitry Andric
443cb14a3feSDimitry Andric  friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y) {
4440b57cec5SDimitry Andric    return __x.__node_ == __y.__node_;
4450b57cec5SDimitry Andric  }
446cb14a3feSDimitry Andric  friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y) {
447cb14a3feSDimitry Andric    return !(__x == __y);
448cb14a3feSDimitry Andric  }
4490b57cec5SDimitry Andric
4500b57cec5SDimitry Andricprivate:
451cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit __hash_local_iterator(
452cb14a3feSDimitry Andric      __next_pointer __node, size_t __bucket, size_t __bucket_count) _NOEXCEPT
4530b57cec5SDimitry Andric      : __node_(__node),
4540b57cec5SDimitry Andric        __bucket_(__bucket),
455cb14a3feSDimitry Andric        __bucket_count_(__bucket_count) {
45681ad6265SDimitry Andric    if (__node_ != nullptr)
45781ad6265SDimitry Andric      __node_ = __node_->__next_;
45881ad6265SDimitry Andric  }
45906c3fb27SDimitry Andric
460cb14a3feSDimitry Andric  template <class, class, class, class>
461cb14a3feSDimitry Andric  friend class __hash_table;
462cb14a3feSDimitry Andric  template <class>
463cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
464cb14a3feSDimitry Andric  template <class>
465cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
4660b57cec5SDimitry Andric};
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andrictemplate <class _ConstNodePtr>
469cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator {
4700b57cec5SDimitry Andric  typedef __hash_node_types<_ConstNodePtr> _NodeTypes;
4710b57cec5SDimitry Andric  typedef _ConstNodePtr __node_pointer;
4720b57cec5SDimitry Andric  typedef typename _NodeTypes::__next_pointer __next_pointer;
4730b57cec5SDimitry Andric
4740b57cec5SDimitry Andric  __next_pointer __node_;
4750b57cec5SDimitry Andric  size_t __bucket_;
4760b57cec5SDimitry Andric  size_t __bucket_count_;
4770b57cec5SDimitry Andric
4780b57cec5SDimitry Andric  typedef pointer_traits<__node_pointer> __pointer_traits;
4790b57cec5SDimitry Andric  typedef typename __pointer_traits::element_type __node;
480bdd1243dSDimitry Andric  typedef __remove_const_t<__node> __non_const_node;
481cb14a3feSDimitry Andric  typedef __rebind_pointer_t<__node_pointer, __non_const_node> __non_const_node_pointer;
482cb14a3feSDimitry Andric
4830b57cec5SDimitry Andricpublic:
484cb14a3feSDimitry Andric  typedef __hash_local_iterator<__non_const_node_pointer> __non_const_iterator;
4850b57cec5SDimitry Andric
4860b57cec5SDimitry Andric  typedef forward_iterator_tag iterator_category;
4870b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_value_type value_type;
4880b57cec5SDimitry Andric  typedef typename _NodeTypes::difference_type difference_type;
4890b57cec5SDimitry Andric  typedef const value_type& reference;
4900b57cec5SDimitry Andric  typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
4910b57cec5SDimitry Andric
492cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) {}
4930b57cec5SDimitry Andric
494cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
4950b57cec5SDimitry Andric      : __node_(__x.__node_),
4960b57cec5SDimitry Andric        __bucket_(__x.__bucket_),
497cb14a3feSDimitry Andric        __bucket_count_(__x.__bucket_count_) {}
4980b57cec5SDimitry Andric
499*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
500*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
501*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
502*0fca6ea1SDimitry Andric    return __node_->__upcast()->__get_value();
503*0fca6ea1SDimitry Andric  }
5040b57cec5SDimitry Andric
505cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
506*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
507*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
5085f757f3fSDimitry Andric    return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
5090b57cec5SDimitry Andric  }
5100b57cec5SDimitry Andric
511cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator& operator++() {
512*0fca6ea1SDimitry Andric    _LIBCPP_ASSERT_NON_NULL(
513*0fca6ea1SDimitry Andric        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_local_iterator");
5140b57cec5SDimitry Andric    __node_ = __node_->__next_;
515bdd1243dSDimitry Andric    if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
5160b57cec5SDimitry Andric      __node_ = nullptr;
5170b57cec5SDimitry Andric    return *this;
5180b57cec5SDimitry Andric  }
5190b57cec5SDimitry Andric
520cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator operator++(int) {
5210b57cec5SDimitry Andric    __hash_const_local_iterator __t(*this);
5220b57cec5SDimitry Andric    ++(*this);
5230b57cec5SDimitry Andric    return __t;
5240b57cec5SDimitry Andric  }
5250b57cec5SDimitry Andric
526cb14a3feSDimitry Andric  friend _LIBCPP_HIDE_FROM_ABI bool
527cb14a3feSDimitry Andric  operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) {
5280b57cec5SDimitry Andric    return __x.__node_ == __y.__node_;
5290b57cec5SDimitry Andric  }
530cb14a3feSDimitry Andric  friend _LIBCPP_HIDE_FROM_ABI bool
531cb14a3feSDimitry Andric  operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) {
532cb14a3feSDimitry Andric    return !(__x == __y);
533cb14a3feSDimitry Andric  }
5340b57cec5SDimitry Andric
5350b57cec5SDimitry Andricprivate:
536cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit __hash_const_local_iterator(
537cb14a3feSDimitry Andric      __next_pointer __node_ptr, size_t __bucket, size_t __bucket_count) _NOEXCEPT
538fe6060f1SDimitry Andric      : __node_(__node_ptr),
5390b57cec5SDimitry Andric        __bucket_(__bucket),
540cb14a3feSDimitry Andric        __bucket_count_(__bucket_count) {
54181ad6265SDimitry Andric    if (__node_ != nullptr)
54281ad6265SDimitry Andric      __node_ = __node_->__next_;
54381ad6265SDimitry Andric  }
54406c3fb27SDimitry Andric
545cb14a3feSDimitry Andric  template <class, class, class, class>
546cb14a3feSDimitry Andric  friend class __hash_table;
547cb14a3feSDimitry Andric  template <class>
548cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
5490b57cec5SDimitry Andric};
5500b57cec5SDimitry Andric
5510b57cec5SDimitry Andrictemplate <class _Alloc>
552cb14a3feSDimitry Andricclass __bucket_list_deallocator {
5530b57cec5SDimitry Andric  typedef _Alloc allocator_type;
5540b57cec5SDimitry Andric  typedef allocator_traits<allocator_type> __alloc_traits;
5550b57cec5SDimitry Andric  typedef typename __alloc_traits::size_type size_type;
5560b57cec5SDimitry Andric
5570b57cec5SDimitry Andric  __compressed_pair<size_type, allocator_type> __data_;
558cb14a3feSDimitry Andric
5590b57cec5SDimitry Andricpublic:
5600b57cec5SDimitry Andric  typedef typename __alloc_traits::pointer pointer;
5610b57cec5SDimitry Andric
562cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
563480093f4SDimitry Andric      : __data_(0, __default_init_tag()) {}
5640b57cec5SDimitry Andric
565cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator(const allocator_type& __a, size_type __size)
5660b57cec5SDimitry Andric      _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
5670b57cec5SDimitry Andric      : __data_(__size, __a) {}
5680b57cec5SDimitry Andric
569cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator(__bucket_list_deallocator&& __x)
5700b57cec5SDimitry Andric      _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
571cb14a3feSDimitry Andric      : __data_(std::move(__x.__data_)) {
5720b57cec5SDimitry Andric    __x.size() = 0;
5730b57cec5SDimitry Andric  }
5740b57cec5SDimitry Andric
575cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __data_.first(); }
576cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __data_.first(); }
5770b57cec5SDimitry Andric
578cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return __data_.second(); }
579cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { return __data_.second(); }
5800b57cec5SDimitry Andric
581cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { __alloc_traits::deallocate(__alloc(), __p, size()); }
5820b57cec5SDimitry Andric};
5830b57cec5SDimitry Andric
584cb14a3feSDimitry Andrictemplate <class _Alloc>
585cb14a3feSDimitry Andricclass __hash_map_node_destructor;
5860b57cec5SDimitry Andric
5870b57cec5SDimitry Andrictemplate <class _Alloc>
588cb14a3feSDimitry Andricclass __hash_node_destructor {
5890b57cec5SDimitry Andric  typedef _Alloc allocator_type;
5900b57cec5SDimitry Andric  typedef allocator_traits<allocator_type> __alloc_traits;
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andricpublic:
5930b57cec5SDimitry Andric  typedef typename __alloc_traits::pointer pointer;
594cb14a3feSDimitry Andric
5950b57cec5SDimitry Andricprivate:
5960b57cec5SDimitry Andric  typedef __hash_node_types<pointer> _NodeTypes;
5970b57cec5SDimitry Andric
5980b57cec5SDimitry Andric  allocator_type& __na_;
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andricpublic:
6010b57cec5SDimitry Andric  bool __value_constructed;
6020b57cec5SDimitry Andric
60306c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_node_destructor(__hash_node_destructor const&)            = default;
60406c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_node_destructor& operator=(const __hash_node_destructor&) = delete;
605cd0c3137SDimitry Andric
606cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit __hash_node_destructor(allocator_type& __na, bool __constructed = false) _NOEXCEPT
6070b57cec5SDimitry Andric      : __na_(__na),
608cb14a3feSDimitry Andric        __value_constructed(__constructed) {}
6090b57cec5SDimitry Andric
610cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT {
6115f757f3fSDimitry Andric    if (__value_constructed) {
6125f757f3fSDimitry Andric      __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__get_value()));
6135f757f3fSDimitry Andric      std::__destroy_at(std::addressof(*__p));
6145f757f3fSDimitry Andric    }
6150b57cec5SDimitry Andric    if (__p)
6160b57cec5SDimitry Andric      __alloc_traits::deallocate(__na_, __p, 1);
6170b57cec5SDimitry Andric  }
6180b57cec5SDimitry Andric
619cb14a3feSDimitry Andric  template <class>
620cb14a3feSDimitry Andric  friend class __hash_map_node_destructor;
6210b57cec5SDimitry Andric};
6220b57cec5SDimitry Andric
62306c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17
6240b57cec5SDimitry Andrictemplate <class _NodeType, class _Alloc>
6250b57cec5SDimitry Andricstruct __generic_container_node_destructor;
6260b57cec5SDimitry Andric
6270b57cec5SDimitry Andrictemplate <class _Tp, class _VoidPtr, class _Alloc>
628cb14a3feSDimitry Andricstruct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc> : __hash_node_destructor<_Alloc> {
6290b57cec5SDimitry Andric  using __hash_node_destructor<_Alloc>::__hash_node_destructor;
6300b57cec5SDimitry Andric};
6310b57cec5SDimitry Andric#endif
6320b57cec5SDimitry Andric
6330b57cec5SDimitry Andrictemplate <class _Key, class _Hash, class _Equal>
6340b57cec5SDimitry Andricstruct __enforce_unordered_container_requirements {
6350b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
6360b57cec5SDimitry Andric  static_assert(__check_hash_requirements<_Key, _Hash>::value,
6370b57cec5SDimitry Andric                "the specified hash does not meet the Hash requirements");
638cb14a3feSDimitry Andric  static_assert(is_copy_constructible<_Equal>::value, "the specified comparator is required to be copy constructible");
6390b57cec5SDimitry Andric#endif
6400b57cec5SDimitry Andric  typedef int type;
6410b57cec5SDimitry Andric};
6420b57cec5SDimitry Andric
6430b57cec5SDimitry Andrictemplate <class _Key, class _Hash, class _Equal>
6440b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
6450b57cec5SDimitry Andric_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value,
6460b57cec5SDimitry Andric                         "the specified comparator type does not provide a viable const call operator")
6470b57cec5SDimitry Andric_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
6480b57cec5SDimitry Andric                         "the specified hash functor does not provide a viable const call operator")
6490b57cec5SDimitry Andric#endif
6500b57cec5SDimitry Andric    typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
6510b57cec5SDimitry Andric    __diagnose_unordered_container_requirements(int);
6520b57cec5SDimitry Andric
6530b57cec5SDimitry Andric// This dummy overload is used so that the compiler won't emit a spurious
6540b57cec5SDimitry Andric// "no matching function for call to __diagnose_unordered_xxx" diagnostic
6550b57cec5SDimitry Andric// when the overload above causes a hard error.
6560b57cec5SDimitry Andrictemplate <class _Key, class _Hash, class _Equal>
6570b57cec5SDimitry Andricint __diagnose_unordered_container_requirements(void*);
6580b57cec5SDimitry Andric
6590b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
660cb14a3feSDimitry Andricclass __hash_table {
6610b57cec5SDimitry Andricpublic:
6620b57cec5SDimitry Andric  typedef _Tp value_type;
6630b57cec5SDimitry Andric  typedef _Hash hasher;
6640b57cec5SDimitry Andric  typedef _Equal key_equal;
6650b57cec5SDimitry Andric  typedef _Alloc allocator_type;
6660b57cec5SDimitry Andric
6670b57cec5SDimitry Andricprivate:
6680b57cec5SDimitry Andric  typedef allocator_traits<allocator_type> __alloc_traits;
669cb14a3feSDimitry Andric  typedef typename __make_hash_node_types<value_type, typename __alloc_traits::void_pointer>::type _NodeTypes;
6700b57cec5SDimitry Andric
671cb14a3feSDimitry Andricpublic:
6720b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_value_type __node_value_type;
6730b57cec5SDimitry Andric  typedef typename _NodeTypes::__container_value_type __container_value_type;
6740b57cec5SDimitry Andric  typedef typename _NodeTypes::key_type key_type;
6750b57cec5SDimitry Andric  typedef value_type& reference;
6760b57cec5SDimitry Andric  typedef const value_type& const_reference;
6770b57cec5SDimitry Andric  typedef typename __alloc_traits::pointer pointer;
6780b57cec5SDimitry Andric  typedef typename __alloc_traits::const_pointer const_pointer;
6790b57cec5SDimitry Andric#ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
6800b57cec5SDimitry Andric  typedef typename __alloc_traits::size_type size_type;
6810b57cec5SDimitry Andric#else
6820b57cec5SDimitry Andric  typedef typename _NodeTypes::size_type size_type;
6830b57cec5SDimitry Andric#endif
6840b57cec5SDimitry Andric  typedef typename _NodeTypes::difference_type difference_type;
685cb14a3feSDimitry Andric
6860b57cec5SDimitry Andricpublic:
6870b57cec5SDimitry Andric  // Create __node
6880b57cec5SDimitry Andric
6890b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_type __node;
690bdd1243dSDimitry Andric  typedef __rebind_alloc<__alloc_traits, __node> __node_allocator;
6910b57cec5SDimitry Andric  typedef allocator_traits<__node_allocator> __node_traits;
6920b57cec5SDimitry Andric  typedef typename _NodeTypes::__void_pointer __void_pointer;
6930b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_pointer __node_pointer;
6940b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_pointer __node_const_pointer;
6950b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_base_type __first_node;
6960b57cec5SDimitry Andric  typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
6970b57cec5SDimitry Andric  typedef typename _NodeTypes::__next_pointer __next_pointer;
6980b57cec5SDimitry Andric
6990b57cec5SDimitry Andricprivate:
7000b57cec5SDimitry Andric  // check for sane allocator pointer rebinding semantics. Rebinding the
7010b57cec5SDimitry Andric  // allocator for a new pointer type should be exactly the same as rebinding
7020b57cec5SDimitry Andric  // the pointer using 'pointer_traits'.
703*0fca6ea1SDimitry Andric  static_assert(is_same<__node_pointer, typename __node_traits::pointer>::value,
7040b57cec5SDimitry Andric                "Allocator does not rebind pointers in a sane manner.");
705bdd1243dSDimitry Andric  typedef __rebind_alloc<__node_traits, __first_node> __node_base_allocator;
7060b57cec5SDimitry Andric  typedef allocator_traits<__node_base_allocator> __node_base_traits;
707*0fca6ea1SDimitry Andric  static_assert(is_same<__node_base_pointer, typename __node_base_traits::pointer>::value,
7080b57cec5SDimitry Andric                "Allocator does not rebind pointers in a sane manner.");
7090b57cec5SDimitry Andric
7100b57cec5SDimitry Andricprivate:
711bdd1243dSDimitry Andric  typedef __rebind_alloc<__node_traits, __next_pointer> __pointer_allocator;
7120b57cec5SDimitry Andric  typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
7130b57cec5SDimitry Andric  typedef unique_ptr<__next_pointer[], __bucket_list_deleter> __bucket_list;
7140b57cec5SDimitry Andric  typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
7150b57cec5SDimitry Andric  typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
7160b57cec5SDimitry Andric
7170b57cec5SDimitry Andric  // --- Member data begin ---
7180b57cec5SDimitry Andric  __bucket_list __bucket_list_;
7190b57cec5SDimitry Andric  __compressed_pair<__first_node, __node_allocator> __p1_;
7200b57cec5SDimitry Andric  __compressed_pair<size_type, hasher> __p2_;
7210b57cec5SDimitry Andric  __compressed_pair<float, key_equal> __p3_;
7220b57cec5SDimitry Andric  // --- Member data end ---
7230b57cec5SDimitry Andric
724cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __p2_.first(); }
725cb14a3feSDimitry Andric
7260b57cec5SDimitry Andricpublic:
727cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __p2_.first(); }
7280b57cec5SDimitry Andric
729cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI hasher& hash_function() _NOEXCEPT { return __p2_.second(); }
730cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI const hasher& hash_function() const _NOEXCEPT { return __p2_.second(); }
7310b57cec5SDimitry Andric
732cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI float& max_load_factor() _NOEXCEPT { return __p3_.first(); }
733cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __p3_.first(); }
7340b57cec5SDimitry Andric
735cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI key_equal& key_eq() _NOEXCEPT { return __p3_.second(); }
736cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI const key_equal& key_eq() const _NOEXCEPT { return __p3_.second(); }
7370b57cec5SDimitry Andric
738cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __p1_.second(); }
739cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __p1_.second(); }
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andricpublic:
7420b57cec5SDimitry Andric  typedef __hash_iterator<__node_pointer> iterator;
7430b57cec5SDimitry Andric  typedef __hash_const_iterator<__node_pointer> const_iterator;
7440b57cec5SDimitry Andric  typedef __hash_local_iterator<__node_pointer> local_iterator;
7450b57cec5SDimitry Andric  typedef __hash_const_local_iterator<__node_pointer> const_local_iterator;
7460b57cec5SDimitry Andric
747cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_table() _NOEXCEPT_(
748cb14a3feSDimitry Andric      is_nothrow_default_constructible<__bucket_list>::value&& is_nothrow_default_constructible<__first_node>::value&&
749cb14a3feSDimitry Andric          is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_default_constructible<hasher>::value&&
7500b57cec5SDimitry Andric              is_nothrow_default_constructible<key_equal>::value);
751cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_table(const hasher& __hf, const key_equal& __eql);
752cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_table(const hasher& __hf, const key_equal& __eql, const allocator_type& __a);
75306c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit __hash_table(const allocator_type& __a);
75406c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u);
75506c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u, const allocator_type& __a);
756cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u) _NOEXCEPT_(
757cb14a3feSDimitry Andric      is_nothrow_move_constructible<__bucket_list>::value&& is_nothrow_move_constructible<__first_node>::value&&
758cb14a3feSDimitry Andric          is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible<hasher>::value&&
7590b57cec5SDimitry Andric              is_nothrow_move_constructible<key_equal>::value);
76006c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u, const allocator_type& __a);
76106c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI ~__hash_table();
7620b57cec5SDimitry Andric
76306c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(const __hash_table& __u);
764cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(__hash_table&& __u)
765cb14a3feSDimitry Andric      _NOEXCEPT_(__node_traits::propagate_on_container_move_assignment::value&&
766cb14a3feSDimitry Andric                     is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable<hasher>::value&&
7670b57cec5SDimitry Andric                         is_nothrow_move_assignable<key_equal>::value);
7680b57cec5SDimitry Andric  template <class _InputIterator>
76906c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __assign_unique(_InputIterator __first, _InputIterator __last);
7700b57cec5SDimitry Andric  template <class _InputIterator>
77106c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __assign_multi(_InputIterator __first, _InputIterator __last);
7720b57cec5SDimitry Andric
773cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
774cb14a3feSDimitry Andric    return std::min<size_type>(__node_traits::max_size(__node_alloc()), numeric_limits<difference_type >::max());
7750b57cec5SDimitry Andric  }
7760b57cec5SDimitry Andric
7770b57cec5SDimitry Andricprivate:
778cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __next_pointer __node_insert_multi_prepare(size_t __cp_hash, value_type& __cp_val);
779cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __node_insert_multi_perform(__node_pointer __cp, __next_pointer __pn) _NOEXCEPT;
7800b57cec5SDimitry Andric
781cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __next_pointer __node_insert_unique_prepare(size_t __nd_hash, value_type& __nd_val);
782cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __node_insert_unique_perform(__node_pointer __ptr) _NOEXCEPT;
7830b57cec5SDimitry Andric
7840b57cec5SDimitry Andricpublic:
785cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
786cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd);
787cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
7880b57cec5SDimitry Andric
7890b57cec5SDimitry Andric  template <class _Key, class... _Args>
790cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args);
7910b57cec5SDimitry Andric
7920b57cec5SDimitry Andric  template <class... _Args>
793cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_impl(_Args&&... __args);
7940b57cec5SDimitry Andric
7950b57cec5SDimitry Andric  template <class _Pp>
796cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Pp&& __x) {
797cb14a3feSDimitry Andric    return __emplace_unique_extract_key(std::forward<_Pp>(__x), __can_extract_key<_Pp, key_type>());
7980b57cec5SDimitry Andric  }
7990b57cec5SDimitry Andric
800cb14a3feSDimitry Andric  template <class _First,
801cb14a3feSDimitry Andric            class _Second,
8025f757f3fSDimitry Andric            __enable_if_t<__can_extract_map_key<_First, key_type, __container_value_type>::value, int> = 0>
803cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_First&& __f, _Second&& __s) {
804cb14a3feSDimitry Andric    return __emplace_unique_key_args(__f, std::forward<_First>(__f), std::forward<_Second>(__s));
8050b57cec5SDimitry Andric  }
8060b57cec5SDimitry Andric
8070b57cec5SDimitry Andric  template <class... _Args>
808cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Args&&... __args) {
8095f757f3fSDimitry Andric    return __emplace_unique_impl(std::forward<_Args>(__args)...);
8100b57cec5SDimitry Andric  }
8110b57cec5SDimitry Andric
8120b57cec5SDimitry Andric  template <class _Pp>
813cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) {
8145f757f3fSDimitry Andric    return __emplace_unique_impl(std::forward<_Pp>(__x));
8150b57cec5SDimitry Andric  }
8160b57cec5SDimitry Andric  template <class _Pp>
817cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) {
8185f757f3fSDimitry Andric    return __emplace_unique_key_args(__x, std::forward<_Pp>(__x));
8190b57cec5SDimitry Andric  }
8200b57cec5SDimitry Andric  template <class _Pp>
821cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) {
8225f757f3fSDimitry Andric    return __emplace_unique_key_args(__x.first, std::forward<_Pp>(__x));
8230b57cec5SDimitry Andric  }
8240b57cec5SDimitry Andric
8250b57cec5SDimitry Andric  template <class... _Args>
826cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator __emplace_multi(_Args&&... __args);
8270b57cec5SDimitry Andric  template <class... _Args>
828cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
8290b57cec5SDimitry Andric
830cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_unique(__container_value_type&& __x) {
8315f757f3fSDimitry Andric    return __emplace_unique_key_args(_NodeTypes::__get_key(__x), std::move(__x));
8320b57cec5SDimitry Andric  }
8330b57cec5SDimitry Andric
834*0fca6ea1SDimitry Andric  template <class _Pp, __enable_if_t<!__is_same_uncvref<_Pp, __container_value_type>::value, int> = 0>
835cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_unique(_Pp&& __x) {
8365f757f3fSDimitry Andric    return __emplace_unique(std::forward<_Pp>(__x));
8370b57cec5SDimitry Andric  }
8380b57cec5SDimitry Andric
8390b57cec5SDimitry Andric  template <class _Pp>
840cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(_Pp&& __x) {
8415f757f3fSDimitry Andric    return __emplace_multi(std::forward<_Pp>(__x));
8420b57cec5SDimitry Andric  }
8430b57cec5SDimitry Andric
8440b57cec5SDimitry Andric  template <class _Pp>
845cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(const_iterator __p, _Pp&& __x) {
8465f757f3fSDimitry Andric    return __emplace_hint_multi(__p, std::forward<_Pp>(__x));
8470b57cec5SDimitry Andric  }
8480b57cec5SDimitry Andric
849cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_unique(const __container_value_type& __x) {
8500b57cec5SDimitry Andric    return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x);
8510b57cec5SDimitry Andric  }
8520b57cec5SDimitry Andric
85306c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17
8540b57cec5SDimitry Andric  template <class _NodeHandle, class _InsertReturnType>
855cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh);
8560b57cec5SDimitry Andric  template <class _NodeHandle>
857cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_unique(const_iterator __hint, _NodeHandle&& __nh);
8580b57cec5SDimitry Andric  template <class _Table>
859cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_unique(_Table& __source);
8600b57cec5SDimitry Andric
8610b57cec5SDimitry Andric  template <class _NodeHandle>
862cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_multi(_NodeHandle&& __nh);
8630b57cec5SDimitry Andric  template <class _NodeHandle>
864cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh);
8650b57cec5SDimitry Andric  template <class _Table>
866cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_multi(_Table& __source);
8670b57cec5SDimitry Andric
8680b57cec5SDimitry Andric  template <class _NodeHandle>
869cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(key_type const& __key);
8700b57cec5SDimitry Andric  template <class _NodeHandle>
871cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const_iterator __it);
8720b57cec5SDimitry Andric#endif
8730b57cec5SDimitry Andric
87406c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
8755f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __rehash_unique(size_type __n) { __rehash<true>(__n); }
8765f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __rehash_multi(size_type __n) { __rehash<false>(__n); }
877cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __reserve_unique(size_type __n) {
878bdd1243dSDimitry Andric    __rehash_unique(static_cast<size_type>(std::ceil(__n / max_load_factor())));
879753f127fSDimitry Andric  }
880cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __reserve_multi(size_type __n) {
881bdd1243dSDimitry Andric    __rehash_multi(static_cast<size_type>(std::ceil(__n / max_load_factor())));
882753f127fSDimitry Andric  }
8830b57cec5SDimitry Andric
884cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const _NOEXCEPT { return __bucket_list_.get_deleter().size(); }
8850b57cec5SDimitry Andric
886cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT;
887cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT;
888cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT;
889cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT;
8900b57cec5SDimitry Andric
8910b57cec5SDimitry Andric  template <class _Key>
892cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type bucket(const _Key& __k) const {
8937a6dacacSDimitry Andric    _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
894cb14a3feSDimitry Andric        bucket_count() > 0, "unordered container::bucket(key) called when bucket_count() == 0");
895bdd1243dSDimitry Andric    return std::__constrain_hash(hash_function()(__k), bucket_count());
8960b57cec5SDimitry Andric  }
8970b57cec5SDimitry Andric
8980b57cec5SDimitry Andric  template <class _Key>
89906c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator find(const _Key& __x);
9000b57cec5SDimitry Andric  template <class _Key>
90106c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Key& __x) const;
9020b57cec5SDimitry Andric
9030b57cec5SDimitry Andric  typedef __hash_node_destructor<__node_allocator> _Dp;
9040b57cec5SDimitry Andric  typedef unique_ptr<__node, _Dp> __node_holder;
9050b57cec5SDimitry Andric
90606c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p);
90706c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last);
9080b57cec5SDimitry Andric  template <class _Key>
90906c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type __erase_unique(const _Key& __k);
9100b57cec5SDimitry Andric  template <class _Key>
91106c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type __erase_multi(const _Key& __k);
91206c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __node_holder remove(const_iterator __p) _NOEXCEPT;
9130b57cec5SDimitry Andric
9140b57cec5SDimitry Andric  template <class _Key>
915cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type __count_unique(const _Key& __k) const;
9160b57cec5SDimitry Andric  template <class _Key>
91706c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const;
9180b57cec5SDimitry Andric
9190b57cec5SDimitry Andric  template <class _Key>
920cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_unique(const _Key& __k);
9210b57cec5SDimitry Andric  template <class _Key>
922cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_unique(const _Key& __k) const;
9230b57cec5SDimitry Andric
9240b57cec5SDimitry Andric  template <class _Key>
925cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_multi(const _Key& __k);
9260b57cec5SDimitry Andric  template <class _Key>
927cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_multi(const _Key& __k) const;
9280b57cec5SDimitry Andric
92906c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void swap(__hash_table& __u)
9300b57cec5SDimitry Andric#if _LIBCPP_STD_VER <= 11
931*0fca6ea1SDimitry Andric      _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal> &&
932cb14a3feSDimitry Andric                 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
933*0fca6ea1SDimitry Andric                  __is_nothrow_swappable_v<__pointer_allocator>) &&
934*0fca6ea1SDimitry Andric                 (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>));
9350b57cec5SDimitry Andric#else
936*0fca6ea1SDimitry Andric      _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal>);
9370b57cec5SDimitry Andric#endif
9380b57cec5SDimitry Andric
939cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT { return max_size(); }
94006c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const;
941cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI float load_factor() const _NOEXCEPT {
9420b57cec5SDimitry Andric    size_type __bc = bucket_count();
9430b57cec5SDimitry Andric    return __bc != 0 ? (float)size() / __bc : 0.f;
9440b57cec5SDimitry Andric  }
945cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void max_load_factor(float __mlf) _NOEXCEPT {
9461db9f3b2SDimitry Andric    // While passing a non-positive load factor is undefined behavior, in practice the result will be benign (the
9471db9f3b2SDimitry Andric    // call will be equivalent to `max_load_factor(load_factor())`, which is also the case for passing a valid value
9481db9f3b2SDimitry Andric    // less than the current `load_factor`).
9491db9f3b2SDimitry Andric    _LIBCPP_ASSERT_PEDANTIC(__mlf > 0, "unordered container::max_load_factor(lf) called with lf <= 0");
9505f757f3fSDimitry Andric    max_load_factor() = std::max(__mlf, load_factor());
9510b57cec5SDimitry Andric  }
9520b57cec5SDimitry Andric
953cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI local_iterator begin(size_type __n) {
954cb14a3feSDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
955cb14a3feSDimitry Andric        __n < bucket_count(), "unordered container::begin(n) called with n >= bucket_count()");
95606c3fb27SDimitry Andric    return local_iterator(__bucket_list_[__n], __n, bucket_count());
9570b57cec5SDimitry Andric  }
9580b57cec5SDimitry Andric
959cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI local_iterator end(size_type __n) {
960cb14a3feSDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
961cb14a3feSDimitry Andric        __n < bucket_count(), "unordered container::end(n) called with n >= bucket_count()");
96206c3fb27SDimitry Andric    return local_iterator(nullptr, __n, bucket_count());
9630b57cec5SDimitry Andric  }
9640b57cec5SDimitry Andric
965cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI const_local_iterator cbegin(size_type __n) const {
966cb14a3feSDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
967cb14a3feSDimitry Andric        __n < bucket_count(), "unordered container::cbegin(n) called with n >= bucket_count()");
96806c3fb27SDimitry Andric    return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
9690b57cec5SDimitry Andric  }
9700b57cec5SDimitry Andric
971cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI const_local_iterator cend(size_type __n) const {
972cb14a3feSDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
973cb14a3feSDimitry Andric        __n < bucket_count(), "unordered container::cend(n) called with n >= bucket_count()");
97406c3fb27SDimitry Andric    return const_local_iterator(nullptr, __n, bucket_count());
9750b57cec5SDimitry Andric  }
9760b57cec5SDimitry Andric
9770b57cec5SDimitry Andricprivate:
97806c3fb27SDimitry Andric  template <bool _UniqueKeys>
97906c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __rehash(size_type __n);
98006c3fb27SDimitry Andric  template <bool _UniqueKeys>
98106c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __do_rehash(size_type __n);
9820b57cec5SDimitry Andric
9830b57cec5SDimitry Andric  template <class... _Args>
98406c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&&... __args);
9850b57cec5SDimitry Andric
9860b57cec5SDimitry Andric  template <class _First, class... _Rest>
98706c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest);
9880b57cec5SDimitry Andric
989cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u) {
990cb14a3feSDimitry Andric    __copy_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());
991cb14a3feSDimitry Andric  }
99206c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u, true_type);
993cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table&, false_type) {}
9940b57cec5SDimitry Andric
99506c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, false_type);
99606c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, true_type)
997cb14a3feSDimitry Andric      _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable<hasher>::value&&
9980b57cec5SDimitry Andric                     is_nothrow_move_assignable<key_equal>::value);
999cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table& __u) _NOEXCEPT_(
10000b57cec5SDimitry Andric      !__node_traits::propagate_on_container_move_assignment::value ||
1001cb14a3feSDimitry Andric      (is_nothrow_move_assignable<__pointer_allocator>::value && is_nothrow_move_assignable<__node_allocator>::value)) {
1002cb14a3feSDimitry Andric    __move_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>());
1003cb14a3feSDimitry Andric  }
1004cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table& __u, true_type) _NOEXCEPT_(
1005cb14a3feSDimitry Andric      is_nothrow_move_assignable<__pointer_allocator>::value&& is_nothrow_move_assignable<__node_allocator>::value) {
1006cb14a3feSDimitry Andric    __bucket_list_.get_deleter().__alloc() = std::move(__u.__bucket_list_.get_deleter().__alloc());
10075f757f3fSDimitry Andric    __node_alloc()                         = std::move(__u.__node_alloc());
10080b57cec5SDimitry Andric  }
1009cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
10100b57cec5SDimitry Andric
101106c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI void __deallocate_node(__next_pointer __np) _NOEXCEPT;
101206c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT;
10130b57cec5SDimitry Andric
1014cb14a3feSDimitry Andric  template <class, class, class, class, class>
1015cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS unordered_map;
1016cb14a3feSDimitry Andric  template <class, class, class, class, class>
1017cb14a3feSDimitry Andric  friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
10180b57cec5SDimitry Andric};
10190b57cec5SDimitry Andric
10200b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1021cb14a3feSDimitry Andricinline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table() _NOEXCEPT_(
1022cb14a3feSDimitry Andric    is_nothrow_default_constructible<__bucket_list>::value&& is_nothrow_default_constructible<__first_node>::value&&
1023cb14a3feSDimitry Andric        is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_default_constructible<hasher>::value&&
10240b57cec5SDimitry Andric            is_nothrow_default_constructible<key_equal>::value)
1025cb14a3feSDimitry Andric    : __p2_(0, __default_init_tag()), __p3_(1.0f, __default_init_tag()) {}
10260b57cec5SDimitry Andric
10270b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1028cb14a3feSDimitry Andricinline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, const key_equal& __eql)
1029cb14a3feSDimitry Andric    : __bucket_list_(nullptr, __bucket_list_deleter()), __p1_(), __p2_(0, __hf), __p3_(1.0f, __eql) {}
10300b57cec5SDimitry Andric
10310b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1032cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(
1033cb14a3feSDimitry Andric    const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
10340b57cec5SDimitry Andric    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1035480093f4SDimitry Andric      __p1_(__default_init_tag(), __node_allocator(__a)),
10360b57cec5SDimitry Andric      __p2_(0, __hf),
1037cb14a3feSDimitry Andric      __p3_(1.0f, __eql) {}
10380b57cec5SDimitry Andric
10390b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
10400b57cec5SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
10410b57cec5SDimitry Andric    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1042480093f4SDimitry Andric      __p1_(__default_init_tag(), __node_allocator(__a)),
1043480093f4SDimitry Andric      __p2_(0, __default_init_tag()),
1044cb14a3feSDimitry Andric      __p3_(1.0f, __default_init_tag()) {}
10450b57cec5SDimitry Andric
10460b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
10470b57cec5SDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
10480b57cec5SDimitry Andric    : __bucket_list_(nullptr,
1049cb14a3feSDimitry Andric                     __bucket_list_deleter(allocator_traits<__pointer_allocator>::select_on_container_copy_construction(
1050cb14a3feSDimitry Andric                                               __u.__bucket_list_.get_deleter().__alloc()),
1051cb14a3feSDimitry Andric                                           0)),
1052cb14a3feSDimitry Andric      __p1_(__default_init_tag(),
1053cb14a3feSDimitry Andric            allocator_traits<__node_allocator>::select_on_container_copy_construction(__u.__node_alloc())),
10540b57cec5SDimitry Andric      __p2_(0, __u.hash_function()),
1055cb14a3feSDimitry Andric      __p3_(__u.__p3_) {}
10560b57cec5SDimitry Andric
10570b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1058cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u, const allocator_type& __a)
10590b57cec5SDimitry Andric    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1060480093f4SDimitry Andric      __p1_(__default_init_tag(), __node_allocator(__a)),
10610b57cec5SDimitry Andric      __p2_(0, __u.hash_function()),
1062cb14a3feSDimitry Andric      __p3_(__u.__p3_) {}
10630b57cec5SDimitry Andric
10640b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1065cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) _NOEXCEPT_(
1066cb14a3feSDimitry Andric    is_nothrow_move_constructible<__bucket_list>::value&& is_nothrow_move_constructible<__first_node>::value&&
1067cb14a3feSDimitry Andric        is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible<hasher>::value&&
10680b57cec5SDimitry Andric            is_nothrow_move_constructible<key_equal>::value)
10695f757f3fSDimitry Andric    : __bucket_list_(std::move(__u.__bucket_list_)),
10705f757f3fSDimitry Andric      __p1_(std::move(__u.__p1_)),
10715f757f3fSDimitry Andric      __p2_(std::move(__u.__p2_)),
1072cb14a3feSDimitry Andric      __p3_(std::move(__u.__p3_)) {
1073cb14a3feSDimitry Andric  if (size() > 0) {
1074cb14a3feSDimitry Andric    __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
10750b57cec5SDimitry Andric    __u.__p1_.first().__next_                                                              = nullptr;
10760b57cec5SDimitry Andric    __u.size()                                                                             = 0;
10770b57cec5SDimitry Andric  }
10780b57cec5SDimitry Andric}
10790b57cec5SDimitry Andric
10800b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1081cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, const allocator_type& __a)
10820b57cec5SDimitry Andric    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1083480093f4SDimitry Andric      __p1_(__default_init_tag(), __node_allocator(__a)),
10845f757f3fSDimitry Andric      __p2_(0, std::move(__u.hash_function())),
1085cb14a3feSDimitry Andric      __p3_(std::move(__u.__p3_)) {
1086cb14a3feSDimitry Andric  if (__a == allocator_type(__u.__node_alloc())) {
10870b57cec5SDimitry Andric    __bucket_list_.reset(__u.__bucket_list_.release());
10880b57cec5SDimitry Andric    __bucket_list_.get_deleter().size()     = __u.__bucket_list_.get_deleter().size();
10890b57cec5SDimitry Andric    __u.__bucket_list_.get_deleter().size() = 0;
1090cb14a3feSDimitry Andric    if (__u.size() > 0) {
10910b57cec5SDimitry Andric      __p1_.first().__next_     = __u.__p1_.first().__next_;
10920b57cec5SDimitry Andric      __u.__p1_.first().__next_ = nullptr;
1093cb14a3feSDimitry Andric      __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
10940b57cec5SDimitry Andric      size()                                                                                 = __u.size();
10950b57cec5SDimitry Andric      __u.size()                                                                             = 0;
10960b57cec5SDimitry Andric    }
10970b57cec5SDimitry Andric  }
10980b57cec5SDimitry Andric}
10990b57cec5SDimitry Andric
11000b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1101cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() {
11020b57cec5SDimitry Andric#if defined(_LIBCPP_CXX03_LANG)
1103*0fca6ea1SDimitry Andric  static_assert(is_copy_constructible<key_equal>::value, "Predicate must be copy-constructible.");
1104*0fca6ea1SDimitry Andric  static_assert(is_copy_constructible<hasher>::value, "Hasher must be copy-constructible.");
11050b57cec5SDimitry Andric#endif
11060b57cec5SDimitry Andric
11070b57cec5SDimitry Andric  __deallocate_node(__p1_.first().__next_);
11080b57cec5SDimitry Andric}
11090b57cec5SDimitry Andric
11100b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1111cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(const __hash_table& __u, true_type) {
1112cb14a3feSDimitry Andric  if (__node_alloc() != __u.__node_alloc()) {
11130b57cec5SDimitry Andric    clear();
11140b57cec5SDimitry Andric    __bucket_list_.reset();
11150b57cec5SDimitry Andric    __bucket_list_.get_deleter().size() = 0;
11160b57cec5SDimitry Andric  }
11170b57cec5SDimitry Andric  __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
11180b57cec5SDimitry Andric  __node_alloc()                         = __u.__node_alloc();
11190b57cec5SDimitry Andric}
11200b57cec5SDimitry Andric
11210b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1122cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>& __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u) {
1123cb14a3feSDimitry Andric  if (this != std::addressof(__u)) {
11240b57cec5SDimitry Andric    __copy_assign_alloc(__u);
11250b57cec5SDimitry Andric    hash_function()   = __u.hash_function();
11260b57cec5SDimitry Andric    key_eq()          = __u.key_eq();
11270b57cec5SDimitry Andric    max_load_factor() = __u.max_load_factor();
11280b57cec5SDimitry Andric    __assign_multi(__u.begin(), __u.end());
11290b57cec5SDimitry Andric  }
11300b57cec5SDimitry Andric  return *this;
11310b57cec5SDimitry Andric}
11320b57cec5SDimitry Andric
11330b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1134cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np) _NOEXCEPT {
11350b57cec5SDimitry Andric  __node_allocator& __na = __node_alloc();
1136cb14a3feSDimitry Andric  while (__np != nullptr) {
11370b57cec5SDimitry Andric    __next_pointer __next    = __np->__next_;
11380b57cec5SDimitry Andric    __node_pointer __real_np = __np->__upcast();
11395f757f3fSDimitry Andric    __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__get_value()));
11405f757f3fSDimitry Andric    std::__destroy_at(std::addressof(*__real_np));
11410b57cec5SDimitry Andric    __node_traits::deallocate(__na, __real_np, 1);
11420b57cec5SDimitry Andric    __np = __next;
11430b57cec5SDimitry Andric  }
11440b57cec5SDimitry Andric}
11450b57cec5SDimitry Andric
11460b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
11470b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1148cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT {
11490b57cec5SDimitry Andric  size_type __bc = bucket_count();
11500b57cec5SDimitry Andric  for (size_type __i = 0; __i < __bc; ++__i)
11510b57cec5SDimitry Andric    __bucket_list_[__i] = nullptr;
11520b57cec5SDimitry Andric  size()                 = 0;
11530b57cec5SDimitry Andric  __next_pointer __cache = __p1_.first().__next_;
11540b57cec5SDimitry Andric  __p1_.first().__next_  = nullptr;
11550b57cec5SDimitry Andric  return __cache;
11560b57cec5SDimitry Andric}
11570b57cec5SDimitry Andric
11580b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1159cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, true_type)
1160cb14a3feSDimitry Andric    _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable<hasher>::value&&
1161cb14a3feSDimitry Andric                   is_nothrow_move_assignable<key_equal>::value) {
11620b57cec5SDimitry Andric  clear();
11630b57cec5SDimitry Andric  __bucket_list_.reset(__u.__bucket_list_.release());
11640b57cec5SDimitry Andric  __bucket_list_.get_deleter().size()     = __u.__bucket_list_.get_deleter().size();
11650b57cec5SDimitry Andric  __u.__bucket_list_.get_deleter().size() = 0;
11660b57cec5SDimitry Andric  __move_assign_alloc(__u);
11670b57cec5SDimitry Andric  size()                = __u.size();
11685f757f3fSDimitry Andric  hash_function()       = std::move(__u.hash_function());
11690b57cec5SDimitry Andric  max_load_factor()     = __u.max_load_factor();
11705f757f3fSDimitry Andric  key_eq()              = std::move(__u.key_eq());
11710b57cec5SDimitry Andric  __p1_.first().__next_ = __u.__p1_.first().__next_;
1172cb14a3feSDimitry Andric  if (size() > 0) {
1173cb14a3feSDimitry Andric    __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
11740b57cec5SDimitry Andric    __u.__p1_.first().__next_                                                              = nullptr;
11750b57cec5SDimitry Andric    __u.size()                                                                             = 0;
11760b57cec5SDimitry Andric  }
11770b57cec5SDimitry Andric}
11780b57cec5SDimitry Andric
11790b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1180cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, false_type) {
11810b57cec5SDimitry Andric  if (__node_alloc() == __u.__node_alloc())
11820b57cec5SDimitry Andric    __move_assign(__u, true_type());
1183cb14a3feSDimitry Andric  else {
11845f757f3fSDimitry Andric    hash_function()   = std::move(__u.hash_function());
11855f757f3fSDimitry Andric    key_eq()          = std::move(__u.key_eq());
11860b57cec5SDimitry Andric    max_load_factor() = __u.max_load_factor();
1187cb14a3feSDimitry Andric    if (bucket_count() != 0) {
11880b57cec5SDimitry Andric      __next_pointer __cache = __detach();
118906c3fb27SDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1190cb14a3feSDimitry Andric      try {
119106c3fb27SDimitry Andric#endif // _LIBCPP_HAS_NO_EXCEPTIONS
11920b57cec5SDimitry Andric        const_iterator __i = __u.begin();
1193cb14a3feSDimitry Andric        while (__cache != nullptr && __u.size() != 0) {
1194cb14a3feSDimitry Andric          __cache->__upcast()->__get_value() = std::move(__u.remove(__i++)->__get_value());
11950b57cec5SDimitry Andric          __next_pointer __next              = __cache->__next_;
11960b57cec5SDimitry Andric          __node_insert_multi(__cache->__upcast());
11970b57cec5SDimitry Andric          __cache = __next;
11980b57cec5SDimitry Andric        }
119906c3fb27SDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1200cb14a3feSDimitry Andric      } catch (...) {
12010b57cec5SDimitry Andric        __deallocate_node(__cache);
12020b57cec5SDimitry Andric        throw;
12030b57cec5SDimitry Andric      }
120406c3fb27SDimitry Andric#endif // _LIBCPP_HAS_NO_EXCEPTIONS
12050b57cec5SDimitry Andric      __deallocate_node(__cache);
12060b57cec5SDimitry Andric    }
12070b57cec5SDimitry Andric    const_iterator __i = __u.begin();
1208cb14a3feSDimitry Andric    while (__u.size() != 0) {
12095f757f3fSDimitry Andric      __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__get_value()));
12100b57cec5SDimitry Andric      __node_insert_multi(__h.get());
12110b57cec5SDimitry Andric      __h.release();
12120b57cec5SDimitry Andric    }
12130b57cec5SDimitry Andric  }
12140b57cec5SDimitry Andric}
12150b57cec5SDimitry Andric
12160b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1217cb14a3feSDimitry Andricinline __hash_table<_Tp, _Hash, _Equal, _Alloc>&
1218cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u) _NOEXCEPT_(
1219cb14a3feSDimitry Andric    __node_traits::propagate_on_container_move_assignment::value&& is_nothrow_move_assignable<__node_allocator>::value&&
1220cb14a3feSDimitry Andric        is_nothrow_move_assignable<hasher>::value&& is_nothrow_move_assignable<key_equal>::value) {
1221cb14a3feSDimitry Andric  __move_assign(__u, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>());
12220b57cec5SDimitry Andric  return *this;
12230b57cec5SDimitry Andric}
12240b57cec5SDimitry Andric
12250b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
12260b57cec5SDimitry Andrictemplate <class _InputIterator>
1227cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, _InputIterator __last) {
12280b57cec5SDimitry Andric  typedef iterator_traits<_InputIterator> _ITraits;
12290b57cec5SDimitry Andric  typedef typename _ITraits::value_type _ItValueType;
1230*0fca6ea1SDimitry Andric  static_assert(is_same<_ItValueType, __container_value_type>::value,
12310b57cec5SDimitry Andric                "__assign_unique may only be called with the containers value type");
12320b57cec5SDimitry Andric
1233cb14a3feSDimitry Andric  if (bucket_count() != 0) {
12340b57cec5SDimitry Andric    __next_pointer __cache = __detach();
123506c3fb27SDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1236cb14a3feSDimitry Andric    try {
123706c3fb27SDimitry Andric#endif // _LIBCPP_HAS_NO_EXCEPTIONS
1238cb14a3feSDimitry Andric      for (; __cache != nullptr && __first != __last; ++__first) {
12395f757f3fSDimitry Andric        __cache->__upcast()->__get_value() = *__first;
12400b57cec5SDimitry Andric        __next_pointer __next              = __cache->__next_;
12410b57cec5SDimitry Andric        __node_insert_unique(__cache->__upcast());
12420b57cec5SDimitry Andric        __cache = __next;
12430b57cec5SDimitry Andric      }
124406c3fb27SDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1245cb14a3feSDimitry Andric    } catch (...) {
12460b57cec5SDimitry Andric      __deallocate_node(__cache);
12470b57cec5SDimitry Andric      throw;
12480b57cec5SDimitry Andric    }
124906c3fb27SDimitry Andric#endif // _LIBCPP_HAS_NO_EXCEPTIONS
12500b57cec5SDimitry Andric    __deallocate_node(__cache);
12510b57cec5SDimitry Andric  }
12520b57cec5SDimitry Andric  for (; __first != __last; ++__first)
12530b57cec5SDimitry Andric    __insert_unique(*__first);
12540b57cec5SDimitry Andric}
12550b57cec5SDimitry Andric
12560b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
12570b57cec5SDimitry Andrictemplate <class _InputIterator>
1258cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, _InputIterator __last) {
12590b57cec5SDimitry Andric  typedef iterator_traits<_InputIterator> _ITraits;
12600b57cec5SDimitry Andric  typedef typename _ITraits::value_type _ItValueType;
1261cb14a3feSDimitry Andric  static_assert(
1262cb14a3feSDimitry Andric      (is_same<_ItValueType, __container_value_type>::value || is_same<_ItValueType, __node_value_type>::value),
12630b57cec5SDimitry Andric      "__assign_multi may only be called with the containers value type"
12640b57cec5SDimitry Andric      " or the nodes value type");
1265cb14a3feSDimitry Andric  if (bucket_count() != 0) {
12660b57cec5SDimitry Andric    __next_pointer __cache = __detach();
126706c3fb27SDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1268cb14a3feSDimitry Andric    try {
126906c3fb27SDimitry Andric#endif // _LIBCPP_HAS_NO_EXCEPTIONS
1270cb14a3feSDimitry Andric      for (; __cache != nullptr && __first != __last; ++__first) {
12715f757f3fSDimitry Andric        __cache->__upcast()->__get_value() = *__first;
12720b57cec5SDimitry Andric        __next_pointer __next              = __cache->__next_;
12730b57cec5SDimitry Andric        __node_insert_multi(__cache->__upcast());
12740b57cec5SDimitry Andric        __cache = __next;
12750b57cec5SDimitry Andric      }
127606c3fb27SDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1277cb14a3feSDimitry Andric    } catch (...) {
12780b57cec5SDimitry Andric      __deallocate_node(__cache);
12790b57cec5SDimitry Andric      throw;
12800b57cec5SDimitry Andric    }
128106c3fb27SDimitry Andric#endif // _LIBCPP_HAS_NO_EXCEPTIONS
12820b57cec5SDimitry Andric    __deallocate_node(__cache);
12830b57cec5SDimitry Andric  }
12840b57cec5SDimitry Andric  for (; __first != __last; ++__first)
12850b57cec5SDimitry Andric    __insert_multi(_NodeTypes::__get_value(*__first));
12860b57cec5SDimitry Andric}
12870b57cec5SDimitry Andric
12880b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1289cb14a3feSDimitry Andricinline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1290cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT {
129106c3fb27SDimitry Andric  return iterator(__p1_.first().__next_);
12920b57cec5SDimitry Andric}
12930b57cec5SDimitry Andric
12940b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1295cb14a3feSDimitry Andricinline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1296cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT {
129706c3fb27SDimitry Andric  return iterator(nullptr);
12980b57cec5SDimitry Andric}
12990b57cec5SDimitry Andric
13000b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1301cb14a3feSDimitry Andricinline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1302cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT {
130306c3fb27SDimitry Andric  return const_iterator(__p1_.first().__next_);
13040b57cec5SDimitry Andric}
13050b57cec5SDimitry Andric
13060b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1307cb14a3feSDimitry Andricinline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1308cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT {
130906c3fb27SDimitry Andric  return const_iterator(nullptr);
13100b57cec5SDimitry Andric}
13110b57cec5SDimitry Andric
13120b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1313cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT {
1314cb14a3feSDimitry Andric  if (size() > 0) {
13150b57cec5SDimitry Andric    __deallocate_node(__p1_.first().__next_);
13160b57cec5SDimitry Andric    __p1_.first().__next_ = nullptr;
13170b57cec5SDimitry Andric    size_type __bc        = bucket_count();
13180b57cec5SDimitry Andric    for (size_type __i = 0; __i < __bc; ++__i)
13190b57cec5SDimitry Andric      __bucket_list_[__i] = nullptr;
13200b57cec5SDimitry Andric    size() = 0;
13210b57cec5SDimitry Andric  }
13220b57cec5SDimitry Andric}
13230b57cec5SDimitry Andric
13240b57cec5SDimitry Andric// Prepare the container for an insertion of the value __value with the hash
13250b57cec5SDimitry Andric// __hash. This does a lookup into the container to see if __value is already
13260b57cec5SDimitry Andric// present, and performs a rehash if necessary. Returns a pointer to the
13270b57cec5SDimitry Andric// existing element if it exists, otherwise nullptr.
13280b57cec5SDimitry Andric//
13290b57cec5SDimitry Andric// Note that this function does forward exceptions if key_eq() throws, and never
13300b57cec5SDimitry Andric// mutates __value or actually inserts into the map.
13310b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1332cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1333cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare(size_t __hash, value_type& __value) {
13340b57cec5SDimitry Andric  size_type __bc = bucket_count();
13350b57cec5SDimitry Andric
1336cb14a3feSDimitry Andric  if (__bc != 0) {
1337bdd1243dSDimitry Andric    size_t __chash         = std::__constrain_hash(__hash, __bc);
13380b57cec5SDimitry Andric    __next_pointer __ndptr = __bucket_list_[__chash];
1339cb14a3feSDimitry Andric    if (__ndptr != nullptr) {
1340cb14a3feSDimitry Andric      for (__ndptr = __ndptr->__next_;
1341cb14a3feSDimitry Andric           __ndptr != nullptr &&
1342cb14a3feSDimitry Andric           (__ndptr->__hash() == __hash || std::__constrain_hash(__ndptr->__hash(), __bc) == __chash);
1343cb14a3feSDimitry Andric           __ndptr = __ndptr->__next_) {
1344cb14a3feSDimitry Andric        if ((__ndptr->__hash() == __hash) && key_eq()(__ndptr->__upcast()->__get_value(), __value))
13450b57cec5SDimitry Andric          return __ndptr;
13460b57cec5SDimitry Andric      }
13470b57cec5SDimitry Andric    }
13480b57cec5SDimitry Andric  }
1349cb14a3feSDimitry Andric  if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1350cb14a3feSDimitry Andric    __rehash_unique(std::max<size_type>(
1351cb14a3feSDimitry Andric        2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
13520b57cec5SDimitry Andric  }
13530b57cec5SDimitry Andric  return nullptr;
13540b57cec5SDimitry Andric}
13550b57cec5SDimitry Andric
13560b57cec5SDimitry Andric// Insert the node __nd into the container by pushing it into the right bucket,
13570b57cec5SDimitry Andric// and updating size(). Assumes that __nd->__hash is up-to-date, and that
13580b57cec5SDimitry Andric// rehashing has already occurred and that no element with the same key exists
13590b57cec5SDimitry Andric// in the map.
13600b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1361cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI void
1362cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_perform(__node_pointer __nd) _NOEXCEPT {
13630b57cec5SDimitry Andric  size_type __bc = bucket_count();
1364bdd1243dSDimitry Andric  size_t __chash = std::__constrain_hash(__nd->__hash(), __bc);
13650b57cec5SDimitry Andric  // insert_after __bucket_list_[__chash], or __first_node if bucket is null
13660b57cec5SDimitry Andric  __next_pointer __pn = __bucket_list_[__chash];
1367cb14a3feSDimitry Andric  if (__pn == nullptr) {
13680b57cec5SDimitry Andric    __pn          = __p1_.first().__ptr();
13690b57cec5SDimitry Andric    __nd->__next_ = __pn->__next_;
13700b57cec5SDimitry Andric    __pn->__next_ = __nd->__ptr();
13710b57cec5SDimitry Andric    // fix up __bucket_list_
13720b57cec5SDimitry Andric    __bucket_list_[__chash] = __pn;
13730b57cec5SDimitry Andric    if (__nd->__next_ != nullptr)
1374bdd1243dSDimitry Andric      __bucket_list_[std::__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr();
1375cb14a3feSDimitry Andric  } else {
13760b57cec5SDimitry Andric    __nd->__next_ = __pn->__next_;
13770b57cec5SDimitry Andric    __pn->__next_ = __nd->__ptr();
13780b57cec5SDimitry Andric  }
13790b57cec5SDimitry Andric  ++size();
13800b57cec5SDimitry Andric}
13810b57cec5SDimitry Andric
13820b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
13830b57cec5SDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1384cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd) {
13855f757f3fSDimitry Andric  __nd->__hash_                  = hash_function()(__nd->__get_value());
1386cb14a3feSDimitry Andric  __next_pointer __existing_node = __node_insert_unique_prepare(__nd->__hash(), __nd->__get_value());
13870b57cec5SDimitry Andric
13880b57cec5SDimitry Andric  // Insert the node, unless it already exists in the container.
13890b57cec5SDimitry Andric  bool __inserted = false;
1390cb14a3feSDimitry Andric  if (__existing_node == nullptr) {
13910b57cec5SDimitry Andric    __node_insert_unique_perform(__nd);
13920b57cec5SDimitry Andric    __existing_node = __nd->__ptr();
13930b57cec5SDimitry Andric    __inserted      = true;
13940b57cec5SDimitry Andric  }
139506c3fb27SDimitry Andric  return pair<iterator, bool>(iterator(__existing_node), __inserted);
13960b57cec5SDimitry Andric}
13970b57cec5SDimitry Andric
13980b57cec5SDimitry Andric// Prepare the container for an insertion of the value __cp_val with the hash
13990b57cec5SDimitry Andric// __cp_hash. This does a lookup into the container to see if __cp_value is
14000b57cec5SDimitry Andric// already present, and performs a rehash if necessary. Returns a pointer to the
1401e8d8bef9SDimitry Andric// last occurrence of __cp_val in the map.
14020b57cec5SDimitry Andric//
14030b57cec5SDimitry Andric// Note that this function does forward exceptions if key_eq() throws, and never
14040b57cec5SDimitry Andric// mutates __value or actually inserts into the map.
14050b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14060b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1407cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_prepare(size_t __cp_hash, value_type& __cp_val) {
14080b57cec5SDimitry Andric  size_type __bc = bucket_count();
1409cb14a3feSDimitry Andric  if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1410cb14a3feSDimitry Andric    __rehash_multi(std::max<size_type>(
1411cb14a3feSDimitry Andric        2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
14120b57cec5SDimitry Andric    __bc = bucket_count();
14130b57cec5SDimitry Andric  }
1414bdd1243dSDimitry Andric  size_t __chash      = std::__constrain_hash(__cp_hash, __bc);
14150b57cec5SDimitry Andric  __next_pointer __pn = __bucket_list_[__chash];
1416cb14a3feSDimitry Andric  if (__pn != nullptr) {
1417cb14a3feSDimitry Andric    for (bool __found = false;
1418cb14a3feSDimitry Andric         __pn->__next_ != nullptr && std::__constrain_hash(__pn->__next_->__hash(), __bc) == __chash;
1419cb14a3feSDimitry Andric         __pn = __pn->__next_) {
14200b57cec5SDimitry Andric      //      __found    key_eq()     action
14210b57cec5SDimitry Andric      //      false       false       loop
14220b57cec5SDimitry Andric      //      true        true        loop
14230b57cec5SDimitry Andric      //      false       true        set __found to true
14240b57cec5SDimitry Andric      //      true        false       break
1425cb14a3feSDimitry Andric      if (__found !=
1426cb14a3feSDimitry Andric          (__pn->__next_->__hash() == __cp_hash && key_eq()(__pn->__next_->__upcast()->__get_value(), __cp_val))) {
14270b57cec5SDimitry Andric        if (!__found)
14280b57cec5SDimitry Andric          __found = true;
14290b57cec5SDimitry Andric        else
14300b57cec5SDimitry Andric          break;
14310b57cec5SDimitry Andric      }
14320b57cec5SDimitry Andric    }
14330b57cec5SDimitry Andric  }
14340b57cec5SDimitry Andric  return __pn;
14350b57cec5SDimitry Andric}
14360b57cec5SDimitry Andric
14370b57cec5SDimitry Andric// Insert the node __cp into the container after __pn (which is the last node in
14380b57cec5SDimitry Andric// the bucket that compares equal to __cp). Rehashing, and checking for
14390b57cec5SDimitry Andric// uniqueness has already been performed (in __node_insert_multi_prepare), so
14400b57cec5SDimitry Andric// all we need to do is update the bucket and size(). Assumes that __cp->__hash
14410b57cec5SDimitry Andric// is up-to-date.
14420b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1443cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform(
1444cb14a3feSDimitry Andric    __node_pointer __cp, __next_pointer __pn) _NOEXCEPT {
14450b57cec5SDimitry Andric  size_type __bc = bucket_count();
1446bdd1243dSDimitry Andric  size_t __chash = std::__constrain_hash(__cp->__hash_, __bc);
1447cb14a3feSDimitry Andric  if (__pn == nullptr) {
14480b57cec5SDimitry Andric    __pn          = __p1_.first().__ptr();
14490b57cec5SDimitry Andric    __cp->__next_ = __pn->__next_;
14500b57cec5SDimitry Andric    __pn->__next_ = __cp->__ptr();
14510b57cec5SDimitry Andric    // fix up __bucket_list_
14520b57cec5SDimitry Andric    __bucket_list_[__chash] = __pn;
14530b57cec5SDimitry Andric    if (__cp->__next_ != nullptr)
1454cb14a3feSDimitry Andric      __bucket_list_[std::__constrain_hash(__cp->__next_->__hash(), __bc)] = __cp->__ptr();
1455cb14a3feSDimitry Andric  } else {
14560b57cec5SDimitry Andric    __cp->__next_ = __pn->__next_;
14570b57cec5SDimitry Andric    __pn->__next_ = __cp->__ptr();
1458cb14a3feSDimitry Andric    if (__cp->__next_ != nullptr) {
1459bdd1243dSDimitry Andric      size_t __nhash = std::__constrain_hash(__cp->__next_->__hash(), __bc);
14600b57cec5SDimitry Andric      if (__nhash != __chash)
14610b57cec5SDimitry Andric        __bucket_list_[__nhash] = __cp->__ptr();
14620b57cec5SDimitry Andric    }
14630b57cec5SDimitry Andric  }
14640b57cec5SDimitry Andric  ++size();
14650b57cec5SDimitry Andric}
14660b57cec5SDimitry Andric
14670b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14680b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1469cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp) {
14705f757f3fSDimitry Andric  __cp->__hash_       = hash_function()(__cp->__get_value());
14715f757f3fSDimitry Andric  __next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__get_value());
14720b57cec5SDimitry Andric  __node_insert_multi_perform(__cp, __pn);
14730b57cec5SDimitry Andric
147406c3fb27SDimitry Andric  return iterator(__cp->__ptr());
14750b57cec5SDimitry Andric}
14760b57cec5SDimitry Andric
14770b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
14780b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1479cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(const_iterator __p, __node_pointer __cp) {
1480cb14a3feSDimitry Andric  if (__p != end() && key_eq()(*__p, __cp->__get_value())) {
14810b57cec5SDimitry Andric    __next_pointer __np = __p.__node_;
14820b57cec5SDimitry Andric    __cp->__hash_       = __np->__hash();
14830b57cec5SDimitry Andric    size_type __bc      = bucket_count();
1484cb14a3feSDimitry Andric    if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1485cb14a3feSDimitry Andric      __rehash_multi(std::max<size_type>(
1486cb14a3feSDimitry Andric          2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
14870b57cec5SDimitry Andric      __bc = bucket_count();
14880b57cec5SDimitry Andric    }
1489bdd1243dSDimitry Andric    size_t __chash      = std::__constrain_hash(__cp->__hash_, __bc);
14900b57cec5SDimitry Andric    __next_pointer __pp = __bucket_list_[__chash];
14910b57cec5SDimitry Andric    while (__pp->__next_ != __np)
14920b57cec5SDimitry Andric      __pp = __pp->__next_;
14930b57cec5SDimitry Andric    __cp->__next_ = __np;
14940b57cec5SDimitry Andric    __pp->__next_ = static_cast<__next_pointer>(__cp);
14950b57cec5SDimitry Andric    ++size();
149606c3fb27SDimitry Andric    return iterator(static_cast<__next_pointer>(__cp));
14970b57cec5SDimitry Andric  }
14980b57cec5SDimitry Andric  return __node_insert_multi(__cp);
14990b57cec5SDimitry Andric}
15000b57cec5SDimitry Andric
15010b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15020b57cec5SDimitry Andrictemplate <class _Key, class... _Args>
15030b57cec5SDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1504cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) {
15050b57cec5SDimitry Andric  size_t __hash   = hash_function()(__k);
15060b57cec5SDimitry Andric  size_type __bc  = bucket_count();
15070b57cec5SDimitry Andric  bool __inserted = false;
15080b57cec5SDimitry Andric  __next_pointer __nd;
15090b57cec5SDimitry Andric  size_t __chash;
1510cb14a3feSDimitry Andric  if (__bc != 0) {
1511bdd1243dSDimitry Andric    __chash = std::__constrain_hash(__hash, __bc);
15120b57cec5SDimitry Andric    __nd    = __bucket_list_[__chash];
1513cb14a3feSDimitry Andric    if (__nd != nullptr) {
1514cb14a3feSDimitry Andric      for (__nd = __nd->__next_;
1515cb14a3feSDimitry Andric           __nd != nullptr && (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1516cb14a3feSDimitry Andric           __nd = __nd->__next_) {
1517cb14a3feSDimitry Andric        if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
15180b57cec5SDimitry Andric          goto __done;
15190b57cec5SDimitry Andric      }
15200b57cec5SDimitry Andric    }
15210b57cec5SDimitry Andric  }
15220b57cec5SDimitry Andric  {
15235f757f3fSDimitry Andric    __node_holder __h = __construct_node_hash(__hash, std::forward<_Args>(__args)...);
1524cb14a3feSDimitry Andric    if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1525cb14a3feSDimitry Andric      __rehash_unique(std::max<size_type>(
1526cb14a3feSDimitry Andric          2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
15270b57cec5SDimitry Andric      __bc    = bucket_count();
1528bdd1243dSDimitry Andric      __chash = std::__constrain_hash(__hash, __bc);
15290b57cec5SDimitry Andric    }
15300b57cec5SDimitry Andric    // insert_after __bucket_list_[__chash], or __first_node if bucket is null
15310b57cec5SDimitry Andric    __next_pointer __pn = __bucket_list_[__chash];
1532cb14a3feSDimitry Andric    if (__pn == nullptr) {
15330b57cec5SDimitry Andric      __pn          = __p1_.first().__ptr();
15340b57cec5SDimitry Andric      __h->__next_  = __pn->__next_;
15350b57cec5SDimitry Andric      __pn->__next_ = __h.get()->__ptr();
15360b57cec5SDimitry Andric      // fix up __bucket_list_
15370b57cec5SDimitry Andric      __bucket_list_[__chash] = __pn;
15380b57cec5SDimitry Andric      if (__h->__next_ != nullptr)
1539cb14a3feSDimitry Andric        __bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] = __h.get()->__ptr();
1540cb14a3feSDimitry Andric    } else {
15410b57cec5SDimitry Andric      __h->__next_  = __pn->__next_;
15420b57cec5SDimitry Andric      __pn->__next_ = static_cast<__next_pointer>(__h.get());
15430b57cec5SDimitry Andric    }
15440b57cec5SDimitry Andric    __nd = static_cast<__next_pointer>(__h.release());
15450b57cec5SDimitry Andric    // increment size
15460b57cec5SDimitry Andric    ++size();
15470b57cec5SDimitry Andric    __inserted = true;
15480b57cec5SDimitry Andric  }
15490b57cec5SDimitry Andric__done:
155006c3fb27SDimitry Andric  return pair<iterator, bool>(iterator(__nd), __inserted);
15510b57cec5SDimitry Andric}
15520b57cec5SDimitry Andric
15530b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15540b57cec5SDimitry Andrictemplate <class... _Args>
15550b57cec5SDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1556cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args) {
15575f757f3fSDimitry Andric  __node_holder __h        = __construct_node(std::forward<_Args>(__args)...);
15580b57cec5SDimitry Andric  pair<iterator, bool> __r = __node_insert_unique(__h.get());
15590b57cec5SDimitry Andric  if (__r.second)
15600b57cec5SDimitry Andric    __h.release();
15610b57cec5SDimitry Andric  return __r;
15620b57cec5SDimitry Andric}
15630b57cec5SDimitry Andric
15640b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15650b57cec5SDimitry Andrictemplate <class... _Args>
15660b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1567cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args) {
15685f757f3fSDimitry Andric  __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
15690b57cec5SDimitry Andric  iterator __r      = __node_insert_multi(__h.get());
15700b57cec5SDimitry Andric  __h.release();
15710b57cec5SDimitry Andric  return __r;
15720b57cec5SDimitry Andric}
15730b57cec5SDimitry Andric
15740b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15750b57cec5SDimitry Andrictemplate <class... _Args>
15760b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1577cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(const_iterator __p, _Args&&... __args) {
15785f757f3fSDimitry Andric  __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
15790b57cec5SDimitry Andric  iterator __r      = __node_insert_multi(__p, __h.get());
15800b57cec5SDimitry Andric  __h.release();
15810b57cec5SDimitry Andric  return __r;
15820b57cec5SDimitry Andric}
15830b57cec5SDimitry Andric
158406c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17
15850b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15860b57cec5SDimitry Andrictemplate <class _NodeHandle, class _InsertReturnType>
1587cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI _InsertReturnType
1588cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(_NodeHandle&& __nh) {
15890b57cec5SDimitry Andric  if (__nh.empty())
15900b57cec5SDimitry Andric    return _InsertReturnType{end(), false, _NodeHandle()};
15910b57cec5SDimitry Andric  pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
15920b57cec5SDimitry Andric  if (__result.second)
15930b57cec5SDimitry Andric    __nh.__release_ptr();
15945f757f3fSDimitry Andric  return _InsertReturnType{__result.first, __result.second, std::move(__nh)};
15950b57cec5SDimitry Andric}
15960b57cec5SDimitry Andric
15970b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
15980b57cec5SDimitry Andrictemplate <class _NodeHandle>
1599cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1600cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(const_iterator, _NodeHandle&& __nh) {
16010b57cec5SDimitry Andric  if (__nh.empty())
16020b57cec5SDimitry Andric    return end();
16030b57cec5SDimitry Andric  pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
16040b57cec5SDimitry Andric  if (__result.second)
16050b57cec5SDimitry Andric    __nh.__release_ptr();
16060b57cec5SDimitry Andric  return __result.first;
16070b57cec5SDimitry Andric}
16080b57cec5SDimitry Andric
16090b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
16100b57cec5SDimitry Andrictemplate <class _NodeHandle>
1611cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI _NodeHandle
1612cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(key_type const& __key) {
16130b57cec5SDimitry Andric  iterator __i = find(__key);
16140b57cec5SDimitry Andric  if (__i == end())
16150b57cec5SDimitry Andric    return _NodeHandle();
16160b57cec5SDimitry Andric  return __node_handle_extract<_NodeHandle>(__i);
16170b57cec5SDimitry Andric}
16180b57cec5SDimitry Andric
16190b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
16200b57cec5SDimitry Andrictemplate <class _NodeHandle>
1621cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI _NodeHandle __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(const_iterator __p) {
16220b57cec5SDimitry Andric  allocator_type __alloc(__node_alloc());
16230b57cec5SDimitry Andric  return _NodeHandle(remove(__p).release(), __alloc);
16240b57cec5SDimitry Andric}
16250b57cec5SDimitry Andric
16260b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
16270b57cec5SDimitry Andrictemplate <class _Table>
1628cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_unique(_Table& __source) {
16290b57cec5SDimitry Andric  static_assert(is_same<__node, typename _Table::__node>::value, "");
16300b57cec5SDimitry Andric
1631cb14a3feSDimitry Andric  for (typename _Table::iterator __it = __source.begin(); __it != __source.end();) {
16320b57cec5SDimitry Andric    __node_pointer __src_ptr       = __it.__node_->__upcast();
16335f757f3fSDimitry Andric    size_t __hash                  = hash_function()(__src_ptr->__get_value());
1634cb14a3feSDimitry Andric    __next_pointer __existing_node = __node_insert_unique_prepare(__hash, __src_ptr->__get_value());
16350b57cec5SDimitry Andric    auto __prev_iter               = __it++;
1636cb14a3feSDimitry Andric    if (__existing_node == nullptr) {
16370b57cec5SDimitry Andric      (void)__source.remove(__prev_iter).release();
16380b57cec5SDimitry Andric      __src_ptr->__hash_ = __hash;
16390b57cec5SDimitry Andric      __node_insert_unique_perform(__src_ptr);
16400b57cec5SDimitry Andric    }
16410b57cec5SDimitry Andric  }
16420b57cec5SDimitry Andric}
16430b57cec5SDimitry Andric
16440b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
16450b57cec5SDimitry Andrictemplate <class _NodeHandle>
1646cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1647cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(_NodeHandle&& __nh) {
16480b57cec5SDimitry Andric  if (__nh.empty())
16490b57cec5SDimitry Andric    return end();
16500b57cec5SDimitry Andric  iterator __result = __node_insert_multi(__nh.__ptr_);
16510b57cec5SDimitry Andric  __nh.__release_ptr();
16520b57cec5SDimitry Andric  return __result;
16530b57cec5SDimitry Andric}
16540b57cec5SDimitry Andric
16550b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
16560b57cec5SDimitry Andrictemplate <class _NodeHandle>
1657cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1658cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh) {
16590b57cec5SDimitry Andric  if (__nh.empty())
16600b57cec5SDimitry Andric    return end();
16610b57cec5SDimitry Andric  iterator __result = __node_insert_multi(__hint, __nh.__ptr_);
16620b57cec5SDimitry Andric  __nh.__release_ptr();
16630b57cec5SDimitry Andric  return __result;
16640b57cec5SDimitry Andric}
16650b57cec5SDimitry Andric
16660b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
16670b57cec5SDimitry Andrictemplate <class _Table>
1668cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi(_Table& __source) {
16690b57cec5SDimitry Andric  static_assert(is_same<typename _Table::__node, __node>::value, "");
16700b57cec5SDimitry Andric
1671cb14a3feSDimitry Andric  for (typename _Table::iterator __it = __source.begin(); __it != __source.end();) {
16720b57cec5SDimitry Andric    __node_pointer __src_ptr = __it.__node_->__upcast();
16735f757f3fSDimitry Andric    size_t __src_hash        = hash_function()(__src_ptr->__get_value());
1674cb14a3feSDimitry Andric    __next_pointer __pn      = __node_insert_multi_prepare(__src_hash, __src_ptr->__get_value());
16750b57cec5SDimitry Andric    (void)__source.remove(__it++).release();
16760b57cec5SDimitry Andric    __src_ptr->__hash_ = __src_hash;
16770b57cec5SDimitry Andric    __node_insert_multi_perform(__src_ptr, __pn);
16780b57cec5SDimitry Andric  }
16790b57cec5SDimitry Andric}
168006c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17
16810b57cec5SDimitry Andric
16820b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1683753f127fSDimitry Andrictemplate <bool _UniqueKeys>
1684cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __n) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK {
16850b57cec5SDimitry Andric  if (__n == 1)
16860b57cec5SDimitry Andric    __n = 2;
16870b57cec5SDimitry Andric  else if (__n & (__n - 1))
1688bdd1243dSDimitry Andric    __n = std::__next_prime(__n);
16890b57cec5SDimitry Andric  size_type __bc = bucket_count();
16900b57cec5SDimitry Andric  if (__n > __bc)
1691753f127fSDimitry Andric    __do_rehash<_UniqueKeys>(__n);
1692cb14a3feSDimitry Andric  else if (__n < __bc) {
1693cb14a3feSDimitry Andric    __n = std::max<size_type>(
16940b57cec5SDimitry Andric        __n,
1695cb14a3feSDimitry Andric        std::__is_hash_power2(__bc) ? std::__next_hash_pow2(size_t(std::ceil(float(size()) / max_load_factor())))
1696cb14a3feSDimitry Andric                                    : std::__next_prime(size_t(std::ceil(float(size()) / max_load_factor()))));
16970b57cec5SDimitry Andric    if (__n < __bc)
1698753f127fSDimitry Andric      __do_rehash<_UniqueKeys>(__n);
16990b57cec5SDimitry Andric  }
17000b57cec5SDimitry Andric}
17010b57cec5SDimitry Andric
17020b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1703753f127fSDimitry Andrictemplate <bool _UniqueKeys>
1704cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) {
17050b57cec5SDimitry Andric  __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1706cb14a3feSDimitry Andric  __bucket_list_.reset(__nbc > 0 ? __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
17070b57cec5SDimitry Andric  __bucket_list_.get_deleter().size() = __nbc;
1708cb14a3feSDimitry Andric  if (__nbc > 0) {
17090b57cec5SDimitry Andric    for (size_type __i = 0; __i < __nbc; ++__i)
17100b57cec5SDimitry Andric      __bucket_list_[__i] = nullptr;
17110b57cec5SDimitry Andric    __next_pointer __pp = __p1_.first().__ptr();
17120b57cec5SDimitry Andric    __next_pointer __cp = __pp->__next_;
1713cb14a3feSDimitry Andric    if (__cp != nullptr) {
1714bdd1243dSDimitry Andric      size_type __chash       = std::__constrain_hash(__cp->__hash(), __nbc);
17150b57cec5SDimitry Andric      __bucket_list_[__chash] = __pp;
17160b57cec5SDimitry Andric      size_type __phash       = __chash;
1717cb14a3feSDimitry Andric      for (__pp = __cp, void(), __cp = __cp->__next_; __cp != nullptr; __cp = __pp->__next_) {
1718bdd1243dSDimitry Andric        __chash = std::__constrain_hash(__cp->__hash(), __nbc);
17190b57cec5SDimitry Andric        if (__chash == __phash)
17200b57cec5SDimitry Andric          __pp = __cp;
1721cb14a3feSDimitry Andric        else {
1722cb14a3feSDimitry Andric          if (__bucket_list_[__chash] == nullptr) {
17230b57cec5SDimitry Andric            __bucket_list_[__chash] = __pp;
17240b57cec5SDimitry Andric            __pp                    = __cp;
17250b57cec5SDimitry Andric            __phash                 = __chash;
1726cb14a3feSDimitry Andric          } else {
17270b57cec5SDimitry Andric            __next_pointer __np = __cp;
1728cb14a3feSDimitry Andric            if _LIBCPP_CONSTEXPR_SINCE_CXX17 (!_UniqueKeys) {
17290b57cec5SDimitry Andric              for (; __np->__next_ != nullptr &&
1730cb14a3feSDimitry Andric                     key_eq()(__cp->__upcast()->__get_value(), __np->__next_->__upcast()->__get_value());
17310b57cec5SDimitry Andric                   __np = __np->__next_)
17320b57cec5SDimitry Andric                ;
1733753f127fSDimitry Andric            }
17340b57cec5SDimitry Andric            __pp->__next_                    = __np->__next_;
17350b57cec5SDimitry Andric            __np->__next_                    = __bucket_list_[__chash]->__next_;
17360b57cec5SDimitry Andric            __bucket_list_[__chash]->__next_ = __cp;
17370b57cec5SDimitry Andric          }
17380b57cec5SDimitry Andric        }
17390b57cec5SDimitry Andric      }
17400b57cec5SDimitry Andric    }
17410b57cec5SDimitry Andric  }
17420b57cec5SDimitry Andric}
17430b57cec5SDimitry Andric
17440b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
17450b57cec5SDimitry Andrictemplate <class _Key>
17460b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1747cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) {
17480b57cec5SDimitry Andric  size_t __hash  = hash_function()(__k);
17490b57cec5SDimitry Andric  size_type __bc = bucket_count();
1750cb14a3feSDimitry Andric  if (__bc != 0) {
1751bdd1243dSDimitry Andric    size_t __chash      = std::__constrain_hash(__hash, __bc);
17520b57cec5SDimitry Andric    __next_pointer __nd = __bucket_list_[__chash];
1753cb14a3feSDimitry Andric    if (__nd != nullptr) {
1754cb14a3feSDimitry Andric      for (__nd = __nd->__next_;
1755cb14a3feSDimitry Andric           __nd != nullptr && (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1756cb14a3feSDimitry Andric           __nd = __nd->__next_) {
1757cb14a3feSDimitry Andric        if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
175806c3fb27SDimitry Andric          return iterator(__nd);
17590b57cec5SDimitry Andric      }
17600b57cec5SDimitry Andric    }
17610b57cec5SDimitry Andric  }
17620b57cec5SDimitry Andric  return end();
17630b57cec5SDimitry Andric}
17640b57cec5SDimitry Andric
17650b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
17660b57cec5SDimitry Andrictemplate <class _Key>
17670b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1768cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const {
17690b57cec5SDimitry Andric  size_t __hash  = hash_function()(__k);
17700b57cec5SDimitry Andric  size_type __bc = bucket_count();
1771cb14a3feSDimitry Andric  if (__bc != 0) {
1772bdd1243dSDimitry Andric    size_t __chash      = std::__constrain_hash(__hash, __bc);
17730b57cec5SDimitry Andric    __next_pointer __nd = __bucket_list_[__chash];
1774cb14a3feSDimitry Andric    if (__nd != nullptr) {
1775cb14a3feSDimitry Andric      for (__nd = __nd->__next_;
1776cb14a3feSDimitry Andric           __nd != nullptr && (__hash == __nd->__hash() || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1777cb14a3feSDimitry Andric           __nd = __nd->__next_) {
1778cb14a3feSDimitry Andric        if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
177906c3fb27SDimitry Andric          return const_iterator(__nd);
17800b57cec5SDimitry Andric      }
17810b57cec5SDimitry Andric    }
17820b57cec5SDimitry Andric  }
17830b57cec5SDimitry Andric  return end();
17840b57cec5SDimitry Andric}
17850b57cec5SDimitry Andric
17860b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
17870b57cec5SDimitry Andrictemplate <class... _Args>
17880b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1789cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) {
1790cb14a3feSDimitry Andric  static_assert(!__is_hash_value_type<_Args...>::value, "Construct cannot be called with a hash value type");
17910b57cec5SDimitry Andric  __node_allocator& __na = __node_alloc();
17920b57cec5SDimitry Andric  __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
17935f757f3fSDimitry Andric
17945f757f3fSDimitry Andric  // Begin the lifetime of the node itself. Note that this doesn't begin the lifetime of the value
17955f757f3fSDimitry Andric  // held inside the node, since we need to use the allocator's construct() method for that.
17965f757f3fSDimitry Andric  //
17975f757f3fSDimitry Andric  // We don't use the allocator's construct() method to construct the node itself since the
17985f757f3fSDimitry Andric  // Cpp17FooInsertable named requirements don't require the allocator's construct() method
17995f757f3fSDimitry Andric  // to work on anything other than the value_type.
18005f757f3fSDimitry Andric  std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ 0);
18015f757f3fSDimitry Andric
18025f757f3fSDimitry Andric  // Now construct the value_type using the allocator's construct() method.
18035f757f3fSDimitry Andric  __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_Args>(__args)...);
18040b57cec5SDimitry Andric  __h.get_deleter().__value_constructed = true;
18055f757f3fSDimitry Andric
18065f757f3fSDimitry Andric  __h->__hash_ = hash_function()(__h->__get_value());
18070b57cec5SDimitry Andric  return __h;
18080b57cec5SDimitry Andric}
18090b57cec5SDimitry Andric
18100b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18110b57cec5SDimitry Andrictemplate <class _First, class... _Rest>
18120b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1813cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest) {
1814cb14a3feSDimitry Andric  static_assert(!__is_hash_value_type<_First, _Rest...>::value, "Construct cannot be called with a hash value type");
18150b57cec5SDimitry Andric  __node_allocator& __na = __node_alloc();
18160b57cec5SDimitry Andric  __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
18175f757f3fSDimitry Andric  std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash);
1818cb14a3feSDimitry Andric  __node_traits::construct(
1819cb14a3feSDimitry Andric      __na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...);
18200b57cec5SDimitry Andric  __h.get_deleter().__value_constructed = true;
18210b57cec5SDimitry Andric  return __h;
18220b57cec5SDimitry Andric}
18230b57cec5SDimitry Andric
18240b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18250b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1826cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) {
18270b57cec5SDimitry Andric  __next_pointer __np = __p.__node_;
1828cb14a3feSDimitry Andric  _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
1829cb14a3feSDimitry Andric      __p != end(), "unordered container::erase(iterator) called with a non-dereferenceable iterator");
183006c3fb27SDimitry Andric  iterator __r(__np);
18310b57cec5SDimitry Andric  ++__r;
18320b57cec5SDimitry Andric  remove(__p);
18330b57cec5SDimitry Andric  return __r;
18340b57cec5SDimitry Andric}
18350b57cec5SDimitry Andric
18360b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18370b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1838cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, const_iterator __last) {
1839cb14a3feSDimitry Andric  for (const_iterator __p = __first; __first != __last; __p = __first) {
18400b57cec5SDimitry Andric    ++__first;
18410b57cec5SDimitry Andric    erase(__p);
18420b57cec5SDimitry Andric  }
18430b57cec5SDimitry Andric  __next_pointer __np = __last.__node_;
184406c3fb27SDimitry Andric  return iterator(__np);
18450b57cec5SDimitry Andric}
18460b57cec5SDimitry Andric
18470b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18480b57cec5SDimitry Andrictemplate <class _Key>
18490b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1850cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k) {
18510b57cec5SDimitry Andric  iterator __i = find(__k);
18520b57cec5SDimitry Andric  if (__i == end())
18530b57cec5SDimitry Andric    return 0;
18540b57cec5SDimitry Andric  erase(__i);
18550b57cec5SDimitry Andric  return 1;
18560b57cec5SDimitry Andric}
18570b57cec5SDimitry Andric
18580b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18590b57cec5SDimitry Andrictemplate <class _Key>
18600b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1861cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k) {
18620b57cec5SDimitry Andric  size_type __r = 0;
18630b57cec5SDimitry Andric  iterator __i  = find(__k);
1864cb14a3feSDimitry Andric  if (__i != end()) {
18650b57cec5SDimitry Andric    iterator __e = end();
1866cb14a3feSDimitry Andric    do {
18670b57cec5SDimitry Andric      erase(__i++);
18680b57cec5SDimitry Andric      ++__r;
18690b57cec5SDimitry Andric    } while (__i != __e && key_eq()(*__i, __k));
18700b57cec5SDimitry Andric  }
18710b57cec5SDimitry Andric  return __r;
18720b57cec5SDimitry Andric}
18730b57cec5SDimitry Andric
18740b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
18750b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1876cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT {
18770b57cec5SDimitry Andric  // current node
18780b57cec5SDimitry Andric  __next_pointer __cn = __p.__node_;
18790b57cec5SDimitry Andric  size_type __bc      = bucket_count();
1880bdd1243dSDimitry Andric  size_t __chash      = std::__constrain_hash(__cn->__hash(), __bc);
18810b57cec5SDimitry Andric  // find previous node
18820b57cec5SDimitry Andric  __next_pointer __pn = __bucket_list_[__chash];
18830b57cec5SDimitry Andric  for (; __pn->__next_ != __cn; __pn = __pn->__next_)
18840b57cec5SDimitry Andric    ;
18850b57cec5SDimitry Andric  // Fix up __bucket_list_
18860b57cec5SDimitry Andric  // if __pn is not in same bucket (before begin is not in same bucket) &&
18870b57cec5SDimitry Andric  //    if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
1888cb14a3feSDimitry Andric  if (__pn == __p1_.first().__ptr() || std::__constrain_hash(__pn->__hash(), __bc) != __chash) {
1889cb14a3feSDimitry Andric    if (__cn->__next_ == nullptr || std::__constrain_hash(__cn->__next_->__hash(), __bc) != __chash)
18900b57cec5SDimitry Andric      __bucket_list_[__chash] = nullptr;
18910b57cec5SDimitry Andric  }
18920b57cec5SDimitry Andric  // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
1893cb14a3feSDimitry Andric  if (__cn->__next_ != nullptr) {
1894bdd1243dSDimitry Andric    size_t __nhash = std::__constrain_hash(__cn->__next_->__hash(), __bc);
18950b57cec5SDimitry Andric    if (__nhash != __chash)
18960b57cec5SDimitry Andric      __bucket_list_[__nhash] = __pn;
18970b57cec5SDimitry Andric  }
18980b57cec5SDimitry Andric  // remove __cn
18990b57cec5SDimitry Andric  __pn->__next_ = __cn->__next_;
19000b57cec5SDimitry Andric  __cn->__next_ = nullptr;
19010b57cec5SDimitry Andric  --size();
19020b57cec5SDimitry Andric  return __node_holder(__cn->__upcast(), _Dp(__node_alloc(), true));
19030b57cec5SDimitry Andric}
19040b57cec5SDimitry Andric
19050b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
19060b57cec5SDimitry Andrictemplate <class _Key>
1907cb14a3feSDimitry Andricinline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1908cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const {
19090b57cec5SDimitry Andric  return static_cast<size_type>(find(__k) != end());
19100b57cec5SDimitry Andric}
19110b57cec5SDimitry Andric
19120b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
19130b57cec5SDimitry Andrictemplate <class _Key>
19140b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1915cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const {
19160b57cec5SDimitry Andric  size_type __r      = 0;
19170b57cec5SDimitry Andric  const_iterator __i = find(__k);
1918cb14a3feSDimitry Andric  if (__i != end()) {
19190b57cec5SDimitry Andric    const_iterator __e = end();
1920cb14a3feSDimitry Andric    do {
19210b57cec5SDimitry Andric      ++__i;
19220b57cec5SDimitry Andric      ++__r;
19230b57cec5SDimitry Andric    } while (__i != __e && key_eq()(*__i, __k));
19240b57cec5SDimitry Andric  }
19250b57cec5SDimitry Andric  return __r;
19260b57cec5SDimitry Andric}
19270b57cec5SDimitry Andric
19280b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
19290b57cec5SDimitry Andrictemplate <class _Key>
19300b57cec5SDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
19310b57cec5SDimitry Andric     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1932cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(const _Key& __k) {
19330b57cec5SDimitry Andric  iterator __i = find(__k);
19340b57cec5SDimitry Andric  iterator __j = __i;
19350b57cec5SDimitry Andric  if (__i != end())
19360b57cec5SDimitry Andric    ++__j;
19370b57cec5SDimitry Andric  return pair<iterator, iterator>(__i, __j);
19380b57cec5SDimitry Andric}
19390b57cec5SDimitry Andric
19400b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
19410b57cec5SDimitry Andrictemplate <class _Key>
19420b57cec5SDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
19430b57cec5SDimitry Andric     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1944cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(const _Key& __k) const {
19450b57cec5SDimitry Andric  const_iterator __i = find(__k);
19460b57cec5SDimitry Andric  const_iterator __j = __i;
19470b57cec5SDimitry Andric  if (__i != end())
19480b57cec5SDimitry Andric    ++__j;
19490b57cec5SDimitry Andric  return pair<const_iterator, const_iterator>(__i, __j);
19500b57cec5SDimitry Andric}
19510b57cec5SDimitry Andric
19520b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
19530b57cec5SDimitry Andrictemplate <class _Key>
19540b57cec5SDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
19550b57cec5SDimitry Andric     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1956cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(const _Key& __k) {
19570b57cec5SDimitry Andric  iterator __i = find(__k);
19580b57cec5SDimitry Andric  iterator __j = __i;
1959cb14a3feSDimitry Andric  if (__i != end()) {
19600b57cec5SDimitry Andric    iterator __e = end();
1961cb14a3feSDimitry Andric    do {
19620b57cec5SDimitry Andric      ++__j;
19630b57cec5SDimitry Andric    } while (__j != __e && key_eq()(*__j, __k));
19640b57cec5SDimitry Andric  }
19650b57cec5SDimitry Andric  return pair<iterator, iterator>(__i, __j);
19660b57cec5SDimitry Andric}
19670b57cec5SDimitry Andric
19680b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
19690b57cec5SDimitry Andrictemplate <class _Key>
19700b57cec5SDimitry Andricpair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
19710b57cec5SDimitry Andric     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1972cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(const _Key& __k) const {
19730b57cec5SDimitry Andric  const_iterator __i = find(__k);
19740b57cec5SDimitry Andric  const_iterator __j = __i;
1975cb14a3feSDimitry Andric  if (__i != end()) {
19760b57cec5SDimitry Andric    const_iterator __e = end();
1977cb14a3feSDimitry Andric    do {
19780b57cec5SDimitry Andric      ++__j;
19790b57cec5SDimitry Andric    } while (__j != __e && key_eq()(*__j, __k));
19800b57cec5SDimitry Andric  }
19810b57cec5SDimitry Andric  return pair<const_iterator, const_iterator>(__i, __j);
19820b57cec5SDimitry Andric}
19830b57cec5SDimitry Andric
19840b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
1985cb14a3feSDimitry Andricvoid __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
19860b57cec5SDimitry Andric#if _LIBCPP_STD_VER <= 11
1987*0fca6ea1SDimitry Andric    _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal> &&
1988cb14a3feSDimitry Andric               (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1989*0fca6ea1SDimitry Andric                __is_nothrow_swappable_v<__pointer_allocator>) &&
1990*0fca6ea1SDimitry Andric               (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>))
19910b57cec5SDimitry Andric#else
1992*0fca6ea1SDimitry Andric    _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal>)
19930b57cec5SDimitry Andric#endif
19940b57cec5SDimitry Andric{
1995cb14a3feSDimitry Andric  _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
1996cb14a3feSDimitry Andric      __node_traits::propagate_on_container_swap::value || this->__node_alloc() == __u.__node_alloc(),
199706c3fb27SDimitry Andric      "unordered container::swap: Either propagate_on_container_swap "
199806c3fb27SDimitry Andric      "must be true or the allocators must compare equal");
19990b57cec5SDimitry Andric  {
20000b57cec5SDimitry Andric    __node_pointer_pointer __npp = __bucket_list_.release();
20010b57cec5SDimitry Andric    __bucket_list_.reset(__u.__bucket_list_.release());
20020b57cec5SDimitry Andric    __u.__bucket_list_.reset(__npp);
20030b57cec5SDimitry Andric  }
20045f757f3fSDimitry Andric  std::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
2005cb14a3feSDimitry Andric  std::__swap_allocator(__bucket_list_.get_deleter().__alloc(), __u.__bucket_list_.get_deleter().__alloc());
20065f757f3fSDimitry Andric  std::__swap_allocator(__node_alloc(), __u.__node_alloc());
20075f757f3fSDimitry Andric  std::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
20080b57cec5SDimitry Andric  __p2_.swap(__u.__p2_);
20090b57cec5SDimitry Andric  __p3_.swap(__u.__p3_);
20100b57cec5SDimitry Andric  if (size() > 0)
2011cb14a3feSDimitry Andric    __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
20120b57cec5SDimitry Andric  if (__u.size() > 0)
2013bdd1243dSDimitry Andric    __u.__bucket_list_[std::__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] =
20140b57cec5SDimitry Andric        __u.__p1_.first().__ptr();
20150b57cec5SDimitry Andric}
20160b57cec5SDimitry Andric
20170b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
20180b57cec5SDimitry Andrictypename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2019cb14a3feSDimitry Andric__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const {
2020cb14a3feSDimitry Andric  _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
2021cb14a3feSDimitry Andric      __n < bucket_count(), "unordered container::bucket_size(n) called with n >= bucket_count()");
20220b57cec5SDimitry Andric  __next_pointer __np = __bucket_list_[__n];
20230b57cec5SDimitry Andric  size_type __bc      = bucket_count();
20240b57cec5SDimitry Andric  size_type __r       = 0;
2025cb14a3feSDimitry Andric  if (__np != nullptr) {
2026cb14a3feSDimitry Andric    for (__np = __np->__next_; __np != nullptr && std::__constrain_hash(__np->__hash(), __bc) == __n;
2027349cc55cSDimitry Andric         __np = __np->__next_, (void)++__r)
20280b57cec5SDimitry Andric      ;
20290b57cec5SDimitry Andric  }
20300b57cec5SDimitry Andric  return __r;
20310b57cec5SDimitry Andric}
20320b57cec5SDimitry Andric
20330b57cec5SDimitry Andrictemplate <class _Tp, class _Hash, class _Equal, class _Alloc>
2034cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI void
2035cb14a3feSDimitry Andricswap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x, __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
2036cb14a3feSDimitry Andric    _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
20370b57cec5SDimitry Andric  __x.swap(__y);
20380b57cec5SDimitry Andric}
20390b57cec5SDimitry Andric
20400b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
20410b57cec5SDimitry Andric
20420b57cec5SDimitry Andric_LIBCPP_POP_MACROS
20430b57cec5SDimitry Andric
204481ad6265SDimitry Andric#endif // _LIBCPP___HASH_TABLE
2045