@@ -1036,21 +1036,7 @@ private:
10361036 }
10371037 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc (__hash_table&, false_type) _NOEXCEPT {}
10381038
1039- _LIBCPP_HIDE_FROM_ABI void __deallocate_node (__node_pointer __nd) _NOEXCEPT {
1040- auto & __alloc = __node_alloc ();
1041- __node_traits::destroy (__alloc, std::addressof (__nd->__get_value ()));
1042- std::__destroy_at (std::__to_address (__nd));
1043- __node_traits::deallocate (__alloc, __nd, 1 );
1044- }
1045-
1046- _LIBCPP_HIDE_FROM_ABI void __deallocate_node_list (__next_pointer __np) _NOEXCEPT {
1047- while (__np != nullptr ) {
1048- __next_pointer __next = __np->__next_ ;
1049- __deallocate_node (__np->__upcast ());
1050- __np = __next;
1051- }
1052- }
1053-
1039+ _LIBCPP_HIDE_FROM_ABI void __deallocate_node (__next_pointer __np) _NOEXCEPT;
10541040 _LIBCPP_HIDE_FROM_ABI __next_pointer __detach () _NOEXCEPT;
10551041
10561042 template <class _From , class _ValueT = _Tp, __enable_if_t <__is_hash_value_type<_ValueT>::value, int > = 0 >
@@ -1188,7 +1174,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() {
11881174 static_assert (is_copy_constructible<hasher>::value, " Hasher must be copy-constructible." );
11891175#endif
11901176
1191- __deallocate_node_list (__first_node_.__next_ );
1177+ __deallocate_node (__first_node_.__next_ );
11921178}
11931179
11941180template <class _Tp , class _Hash , class _Equal , class _Alloc >
@@ -1264,7 +1250,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __other)
12641250 // At this point we either have consumed the whole incoming hash table, or we don't have any more nodes to reuse in
12651251 // the destination. Either continue with constructing new nodes, or deallocate the left over nodes.
12661252 if (__own_iter->__next_ ) {
1267- __deallocate_node_list (__own_iter->__next_ );
1253+ __deallocate_node (__own_iter->__next_ );
12681254 __own_iter->__next_ = nullptr ;
12691255 } else {
12701256 __copy_construct (__other_iter, __own_iter, __current_chash);
@@ -1275,6 +1261,19 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __other)
12751261 return *this ;
12761262}
12771263
1264+ template <class _Tp , class _Hash , class _Equal , class _Alloc >
1265+ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np) _NOEXCEPT {
1266+ __node_allocator& __na = __node_alloc ();
1267+ while (__np != nullptr ) {
1268+ __next_pointer __next = __np->__next_ ;
1269+ __node_pointer __real_np = __np->__upcast ();
1270+ __node_traits::destroy (__na, std::addressof (__real_np->__get_value ()));
1271+ std::__destroy_at (std::addressof (*__real_np));
1272+ __node_traits::deallocate (__na, __real_np, 1 );
1273+ __np = __next;
1274+ }
1275+ }
1276+
12781277template <class _Tp , class _Hash , class _Equal , class _Alloc >
12791278typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
12801279__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT {
@@ -1330,11 +1329,11 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u,
13301329 }
13311330#if _LIBCPP_HAS_EXCEPTIONS
13321331 } catch (...) {
1333- __deallocate_node_list (__cache);
1332+ __deallocate_node (__cache);
13341333 throw ;
13351334 }
13361335#endif // _LIBCPP_HAS_EXCEPTIONS
1337- __deallocate_node_list (__cache);
1336+ __deallocate_node (__cache);
13381337 }
13391338 const_iterator __i = __u.begin ();
13401339 while (__u.size () != 0 )
@@ -1373,11 +1372,11 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __
13731372 }
13741373#if _LIBCPP_HAS_EXCEPTIONS
13751374 } catch (...) {
1376- __deallocate_node_list (__cache);
1375+ __deallocate_node (__cache);
13771376 throw ;
13781377 }
13791378#endif // _LIBCPP_HAS_EXCEPTIONS
1380- __deallocate_node_list (__cache);
1379+ __deallocate_node (__cache);
13811380 }
13821381 for (; __first != __last; ++__first)
13831382 __emplace_unique (*__first);
@@ -1403,11 +1402,11 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f
14031402 }
14041403#if _LIBCPP_HAS_EXCEPTIONS
14051404 } catch (...) {
1406- __deallocate_node_list (__cache);
1405+ __deallocate_node (__cache);
14071406 throw ;
14081407 }
14091408#endif // _LIBCPP_HAS_EXCEPTIONS
1410- __deallocate_node_list (__cache);
1409+ __deallocate_node (__cache);
14111410 }
14121411 for (; __first != __last; ++__first)
14131412 __emplace_multi (*__first);
@@ -1440,7 +1439,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT {
14401439template <class _Tp , class _Hash , class _Equal , class _Alloc >
14411440void __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear () _NOEXCEPT {
14421441 if (size () > 0 ) {
1443- __deallocate_node_list (__first_node_.__next_ );
1442+ __deallocate_node (__first_node_.__next_ );
14441443 __first_node_.__next_ = nullptr ;
14451444 size_type __bc = bucket_count ();
14461445 for (size_type __i = 0 ; __i < __bc; ++__i)
@@ -1900,57 +1899,12 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) {
19001899template <class _Tp , class _Hash , class _Equal , class _Alloc >
19011900typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
19021901__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase (const_iterator __first, const_iterator __last) {
1903- if (__first == __last)
1904- return iterator (__last.__node_ );
1905-
1906- // current node
1907- __next_pointer __current = __first.__node_ ;
1908- size_type __bucket_count = bucket_count ();
1909- size_t __chash = std::__constrain_hash (__current->__hash (), __bucket_count);
1910- // find previous node
1911- __next_pointer __before_first = __bucket_list_[__chash];
1912- for (; __before_first->__next_ != __current; __before_first = __before_first->__next_ )
1913- ;
1914-
1915- __next_pointer __last_node = __last.__node_ ;
1916-
1917- // If __before_first is in the same bucket (i.e. the first element we erase is not the first in the bucket), clear
1918- // this bucket first without re-linking it
1919- if (__before_first != __first_node_.__ptr () &&
1920- std::__constrain_hash (__before_first->__hash (), __bucket_count) == __chash) {
1921- while (__current != __last_node) {
1922- if (auto __next_chash = std::__constrain_hash (__current->__hash (), __bucket_count); __next_chash != __chash) {
1923- __chash = __next_chash;
1924- break ;
1925- }
1926- auto __next = __current->__next_ ;
1927- __deallocate_node (__current->__upcast ());
1928- __current = __next;
1929- --__size_;
1930- }
1902+ for (const_iterator __p = __first; __first != __last; __p = __first) {
1903+ ++__first;
1904+ erase (__p);
19311905 }
1932-
1933- while (__current != __last_node) {
1934- auto __next = __current->__next_ ;
1935- __deallocate_node (__current->__upcast ());
1936- __current = __next;
1937- --__size_;
1938-
1939- // When switching buckets, set the old bucket to be empty and update the next bucket to have __before_first as its
1940- // before-first element
1941- if (__next) {
1942- if (auto __next_chash = std::__constrain_hash (__next->__hash (), __bucket_count); __next_chash != __chash) {
1943- __bucket_list_[__chash] = nullptr ;
1944- __chash = __next_chash;
1945- __bucket_list_[__chash] = __before_first;
1946- }
1947- }
1948- }
1949-
1950- // re-link __before_first with __last
1951- __before_first->__next_ = __current;
1952-
1953- return iterator (__last.__node_ );
1906+ __next_pointer __np = __last.__node_ ;
1907+ return iterator (__np);
19541908}
19551909
19561910template <class _Tp , class _Hash , class _Equal , class _Alloc >
0 commit comments