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