mirror of
https://github.com/intel/llvm.git
synced 2026-02-08 08:57:43 +08:00
[libc++] Fix ranges::binary_search() returning true for cases where the element is not in the range
Fixes #61160 Reviewed By: ldionne, #libc Spies: libcxx-commits Differential Revision: https://reviews.llvm.org/D145287
This commit is contained in:
@@ -36,7 +36,7 @@ struct __fn {
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
|
||||
bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj);
|
||||
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first));
|
||||
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret));
|
||||
}
|
||||
|
||||
template <forward_range _Range, class _Type, class _Proj = identity,
|
||||
@@ -46,7 +46,7 @@ struct __fn {
|
||||
auto __first = ranges::begin(__r);
|
||||
auto __last = ranges::end(__r);
|
||||
auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj);
|
||||
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first));
|
||||
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret));
|
||||
}
|
||||
};
|
||||
} // namespace __binary_search
|
||||
|
||||
@@ -131,6 +131,13 @@ constexpr void test_iterators() {
|
||||
auto range = std::ranges::subrange(It(a), Sent(It(a + 5)));
|
||||
assert(std::ranges::binary_search(range, 1));
|
||||
}
|
||||
|
||||
{ // check that false is returned when the element doesn't exist, but an element with a greater value is in the range
|
||||
int a[] = {1, 2, 4};
|
||||
assert(!std::ranges::binary_search(It(a), Sent(It(a + 3)), 3));
|
||||
auto range = std::ranges::subrange(It(a), Sent(It(a + 3)));
|
||||
assert(!std::ranges::binary_search(range, 3));
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
|
||||
@@ -194,6 +194,22 @@ constexpr void test_iterators() {
|
||||
assert(base(ret) == a);
|
||||
}
|
||||
}
|
||||
|
||||
{ // check that the middle of a range is returned when there are smaller and larger elements
|
||||
{
|
||||
int a[] = {1, 2, 3, 4, 6, 7, 8};
|
||||
auto ret = std::ranges::lower_bound(It(a), It(a + 7), 5);
|
||||
assert(base(ret) == a + 4);
|
||||
assert(*ret == 6);
|
||||
}
|
||||
{
|
||||
int a[] = {1, 2, 3, 4, 6, 7, 8};
|
||||
auto range = std::ranges::subrange(It(a), It(a + 7));
|
||||
auto ret = std::ranges::lower_bound(range, 5);
|
||||
assert(base(ret) == a + 4);
|
||||
assert(*ret == 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
|
||||
@@ -193,6 +193,22 @@ constexpr void test_iterators() {
|
||||
assert(base(ret) == a + 1);
|
||||
}
|
||||
}
|
||||
|
||||
{ // check that the middle of a range is returned when there are smaller and larger elements
|
||||
{
|
||||
int a[] = {1, 2, 3, 4, 6, 7, 8};
|
||||
auto ret = std::ranges::upper_bound(It(a), It(a + 7), 5);
|
||||
assert(base(ret) == a + 4);
|
||||
assert(*ret == 6);
|
||||
}
|
||||
{
|
||||
int a[] = {1, 2, 3, 4, 6, 7, 8};
|
||||
auto range = std::ranges::subrange(It(a), It(a + 7));
|
||||
auto ret = std::ranges::upper_bound(range, 5);
|
||||
assert(base(ret) == a + 4);
|
||||
assert(*ret == 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
|
||||
Reference in New Issue
Block a user