[libcxx-commits] [libcxx] [libc++] [containers] P2077R3: Heterogeneous erasure overloads for associative containers (PR #174680)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jan 7 08:46:48 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Rafail Shakhin ogly (rsaddatimov)

<details>
<summary>Changes</summary>

Closes #<!-- -->105165

---

Patch is 86.45 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/174680.diff


42 Files Affected:

- (modified) libcxx/docs/FeatureTestMacroTable.rst (+1-1) 
- (modified) libcxx/docs/ReleaseNotes/22.rst (+1) 
- (modified) libcxx/docs/Status/Cxx23Papers.csv (+1-1) 
- (modified) libcxx/include/__hash_table (+8-8) 
- (modified) libcxx/include/__tree (+9-8) 
- (modified) libcxx/include/map (+61-2) 
- (modified) libcxx/include/set (+62-2) 
- (modified) libcxx/include/unordered_map (+60-2) 
- (modified) libcxx/include/unordered_set (+60-2) 
- (modified) libcxx/include/version (+1-1) 
- (modified) libcxx/test/libcxx/containers/associative/map/map.nodiscard.verify.cpp (+4) 
- (modified) libcxx/test/libcxx/containers/associative/map/multimap.nodiscard.verify.cpp (+4) 
- (modified) libcxx/test/libcxx/containers/associative/set/multiset.nodiscard.verify.cpp (+4) 
- (modified) libcxx/test/libcxx/containers/associative/set/set.nodiscard.verify.cpp (+4) 
- (modified) libcxx/test/libcxx/containers/unord/unord.map/nodiscard.verify.cpp (+4) 
- (modified) libcxx/test/libcxx/containers/unord/unord.multimap/nodiscard.verify.cpp (+4) 
- (modified) libcxx/test/libcxx/containers/unord/unord.multiset/nodiscard.verify.cpp (+4) 
- (modified) libcxx/test/libcxx/containers/unord/unord.set/nodiscard.verify.cpp (+4) 
- (added) libcxx/test/std/containers/associative/map/map.erasure/erase.transparent.pass.cpp (+28) 
- (added) libcxx/test/std/containers/associative/map/map.modifiers/extract.transparent.pass.cpp (+27) 
- (added) libcxx/test/std/containers/associative/multimap/multimap.erasure/erase.transparent.pass.cpp (+29) 
- (added) libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract.transparent.pass.cpp (+27) 
- (added) libcxx/test/std/containers/associative/multiset/extract.transparent.pass.cpp (+27) 
- (added) libcxx/test/std/containers/associative/multiset/multiset.erasure/erase.transparent.pass.cpp (+27) 
- (added) libcxx/test/std/containers/associative/set/erase.transparent.pass.cpp (+27) 
- (added) libcxx/test/std/containers/associative/set/extract.transparent.pass.cpp (+27) 
- (added) libcxx/test/std/containers/unord/unord.map/erase.transparent.pass.cpp (+56) 
- (added) libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/extract.transparent.pass.cpp (+56) 
- (added) libcxx/test/std/containers/unord/unord.multimap/erase.transparent.pass.cpp (+56) 
- (added) libcxx/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/extract.transparent.pass.cpp (+56) 
- (added) libcxx/test/std/containers/unord/unord.multiset/erase.transparent.pass.cpp (+56) 
- (added) libcxx/test/std/containers/unord/unord.multiset/extract.transparent.pass.cpp (+56) 
- (added) libcxx/test/std/containers/unord/unord.set/erase.transparent.pass.cpp (+56) 
- (added) libcxx/test/std/containers/unord/unord.set/extract.transparent.pass.cpp (+56) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/map.version.compile.pass.cpp (+10-22) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/set.version.compile.pass.cpp (+10-22) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/unordered_map.version.compile.pass.cpp (+10-22) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/unordered_set.version.compile.pass.cpp (+10-22) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+10-22) 
- (added) libcxx/test/support/test_transparent_associative.hpp (+124) 
- (modified) libcxx/test/support/test_transparent_unordered.h (+72-27) 
- (modified) libcxx/utils/generate_feature_test_macro_components.py (-1) 


``````````diff
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 32911d0f64449..9beb5b511b5bb 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -314,7 +314,7 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_allocate_at_least``                            ``202302L``
     ---------------------------------------------------------- -----------------
-    ``__cpp_lib_associative_heterogeneous_erasure``            *unimplemented*
+    ``__cpp_lib_associative_heterogeneous_erasure``            ``202110L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_bind_back``                                    ``202202L``
     ---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 3e2b3e6633bb1..f9313a6f5907b 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -38,6 +38,7 @@ What's New in Libc++ 22.0.0?
 Implemented Papers
 ------------------
 
+- P2077R3: Heterogeneous erasure overloads for associative containers (`Github <https://llvm.org/PR105165>`__)
 - P2592R3: Hashing support for ``std::chrono`` value classes (`Github <https://llvm.org/PR105358>`__)
 - P2321R2: ``zip`` (`Github <https://llvm.org/PR105169>`__) (The paper is partially implemented. ``zip_transform_view``,
   ``adjacent_view``, and ``adjacent_transform_view`` are implemented in this release)
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index e4c6cb0f51065..842bfb713a390 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -30,7 +30,7 @@
 "`P1147R1 <https://wg21.link/P1147R1>`__","Printing ``volatile`` Pointers","2021-10 (Virtual)","|Complete|","14","`#105161 <https://github.com/llvm/llvm-project/issues/105161>`__",""
 "`P1272R4 <https://wg21.link/P1272R4>`__","Byteswapping for fun&&nuf","2021-10 (Virtual)","|Complete|","14","`#105163 <https://github.com/llvm/llvm-project/issues/105163>`__",""
 "`P1675R2 <https://wg21.link/P1675R2>`__","``rethrow_exception`` must be allowed to copy","2021-10 (Virtual)","|Nothing To Do|","","`#105164 <https://github.com/llvm/llvm-project/issues/105164>`__",""
-"`P2077R3 <https://wg21.link/P2077R3>`__","Heterogeneous erasure overloads for associative containers","2021-10 (Virtual)","","","`#105165 <https://github.com/llvm/llvm-project/issues/105165>`__",""
+"`P2077R3 <https://wg21.link/P2077R3>`__","Heterogeneous erasure overloads for associative containers","2021-10 (Virtual)","Complete","22","`#105165 <https://github.com/llvm/llvm-project/issues/105165>`__",""
 "`P2251R1 <https://wg21.link/P2251R1>`__","Require ``span`` & ``basic_string_view`` to be Trivially Copyable","2021-10 (Virtual)","|Complete|","14","`#105166 <https://github.com/llvm/llvm-project/issues/105166>`__",""
 "`P2301R1 <https://wg21.link/P2301R1>`__","Add a ``pmr`` alias for ``std::stacktrace``","2021-10 (Virtual)","","","`#105167 <https://github.com/llvm/llvm-project/issues/105167>`__",""
 "`P2321R2 <https://wg21.link/P2321R2>`__","``zip``","2021-10 (Virtual)","|In Progress|","","`#105169 <https://github.com/llvm/llvm-project/issues/105169>`__",""
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index ef487fb06dd5e..ff52ac5c01f2d 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -882,10 +882,10 @@ public:
   template <class _Table>
   _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_multi(_Table& __source);
 
+  template <class _NodeHandle, class _Key>
+  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const _Key& __key);
   template <class _NodeHandle>
-  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(key_type const& __key);
-  template <class _NodeHandle>
-  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const_iterator __it);
+  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract_iterator(const_iterator __it);
 #endif
 
   _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
@@ -1634,18 +1634,18 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(const_iter
 }
 
 template <class _Tp, class _Hash, class _Equal, class _Alloc>
-template <class _NodeHandle>
-_LIBCPP_HIDE_FROM_ABI _NodeHandle
-__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(key_type const& __key) {
+template <class _NodeHandle, class _Key>
+_LIBCPP_HIDE_FROM_ABI _NodeHandle __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(const _Key& __key) {
   iterator __i = find(__key);
   if (__i == end())
     return _NodeHandle();
-  return __node_handle_extract<_NodeHandle>(__i);
+  return __node_handle_extract_iterator<_NodeHandle>(__i);
 }
 
 template <class _Tp, class _Hash, class _Equal, class _Alloc>
 template <class _NodeHandle>
-_LIBCPP_HIDE_FROM_ABI _NodeHandle __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(const_iterator __p) {
+_LIBCPP_HIDE_FROM_ABI _NodeHandle
+__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract_iterator(const_iterator __p) {
   allocator_type __alloc(__node_alloc());
   return _NodeHandle(remove(__p).release(), __alloc);
 }
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index fbb48f8196964..8a12e75033d20 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -1188,10 +1188,10 @@ public:
   template <class _Comp2>
   _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_multi(__tree<_Tp, _Comp2, _Allocator>& __source);
 
+  template <class _NodeHandle, class _Key>
+  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const _Key&);
   template <class _NodeHandle>
-  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(key_type const&);
-  template <class _NodeHandle>
-  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const_iterator);
+  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract_iterator(const_iterator);
 #endif
 
   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p);
@@ -1943,7 +1943,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __n
   if (__nh.empty())
     return _InsertReturnType{end(), false, _NodeHandle()};
 
-  __node_pointer __ptr = __nh.__ptr_;
+  __node_pointer __ptr     = __nh.__ptr_;
   auto [__parent, __child] = __find_equal(__ptr->__get_value());
   if (__child != nullptr)
     return _InsertReturnType{iterator(static_cast<__node_pointer>(__child)), false, std::move(__nh)};
@@ -1973,17 +1973,18 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __
 }
 
 template <class _Tp, class _Compare, class _Allocator>
-template <class _NodeHandle>
-_LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key) {
+template <class _NodeHandle, class _Key>
+_LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const _Key& __key) {
   iterator __it = find(__key);
   if (__it == end())
     return _NodeHandle();
-  return __node_handle_extract<_NodeHandle>(__it);
+  return __node_handle_extract_iterator<_NodeHandle>(__it);
 }
 
 template <class _Tp, class _Compare, class _Allocator>
 template <class _NodeHandle>
-_LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const_iterator __p) {
+_LIBCPP_HIDE_FROM_ABI _NodeHandle
+__tree<_Tp, _Compare, _Allocator>::__node_handle_extract_iterator(const_iterator __p) {
   __node_pointer __np = __p.__get_np();
   __remove_node_pointer(__np);
   return _NodeHandle(__np, __alloc());
diff --git a/libcxx/include/map b/libcxx/include/map
index 03c92e152e04f..1993e2bbdeb21 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -149,6 +149,9 @@ public:
 
     node_type extract(const_iterator position);                                       // C++17
     node_type extract(const key_type& x);                                             // C++17
+    template <typename K>
+      node_type extract(K&& k);                                                       // C++23
+
     insert_return_type insert(node_type&& nh);                                        // C++17
     iterator insert(const_iterator hint, node_type&& nh);                             // C++17
 
@@ -172,7 +175,10 @@ public:
     iterator  erase(const_iterator position);
     iterator  erase(iterator position); // C++14
     size_type erase(const key_type& k);
+    template <typename K>
+      size_type erase(K&& k); // C++23
     iterator  erase(const_iterator first, const_iterator last);
+
     void clear() noexcept;
 
     template<class C2>
@@ -428,13 +434,19 @@ public:
 
     node_type extract(const_iterator position);                                       // C++17
     node_type extract(const key_type& x);                                             // C++17
+    template <typename K>
+      node_type extract(K&& k);                                                       // C++23
+
     iterator insert(node_type&& nh);                                                  // C++17
     iterator insert(const_iterator hint, node_type&& nh);                             // C++17
 
     iterator  erase(const_iterator position);
     iterator  erase(iterator position); // C++14
     size_type erase(const key_type& k);
+    template <typename K>
+      size_type erase(K&& k); // C++23
     iterator  erase(const_iterator first, const_iterator last);
+
     void clear() noexcept;
 
     template<class C2>
@@ -1263,6 +1275,18 @@ public:
   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) {
     return __tree_.erase(__f.__i_, __l.__i_);
   }
+
+#  if _LIBCPP_STD_VER >= 23
+
+  template <class _Kp>
+    requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
+             !is_convertible_v<_Kp &&, const_iterator>)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __kp) {
+    return __tree_.__erase_unique(__kp);
+  }
+
+#  endif // _LIBCPP_STD_VER >= 23
+
   _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __tree_.clear(); }
 
 #  if _LIBCPP_STD_VER >= 17
@@ -1280,8 +1304,20 @@ public:
     return __tree_.template __node_handle_extract<node_type>(__key);
   }
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
-    return __tree_.template __node_handle_extract<node_type>(__it.__i_);
+    return __tree_.template __node_handle_extract_iterator<node_type>(__it.__i_);
+  }
+
+#    if _LIBCPP_STD_VER >= 23
+
+  template <class _Kp>
+    requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
+             !is_convertible_v<_Kp &&, const_iterator>)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(_Kp&& __kp) {
+    return __tree_.template __node_handle_extract<node_type>(__kp);
   }
+
+#    endif // _LIBCPP_STD_VER >= 23
+
   template <class _Compare2>
   _LIBCPP_HIDE_FROM_ABI void merge(map<key_type, mapped_type, _Compare2, allocator_type>& __source) {
     _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
@@ -1865,6 +1901,17 @@ public:
     return __tree_.erase(__f.__i_, __l.__i_);
   }
 
+#  if _LIBCPP_STD_VER >= 23
+
+  template <class _Kp>
+    requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
+             !is_convertible_v<_Kp &&, const_iterator>)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __kp) {
+    return __tree_.__erase_multi(__kp);
+  }
+
+#  endif // _LIBCPP_STD_VER >= 23
+
 #  if _LIBCPP_STD_VER >= 17
   _LIBCPP_HIDE_FROM_ABI iterator insert(node_type&& __nh) {
     _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(),
@@ -1880,8 +1927,20 @@ public:
     return __tree_.template __node_handle_extract<node_type>(__key);
   }
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
-    return __tree_.template __node_handle_extract<node_type>(__it.__i_);
+    return __tree_.template __node_handle_extract_iterator<node_type>(__it.__i_);
   }
+
+#    if _LIBCPP_STD_VER >= 23
+
+  template <class _Kp>
+    requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
+             !is_convertible_v<_Kp &&, const_iterator>)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(_Kp&& __kp) {
+    return __tree_.template __node_handle_extract<node_type>(__kp);
+  }
+
+#    endif // _LIBCPP_STD_VER >= 23
+
   template <class _Compare2>
   _LIBCPP_HIDE_FROM_ABI void merge(multimap<key_type, mapped_type, _Compare2, allocator_type>& __source) {
     _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
diff --git a/libcxx/include/set b/libcxx/include/set
index 265c2f6cb6501..cb66dd8b3d745 100644
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -125,13 +125,19 @@ public:
 
     node_type extract(const_iterator position);                                       // C++17
     node_type extract(const key_type& x);                                             // C++17
+    template <typename K>
+      node_type extract(K&& k);                                                       // C++23
+
     insert_return_type insert(node_type&& nh);                                        // C++17
     iterator insert(const_iterator hint, node_type&& nh);                             // C++17
 
     iterator  erase(const_iterator position);
     iterator  erase(iterator position);  // C++14
     size_type erase(const key_type& k);
+    template <typename K>
+      size_type erase(K&& k); // C++23
     iterator  erase(const_iterator first, const_iterator last);
+
     void clear() noexcept;
 
     template<class C2>
@@ -370,6 +376,9 @@ public:
 
     node_type extract(const_iterator position);                                       // C++17
     node_type extract(const key_type& x);                                             // C++17
+    template <typename K>
+      node_type extract(K&& k);                                                       // C++23
+
     iterator insert(node_type&& nh);                                                  // C++17
     iterator insert(const_iterator hint, node_type&& nh);                             // C++17
 
@@ -377,6 +386,9 @@ public:
     iterator  erase(iterator position);  // C++14
     size_type erase(const key_type& k);
     iterator  erase(const_iterator first, const_iterator last);
+    template <typename K>
+      size_type erase(K&& k); // C++23
+
     void clear() noexcept;
 
     template<class C2>
@@ -770,6 +782,18 @@ public:
   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __tree_.erase(__p); }
   _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __tree_.__erase_unique(__k); }
   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) { return __tree_.erase(__f, __l); }
+
+#  if _LIBCPP_STD_VER >= 23
+
+  template <class _Kp>
+    requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
+             !is_convertible_v<_Kp &&, const_iterator>)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __kp) {
+    return __tree_.__erase_unique(__kp);
+  }
+
+#  endif // _LIBCPP_STD_VER >= 23
+
   _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __tree_.clear(); }
 
 #  if _LIBCPP_STD_VER >= 17
@@ -787,8 +811,20 @@ public:
     return __tree_.template __node_handle_extract<node_type>(__key);
   }
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
-    return __tree_.template __node_handle_extract<node_type>(__it);
+    return __tree_.template __node_handle_extract_iterator<node_type>(__it);
+  }
+
+#    if _LIBCPP_STD_VER >= 23
+
+  template <class _Kp>
+    requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
+             !is_convertible_v<_Kp &&, const_iterator>)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(_Kp&& __kp) {
+    return __tree_.template __node_handle_extract<node_type>(__kp);
   }
+
+#    endif // _LIBCPP_STD_VER >= 23
+
   template <class _Compare2>
   _LIBCPP_HIDE_FROM_ABI void merge(set<key_type, _Compare2, allocator_type>& __source) {
     _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
@@ -1245,6 +1281,18 @@ public:
   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __tree_.erase(__p); }
   _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __tree_.__erase_multi(__k); }
   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) { return __tree_.erase(__f, __l); }
+
+#  if _LIBCPP_STD_VER >= 23
+
+  template <class _Kp>
+    requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
+             !is_convertible_v<_Kp &&, const_iterator>)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __kp) {
+    return __tree_.__erase_multi(__kp);
+  }
+
+#  endif // _LIBCPP_STD_VER >= 23
+
   _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __tree_.clear(); }
 
 #  if _LIBCPP_STD_VER >= 17
@@ -1262,8 +1310,20 @@ public:
     return __tree_.template __node_handle_extract<node_type>(__key);
   }
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
-    return __tree_.template __node_handle_extract<node_type>(__it);
+    return __tree_.template __node_handle_extract_iterator<node_type>(__it);
   }
+
+#    if _LIBCPP_STD_VER >= 23
+
+  template <class _Kp>
+    requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
+             !is_convertible_v<_Kp &&, const_iterator>)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(_Kp&& __kp) {
+    return __tree_.template __node_handle_extract<node_type>(__kp);
+  }
+
+#    endif // _LIBCPP_STD_VER >= 23
+
   template <class _Compare2>
   _LIBCPP_HIDE_FROM_ABI void merge(multiset<key_type, _Compare2, allocator_type>& __source) {
     _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map
index ca53348eb5e2a..2c6208ccebdcb 100644
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -139,6 +139,9 @@ public:
 
     node_type extract(const_iterator position);                                       // C++17
     node_type extract(const key_type& x);                                             // C++17
+    template <typename K>
+      node_type extract(K&& k);                                                       // C++23
+
     insert_return_type insert(node_type&& nh);                                        // C++17
     iterator           insert(const_iterator hint, node_type&& nh);                   // C++17
 
@@ -162,7 +165,10 @@ public:
     iterator erase(const_iterator position);
     iterator erase(iterator position);  // C++14
     size_type erase(const key_type& k);
+    template <typename K>
+      size_type erase(K&& k); // C++23
     iterator erase(const_iterator first, const_iterator last);
+
     void clear() noexcept;
 
     template<class H2, class P2>
@@ -425,13 +431,19 @@ public:
 
     node_type extract(const_iterator position);                // C++17
     node_type extract(const key_type& x);                      // C++17
+    template <typename K>
+      node_type extract(K&& k);                                // C++23
+
     iterator insert(node_type&& nh);                           // C++17
     iterator insert(const_iterator hint, node_type&& nh);      // C++17
 
     iterator erase(const_iterator position);
     iterator erase(iterator position);  // C++14
     size_type erase(const key_type& k);
+    template <typename K>
+      size_type erase(K&& k); // C++23
     iterator erase(const_iterator first, const_iterator last);
+
     void clear() noexcept;
 
     template<class H2, class P2>
@@ -1158,6 +1170,18 @@ public:
   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
     return __table_.erase(__first.__i_, __last.__i_);
   }
+
+#  if _LIBCPP_STD_VER >= 23
+
+  template <class _Kp>
+    requires(__is_transparent_v<hasher> && __is_transparent_v<key_equal> && !is_convertible_v<_Kp &&, iterator> &&
+             !is_convertible_v<_Kp &&, const_iterator>)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __kp) {
+    return __table_.__erase_unique(__kp);
+  }...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/174680


More information about the libcxx-commits mailing list