@@ -1036,21 +1036,7 @@ private:
1036
1036
}
1037
1037
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc (__hash_table&, false_type) _NOEXCEPT {}
1038
1038
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;
1054
1040
_LIBCPP_HIDE_FROM_ABI __next_pointer __detach () _NOEXCEPT;
1055
1041
1056
1042
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() {
1188
1174
static_assert (is_copy_constructible<hasher>::value, " Hasher must be copy-constructible." );
1189
1175
#endif
1190
1176
1191
- __deallocate_node_list (__first_node_.__next_ );
1177
+ __deallocate_node (__first_node_.__next_ );
1192
1178
}
1193
1179
1194
1180
template <class _Tp , class _Hash , class _Equal , class _Alloc >
@@ -1264,7 +1250,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __other)
1264
1250
// At this point we either have consumed the whole incoming hash table, or we don't have any more nodes to reuse in
1265
1251
// the destination. Either continue with constructing new nodes, or deallocate the left over nodes.
1266
1252
if (__own_iter->__next_ ) {
1267
- __deallocate_node_list (__own_iter->__next_ );
1253
+ __deallocate_node (__own_iter->__next_ );
1268
1254
__own_iter->__next_ = nullptr ;
1269
1255
} else {
1270
1256
__copy_construct (__other_iter, __own_iter, __current_chash);
@@ -1275,6 +1261,19 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __other)
1275
1261
return *this ;
1276
1262
}
1277
1263
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
+
1278
1277
template <class _Tp , class _Hash , class _Equal , class _Alloc >
1279
1278
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1280
1279
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT {
@@ -1330,11 +1329,11 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u,
1330
1329
}
1331
1330
#if _LIBCPP_HAS_EXCEPTIONS
1332
1331
} catch (...) {
1333
- __deallocate_node_list (__cache);
1332
+ __deallocate_node (__cache);
1334
1333
throw ;
1335
1334
}
1336
1335
#endif // _LIBCPP_HAS_EXCEPTIONS
1337
- __deallocate_node_list (__cache);
1336
+ __deallocate_node (__cache);
1338
1337
}
1339
1338
const_iterator __i = __u.begin ();
1340
1339
while (__u.size () != 0 )
@@ -1373,11 +1372,11 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __
1373
1372
}
1374
1373
#if _LIBCPP_HAS_EXCEPTIONS
1375
1374
} catch (...) {
1376
- __deallocate_node_list (__cache);
1375
+ __deallocate_node (__cache);
1377
1376
throw ;
1378
1377
}
1379
1378
#endif // _LIBCPP_HAS_EXCEPTIONS
1380
- __deallocate_node_list (__cache);
1379
+ __deallocate_node (__cache);
1381
1380
}
1382
1381
for (; __first != __last; ++__first)
1383
1382
__emplace_unique (*__first);
@@ -1403,11 +1402,11 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f
1403
1402
}
1404
1403
#if _LIBCPP_HAS_EXCEPTIONS
1405
1404
} catch (...) {
1406
- __deallocate_node_list (__cache);
1405
+ __deallocate_node (__cache);
1407
1406
throw ;
1408
1407
}
1409
1408
#endif // _LIBCPP_HAS_EXCEPTIONS
1410
- __deallocate_node_list (__cache);
1409
+ __deallocate_node (__cache);
1411
1410
}
1412
1411
for (; __first != __last; ++__first)
1413
1412
__emplace_multi (*__first);
@@ -1440,7 +1439,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT {
1440
1439
template <class _Tp , class _Hash , class _Equal , class _Alloc >
1441
1440
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear () _NOEXCEPT {
1442
1441
if (size () > 0 ) {
1443
- __deallocate_node_list (__first_node_.__next_ );
1442
+ __deallocate_node (__first_node_.__next_ );
1444
1443
__first_node_.__next_ = nullptr ;
1445
1444
size_type __bc = bucket_count ();
1446
1445
for (size_type __i = 0 ; __i < __bc; ++__i)
@@ -1900,57 +1899,12 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) {
1900
1899
template <class _Tp , class _Hash , class _Equal , class _Alloc >
1901
1900
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1902
1901
__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);
1931
1905
}
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);
1954
1908
}
1955
1909
1956
1910
template <class _Tp , class _Hash , class _Equal , class _Alloc >
0 commit comments