[libcxx-commits] [libcxx] [libc++] Implement P2077R3 Heterogeneous erasure overloads for associative containers (PR #78277)
Mital Ashok via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jan 16 05:49:39 PST 2024
https://github.com/MitalAshok created https://github.com/llvm/llvm-project/pull/78277
Implements [P2077R3](https://wg21.link/P2077R3).
Note that given a non-const or non-lvalue argument `k`, `m.extract(k)`/`m.erase(k)` converts to a const lvalue, similarly to what would have happened if the functions took by `const _K2&` instead of `_K2&&`. This is intentional since the comparator / hasher+key_equal shouldn't modify the argument. The exact wording is here: https://wg21.link/associative.reqmts.general#123
>From db3ba9998384f103b388be36cca99094c4bebf3e Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Tue, 16 Jan 2024 13:31:06 +0000
Subject: [PATCH] [libc++] Implement P2077R3 Heterogeneous erasure overloads
for associative containers
---
libcxx/docs/ReleaseNotes/18.rst | 1 +
libcxx/docs/Status/Cxx23Papers.csv | 4 +-
libcxx/include/__hash_table | 8 +--
libcxx/include/__tree | 8 +--
libcxx/include/map | 40 ++++++++++--
libcxx/include/set | 36 ++++++++++-
libcxx/include/unordered_map | 36 ++++++++++-
libcxx/include/unordered_set | 42 +++++++++++--
libcxx/include/version | 2 +-
.../map/map.modifiers/erase_tran.pass.cpp | 58 ++++++++++++++++++
.../erase_tran1.compile.fail.cpp | 40 ++++++++++++
.../erase_tran2.compile.fail.cpp | 40 ++++++++++++
.../erase_tran3.compile.fail.cpp | 40 ++++++++++++
.../map/map.modifiers/erase_tran4.pass.cpp | 49 +++++++++++++++
.../map/map.modifiers/erase_tran5.pass.cpp | 52 ++++++++++++++++
.../map/map.modifiers/extract_tran.pass.cpp | 61 +++++++++++++++++++
.../extract_tran1.compile.fail.cpp | 40 ++++++++++++
.../extract_tran2.compile.fail.cpp | 40 ++++++++++++
.../extract_tran3.compile.fail.cpp | 40 ++++++++++++
.../map/map.modifiers/extract_tran4.pass.cpp | 49 +++++++++++++++
.../map/map.modifiers/extract_tran5.pass.cpp | 52 ++++++++++++++++
.../multimap.modifiers/erase_tran.pass.cpp | 58 ++++++++++++++++++
.../erase_tran1.compile.fail.cpp | 40 ++++++++++++
.../erase_tran2.compile.fail.cpp | 40 ++++++++++++
.../erase_tran3.compile.fail.cpp | 40 ++++++++++++
.../multimap.modifiers/erase_tran4.pass.cpp | 49 +++++++++++++++
.../multimap.modifiers/erase_tran5.pass.cpp | 52 ++++++++++++++++
.../multimap.modifiers/extract_tran.pass.cpp | 61 +++++++++++++++++++
.../extract_tran1.compile.fail.cpp | 40 ++++++++++++
.../extract_tran2.compile.fail.cpp | 40 ++++++++++++
.../extract_tran3.compile.fail.cpp | 40 ++++++++++++
.../multimap.modifiers/extract_tran4.pass.cpp | 49 +++++++++++++++
.../multimap.modifiers/extract_tran5.pass.cpp | 52 ++++++++++++++++
.../associative/multiset/erase_tran.pass.cpp | 58 ++++++++++++++++++
.../multiset/erase_tran1.compile.fail.cpp | 40 ++++++++++++
.../multiset/erase_tran2.compile.fail.cpp | 40 ++++++++++++
.../multiset/erase_tran3.compile.fail.cpp | 40 ++++++++++++
.../associative/multiset/erase_tran4.pass.cpp | 49 +++++++++++++++
.../associative/multiset/erase_tran5.pass.cpp | 52 ++++++++++++++++
.../multiset/extract_tran.pass.cpp | 61 +++++++++++++++++++
.../multiset/extract_tran1.compile.fail.cpp | 40 ++++++++++++
.../multiset/extract_tran2.compile.fail.cpp | 40 ++++++++++++
.../multiset/extract_tran3.compile.fail.cpp | 40 ++++++++++++
.../multiset/extract_tran4.pass.cpp | 49 +++++++++++++++
.../multiset/extract_tran5.pass.cpp | 52 ++++++++++++++++
.../associative/set/erase_tran.pass.cpp | 58 ++++++++++++++++++
.../set/erase_tran1.compile.fail.cpp | 40 ++++++++++++
.../set/erase_tran2.compile.fail.cpp | 40 ++++++++++++
.../set/erase_tran3.compile.fail.cpp | 40 ++++++++++++
.../associative/set/erase_tran4.pass.cpp | 49 +++++++++++++++
.../associative/set/erase_tran5.pass.cpp | 52 ++++++++++++++++
.../associative/set/extract_tran.pass.cpp | 61 +++++++++++++++++++
.../set/extract_tran1.compile.fail.cpp | 40 ++++++++++++
.../set/extract_tran2.compile.fail.cpp | 40 ++++++++++++
.../set/extract_tran3.compile.fail.cpp | 40 ++++++++++++
.../associative/set/extract_tran4.pass.cpp | 49 +++++++++++++++
.../associative/set/extract_tran5.pass.cpp | 52 ++++++++++++++++
57 files changed, 2397 insertions(+), 24 deletions(-)
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/erase_tran.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/erase_tran1.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/erase_tran2.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/erase_tran3.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/erase_tran4.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/erase_tran5.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/extract_tran.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/extract_tran1.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/extract_tran2.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/extract_tran3.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/extract_tran4.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/map/map.modifiers/extract_tran5.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran1.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran2.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran3.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran4.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran5.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran1.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran2.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran3.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran4.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran5.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/erase_tran.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/erase_tran1.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/erase_tran2.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/erase_tran3.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/erase_tran4.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/erase_tran5.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/extract_tran.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/extract_tran1.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/extract_tran2.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/extract_tran3.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/extract_tran4.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/multiset/extract_tran5.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/set/erase_tran.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/set/erase_tran1.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/set/erase_tran2.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/set/erase_tran3.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/set/erase_tran4.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/set/erase_tran5.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/set/extract_tran.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/set/extract_tran1.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/set/extract_tran2.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/set/extract_tran3.compile.fail.cpp
create mode 100644 libcxx/test/std/containers/associative/set/extract_tran4.pass.cpp
create mode 100644 libcxx/test/std/containers/associative/set/extract_tran5.pass.cpp
diff --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst
index 62a1fec627d0ca..8db818ef490203 100644
--- a/libcxx/docs/ReleaseNotes/18.rst
+++ b/libcxx/docs/ReleaseNotes/18.rst
@@ -60,6 +60,7 @@ Implemented Papers
- P0521R0 - Proposed Resolution for CA 14 (``shared_ptr`` ``use_count/unique``)
- P1759R6 - Native handles and file streams
- P2517R1 - Add a conditional ``noexcept`` specification to ``std::apply``
+- P2077R3 - Heterogeneous erasure overloads for associative containers
Improvements and New Features
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index ebab3ef735b617..5e091f6151399b 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -30,7 +30,7 @@
"`P1147R1 <https://wg21.link/P1147R1>`__","LWG","Printing ``volatile`` Pointers","October 2021","|Complete|","14.0"
"`P1272R4 <https://wg21.link/P1272R4>`__","LWG","Byteswapping for fun&&nuf","October 2021","|Complete|","14.0"
"`P1675R2 <https://wg21.link/P1675R2>`__","LWG","``rethrow_exception`` must be allowed to copy","October 2021","",""
-"`P2077R3 <https://wg21.link/P2077R3>`__","LWG","Heterogeneous erasure overloads for associative containers","October 2021","",""
+"`P2077R3 <https://wg21.link/P2077R3>`__","LWG","Heterogeneous erasure overloads for associative containers","October 2021","|Complete|","18.0"
"`P2251R1 <https://wg21.link/P2251R1>`__","LWG","Require ``span`` & ``basic_string_view`` to be Trivially Copyable","October 2021","|Complete|","14.0"
"`P2301R1 <https://wg21.link/P2301R1>`__","LWG","Add a ``pmr`` alias for ``std::stacktrace``","October 2021","",""
"`P2321R2 <https://wg21.link/P2321R2>`__","LWG","``zip``","October 2021","|In Progress|","","|ranges|"
@@ -59,7 +59,7 @@
"`P1467R9 <https://wg21.link/P1467R9>`__","LWG","Extended ``floating-point`` types and standard names","July 2022","",""
"`P1642R11 <https://wg21.link/P1642R11>`__","LWG","Freestanding ``[utilities]``, ``[ranges]``, and ``[iterators]``","July 2022","",""
"`P1899R3 <https://wg21.link/P1899R3>`__","LWG","``stride_view``","July 2022","","","|ranges|"
-"`P2093R14 <https://wg21.link/P2093R14>`__","LWG","Formatted output","July 2022","","|Complete|","18.0"
+"`P2093R14 <https://wg21.link/P2093R14>`__","LWG","Formatted output","July 2022","|Complete|","18.0",""
"`P2165R4 <https://wg21.link/P2165R4>`__","LWG","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","July 2022","",""
"`P2278R4 <https://wg21.link/P2278R4>`__","LWG","``cbegin`` should always return a constant iterator","July 2022","","","|ranges|"
"`P2286R8 <https://wg21.link/P2286R8>`__","LWG","Formatting Ranges","July 2022","|Complete|","16.0","|format| |ranges|"
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 4ca49fe42606c7..0d7c38f9d056f5 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -836,8 +836,8 @@ public:
template <class _Table>
_LIBCPP_HIDE_FROM_ABI void __node_handle_merge_multi(_Table& __source);
- template <class _NodeHandle>
- _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(key_type const& __key);
+ template <class _NodeHandle, class _Key>
+ _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_find_and_extract(const _Key& __key);
template <class _NodeHandle>
_LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const_iterator __it);
#endif
@@ -1579,9 +1579,9 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(const_iter
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
-template <class _NodeHandle>
+template <class _NodeHandle, class _Key>
_LIBCPP_HIDE_FROM_ABI _NodeHandle
-__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(key_type const& __key) {
+__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_find_and_extract(const _Key& __key) {
iterator __i = find(__key);
if (__i == end())
return _NodeHandle();
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 2dcc3c614d3660..84cda01df51494 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -1168,8 +1168,8 @@ public:
template <class _Tree>
_LIBCPP_HIDE_FROM_ABI void __node_handle_merge_multi(_Tree& __source);
- template <class _NodeHandle>
- _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(key_type const&);
+ template <class _NodeHandle, class _Key>
+ _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_find_and_extract(const _Key&);
template <class _NodeHandle>
_LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const_iterator);
#endif
@@ -1963,8 +1963,8 @@ __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_find_and_extract(const _Key& __key) {
iterator __it = find(__key);
if (__it == end())
return _NodeHandle();
diff --git a/libcxx/include/map b/libcxx/include/map
index f122f2ebb15b52..5b3515c228e0b5 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -149,6 +149,8 @@ public:
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
+ template <class K>
+ node_type extract(K&& x); // C++23
insert_return_type insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
@@ -170,8 +172,10 @@ public:
iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17
iterator erase(const_iterator position);
- iterator erase(iterator position); // C++14
+ iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
+ template <class K>
+ size_type erase(K&& x); // C++23
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
@@ -428,12 +432,16 @@ public:
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
+ template <class K>
+ node_type extract(K&& x); // 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
+ iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
+ template <class K>
+ size_type erase(K&& x); // C++23
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
@@ -1309,6 +1317,12 @@ public:
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __tree_.erase(__p.__i_); }
_LIBCPP_HIDE_FROM_ABI iterator erase(iterator __p) { return __tree_.erase(__p.__i_); }
_LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __tree_.__erase_unique(__k); }
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<_Compare, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI size_type erase(_K2&& __k) {
+ return __tree_.__erase_unique(__k);
+ }
+#endif
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) {
return __tree_.erase(__f.__i_, __l.__i_);
}
@@ -1326,11 +1340,17 @@ public:
return __tree_.template __node_handle_insert_unique<node_type>(__hint.__i_, std::move(__nh));
}
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
- return __tree_.template __node_handle_extract<node_type>(__key);
+ return __tree_.template __node_handle_find_and_extract<node_type>(__key);
}
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
return __tree_.template __node_handle_extract<node_type>(__it.__i_);
}
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<_Compare, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI node_type extract(_K2&& __key) {
+ return __tree_.template __node_handle_find_and_extract<node_type>(__key);
+ }
+#endif
template <class _Compare2>
_LIBCPP_HIDE_FROM_ABI void merge(map<key_type, mapped_type, _Compare2, allocator_type>& __source) {
_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
@@ -1900,6 +1920,12 @@ public:
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __tree_.erase(__p.__i_); }
_LIBCPP_HIDE_FROM_ABI iterator erase(iterator __p) { return __tree_.erase(__p.__i_); }
_LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __tree_.__erase_multi(__k); }
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<_Compare, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI size_type erase(_K2&& __k) {
+ return __tree_.__erase_multi(__k);
+ }
+#endif
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) {
return __tree_.erase(__f.__i_, __l.__i_);
}
@@ -1916,11 +1942,17 @@ public:
return __tree_.template __node_handle_insert_multi<node_type>(__hint.__i_, std::move(__nh));
}
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
- return __tree_.template __node_handle_extract<node_type>(__key);
+ return __tree_.template __node_handle_find_and_extract<node_type>(__key);
}
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
return __tree_.template __node_handle_extract<node_type>(__it.__i_);
}
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<_Compare, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI node_type extract(_K2&& __key) {
+ return __tree_.template __node_handle_find_and_extract<node_type>(__key);
+ }
+#endif
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 55ba8f8208be1b..832ed876253c86 100644
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -125,12 +125,16 @@ public:
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
+ template <class K>
+ node_type extract(K&& x); // 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 <class K>
+ size_type erase(K&& x); // C++23
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
@@ -370,12 +374,16 @@ public:
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
+ template <class K>
+ node_type extract(K&& x); // 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 <class K>
+ size_type erase(K&& x); // C++23
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
@@ -764,6 +772,12 @@ 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); }
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<_Compare, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI size_type erase(_K2&& __k) {
+ return __tree_.__erase_unique(__k);
+ }
+#endif
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) { return __tree_.erase(__f, __l); }
_LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __tree_.clear(); }
@@ -779,11 +793,17 @@ public:
return __tree_.template __node_handle_insert_unique<node_type>(__hint, std::move(__nh));
}
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
- return __tree_.template __node_handle_extract<node_type>(__key);
+ return __tree_.template __node_handle_find_and_extract<node_type>(__key);
}
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
return __tree_.template __node_handle_extract<node_type>(__it);
}
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<_Compare, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI node_type extract(_K2&& __key) {
+ return __tree_.template __node_handle_find_and_extract<node_type>(__key);
+ }
+#endif
template <class _Compare2>
_LIBCPP_HIDE_FROM_ABI void merge(set<key_type, _Compare2, allocator_type>& __source) {
_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
@@ -1222,6 +1242,12 @@ 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); }
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<_Compare, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI size_type erase(_K2&& __k) {
+ return __tree_.__erase_multi(__k);
+ }
+#endif
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) { return __tree_.erase(__f, __l); }
_LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __tree_.clear(); }
@@ -1237,11 +1263,17 @@ public:
return __tree_.template __node_handle_insert_multi<node_type>(__hint, std::move(__nh));
}
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
- return __tree_.template __node_handle_extract<node_type>(__key);
+ return __tree_.template __node_handle_find_and_extract<node_type>(__key);
}
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
return __tree_.template __node_handle_extract<node_type>(__it);
}
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<_Compare, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI node_type extract(_K2&& __key) {
+ return __tree_.template __node_handle_find_and_extract<node_type>(__key);
+ }
+#endif
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 4be25fc1cdd8fe..42889a06ed019a 100644
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -139,6 +139,8 @@ public:
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
+ template <class K>
+ node_type extract(K&& x); // C++23
insert_return_type insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
@@ -162,6 +164,8 @@ public:
iterator erase(const_iterator position);
iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
+ template <class K>
+ size_type erase(K&& x); // C++23
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
@@ -425,12 +429,16 @@ public:
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
+ template <class K>
+ node_type extract(K&& x); // 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 <class K>
+ size_type erase(K&& x); // C++23
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
@@ -1322,6 +1330,12 @@ public:
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __table_.erase(__p.__i_); }
_LIBCPP_HIDE_FROM_ABI iterator erase(iterator __p) { return __table_.erase(__p.__i_); }
_LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_unique(__k); }
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI size_type erase(_K2&& __k) {
+ return __table_.__erase_unique(__k);
+ }
+#endif
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
return __table_.erase(__first.__i_, __last.__i_);
}
@@ -1339,11 +1353,17 @@ public:
return __table_.template __node_handle_insert_unique<node_type>(__hint.__i_, std::move(__nh));
}
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
- return __table_.template __node_handle_extract<node_type>(__key);
+ return __table_.template __node_handle_find_and_extract<node_type>(__key);
}
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
return __table_.template __node_handle_extract<node_type>(__it.__i_);
}
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI node_type extract(_K2&& __key) {
+ return __table_.template __node_handle_find_and_extract<node_type>(__key);
+ }
+#endif
template <class _H2, class _P2>
_LIBCPP_HIDE_FROM_ABI void merge(unordered_map<key_type, mapped_type, _H2, _P2, allocator_type>& __source) {
@@ -2073,6 +2093,12 @@ public:
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __table_.erase(__p.__i_); }
_LIBCPP_HIDE_FROM_ABI iterator erase(iterator __p) { return __table_.erase(__p.__i_); }
_LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_multi(__k); }
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI size_type erase(_K2&& __k) {
+ return __table_.__erase_multi(__k);
+ }
+#endif
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
return __table_.erase(__first.__i_, __last.__i_);
}
@@ -2090,11 +2116,17 @@ public:
return __table_.template __node_handle_insert_multi<node_type>(__hint.__i_, std::move(__nh));
}
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
- return __table_.template __node_handle_extract<node_type>(__key);
+ return __table_.template __node_handle_find_and_extract<node_type>(__key);
}
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
return __table_.template __node_handle_extract<node_type>(__it.__i_);
}
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI node_type extract(_K2&& __key) {
+ return __table_.template __node_handle_find_and_extract<node_type>(__key);
+ }
+#endif
template <class _H2, class _P2>
_LIBCPP_HIDE_FROM_ABI void merge(unordered_multimap<key_type, mapped_type, _H2, _P2, allocator_type>& __source) {
diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set
index 6414885f4c514a..009ef835a0d523 100644
--- a/libcxx/include/unordered_set
+++ b/libcxx/include/unordered_set
@@ -131,12 +131,16 @@ public:
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
+ template <class K>
+ node_type extract(K&& x); // 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 <class K>
+ size_type erase(K&& x); // C++23
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
@@ -379,12 +383,16 @@ public:
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
+ template <class K>
+ node_type extract(K&& x); // 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 <class K>
+ size_type erase(K&& x); // C++23
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
@@ -777,6 +785,12 @@ public:
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __table_.erase(__p); }
_LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_unique(__k); }
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI size_type erase(_K2&& __k) {
+ return __table_.__erase_unique(__k);
+ }
+#endif
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
return __table_.erase(__first, __last);
}
@@ -794,11 +808,17 @@ public:
return __table_.template __node_handle_insert_unique<node_type>(__h, std::move(__nh));
}
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
- return __table_.template __node_handle_extract<node_type>(__key);
+ return __table_.template __node_handle_find_and_extract<node_type>(__key);
}
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
return __table_.template __node_handle_extract<node_type>(__it);
}
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI node_type extract(_K2&& __key) {
+ return __table_.template __node_handle_find_and_extract<node_type>(__key);
+ }
+#endif
template <class _H2, class _P2>
_LIBCPP_HIDE_FROM_ABI void merge(unordered_set<key_type, _H2, _P2, allocator_type>& __source) {
@@ -1389,12 +1409,18 @@ public:
"node_type with incompatible allocator passed to unordered_multiset::insert()");
return __table_.template __node_handle_insert_multi<node_type>(__hint, std::move(__nh));
}
- _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __position) {
- return __table_.template __node_handle_extract<node_type>(__position);
- }
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
- return __table_.template __node_handle_extract<node_type>(__key);
+ return __table_.template __node_handle_find_and_extract<node_type>(__key);
+ }
+ _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
+ return __table_.template __node_handle_extract<node_type>(__it);
+ }
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI node_type extract(_K2&& __key) {
+ return __table_.template __node_handle_find_and_extract<node_type>(__key);
}
+#endif
template <class _H2, class _P2>
_LIBCPP_HIDE_FROM_ABI void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>& __source) {
@@ -1424,6 +1450,12 @@ public:
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __table_.erase(__p); }
_LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_multi(__k); }
+#if _LIBCPP_STD_VER >= 23
+ template <typename _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value && !(is_convertible_v<_K2&&, iterator> || is_convertible_v<_K2&&, const_iterator>), int> = 0>
+ _LIBCPP_HIDE_FROM_ABI size_type erase(_K2&& __k) {
+ return __table_.__erase_multi(__k);
+ }
+#endif
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
return __table_.erase(__first, __last);
}
diff --git a/libcxx/include/version b/libcxx/include/version
index c96647894dce63..d514f3e5003507 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -434,7 +434,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
#if _LIBCPP_STD_VER >= 23
# define __cpp_lib_adaptor_iterator_pair_constructor 202106L
# define __cpp_lib_allocate_at_least 202106L
-// # define __cpp_lib_associative_heterogeneous_erasure 202110L
+# define __cpp_lib_associative_heterogeneous_erasure 202110L
// # define __cpp_lib_bind_back 202202L
# define __cpp_lib_byteswap 202110L
# define __cpp_lib_constexpr_bitset 202207L
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran.pass.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran.pass.cpp
new file mode 100644
index 00000000000000..cd77c3ce27a7c5
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::map<int, double, transparent_less> M;
+ M example;
+ assert(example.erase(C2Int{5}) == 0);
+ }
+ {
+ typedef std::map<int, double, transparent_less_not_referenceable> M;
+ M example;
+ assert(example.erase(C2Int{5}) == 0);
+ }
+ {
+ typedef std::map<int, double, transparent_less> M;
+ M example;
+ example.insert({ 5, 1. });
+ example.insert({ 6, 2. });
+ example.insert({ 4, 0. });
+ assert(example.size() == 3);
+ M::size_type erased = example.erase(C2Int{5});
+ assert(erased == 1);
+ assert(example.size() == 2);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran1.compile.fail.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran1.compile.fail.cpp
new file mode 100644
index 00000000000000..cc3269a85ba93c
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran1.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::map<int, double, transparent_less_no_type> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran2.compile.fail.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran2.compile.fail.cpp
new file mode 100644
index 00000000000000..e408ec93bc9ba8
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran2.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::map<int, double, transparent_less_private> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran3.compile.fail.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran3.compile.fail.cpp
new file mode 100644
index 00000000000000..26e305352e008e
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran3.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::map<int, double, transparent_less_not_a_type> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran4.pass.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran4.pass.cpp
new file mode 100644
index 00000000000000..35f8e616616fff
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran4.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::map<int, double, transparent_less> M;
+M example;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() {
+ return example.begin();
+ }
+};
+
+int main(int, char**)
+{
+ {
+ example.insert({ 2, 3. });
+ M::iterator erased = example.erase(Convertible());
+ assert(example.empty() && erased == example.end());
+ }
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran5.pass.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran5.pass.cpp
new file mode 100644
index 00000000000000..c65d80a8f11ce9
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/erase_tran5.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::map<int, double, transparent_less> M;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() const {
+ assert(false);
+ }
+private:
+ operator M::const_iterator();
+};
+
+int main(int, char**)
+{
+ {
+ Convertible c;
+ M example;
+ example.insert({ 0, 1. });
+ M::size_type erased = example.erase(c);
+ assert(erased == 1);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran.pass.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran.pass.cpp
new file mode 100644
index 00000000000000..586c3a0100e613
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::map<int, double, transparent_less> M;
+ M example;
+ assert(example.extract(C2Int{5}).empty());
+ }
+ {
+ typedef std::map<int, double, transparent_less_not_referenceable> M;
+ M example;
+ assert(example.extract(C2Int{5}).empty());
+ }
+ {
+ typedef std::map<int, double, transparent_less> M;
+ M example;
+ example.insert({ 5, 1. });
+ example.insert({ 6, 2. });
+ example.insert({ 4, 0. });
+ assert(example.size() == 3);
+ M::node_type nh = example.extract(C2Int{5});
+ assert(nh && nh.key() == 5 && nh.mapped() == 1.);
+ assert(example.size() == 2);
+ example.insert(std::move(nh));
+ assert(example.size() == 3);
+ assert(example.find(5)->second == 1.);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran1.compile.fail.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran1.compile.fail.cpp
new file mode 100644
index 00000000000000..4c5e84ed0a585e
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran1.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::map<int, double, transparent_less_no_type> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran2.compile.fail.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran2.compile.fail.cpp
new file mode 100644
index 00000000000000..7c5f2e7fa6ca34
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran2.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::map<int, double, transparent_less_private> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran3.compile.fail.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran3.compile.fail.cpp
new file mode 100644
index 00000000000000..b8377318d4fffc
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran3.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::map<int, double, transparent_less_not_a_type> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran4.pass.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran4.pass.cpp
new file mode 100644
index 00000000000000..cf11b09ef87c87
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran4.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::map<int, double, transparent_less> M;
+M example;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() {
+ return example.begin();
+ }
+};
+
+int main(int, char**)
+{
+ {
+ example.insert({ 2, 3. });
+ M::node_type nh = example.extract(Convertible());
+ assert(nh && nh.key() == 2 && nh.mapped() == 3.);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran5.pass.cpp b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran5.pass.cpp
new file mode 100644
index 00000000000000..f2c3ba0501a65f
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.modifiers/extract_tran5.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class map
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::map<int, double, transparent_less> M;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() const {
+ assert(false);
+ }
+private:
+ operator M::const_iterator();
+};
+
+int main(int, char**)
+{
+ {
+ Convertible c;
+ M example;
+ example.insert({ 0, 1. });
+ M::node_type nh = example.extract(c);
+ assert(nh && nh.key() == 0 && nh.mapped() == 1.);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran.pass.cpp
new file mode 100644
index 00000000000000..f1b4f512037026
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multimap<int, double, transparent_less> M;
+ M example;
+ assert(example.erase(C2Int{5}) == 0);
+ }
+ {
+ typedef std::multimap<int, double, transparent_less_not_referenceable> M;
+ M example;
+ assert(example.erase(C2Int{5}) == 0);
+ }
+ {
+ typedef std::multimap<int, double, transparent_less> M;
+ M example;
+ example.insert({ 5, 1. });
+ example.insert({ 6, 2. });
+ example.insert({ 4, 0. });
+ assert(example.size() == 3);
+ M::size_type erased = example.erase(C2Int{5});
+ assert(erased == 1);
+ assert(example.size() == 2);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran1.compile.fail.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran1.compile.fail.cpp
new file mode 100644
index 00000000000000..8933471c30c7a3
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran1.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multimap<int, double, transparent_less_no_type> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran2.compile.fail.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran2.compile.fail.cpp
new file mode 100644
index 00000000000000..2d0a51caf31413
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran2.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multimap<int, double, transparent_less_private> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran3.compile.fail.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran3.compile.fail.cpp
new file mode 100644
index 00000000000000..f0afe4797e9ca9
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran3.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multimap<int, double, transparent_less_not_a_type> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran4.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran4.pass.cpp
new file mode 100644
index 00000000000000..e3bc93f262f638
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran4.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::multimap<int, double, transparent_less> M;
+M example;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() {
+ return example.begin();
+ }
+};
+
+int main(int, char**)
+{
+ {
+ example.insert({ 2, 3. });
+ M::iterator erased = example.erase(Convertible());
+ assert(example.empty() && erased == example.end());
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran5.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran5.pass.cpp
new file mode 100644
index 00000000000000..c97389c79d43cb
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/erase_tran5.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::multimap<int, double, transparent_less> M;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() const {
+ assert(false);
+ }
+private:
+ operator M::const_iterator();
+};
+
+int main(int, char**)
+{
+ {
+ Convertible c;
+ M example;
+ example.insert({ 0, 1. });
+ M::size_type erased = example.erase(c);
+ assert(erased == 1);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran.pass.cpp
new file mode 100644
index 00000000000000..34f02a7acad60f
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multimap<int, double, transparent_less> M;
+ M example;
+ assert(example.extract(C2Int{5}).empty());
+ }
+ {
+ typedef std::multimap<int, double, transparent_less_not_referenceable> M;
+ M example;
+ assert(example.extract(C2Int{5}).empty());
+ }
+ {
+ typedef std::multimap<int, double, transparent_less> M;
+ M example;
+ example.insert({ 5, 1. });
+ example.insert({ 6, 2. });
+ example.insert({ 4, 0. });
+ assert(example.size() == 3);
+ M::node_type nh = example.extract(C2Int{5});
+ assert(nh && nh.key() == 5 && nh.mapped() == 1.);
+ assert(example.size() == 2);
+ example.insert(std::move(nh));
+ assert(example.size() == 3);
+ assert(example.find(5)->second == 1.);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran1.compile.fail.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran1.compile.fail.cpp
new file mode 100644
index 00000000000000..4ab69c5af8b7a0
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran1.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multimap<int, double, transparent_less_no_type> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran2.compile.fail.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran2.compile.fail.cpp
new file mode 100644
index 00000000000000..0a0ec1d84978ef
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran2.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multimap<int, double, transparent_less_private> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran3.compile.fail.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran3.compile.fail.cpp
new file mode 100644
index 00000000000000..57b38365209a16
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran3.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multimap<int, double, transparent_less_not_a_type> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran4.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran4.pass.cpp
new file mode 100644
index 00000000000000..c1fc7677779e91
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran4.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::multimap<int, double, transparent_less> M;
+M example;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() {
+ return example.begin();
+ }
+};
+
+int main(int, char**)
+{
+ {
+ example.insert({ 2, 3. });
+ M::node_type nh = example.extract(Convertible());
+ assert(nh && nh.key() == 2 && nh.mapped() == 3.);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran5.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran5.pass.cpp
new file mode 100644
index 00000000000000..d6a994f3c2762f
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.modifiers/extract_tran5.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <map>
+
+// class multimap
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <map>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::multimap<int, double, transparent_less> M;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() const {
+ assert(false);
+ }
+private:
+ operator M::const_iterator();
+};
+
+int main(int, char**)
+{
+ {
+ Convertible c;
+ M example;
+ example.insert({ 0, 1. });
+ M::node_type nh = example.extract(c);
+ assert(nh && nh.key() == 0 && nh.mapped() == 1.);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/erase_tran.pass.cpp b/libcxx/test/std/containers/associative/multiset/erase_tran.pass.cpp
new file mode 100644
index 00000000000000..224e890ecc529f
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/erase_tran.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multiset<int, transparent_less> M;
+ M example;
+ assert(example.erase(C2Int{5}) == 0);
+ }
+ {
+ typedef std::multiset<int, transparent_less_not_referenceable> M;
+ M example;
+ assert(example.erase(C2Int{5}) == 0);
+ }
+ {
+ typedef std::multiset<int, transparent_less> M;
+ M example;
+ example.insert(5);
+ example.insert(6);
+ example.insert(4);
+ assert(example.size() == 3);
+ M::size_type erased = example.erase(C2Int{5});
+ assert(erased == 1);
+ assert(example.size() == 2);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/associative/multiset/erase_tran1.compile.fail.cpp b/libcxx/test/std/containers/associative/multiset/erase_tran1.compile.fail.cpp
new file mode 100644
index 00000000000000..75c4379d745357
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/erase_tran1.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multiset<int, transparent_less_no_type> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/erase_tran2.compile.fail.cpp b/libcxx/test/std/containers/associative/multiset/erase_tran2.compile.fail.cpp
new file mode 100644
index 00000000000000..898c366032a1a2
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/erase_tran2.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multiset<int, transparent_less_private> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/erase_tran3.compile.fail.cpp b/libcxx/test/std/containers/associative/multiset/erase_tran3.compile.fail.cpp
new file mode 100644
index 00000000000000..17b4cf8f352b71
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/erase_tran3.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multiset<int, transparent_less_not_a_type> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/erase_tran4.pass.cpp b/libcxx/test/std/containers/associative/multiset/erase_tran4.pass.cpp
new file mode 100644
index 00000000000000..6798006f602451
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/erase_tran4.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::multiset<int, transparent_less> M;
+M example;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() {
+ return example.begin();
+ }
+};
+
+int main(int, char**)
+{
+ {
+ example.insert(2);
+ M::iterator erased = example.erase(Convertible());
+ assert(example.empty() && erased == example.end());
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/erase_tran5.pass.cpp b/libcxx/test/std/containers/associative/multiset/erase_tran5.pass.cpp
new file mode 100644
index 00000000000000..7dca3421f040a0
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/erase_tran5.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::multiset<int, transparent_less> M;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() const {
+ assert(false);
+ }
+private:
+ operator M::const_iterator();
+};
+
+int main(int, char**)
+{
+ {
+ Convertible c;
+ M example;
+ example.insert(0);
+ M::size_type erased = example.erase(c);
+ assert(erased == 1);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/extract_tran.pass.cpp b/libcxx/test/std/containers/associative/multiset/extract_tran.pass.cpp
new file mode 100644
index 00000000000000..c155d09bb948b7
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/extract_tran.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multiset<int, transparent_less> M;
+ M example;
+ assert(example.extract(C2Int{5}).empty());
+ }
+ {
+ typedef std::multiset<int, transparent_less_not_referenceable> M;
+ M example;
+ assert(example.extract(C2Int{5}).empty());
+ }
+ {
+ typedef std::multiset<int, transparent_less> M;
+ M example;
+ example.insert(5);
+ example.insert(6);
+ example.insert(4);
+ assert(example.size() == 3);
+ M::node_type nh = example.extract(C2Int{5});
+ assert(nh && nh.value() == 5);
+ assert(example.size() == 2);
+ example.insert(std::move(nh));
+ assert(example.size() == 3);
+ assert(*example.find(5) == 5);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/associative/multiset/extract_tran1.compile.fail.cpp b/libcxx/test/std/containers/associative/multiset/extract_tran1.compile.fail.cpp
new file mode 100644
index 00000000000000..b3d4f6473ac5fc
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/extract_tran1.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multiset<int, transparent_less_no_type> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/extract_tran2.compile.fail.cpp b/libcxx/test/std/containers/associative/multiset/extract_tran2.compile.fail.cpp
new file mode 100644
index 00000000000000..8fc73752ce970c
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/extract_tran2.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multiset<int, transparent_less_private> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/extract_tran3.compile.fail.cpp b/libcxx/test/std/containers/associative/multiset/extract_tran3.compile.fail.cpp
new file mode 100644
index 00000000000000..e9b4a6b499d880
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/extract_tran3.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::multiset<int, transparent_less_not_a_type> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/extract_tran4.pass.cpp b/libcxx/test/std/containers/associative/multiset/extract_tran4.pass.cpp
new file mode 100644
index 00000000000000..ec526ac4b8509b
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/extract_tran4.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::multiset<int, transparent_less> M;
+M example;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() {
+ return example.begin();
+ }
+};
+
+int main(int, char**)
+{
+ {
+ example.insert(2);
+ M::node_type nh = example.extract(Convertible());
+ assert(nh && nh.value() == 2);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/multiset/extract_tran5.pass.cpp b/libcxx/test/std/containers/associative/multiset/extract_tran5.pass.cpp
new file mode 100644
index 00000000000000..4049e28b5c3113
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/extract_tran5.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class multiset
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::multiset<int, transparent_less> M;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() const {
+ assert(false);
+ }
+private:
+ operator M::const_iterator();
+};
+
+int main(int, char**)
+{
+ {
+ Convertible c;
+ M example;
+ example.insert(0);
+ M::node_type nh = example.extract(c);
+ assert(nh && nh.value() == 0);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/erase_tran.pass.cpp b/libcxx/test/std/containers/associative/set/erase_tran.pass.cpp
new file mode 100644
index 00000000000000..41360c0c551d96
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/erase_tran.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::set<int, transparent_less> M;
+ M example;
+ assert(example.erase(C2Int{5}) == 0);
+ }
+ {
+ typedef std::set<int, transparent_less_not_referenceable> M;
+ M example;
+ assert(example.erase(C2Int{5}) == 0);
+ }
+ {
+ typedef std::set<int, transparent_less> M;
+ M example;
+ example.insert(5);
+ example.insert(6);
+ example.insert(4);
+ assert(example.size() == 3);
+ M::size_type erased = example.erase(C2Int{5});
+ assert(erased == 1);
+ assert(example.size() == 2);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/associative/set/erase_tran1.compile.fail.cpp b/libcxx/test/std/containers/associative/set/erase_tran1.compile.fail.cpp
new file mode 100644
index 00000000000000..b92e1528a1fb78
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/erase_tran1.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::set<int, transparent_less_no_type> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/erase_tran2.compile.fail.cpp b/libcxx/test/std/containers/associative/set/erase_tran2.compile.fail.cpp
new file mode 100644
index 00000000000000..47ee54c9497178
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/erase_tran2.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::set<int, transparent_less_private> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/erase_tran3.compile.fail.cpp b/libcxx/test/std/containers/associative/set/erase_tran3.compile.fail.cpp
new file mode 100644
index 00000000000000..f82f962792fade
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/erase_tran3.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::set<int, transparent_less_not_a_type> M;
+
+ TEST_IGNORE_NODISCARD M().erase(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/erase_tran4.pass.cpp b/libcxx/test/std/containers/associative/set/erase_tran4.pass.cpp
new file mode 100644
index 00000000000000..75985fd660a21e
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/erase_tran4.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::set<int, transparent_less> M;
+M example;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() {
+ return example.begin();
+ }
+};
+
+int main(int, char**)
+{
+ {
+ example.insert(2);
+ M::iterator erased = example.erase(Convertible());
+ assert(example.empty() && erased == example.end());
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/erase_tran5.pass.cpp b/libcxx/test/std/containers/associative/set/erase_tran5.pass.cpp
new file mode 100644
index 00000000000000..f27038d662aa74
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/erase_tran5.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// size_type erase(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::set<int, transparent_less> M;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() const {
+ assert(false);
+ }
+private:
+ operator M::const_iterator();
+};
+
+int main(int, char**)
+{
+ {
+ Convertible c;
+ M example;
+ example.insert(0);
+ M::size_type erased = example.erase(c);
+ assert(erased == 1);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/extract_tran.pass.cpp b/libcxx/test/std/containers/associative/set/extract_tran.pass.cpp
new file mode 100644
index 00000000000000..7a71b95969ec37
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/extract_tran.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::set<int, transparent_less> M;
+ M example;
+ assert(example.extract(C2Int{5}).empty());
+ }
+ {
+ typedef std::set<int, transparent_less_not_referenceable> M;
+ M example;
+ assert(example.extract(C2Int{5}).empty());
+ }
+ {
+ typedef std::set<int, transparent_less> M;
+ M example;
+ example.insert(5);
+ example.insert(6);
+ example.insert(4);
+ assert(example.size() == 3);
+ M::node_type nh = example.extract(C2Int{5});
+ assert(nh && nh.value() == 5);
+ assert(example.size() == 2);
+ example.insert(std::move(nh));
+ assert(example.size() == 3);
+ assert(*example.find(5) == 5);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/associative/set/extract_tran1.compile.fail.cpp b/libcxx/test/std/containers/associative/set/extract_tran1.compile.fail.cpp
new file mode 100644
index 00000000000000..1607027aab059a
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/extract_tran1.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::set<int, transparent_less_no_type> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/extract_tran2.compile.fail.cpp b/libcxx/test/std/containers/associative/set/extract_tran2.compile.fail.cpp
new file mode 100644
index 00000000000000..44f80c0576b63d
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/extract_tran2.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::set<int, transparent_less_private> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/extract_tran3.compile.fail.cpp b/libcxx/test/std/containers/associative/set/extract_tran3.compile.fail.cpp
new file mode 100644
index 00000000000000..cf8a167163d0ff
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/extract_tran3.compile.fail.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+int main(int, char**)
+{
+ {
+ typedef std::set<int, transparent_less_not_a_type> M;
+
+ TEST_IGNORE_NODISCARD M().extract(C2Int{5});
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/extract_tran4.pass.cpp b/libcxx/test/std/containers/associative/set/extract_tran4.pass.cpp
new file mode 100644
index 00000000000000..09131308bc46de
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/extract_tran4.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::set<int, transparent_less> M;
+M example;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() {
+ return example.begin();
+ }
+};
+
+int main(int, char**)
+{
+ {
+ example.insert(2);
+ M::node_type nh = example.extract(Convertible());
+ assert(nh && nh.value() == 2);
+ }
+}
diff --git a/libcxx/test/std/containers/associative/set/extract_tran5.pass.cpp b/libcxx/test/std/containers/associative/set/extract_tran5.pass.cpp
new file mode 100644
index 00000000000000..e5eefcc0501b5d
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/extract_tran5.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: c++03, c++11, c++14, c++17, c++20
+
+// <set>
+
+// class set
+
+// template<class K>
+// node_type extract(K&& x);
+//
+// The member function templates find, count, lower_bound, upper_bound,
+// equal_range, erase, and extract shall not participate in overload resolution
+// unless the qualified-id Compare::is_transparent is valid and denotes a type.
+// Additionally, the member function templates erase and extract shall not
+// participate in overload resolution if is_convertible_v<K&&, iterator> ||
+// is_convertible_v<K&&, const_iterator> is true, where K is the type
+// substituted as the first template argument
+
+
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "is_transparent.h"
+
+typedef std::set<int, transparent_less> M;
+
+struct Convertible : C2Int {
+ operator M::const_iterator() const {
+ assert(false);
+ }
+private:
+ operator M::const_iterator();
+};
+
+int main(int, char**)
+{
+ {
+ Convertible c;
+ M example;
+ example.insert(0);
+ M::node_type nh = example.extract(c);
+ assert(nh && nh.value() == 0);
+ }
+}
More information about the libcxx-commits
mailing list