[libcxx-commits] [libcxx] [libc++] Make sure `flat_{multi}map::key_compare` handle `boolean-testable` correctly (PR #132621)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jun 7 12:26:50 PDT 2025


https://github.com/huixie90 updated https://github.com/llvm/llvm-project/pull/132621

>From e0f56c01092be3319f73d076e484640feb8dd22c Mon Sep 17 00:00:00 2001
From: Hewill Kang <hewillk at gmail.com>
Date: Mon, 24 Mar 2025 01:09:36 +0800
Subject: [PATCH 1/4] [libc++] Make sure compare handle boolean-testable
 correctly

---
 libcxx/include/__flat_map/flat_map.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h
index a0594ed9dc411..2f32497ab20d3 100644
--- a/libcxx/include/__flat_map/flat_map.h
+++ b/libcxx/include/__flat_map/flat_map.h
@@ -846,7 +846,7 @@ class flat_map {
         __compare_(std::forward<_CompArg>(__comp)...) {}
 
   _LIBCPP_HIDE_FROM_ABI bool __is_sorted_and_unique(auto&& __key_container) const {
-    auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) { return !__compare_(__x, __y); };
+    auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) -> bool { return !__compare_(__x, __y); };
     return ranges::adjacent_find(__key_container, __greater_or_equal_to) == ranges::end(__key_container);
   }
 
@@ -870,7 +870,7 @@ class flat_map {
       auto __zv                  = ranges::views::zip(__containers_.keys, __containers_.values);
       auto __append_start_offset = __containers_.keys.size() - __num_of_appended;
       auto __end                 = __zv.end();
-      auto __compare_key         = [this](const auto& __p1, const auto& __p2) {
+      auto __compare_key         = [this](const auto& __p1, const auto& __p2) -> bool {
         return __compare_(std::get<0>(__p1), std::get<0>(__p2));
       };
       if constexpr (!_WasSorted) {

>From 436ae2ed9977bf87c4e5b5b04cc13477416f20db Mon Sep 17 00:00:00 2001
From: Hewill Kang <hewillk at gmail.com>
Date: Mon, 24 Mar 2025 01:17:57 +0800
Subject: [PATCH 2/4] [libc++] Make sure compare handle boolean-testable
 correctly

---
 libcxx/include/__flat_map/flat_multimap.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__flat_map/flat_multimap.h b/libcxx/include/__flat_map/flat_multimap.h
index ea77fb5d79bd2..664dc0eed1bb6 100644
--- a/libcxx/include/__flat_map/flat_multimap.h
+++ b/libcxx/include/__flat_map/flat_multimap.h
@@ -777,7 +777,7 @@ class flat_multimap {
       auto __zv                  = ranges::views::zip(__containers_.keys, __containers_.values);
       auto __append_start_offset = __containers_.keys.size() - __num_appended;
       auto __end                 = __zv.end();
-      auto __compare_key         = [this](const auto& __p1, const auto& __p2) {
+      auto __compare_key         = [this](const auto& __p1, const auto& __p2) -> bool {
         return __compare_(std::get<0>(__p1), std::get<0>(__p2));
       };
       if constexpr (!_WasSorted) {

>From 393d9e6b6a85378523983cd33cb052dc0414080f Mon Sep 17 00:00:00 2001
From: Hui Xie <hui.xie1990 at gmail.com>
Date: Sat, 17 May 2025 08:16:20 +0100
Subject: [PATCH 3/4] Added Unit Tests

---
 .../robust_against_nonbool.compile.pass.cpp   | 50 +++++++++++++++++++
 .../robust_against_nonbool.compile.pass.cpp   | 46 +++++++++++++++++
 2 files changed, 96 insertions(+)
 create mode 100644 libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp

diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp
new file mode 100644
index 0000000000000..905efe1bdb4ea
--- /dev/null
+++ b/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <flat_map>
+//
+// flat_map should support comparator that return a non-boolean
+// value as long as the returned type is implicitly convertible to bool.
+
+#include <flat_map>
+#include <ranges>
+
+#include "boolean_testable.h"
+
+void test() {
+  using Key   = StrictComparable<int>;
+  using Value = StrictComparable<int>;
+  std::flat_map<Key, Value> m1;
+  std::flat_map m2(std::from_range, m1, StrictBinaryPredicate);
+  std::flat_map m3(std::sorted_unique, m1.keys(), m1.values(), StrictBinaryPredicate);
+  std::flat_map m4(m1.begin(), m1.end(), StrictBinaryPredicate);
+  m2.insert(m1.begin(), m1.end());
+  m2.insert(std::sorted_unique, m1.begin(), m1.end());
+  m2.insert_range(m1);
+  (void)m2.at(2);
+  m3[1] = 2;
+  m3.insert_or_assign(1, 2);
+  m4.try_emplace(1, 2);
+  m2.emplace(1, 2);
+  m2.emplace_hint(m2.begin(), 1, 2);
+  for (const auto& [k, v] : m2) {
+    (void)k;
+    (void)v;
+  }
+  (void)m2.find(Key{1});
+  (void)m2.equal_range(Key{1});
+  (void)(m2 == m2);
+  m2.erase(m2.begin());
+  m2.erase(m2.begin(), m2.end());
+  std::erase_if(
+      m2, []<class T>(std::pair<const StrictComparable<T>&, const StrictComparable<T>&>) -> BooleanTestable const& {
+        return yes;
+      });
+}
diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp
new file mode 100644
index 0000000000000..96f83568b5aa9
--- /dev/null
+++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <flat_map>
+//
+// flat_multimap should support comparator that return a non-boolean
+// value as long as the returned type is implicitly convertible to bool.
+
+#include <flat_map>
+#include <ranges>
+
+#include "boolean_testable.h"
+
+void test() {
+  using Key   = StrictComparable<int>;
+  using Value = StrictComparable<int>;
+  std::flat_multimap<Key, Value> m1;
+  std::flat_multimap m2(std::from_range, m1, StrictBinaryPredicate);
+  std::flat_multimap m3(std::sorted_equivalent, m1.keys(), m1.values(), StrictBinaryPredicate);
+  std::flat_multimap m4(m1.begin(), m1.end(), StrictBinaryPredicate);
+  m2.insert(m1.begin(), m1.end());
+  m2.insert(std::sorted_equivalent, m1.begin(), m1.end());
+  m2.insert_range(m1);
+  m2.emplace(1, 2);
+  m2.emplace_hint(m2.begin(), 1, 2);
+  for (const auto& [k, v] : m2) {
+    (void)k;
+    (void)v;
+  }
+  (void)m2.find(Key{1});
+  (void)m2.equal_range(Key{1});
+  (void)(m2 == m2);
+  m2.erase(m2.begin());
+  m2.erase(m2.begin(), m2.end());
+  std::erase_if(
+      m2, []<class T>(std::pair<const StrictComparable<T>&, const StrictComparable<T>&>) -> BooleanTestable const& {
+        return yes;
+      });
+}

>From 986530c2595f1e6f6c5d3f50c623ec6deff1fead Mon Sep 17 00:00:00 2001
From: Hui Xie <hui.xie1990 at gmail.com>
Date: Sat, 17 May 2025 11:48:38 +0100
Subject: [PATCH 4/4] CI

---
 .../flat.map/robust_against_nonbool.compile.pass.cpp             | 1 +
 .../flat.multimap/robust_against_nonbool.compile.pass.cpp        | 1 +
 2 files changed, 2 insertions(+)

diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp
index 905efe1bdb4ea..8b9e631bcdaff 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp
@@ -14,6 +14,7 @@
 // value as long as the returned type is implicitly convertible to bool.
 
 #include <flat_map>
+#include <vector>
 #include <ranges>
 
 #include "boolean_testable.h"
diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp
index 96f83568b5aa9..e4be75d83c50c 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp
@@ -15,6 +15,7 @@
 
 #include <flat_map>
 #include <ranges>
+#include <vector>
 
 #include "boolean_testable.h"
 



More information about the libcxx-commits mailing list