[libcxx-commits] [libcxx] [libc++] Add __is_transparently_comparable_v optimizations for set and multiset [Issue 187105] (PR #189735)
Michael Levine via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Apr 9 21:58:09 PDT 2026
https://github.com/levinem updated https://github.com/llvm/llvm-project/pull/189735
>From 508f88ced34aa636b9bf3ee66ec71d5f984e4f20 Mon Sep 17 00:00:00 2001
From: mlevine55 <mlevine55 at bloomberg.net>
Date: Thu, 26 Mar 2026 12:11:29 -0400
Subject: [PATCH 1/3] added __is_transparently_comparable_v optimizations for
multimap and for some map functions
Signed-off-by: mlevine55 <mlevine55 at bloomberg.net>
---
libcxx/include/map | 52 ++++--
...kup_with_transparently_comparable.pass.cpp | 150 ++++++++++++++++++
2 files changed, 189 insertions(+), 13 deletions(-)
create mode 100644 libcxx/test/libcxx/containers/associative/lookup_with_transparently_comparable.pass.cpp
diff --git a/libcxx/include/map b/libcxx/include/map
index b7031aeb51c7a..09db3982db526 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -1331,7 +1331,9 @@ public:
return __tree_.__count_unique(__k);
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
return __tree_.__count_multi(__k);
}
@@ -1403,11 +1405,15 @@ public:
return __tree_.__equal_range_unique(__k);
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
return __tree_.__equal_range_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
return __tree_.__equal_range_multi(__k);
}
@@ -1917,11 +1923,15 @@ public:
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
return __tree_.find(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
return __tree_.find(__k);
}
@@ -1931,7 +1941,9 @@ public:
return __tree_.__count_multi(__k);
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
return __tree_.__count_multi(__k);
}
@@ -1939,7 +1951,9 @@ public:
# if _LIBCPP_STD_VER >= 20
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
return find(__k) != end();
}
@@ -1954,12 +1968,16 @@ public:
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
return __tree_.__lower_bound_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
return __tree_.__lower_bound_multi(__k);
}
@@ -1974,11 +1992,15 @@ public:
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
return __tree_.__upper_bound_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
return __tree_.__upper_bound_multi(__k);
}
@@ -1991,11 +2013,15 @@ public:
return __tree_.__equal_range_multi(__k);
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
return __tree_.__equal_range_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
return __tree_.__equal_range_multi(__k);
}
diff --git a/libcxx/test/libcxx/containers/associative/lookup_with_transparently_comparable.pass.cpp b/libcxx/test/libcxx/containers/associative/lookup_with_transparently_comparable.pass.cpp
new file mode 100644
index 0000000000000..24bba0b571633
--- /dev/null
+++ b/libcxx/test/libcxx/containers/associative/lookup_with_transparently_comparable.pass.cpp
@@ -0,0 +1,150 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// Make sure that lookup operations on ordered associative containers are
+// transparent when they can, even when not using a comparator that advertises
+// itself as transparent (e.g. std::less<>). This is a libc++ QoI extension.
+//
+// At the moment, we only implement this optimization when the key stored in
+// the container is std::string, so the tests are written with that assumption.
+
+#include <cassert>
+#include <functional>
+#include <map>
+#include <set>
+#include <string>
+
+#include "count_new.h"
+#include "test_macros.h"
+
+template <class Container>
+void test() {
+ // Use a string longer than the SSO so that construction must allocate.
+ const char* key = "long-string-to-exceed-SSO-buffer";
+
+ // find
+ {
+ Container c;
+ globalMemCounter.reset();
+ (void)c.find(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+ {
+ Container const c;
+ globalMemCounter.reset();
+ (void)c.find(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+
+ // count
+ {
+ Container c;
+ globalMemCounter.reset();
+ (void)c.count(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+ {
+ Container const c;
+ globalMemCounter.reset();
+ (void)c.count(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+
+#if TEST_STD_VER >= 20
+ // contains
+ {
+ Container c;
+ globalMemCounter.reset();
+ (void)c.contains(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+ {
+ Container const c;
+ globalMemCounter.reset();
+ (void)c.contains(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+#endif
+
+ // lower_bound
+ {
+ Container c;
+ globalMemCounter.reset();
+ (void)c.lower_bound(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+ {
+ Container const c;
+ globalMemCounter.reset();
+ (void)c.lower_bound(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+
+ // upper_bound
+ {
+ Container c;
+ globalMemCounter.reset();
+ (void)c.upper_bound(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+ {
+ Container const c;
+ globalMemCounter.reset();
+ (void)c.upper_bound(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+
+ // equal_range
+ {
+ Container c;
+ globalMemCounter.reset();
+ (void)c.equal_range(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+ {
+ Container const c;
+ globalMemCounter.reset();
+ (void)c.equal_range(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+}
+
+int main(int, char**) {
+ test<std::map<std::string, int>>();
+ test<std::multimap<std::string, int>>();
+ // TODO: Implement the optimization for set and multiset
+ // test<std::set<std::string>>();
+ // test<std::multiset<std::string>>();
+
+ test<std::map<std::string, int, std::greater<std::string>>>();
+ test<std::multimap<std::string, int, std::greater<std::string>>>();
+ // test<std::set<std::string, std::greater<std::string>>>();
+ // test<std::multiset<std::string, std::greater<std::string>>>();
+
+ {
+ // std::map only: map::at
+ std::map<std::string, int> c;
+ char const* key = "long-string-to-exceed-SSO-buffer";
+ c[key] = 1;
+ {
+ globalMemCounter.reset();
+ (void)c.at(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+ {
+ const std::map<std::string, int>& cc = c;
+ globalMemCounter.reset();
+ (void)cc.at(key);
+ assert(globalMemCounter.checkNewCalledEq(0));
+ }
+ }
+
+ return 0;
+}
>From 7c98d24204f4e9ab78495459b5cdcc5962264d25 Mon Sep 17 00:00:00 2001
From: mlevine55 <mlevine55 at bloomberg.net>
Date: Thu, 26 Mar 2026 13:23:14 -0400
Subject: [PATCH 2/3] copy of a different pr's test setup that can be expanded
in that test file directly
Signed-off-by: mlevine55 <mlevine55 at bloomberg.net>
---
...kup_with_transparently_comparable.pass.cpp | 150 ------------------
1 file changed, 150 deletions(-)
delete mode 100644 libcxx/test/libcxx/containers/associative/lookup_with_transparently_comparable.pass.cpp
diff --git a/libcxx/test/libcxx/containers/associative/lookup_with_transparently_comparable.pass.cpp b/libcxx/test/libcxx/containers/associative/lookup_with_transparently_comparable.pass.cpp
deleted file mode 100644
index 24bba0b571633..0000000000000
--- a/libcxx/test/libcxx/containers/associative/lookup_with_transparently_comparable.pass.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// Make sure that lookup operations on ordered associative containers are
-// transparent when they can, even when not using a comparator that advertises
-// itself as transparent (e.g. std::less<>). This is a libc++ QoI extension.
-//
-// At the moment, we only implement this optimization when the key stored in
-// the container is std::string, so the tests are written with that assumption.
-
-#include <cassert>
-#include <functional>
-#include <map>
-#include <set>
-#include <string>
-
-#include "count_new.h"
-#include "test_macros.h"
-
-template <class Container>
-void test() {
- // Use a string longer than the SSO so that construction must allocate.
- const char* key = "long-string-to-exceed-SSO-buffer";
-
- // find
- {
- Container c;
- globalMemCounter.reset();
- (void)c.find(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
- {
- Container const c;
- globalMemCounter.reset();
- (void)c.find(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
-
- // count
- {
- Container c;
- globalMemCounter.reset();
- (void)c.count(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
- {
- Container const c;
- globalMemCounter.reset();
- (void)c.count(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
-
-#if TEST_STD_VER >= 20
- // contains
- {
- Container c;
- globalMemCounter.reset();
- (void)c.contains(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
- {
- Container const c;
- globalMemCounter.reset();
- (void)c.contains(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
-#endif
-
- // lower_bound
- {
- Container c;
- globalMemCounter.reset();
- (void)c.lower_bound(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
- {
- Container const c;
- globalMemCounter.reset();
- (void)c.lower_bound(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
-
- // upper_bound
- {
- Container c;
- globalMemCounter.reset();
- (void)c.upper_bound(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
- {
- Container const c;
- globalMemCounter.reset();
- (void)c.upper_bound(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
-
- // equal_range
- {
- Container c;
- globalMemCounter.reset();
- (void)c.equal_range(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
- {
- Container const c;
- globalMemCounter.reset();
- (void)c.equal_range(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
-}
-
-int main(int, char**) {
- test<std::map<std::string, int>>();
- test<std::multimap<std::string, int>>();
- // TODO: Implement the optimization for set and multiset
- // test<std::set<std::string>>();
- // test<std::multiset<std::string>>();
-
- test<std::map<std::string, int, std::greater<std::string>>>();
- test<std::multimap<std::string, int, std::greater<std::string>>>();
- // test<std::set<std::string, std::greater<std::string>>>();
- // test<std::multiset<std::string, std::greater<std::string>>>();
-
- {
- // std::map only: map::at
- std::map<std::string, int> c;
- char const* key = "long-string-to-exceed-SSO-buffer";
- c[key] = 1;
- {
- globalMemCounter.reset();
- (void)c.at(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
- {
- const std::map<std::string, int>& cc = c;
- globalMemCounter.reset();
- (void)cc.at(key);
- assert(globalMemCounter.checkNewCalledEq(0));
- }
- }
-
- return 0;
-}
>From 1fdca3169109098032e24a1ab3e7991ffaf896c1 Mon Sep 17 00:00:00 2001
From: mlevine55 <mlevine55 at bloomberg.net>
Date: Tue, 31 Mar 2026 14:31:47 -0400
Subject: [PATCH 3/3] set and multiset optimizations
Signed-off-by: mlevine55 <mlevine55 at bloomberg.net>
---
libcxx/include/set | 80 ++++++++++++++++++++++++++++++++++------------
1 file changed, 60 insertions(+), 20 deletions(-)
diff --git a/libcxx/include/set b/libcxx/include/set
index 695b6c87e3984..ff1de085c1d8b 100644
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -825,11 +825,15 @@ public:
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
return __tree_.find(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
return __tree_.find(__k);
}
@@ -839,7 +843,9 @@ public:
return __tree_.__count_unique(__k);
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
return __tree_.__count_multi(__k);
}
@@ -847,7 +853,9 @@ public:
# if _LIBCPP_STD_VER >= 20
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
return find(__k) != end();
}
@@ -864,12 +872,16 @@ public:
// The transparent versions of the lookup functions use the _multi version, since a non-element key is allowed to
// match multiple elements.
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
return __tree_.__lower_bound_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
return __tree_.__lower_bound_multi(__k);
}
@@ -884,11 +896,15 @@ public:
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
return __tree_.__upper_bound_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
return __tree_.__upper_bound_multi(__k);
}
@@ -901,11 +917,15 @@ public:
return __tree_.__equal_range_unique(__k);
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
return __tree_.__equal_range_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
return __tree_.__equal_range_multi(__k);
}
@@ -1302,11 +1322,15 @@ public:
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
return __tree_.find(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
return __tree_.find(__k);
}
@@ -1316,7 +1340,9 @@ public:
return __tree_.__count_multi(__k);
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
return __tree_.__count_multi(__k);
}
@@ -1324,7 +1350,9 @@ public:
# if _LIBCPP_STD_VER >= 20
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
return find(__k) != end();
}
@@ -1339,12 +1367,16 @@ public:
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
return __tree_.__lower_bound_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
return __tree_.__lower_bound_multi(__k);
}
@@ -1359,11 +1391,15 @@ public:
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
return __tree_.__upper_bound_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
return __tree_.__upper_bound_multi(__k);
}
@@ -1376,11 +1412,15 @@ public:
return __tree_.__equal_range_multi(__k);
}
# if _LIBCPP_STD_VER >= 14
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
return __tree_.__equal_range_multi(__k);
}
- template <typename _K2, class _Comp = _Compare, enable_if_t<__is_transparent_v<_Comp>, int> = 0>
+ template <typename _K2,
+ class _Comp = _Compare,
+ enable_if_t<__is_transparent_v<_Comp> || __is_transparently_comparable_v<_Comp, key_type, _K2>, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
return __tree_.__equal_range_multi(__k);
}
More information about the libcxx-commits
mailing list