[libc++] Make sure flat_set::key_compare handle boolean-testable correctly (#132622)

Also add test for `flat_multiset` to avoid regression.

---------

Co-authored-by: Hui Xie <hui.xie1990@gmail.com>
Co-authored-by: A. Jiang <de34@live.cn>
This commit is contained in:
Hewill Kang 2026-01-03 22:50:45 +08:00 committed by GitHub
parent 8663c306e9
commit 19358ca38c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 89 additions and 1 deletions

View File

@ -679,7 +679,7 @@ public:
private:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 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);
}

View File

@ -0,0 +1,44 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++23
// <flat_set>
//
// flat_multiset should support comparator that return a non-boolean value
// as long as the returned type is implicitly convertible to bool.
#include <flat_set>
#include <vector>
#include <ranges>
#include "boolean_testable.h"
void test() {
using Key = StrictComparable<int>;
std::vector<Key> v;
std::flat_multiset<Key> m1;
std::flat_multiset m2(std::from_range, v, StrictBinaryPredicate);
std::flat_multiset m3(std::sorted_equivalent, v, StrictBinaryPredicate);
std::flat_multiset 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);
m3.insert(1);
m2.emplace(1);
m2.emplace_hint(m2.begin(), 1);
for (const auto& k : m2) {
(void)k;
}
(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>(const StrictComparable<T>&) -> const BooleanTestable& { return yes; });
}

View File

@ -0,0 +1,44 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++23
// <flat_set>
//
// flat_set should support comparator that return a non-boolean
// value as long as the returned type is implicitly convertible to bool.
#include <flat_set>
#include <vector>
#include <ranges>
#include "boolean_testable.h"
void test() {
using Key = StrictComparable<int>;
std::vector<Key> v;
std::flat_set<Key> m1;
std::flat_set m2(std::from_range, v, StrictBinaryPredicate);
std::flat_set m3(std::sorted_unique, v, StrictBinaryPredicate);
std::flat_set 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);
m3.insert(1);
m2.emplace(1);
m2.emplace_hint(m2.begin(), 1);
for (const auto& k : m2) {
(void)k;
}
(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>(const StrictComparable<T>&) -> BooleanTestable const& { return yes; });
}