[libcxx-commits] [libcxx] [libcxx] patch for implementing ranges::find_last (PR #67270)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Sep 24 12:04:03 PDT 2023
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff 68765143c6765a694d40d4c3fea43893cc025433 392dff0b9d134233e2fe1807fd27133b682822d1 -- libcxx/include/__algorithm/ranges_find_last.h libcxx/include/__algorithm/ranges_find_last_if.h libcxx/include/__algorithm/ranges_find_last_if_not.h libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last.pass.cpp libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if.pass.cpp libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if_not.pass.cpp libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp libcxx/test/libcxx/diagnostics/ranges.nodiscard_extensions.verify.cpp libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp libcxx/test/std/library/description/conventions/customization.point.object/niebloid.compile.pass.cpp libcxx/test/support/almost_satisfies_types.h
``````````
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/libcxx/include/__algorithm/ranges_find_last.h b/libcxx/include/__algorithm/ranges_find_last.h
index 81c2caef413b..80baa6eaea4f 100644
--- a/libcxx/include/__algorithm/ranges_find_last.h
+++ b/libcxx/include/__algorithm/ranges_find_last.h
@@ -12,8 +12,8 @@
#include <__algorithm/ranges_find_last_if.h>
#include <__config>
#include <__functional/identity.h>
-#include <__iterator/concepts.h>
#include <__functional/ranges_operations.h>
+#include <__iterator/concepts.h>
#include <__iterator/projected.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
@@ -33,17 +33,17 @@ namespace ranges {
namespace __find_last {
struct __fn {
template <forward_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, class _Proj = identity>
- requires indirect_binary_predicate <ranges::equal_to, projected<_Ip, _Proj>, const _Tp*>
+ requires indirect_binary_predicate<ranges::equal_to, projected<_Ip, _Proj>, const _Tp*>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Ip>
- operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const {
+ operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const {
auto __pred = [&](auto&& __e) { return std::forward<decltype(__e)>(__e) == __value; };
return ranges::__find_last_if_impl(std::move(__first), std::move(__last), __pred, __proj);
}
template <forward_range _Rp, class _Tp, class _Proj = identity>
- requires indirect_binary_predicate <ranges::equal_to, projected<iterator_t<_Rp>, _Proj>, const _Tp*>
+ requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Rp>, _Proj>, const _Tp*>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Rp>
- operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const {
+ operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const {
auto __pred = [&](auto&& __e) { return std::forward<decltype(__e)>(__e) == __value; };
return ranges::__find_last_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj);
}
diff --git a/libcxx/include/__algorithm/ranges_find_last_if_not.h b/libcxx/include/__algorithm/ranges_find_last_if_not.h
index e1b29d8f4870..042812e7fe16 100644
--- a/libcxx/include/__algorithm/ranges_find_last_if_not.h
+++ b/libcxx/include/__algorithm/ranges_find_last_if_not.h
@@ -34,13 +34,13 @@ namespace __find_last_if_not {
struct __fn {
static constexpr auto __make_negate_pred = [](auto&& __pred) {
return [&__pred](auto&& __e) { return !std::invoke(__pred, std::forward<decltype(__e)>(__e)); };
-};
+ };
template <forward_iterator _Ip,
sentinel_for<_Ip> _Sp,
class _Proj = identity,
indirect_unary_predicate<projected<_Ip, _Proj>> _Pred>
- _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Ip>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Ip>
operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const {
auto __negate_pred = __make_negate_pred(__pred);
return ranges::__find_last_if_impl(std::move(__first), std::move(__last), __negate_pred, __proj);
@@ -49,7 +49,7 @@ struct __fn {
template <forward_range _Rp,
class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Rp>, _Proj>> _Pred>
- _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Rp>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Rp>
operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const {
auto __negate_pred = __make_negate_pred(__pred);
return ranges::__find_last_if_impl(ranges::begin(__r), ranges::end(__r), __negate_pred, __proj);
diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp
index 85d5ba35d818..e76c2494238c 100644
--- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp
+++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp
@@ -118,10 +118,16 @@ constexpr bool all_the_algorithms()
(void)std::ranges::find_if(a, UnaryTrue(&copies)); assert(copies == 0);
(void)std::ranges::find_if_not(first, last, UnaryTrue(&copies)); assert(copies == 0);
(void)std::ranges::find_if_not(a, UnaryTrue(&copies)); assert(copies == 0);
- (void)std::ranges::find_last_if(first, last, UnaryTrue(&copies)); assert(copies == 1); copies = 0;
- (void)std::ranges::find_last_if(a, UnaryTrue(&copies)); assert(copies == 1); copies = 0;
- (void)std::ranges::find_last_if_not(first, last, UnaryTrue(&copies)); assert(copies == 0);
- (void)std::ranges::find_last_if_not(a, UnaryTrue(&copies)); assert(copies == 0);
+ (void)std::ranges::find_last_if(first, last, UnaryTrue(&copies));
+ assert(copies == 1);
+ copies = 0;
+ (void)std::ranges::find_last_if(a, UnaryTrue(&copies));
+ assert(copies == 1);
+ copies = 0;
+ (void)std::ranges::find_last_if_not(first, last, UnaryTrue(&copies));
+ assert(copies == 0);
+ (void)std::ranges::find_last_if_not(a, UnaryTrue(&copies));
+ assert(copies == 0);
(void)std::ranges::for_each(first, last, UnaryVoid(&copies)); assert(copies == 1); copies = 0;
(void)std::ranges::for_each(a, UnaryVoid(&copies)); assert(copies == 1); copies = 0;
(void)std::ranges::for_each_n(first, count, UnaryVoid(&copies)); assert(copies == 1); copies = 0;
diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
index d3939881ab21..acac23972b63 100644
--- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
+++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
@@ -104,12 +104,24 @@ constexpr bool all_the_algorithms()
(void)std::ranges::find_if(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::find_if_not(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::find_if_not(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
- (void)std::ranges::find_last(first, last, value, Proj(&copies)); assert(copies == 1); copies = 0;
- (void)std::ranges::find_last(a, value, Proj(&copies)); assert(copies == 1); copies = 0;
- (void)std::ranges::find_last_if(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 1); copies = 0;
- (void)std::ranges::find_last_if(a, UnaryTrue(), Proj(&copies)); assert(copies == 1); copies = 0;
- (void)std::ranges::find_last_if_not(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 1); copies = 0;
- (void)std::ranges::find_last_if_not(a, UnaryTrue(), Proj(&copies)); assert(copies == 1); copies = 0;
+ (void)std::ranges::find_last(first, last, value, Proj(&copies));
+ assert(copies == 1);
+ copies = 0;
+ (void)std::ranges::find_last(a, value, Proj(&copies));
+ assert(copies == 1);
+ copies = 0;
+ (void)std::ranges::find_last_if(first, last, UnaryTrue(), Proj(&copies));
+ assert(copies == 1);
+ copies = 0;
+ (void)std::ranges::find_last_if(a, UnaryTrue(), Proj(&copies));
+ assert(copies == 1);
+ copies = 0;
+ (void)std::ranges::find_last_if_not(first, last, UnaryTrue(), Proj(&copies));
+ assert(copies == 1);
+ copies = 0;
+ (void)std::ranges::find_last_if_not(a, UnaryTrue(), Proj(&copies));
+ assert(copies == 1);
+ copies = 0;
(void)std::ranges::for_each(first, last, UnaryVoid(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::for_each(a, UnaryVoid(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::for_each_n(first, count, UnaryVoid(), Proj(&copies)); assert(copies == 0);
diff --git a/libcxx/test/libcxx/diagnostics/ranges.nodiscard_extensions.verify.cpp b/libcxx/test/libcxx/diagnostics/ranges.nodiscard_extensions.verify.cpp
index 7528acdae28d..e2ec1ea7c396 100644
--- a/libcxx/test/libcxx/diagnostics/ranges.nodiscard_extensions.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/ranges.nodiscard_extensions.verify.cpp
@@ -41,10 +41,14 @@ void test() {
std::ranges::find_if_not(iter, iter, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::ranges::find_if(range, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::ranges::find_if(iter, iter, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- std::ranges::find_last_if(range, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- std::ranges::find_last_if(iter, iter, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- std::ranges::find_last_if_not(range, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- std::ranges::find_last_if_not(iter, iter, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::ranges::find_last_if(
+ range, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::ranges::find_last_if(
+ iter, iter, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::ranges::find_last_if_not(
+ range, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::ranges::find_last_if_not(
+ iter, iter, pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::ranges::find(range, 1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::ranges::find(iter, iter, 1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::ranges::includes(range, range); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last.pass.cpp
index 03a37714d96c..3d09f00b5ea4 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last.pass.cpp
@@ -31,9 +31,7 @@
struct NotEqualityComparable {};
template <class It, class Sent = It>
-concept HasFindIt = requires(It it, Sent sent) {
- std::ranges::find_last(it, sent, *it);
-};
+concept HasFindIt = requires(It it, Sent sent) { std::ranges::find_last(it, sent, *it); };
static_assert(HasFindIt<int*>);
static_assert(!HasFindIt<NotEqualityComparable*>);
static_assert(!HasFindIt<InputIteratorNotDerivedFrom>);
@@ -46,9 +44,7 @@ static_assert(!HasFindIt<int*, int>);
static_assert(!HasFindIt<int, int*>);
template <class Range, class ValT>
-concept HasFindR = requires(Range r) {
- std::ranges::find_last(r, ValT{});
-};
+concept HasFindR = requires(Range r) { std::ranges::find_last(r, ValT{}); };
static_assert(HasFindR<std::array<int, 1>, int>);
static_assert(!HasFindR<int, int>);
@@ -79,205 +75,203 @@ struct NonConstComparableRValue {
};
constexpr bool test() {
-
{// check that projections are used properly and called with the reference to the element the iterator is pointing to
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, a + 4, a + 3, [](int& i) { return &i; });
- assert(ret.data() == a + 3);
- }
-
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, a + 3, [](int& i) { return &i; });
- assert(ret.data() == a + 3);
- }
+ {int a[] = {1, 2, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret =
+ std::ranges::find_last(a, a + 4, a + 3, [](int& i) { return &i; });
+ assert(ret.data() == a + 3);
+}
- }
+{
+ int a[] = {1, 2, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, a + 3, [](int& i) { return &i; });
+ assert(ret.data() == a + 3);
+}
+}
- {// check that the end element is returned
-
- {
- struct S{
- int comp;
- int other;
- };
-
- S a[] = {{0, 0}, {0, 2}, {0, 1}};
- std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last(a, 0, &S::comp);
- assert(ret.data() == a + 2);
- assert(ret.data()->comp == 0);
- assert(ret.data()->other == 1);
- }
-
- {
- struct S {
- int comp;
- int other;
- };
-
- S a[] = {{0, 0}, {0, 2}, {0, 1}};
- std::same_as<std::ranges::subrange<S*>> auto ret = std::ranges::find_last(a, a + 3, 0, &S::comp);
- assert(ret.data() == a + 2);
- assert(ret.data()->comp == 0);
- assert(ret.data()->other == 1);
- }
+{// check that the end element is returned
- }
+ {struct S{int comp;
+int other;
+}
+;
- {// check that end + 1 iterator is returned with no match
+S a[] = {{0, 0}, {0, 2}, {0, 1}};
+std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last(a, 0, &S::comp);
+assert(ret.data() == a + 2);
+assert(ret.data()->comp == 0);
+assert(ret.data()->other == 1);
+}
- {
- int a[] = {1, 1, 1};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, a + 3, 0);
- assert(ret.data() == a + 3);
- }
+{
+ struct S {
+ int comp;
+ int other;
+ };
+
+ S a[] = {{0, 0}, {0, 2}, {0, 1}};
+ std::same_as<std::ranges::subrange<S*>> auto ret = std::ranges::find_last(a, a + 3, 0, &S::comp);
+ assert(ret.data() == a + 2);
+ assert(ret.data()->comp == 0);
+ assert(ret.data()->other == 1);
+}
+}
- {
- int a[] = {1, 1, 1};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, 0);
- assert(ret.data() == a + 3);
- }
+{// check that end + 1 iterator is returned with no match
- }
+ {int a[] = {1, 1, 1};
+std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, a + 3, 0);
+assert(ret.data() == a + 3);
+}
+
+{
+ int a[] = {1, 1, 1};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, 0);
+ assert(ret.data() == a + 3);
+}
+}
- {// check that ranges::dangling is returned
+{ // check that ranges::dangling is returned
[[maybe_unused]] std::same_as<std::ranges::dangling> auto ret = std::ranges::find_last(std::array{1, 2}, 3);
- }
+}
- {// check that an iterator is returned with a borrowing range
- int a[] = {1, 1, 2, 3, 4};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(std::views::all(a), 1);
- assert(ret.data() == a + 1);
- assert(*(ret.data()) == 1);
- }
+{ // check that an iterator is returned with a borrowing range
+ int a[] = {1, 1, 2, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(std::views::all(a), 1);
+ assert(ret.data() == a + 1);
+ assert(*(ret.data()) == 1);
+}
- {// check that std::invoke is used
+{// check that std::invoke is used
- {
- struct S{
- int i;
- };
+ {struct S{int i;
+}
+;
- S a[] = {S{1}, S{3}, S{2}};
- std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last(a, 4, &S::i);
- assert(ret.data() == a + 3);
- }
+S a[] = {S{1}, S{3}, S{2}};
+std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last(a, 4, &S::i);
+assert(ret.data() == a + 3);
+}
- {
- struct S {
- int i;
- };
+{
+ struct S {
+ int i;
+ };
- S a[] = {S{1}, S{3}, S{2}};
- std::same_as<std::ranges::subrange<S*>> auto ret = std::ranges::find_last(a, a + 3, 4, &S::i);
- assert(ret.data() == a + 3);
- }
- }
+ S a[] = {S{1}, S{3}, S{2}};
+ std::same_as<std::ranges::subrange<S*>> auto ret = std::ranges::find_last(a, a + 3, 4, &S::i);
+ assert(ret.data() == a + 3);
+}
+}
- {// count invocations of the projection
-
- {
- int a[] = {1, 2, 2, 3, 4};
- int projection_count = 0;
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, a + 5, 2, [&](int i) { ++projection_count; return i; });
- assert(ret.data() == a + 2);
- assert(*(ret.data()) == 2);
- assert(projection_count == 5);
- }
-
- {
- int a[] = {1, 2, 2, 3, 4};
- int projection_count = 0;
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, 2, [&](int i) { ++projection_count; return i; });
- assert(ret.data() == a + 2);
- assert(*(ret.data()) == 2);
- assert(projection_count == 5);
- }
+{// count invocations of the projection
+
+ {int a[] = {1, 2, 2, 3, 4};
+int projection_count = 0;
+std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, a + 5, 2, [&](int i) {
+ ++projection_count;
+ return i;
+});
+assert(ret.data() == a + 2);
+assert(*(ret.data()) == 2);
+assert(projection_count == 5);
+}
- }
+{
+ int a[] = {1, 2, 2, 3, 4};
+ int projection_count = 0;
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, 2, [&](int i) {
+ ++projection_count;
+ return i;
+ });
+ assert(ret.data() == a + 2);
+ assert(*(ret.data()) == 2);
+ assert(projection_count == 5);
+}
+}
- {// check comparison order
+{// check comparison order
- {
- OneWayComparable a[] = {OneWayComparable{true}};
- std::same_as<std::ranges::subrange<OneWayComparable*>> auto ret = std::ranges::find_last(a, a + 1, OneWayComparable{false});
- assert(ret.data() == a);
- }
+ {OneWayComparable a[] = {OneWayComparable{true}};
+std::same_as<std::ranges::subrange<OneWayComparable*>> auto ret =
+ std::ranges::find_last(a, a + 1, OneWayComparable{false});
+assert(ret.data() == a);
+}
- {
- OneWayComparable a[] = {OneWayComparable{true}};
- std::same_as<std::ranges::borrowed_subrange_t<OneWayComparable(&)[1]>> auto ret = std::ranges::find_last(a, OneWayComparable{false});
- assert(ret.data() == a);
- }
+{
+ OneWayComparable a[] = {OneWayComparable{true}};
+ std::same_as<std::ranges::borrowed_subrange_t<OneWayComparable(&)[1]>> auto ret =
+ std::ranges::find_last(a, OneWayComparable{false});
+ assert(ret.data() == a);
+}
+}
- }
+{// check that the return type of `iter::operator*` doesn't change
- {// check that the return type of `iter::operator*` doesn't change
-
- {
- NonConstComparableLValue a[] = {NonConstComparableLValue{}};
- std::same_as<std::ranges::subrange<NonConstComparableLValue*>> auto ret = std::ranges::find_last(a, a + 1, NonConstComparableLValue{});
- assert(ret.data() == a);
- }
-
- {
- using It = std::move_iterator<NonConstComparableRValue*>;
- NonConstComparableRValue a[] = {NonConstComparableRValue{}};
- std::same_as<std::ranges::subrange<std::move_iterator<NonConstComparableRValue*>>> auto ret = std::ranges::find_last(It(a), It(a + 1), NonConstComparableRValue{});
- assert(ret.begin().base() == a);
- }
-
- {
- NonConstComparableLValue a[] = {NonConstComparableLValue{}};
- std::same_as<std::ranges::borrowed_subrange_t<NonConstComparableLValue(&)[1]>> auto ret = std::ranges::find_last(a, NonConstComparableLValue{});
- assert(ret.data() == a);
- }
-
- {
- using It = std::move_iterator<NonConstComparableRValue*>;
- NonConstComparableRValue a[] = {NonConstComparableRValue{}};
- auto range = std::ranges::subrange(It(a), It(a + 1));
- std::same_as<std::ranges::borrowed_subrange_t<std::ranges::subrange<std::move_iterator<NonConstComparableRValue*>,
- std::move_iterator<NonConstComparableRValue*>,
- std::ranges::subrange_kind::sized>&>> auto ret = std::ranges::find_last(range, NonConstComparableRValue{});
- assert(ret.begin().base() == a);
- }
+ {NonConstComparableLValue a[] = {NonConstComparableLValue{}};
+std::same_as<std::ranges::subrange<NonConstComparableLValue*>> auto ret =
+ std::ranges::find_last(a, a + 1, NonConstComparableLValue{});
+assert(ret.data() == a);
+}
- }
+{
+ using It = std::move_iterator<NonConstComparableRValue*>;
+ NonConstComparableRValue a[] = {NonConstComparableRValue{}};
+ std::same_as<std::ranges::subrange<std::move_iterator<NonConstComparableRValue*>>> auto ret =
+ std::ranges::find_last(It(a), It(a + 1), NonConstComparableRValue{});
+ assert(ret.begin().base() == a);
+}
- {// check that an empty range works
- {
- std::array<int, 0> a = {};
- int search_value = 1;
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a.begin(), a.end(), search_value);
- assert(ret.data() == a.end());
- }
-
- {
- std::array<int, 0> a = {};
- int search_value = 1;
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, search_value);
- assert(ret.data() == a.end());
- }
+{
+ NonConstComparableLValue a[] = {NonConstComparableLValue{}};
+ std::same_as<std::ranges::borrowed_subrange_t<NonConstComparableLValue(&)[1]>> auto ret =
+ std::ranges::find_last(a, NonConstComparableLValue{});
+ assert(ret.data() == a);
+}
- }
+{
+ using It = std::move_iterator<NonConstComparableRValue*>;
+ NonConstComparableRValue a[] = {NonConstComparableRValue{}};
+ auto range = std::ranges::subrange(It(a), It(a + 1));
+ std::same_as<std::ranges::borrowed_subrange_t<std::ranges::subrange<std::move_iterator<NonConstComparableRValue*>,
+ std::move_iterator<NonConstComparableRValue*>,
+ std::ranges::subrange_kind::sized>&>> auto ret =
+ std::ranges::find_last(range, NonConstComparableRValue{});
+ assert(ret.begin().base() == a);
+}
+}
+
+{// check that an empty range works
+ {std::array<int, 0> a = {};
+int search_value = 1;
+std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a.begin(), a.end(), search_value);
+assert(ret.data() == a.end());
+}
+
+{
+ std::array<int, 0> a = {};
+ int search_value = 1;
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last(a, search_value);
+ assert(ret.data() == a.end());
+}
+}
- {// check that the implicit conversion to bool works
-
- {
- StrictComparable<int> a[] = {1, 2, 2, 3, 4};
- std::same_as<std::ranges::subrange<StrictComparable<int>*>> auto ret = std::ranges::find_last(a, a + 4, StrictComparable<int>{2});
- assert(ret.data() == a + 2);
- }
+{ // check that the implicit conversion to bool works
- {
- StrictComparable<int> a[] = {1, 2, 2, 3, 4};
- std::same_as<std::ranges::borrowed_subrange_t<StrictComparable<int>(&)[5]>> auto ret = std::ranges::find_last(a, StrictComparable<int>{2});
- assert(ret.data() == a + 2);
- }
+ {
+ StrictComparable<int> a[] = {1, 2, 2, 3, 4};
+ std::same_as<std::ranges::subrange<StrictComparable<int>*>> auto ret =
+ std::ranges::find_last(a, a + 4, StrictComparable<int>{2});
+ assert(ret.data() == a + 2);
+ }
+ {
+ StrictComparable<int> a[] = {1, 2, 2, 3, 4};
+ std::same_as<std::ranges::borrowed_subrange_t<StrictComparable<int>(&)[5]>> auto ret =
+ std::ranges::find_last(a, StrictComparable<int>{2});
+ assert(ret.data() == a + 2);
}
+}
return true;
}
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if.pass.cpp
index 6beb36f38f9c..886f1749b232 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if.pass.cpp
@@ -32,9 +32,7 @@ struct Predicate {
};
template <class It, class Sent = It>
-concept HasFindLastIfIt = requires(It it, Sent sent) {
- std::ranges::find_last_if(it, sent, Predicate{});
-};
+concept HasFindLastIfIt = requires(It it, Sent sent) { std::ranges::find_last_if(it, sent, Predicate{}); };
static_assert(HasFindLastIfIt<int*>);
static_assert(!HasFindLastIfIt<InputIteratorNotDerivedFrom>);
static_assert(!HasFindLastIfIt<InputIteratorNotIndirectlyReadable>);
@@ -46,18 +44,14 @@ static_assert(!HasFindLastIfIt<int*, int>);
static_assert(!HasFindLastIfIt<int, int*>);
template <class Pred>
-concept HasFindLastIfPred = requires(int* it, Pred pred) {
- std::ranges::find_last_if(it, it, pred);
-};
+concept HasFindLastIfPred = requires(int* it, Pred pred) { std::ranges::find_last_if(it, it, pred); };
static_assert(HasFindLastIfPred<IndirectUnaryPredicate>);
static_assert(!HasFindLastIfPred<IndirectUnaryPredicateNotCopyConstructible>);
static_assert(!HasFindLastIfPred<IndirectUnaryPredicateNotPredicate>);
template <class R>
-concept HasFindLastIfR = requires(R r) {
- std::ranges::find_last_if(r, Predicate{});
-};
+concept HasFindLastIfR = requires(R r) { std::ranges::find_last_if(r, Predicate{}); };
static_assert(HasFindLastIfR<std::array<int, 0>>);
static_assert(!HasFindLastIfR<int>);
@@ -71,128 +65,123 @@ template <class It, class Sent = It>
constexpr void test_iterators() {
{// Test with an empty range
- {
- int a[] = {};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if(It(a), Sent(It(a)), [](int x) { return x == 4; });
- assert(ret.empty());
- }
-
- {
- int a[] = {};
- auto range = std::ranges::subrange(It(a), Sent(It(a)));
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if(range, [](int x) { return x == 4; });
- assert(ret.empty());
- }
-
- }
-
- {// Test with a single element range
+ {int a[] = {};
+ std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if(It(a), Sent(It(a)), [](int x) { return x == 4; });
+ assert(ret.empty());
+}
- {
- int a[] = {4};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if(It(a), Sent(It(a + 1)), [](int x) { return x == 4; });
- assert(base(ret.begin()) == a);
- assert(*ret.begin() == 4);
- }
+{
+ int a[] = {};
+ auto range = std::ranges::subrange(It(a), Sent(It(a)));
+ std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if(range, [](int x) { return x == 4; });
+ assert(ret.empty());
+}
+}
- {
- int a[] = {4};
- std::same_as<std::ranges::borrowed_subrange_t<int (&)[1]>> auto ret = std::ranges::find_last_if(a, [](int x) { return x == 4; });
- assert(base(ret.begin()) == a);
- assert(*ret.begin() == 4);
- }
+{// Test with a single element range
- }
+ {int a[] = {4};
+std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if(It(a), Sent(It(a + 1)), [](int x) { return x == 4; });
+assert(base(ret.begin()) == a);
+assert(*ret.begin() == 4);
+}
- {// Test when no element satisfies the predicate
+{
+ int a[] = {4};
+ std::same_as<std::ranges::borrowed_subrange_t<int(&)[1]>> auto ret =
+ std::ranges::find_last_if(a, [](int x) { return x == 4; });
+ assert(base(ret.begin()) == a);
+ assert(*ret.begin() == 4);
+}
+}
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if(It(a), Sent(It(a + 4)), [](int x) { return x == 5; });
- assert(ret.empty());
- }
-
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::borrowed_subrange_t<int (&)[4]>> auto ret = std::ranges::find_last_if(a, [](int x) { return x == 5; });
- assert(ret.empty());
- }
+{// Test when no element satisfies the predicate
- }
+ {int a[] = {1, 2, 3, 4};
+std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if(It(a), Sent(It(a + 4)), [](int x) { return x == 5; });
+assert(ret.empty());
+}
- {// Test when all elements satisfy the predicate
+{
+ int a[] = {1, 2, 3, 4};
+ std::same_as<std::ranges::borrowed_subrange_t<int(&)[4]>> auto ret =
+ std::ranges::find_last_if(a, [](int x) { return x == 5; });
+ assert(ret.empty());
+}
+}
- {
- int a[] = {4, 4, 4, 4};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if(It(a), Sent(It(a + 4)), [](int x) { return x == 4; });
- assert(base(ret.begin()) == a + 3);
- assert(*ret.begin() == 4);
- }
+{// Test when all elements satisfy the predicate
- {
- int a[] = {4, 4, 4, 4};
- std::same_as<std::ranges::borrowed_subrange_t<int (&)[4]>> auto ret = std::ranges::find_last_if(a, [](int x) { return x == 4; });
- assert(base(ret.begin()) == a + 3);
- assert(*ret.begin() == 4);
- }
+ {int a[] = {4, 4, 4, 4};
+std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if(It(a), Sent(It(a + 4)), [](int x) { return x == 4; });
+assert(base(ret.begin()) == a + 3);
+assert(*ret.begin() == 4);
+}
- }
+{
+ int a[] = {4, 4, 4, 4};
+ std::same_as<std::ranges::borrowed_subrange_t<int(&)[4]>> auto ret =
+ std::ranges::find_last_if(a, [](int x) { return x == 4; });
+ assert(base(ret.begin()) == a + 3);
+ assert(*ret.begin() == 4);
+}
+}
- {// Test when the element being searched is the first one
+{// Test when the element being searched is the first one
- {
- int a[] = {4, 1, 2, 3};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if(It(a), Sent(It(a + 4)), [](int x) { return x == 4; });
- assert(base(ret.begin()) == a);
- assert(*ret.begin() == 4);
- }
+ {int a[] = {4, 1, 2, 3};
+std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if(It(a), Sent(It(a + 4)), [](int x) { return x == 4; });
+assert(base(ret.begin()) == a);
+assert(*ret.begin() == 4);
+}
- {
- int a[] = {4, 1, 2, 3};
- std::same_as<std::ranges::borrowed_subrange_t<int (&)[4]>> auto ret = std::ranges::find_last_if(a, [](int x) { return x == 4; });
- assert(base(ret.begin()) == a);
- assert(*ret.begin() == 4);
- }
+{
+ int a[] = {4, 1, 2, 3};
+ std::same_as<std::ranges::borrowed_subrange_t<int(&)[4]>> auto ret =
+ std::ranges::find_last_if(a, [](int x) { return x == 4; });
+ assert(base(ret.begin()) == a);
+ assert(*ret.begin() == 4);
+}
+}
- }
+{// Test when the element being searched is the last one
- {// Test when the element being searched is the last one
+ {int a[] = {1, 2, 3, 4};
+std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if(It(a), Sent(It(a + 4)), [](int x) { return x == 4; });
+assert(base(ret.begin()) == a + 3);
+assert(*ret.begin() == 4);
+}
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if(It(a), Sent(It(a + 4)), [](int x) { return x == 4; });
- assert(base(ret.begin()) == a + 3);
- assert(*ret.begin() == 4);
- }
+{
+ int a[] = {1, 2, 3, 4};
+ std::same_as<std::ranges::borrowed_subrange_t<int(&)[4]>> auto ret =
+ std::ranges::find_last_if(a, [](int x) { return x == 4; });
+ assert(base(ret.begin()) == a + 3);
+ assert(*ret.begin() == 4);
+}
+}
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::borrowed_subrange_t<int (&)[4]>> auto ret = std::ranges::find_last_if(a, [](int x) { return x == 4; });
- assert(base(ret.begin()) == a + 3);
- assert(*ret.begin() == 4);
- }
+{ // check that past-the-end iterator is returned with no match
+ {
+ int a[] = {1, 1, 1};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, a + 3, [](int) { return false; });
+ assert(ret.data() == a + 3);
}
-
- {// check that past-the-end iterator is returned with no match
-
- {
- int a[] = {1, 1, 1};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, a + 3, [](int) { return false; });
- assert(ret.data() == a + 3);
- }
-
- {
- int a[] = {1, 1, 1};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, [](int) { return false; });
- assert(ret.data() == a + 3);
- }
-
+ {
+ int a[] = {1, 1, 1};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, [](int) { return false; });
+ assert(ret.data() == a + 3);
}
-
}
-
+}
struct NonConstComparableValue {
friend constexpr bool operator==(const NonConstComparableValue&, const NonConstComparableValue&) { return false; }
@@ -211,149 +200,163 @@ constexpr bool test() {
{// check that projections are used properly and called with the reference to the element the iterator is pointing to
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, a + 4, [&](int* i) { return i == a + 3; }, [](int& i) { return &i; });
- assert(ret.data() == a + 3);
- }
-
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, [&](int* i) { return i == a + 3; }, [](int& i) { return &i; });
- assert(ret.data() == a + 3);
- }
+ {int a[] = {1, 2, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(
+ a, a + 4, [&](int* i) { return i == a + 3; }, [](int& i) { return &i; });
+ assert(ret.data() == a + 3);
+}
- }
+{
+ int a[] = {1, 2, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(
+ a, [&](int* i) { return i == a + 3; }, [](int& i) { return &i; });
+ assert(ret.data() == a + 3);
+}
+}
- {// check that the last element is returned
-
- {
- struct S {
- int comp;
- int other;
- };
-
- S a[] = {{0, 0}, {0, 2}, {0, 1}};
- std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last_if(a, [](int i) { return i == 0; }, &S::comp);
- assert(ret.data() == a + 2);
- assert(ret.data()->comp == 0);
- assert(ret.data()->other == 1);
- }
-
- {
- struct S {
- int comp;
- int other;
- };
-
- S a[] = {{0, 0}, {0, 2}, {0, 1}};
- std::same_as<std::ranges::subrange<S *>> auto ret = std::ranges::find_last_if(a, a + 3, [](int i) { return i == 0; }, &S::comp);
- assert(ret.data() == a + 2);
- assert(ret.data()->comp == 0);
- assert(ret.data()->other == 1);
- }
+{// check that the last element is returned
- }
+ {struct S{int comp;
+int other;
+}
+;
+
+S a[] = {{0, 0}, {0, 2}, {0, 1}};
+std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last_if(
+ a, [](int i) { return i == 0; }, &S::comp);
+assert(ret.data() == a + 2);
+assert(ret.data()->comp == 0);
+assert(ret.data()->other == 1);
+}
- {// check that ranges::dangling is returned
- [[maybe_unused]] std::same_as<std::ranges::dangling> auto ret = std::ranges::find_last_if(std::array{1, 2}, [](int) { return false; });
- }
+{
+ struct S {
+ int comp;
+ int other;
+ };
+
+ S a[] = {{0, 0}, {0, 2}, {0, 1}};
+ std::same_as<std::ranges::subrange<S*>> auto ret = std::ranges::find_last_if(
+ a, a + 3, [](int i) { return i == 0; }, &S::comp);
+ assert(ret.data() == a + 2);
+ assert(ret.data()->comp == 0);
+ assert(ret.data()->other == 1);
+}
+}
- {// check that an iterator is returned with a borrowing range
- int a[] = {1, 1, 2, 3, 4};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(std::views::all(a), [](int) { return true; });
- assert(ret.data() == a + 4);
- }
+{ // check that ranges::dangling is returned
+ [[maybe_unused]] std::same_as<std::ranges::dangling> auto ret =
+ std::ranges::find_last_if(std::array{1, 2}, [](int) { return false; });
+}
- {// check that std::invoke is used
+{ // check that an iterator is returned with a borrowing range
+ int a[] = {1, 1, 2, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret =
+ std::ranges::find_last_if(std::views::all(a), [](int) { return true; });
+ assert(ret.data() == a + 4);
+}
- {
- struct S {
- int i;
- };
+{// check that std::invoke is used
- S a[] = {S{1}, S{3}, S{2}};
- std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last_if(a, [](int) { return false; }, &S::i);
- assert(ret.data() == a + 3);
- }
+ {struct S{int i;
+}
+;
- {
- struct S {
- int i;
- };
+S a[] = {S{1}, S{3}, S{2}};
+std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last_if(
+ a, [](int) { return false; }, &S::i);
+assert(ret.data() == a + 3);
+}
- S a[] = {S{1}, S{3}, S{2}};
- std::same_as<std::ranges::subrange<S*>> auto ret = std::ranges::find_last_if(a, a + 3, [](int) { return false; }, &S::i);
- assert(ret.data() == a + 3);
- }
+{
+ struct S {
+ int i;
+ };
- }
+ S a[] = {S{1}, S{3}, S{2}};
+ std::same_as<std::ranges::subrange<S*>> auto ret = std::ranges::find_last_if(
+ a, a + 3, [](int) { return false; }, &S::i);
+ assert(ret.data() == a + 3);
+}
+}
- {// count projection and predicate invocation count
+{// count projection and predicate invocation count
+
+ {int a[] = {1, 2, 2, 3, 4};
+int predicate_count = 0;
+int projection_count = 0;
+std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(
+ a,
+ a + 5,
+ [&](int i) {
+ ++predicate_count;
+ return i == 2;
+ },
+ [&](int i) {
+ ++projection_count;
+ return i;
+ });
+assert(ret.data() == a + 2);
+assert(*(ret.data()) == 2);
+assert(predicate_count == 5);
+assert(projection_count == 5);
+}
- {
- int a[] = {1, 2, 2, 3, 4};
- int predicate_count = 0;
- int projection_count = 0;
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, a + 5, [&](int i) { ++predicate_count; return i == 2; }, [&](int i) {
+{
+ int a[] = {1, 2, 2, 3, 4};
+ int predicate_count = 0;
+ int projection_count = 0;
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(
+ a,
+ [&](int i) {
+ ++predicate_count;
+ return i == 2;
+ },
+ [&](int i) {
++projection_count;
return i;
});
- assert(ret.data() == a + 2);
- assert(*(ret.data()) == 2);
- assert(predicate_count == 5);
- assert(projection_count == 5);
- }
-
- {
- int a[] = {1, 2, 2, 3, 4};
- int predicate_count = 0;
- int projection_count = 0;
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, [&](int i) { ++predicate_count; return i == 2; }, [&](int i) {
- ++projection_count;
- return i;
- });
- assert(ret.data() == a + 2);
- assert(*(ret.data()) == 2);
- assert(predicate_count == 5);
- assert(projection_count == 5);
- }
+ assert(ret.data() == a + 2);
+ assert(*(ret.data()) == 2);
+ assert(predicate_count == 5);
+ assert(projection_count == 5);
+}
+}
- }
+{// check that the return type of `iter::operator*` doesn't change
- {// check that the return type of `iter::operator*` doesn't change
+ {NonConstComparableValue a[] = {NonConstComparableValue{}};
+std::same_as<std::ranges::subrange<NonConstComparableValue*>> auto ret =
+ std::ranges::find_last_if(a, a + 1, [](auto&& e) { return e == NonConstComparableValue{}; });
+assert(ret.data() == a);
+}
- {
- NonConstComparableValue a[] = {NonConstComparableValue{}};
- std::same_as<std::ranges::subrange<NonConstComparableValue *>> auto ret = std::ranges::find_last_if(a, a + 1, [](auto&& e) { return e == NonConstComparableValue{}; });
- assert(ret.data() == a);
- }
+{
+ NonConstComparableValue a[] = {NonConstComparableValue{}};
+ std::same_as<std::ranges::borrowed_subrange_t<NonConstComparableValue(&)[1]>> auto ret =
+ std::ranges::find_last_if(a, [](auto&& e) { return e == NonConstComparableValue{}; });
+ assert(ret.data() == a);
+}
+}
- {
- NonConstComparableValue a[] = {NonConstComparableValue{}};
- std::same_as<std::ranges::borrowed_subrange_t<NonConstComparableValue (&)[1]>> auto ret = std::ranges::find_last_if(a, [](auto&& e) { return e == NonConstComparableValue{}; });
- assert(ret.data() == a);
- }
+{ // check that the implicit conversion to bool works
+ {
+ int a[] = {1, 2, 3, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret =
+ std::ranges::find_last_if(a, a + 4, [](const int& i) { return BooleanTestable{i == 3}; });
+ assert(ret.data() == a + 3);
}
- {// check that the implicit conversion to bool works
-
- {
- int a[] = {1, 2, 3, 3, 4};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, a + 4, [](const int& i) { return BooleanTestable{i == 3}; });
- assert(ret.data() == a + 3);
- }
-
- {
- int a[] = {1, 2, 3, 3, 4};
- std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if(a, [](const int& b) { return BooleanTestable{b == 3}; });
- assert(ret.data() == a + 3);
- }
-
+ {
+ int a[] = {1, 2, 3, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret =
+ std::ranges::find_last_if(a, [](const int& b) { return BooleanTestable{b == 3}; });
+ assert(ret.data() == a + 3);
}
+}
- return true;
+return true;
}
int main(int, char**) {
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if_not.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if_not.pass.cpp
index daca8e7c0d04..6e01e3fff535 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if_not.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_last_if_not.pass.cpp
@@ -32,9 +32,7 @@ struct Predicate {
};
template <class It, class Sent = It>
-concept HasFindLastIfNotIt = requires(It it, Sent sent) {
- std::ranges::find_last_if_not(it, sent, Predicate{});
-};
+concept HasFindLastIfNotIt = requires(It it, Sent sent) { std::ranges::find_last_if_not(it, sent, Predicate{}); };
static_assert(HasFindLastIfNotIt<int*>);
static_assert(!HasFindLastIfNotIt<InputIteratorNotDerivedFrom>);
static_assert(!HasFindLastIfNotIt<InputIteratorNotIndirectlyReadable>);
@@ -46,18 +44,14 @@ static_assert(!HasFindLastIfNotIt<int*, int>);
static_assert(!HasFindLastIfNotIt<int, int*>);
template <class Pred>
-concept HasFindLastIfNotPred = requires(int* it, Pred pred) {
- std::ranges::find_last_if_not(it, it, pred);
-};
+concept HasFindLastIfNotPred = requires(int* it, Pred pred) { std::ranges::find_last_if_not(it, it, pred); };
static_assert(HasFindLastIfNotPred<IndirectUnaryPredicate>);
static_assert(!HasFindLastIfNotPred<IndirectUnaryPredicateNotCopyConstructible>);
static_assert(!HasFindLastIfNotPred<IndirectUnaryPredicateNotPredicate>);
template <class R>
-concept HasFindLastIfNotR = requires(R r) {
- std::ranges::find_last_if_not(r, Predicate{});
-};
+concept HasFindLastIfNotR = requires(R r) { std::ranges::find_last_if_not(r, Predicate{}); };
static_assert(HasFindLastIfNotR<std::array<int, 0>>);
static_assert(!HasFindLastIfNotR<int>);
static_assert(!HasFindLastIfNotR<InputRangeNotDerivedFrom>);
@@ -68,79 +62,76 @@ static_assert(!HasFindLastIfNotR<InputRangeNotSentinelEqualityComparableWith>);
template <class It, class Sent = It>
constexpr void test_iterators() {
-
{// Test with an empty range
-
- {
- int a[] = {};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if_not(It(a), Sent(It(a)), [](int) { return false; });
- assert(ret.empty());
- }
-
- {
- int a[] = {};
- auto range = std::ranges::subrange(It(a), Sent(It(a)));
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if_not(range, [](int) { return false; });
- assert(ret.empty());
- }
- }
+ {int a[] = {};
+ std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if_not(It(a), Sent(It(a)), [](int) { return false; });
+ assert(ret.empty());
+}
+{
+ int a[] = {};
+ auto range = std::ranges::subrange(It(a), Sent(It(a)));
+ std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if_not(range, [](int) { return false; });
+ assert(ret.empty());
+}
+}
- {// Test with a single element range
+{// Test with a single element range
- {
- int a[] = {1};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if_not(It(a), Sent(It(a + 1)), [](int) { return false; });
- assert(base(ret.begin()) == a);
- assert(*ret.begin() == 1);
- }
+ {int a[] = {1};
+std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if_not(It(a), Sent(It(a + 1)), [](int) { return false; });
+assert(base(ret.begin()) == a);
+assert(*ret.begin() == 1);
+}
- {
- int a[] = {1};
- std::same_as<std::ranges::borrowed_subrange_t<int (&)[1]>> auto ret = std::ranges::find_last_if_not(a, [](int) { return false; });
- assert(base(ret.begin()) == a);
- assert(*ret.begin() == 1);
- }
+{
+ int a[] = {1};
+ std::same_as<std::ranges::borrowed_subrange_t<int(&)[1]>> auto ret =
+ std::ranges::find_last_if_not(a, [](int) { return false; });
+ assert(base(ret.begin()) == a);
+ assert(*ret.begin() == 1);
+}
+}
- }
+{// Test with a range where each element satisfies the predicate
- {// Test with a range where each element satisfies the predicate
+ {int a[] = {1, 2, 3, 4, 5};
+std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if_not(It(a), Sent(It(a + 5)), [](int) { return false; });
+assert(base(ret.begin()) == a + 4);
+assert(*ret.begin() == 5);
+}
- {
- int a[] = {1, 2, 3, 4, 5};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if_not(It(a), Sent(It(a + 5)), [](int) { return false; });
- assert(base(ret.begin()) == a + 4);
- assert(*ret.begin() == 5);
- }
+{
+ int a[] = {1, 2, 3, 4, 5};
+ std::same_as<std::ranges::borrowed_subrange_t<int(&)[5]>> auto ret =
+ std::ranges::find_last_if_not(a, [](int) { return false; });
+ assert(base(ret.begin()) == a + 4);
+ assert(*ret.begin() == 5);
+}
+}
- {
- int a[] = {1, 2, 3, 4, 5};
- std::same_as<std::ranges::borrowed_subrange_t<int (&)[5]>> auto ret = std::ranges::find_last_if_not(a, [](int) { return false; });
- assert(base(ret.begin()) == a + 4);
- assert(*ret.begin() == 5);
- }
+{ // Test with a range where no element satisfies the predicate
+ {
+ int a[] = {1, 2, 3, 4, 5};
+ std::same_as<std::ranges::subrange<It>> auto ret =
+ std::ranges::find_last_if_not(It(a), Sent(It(a + 5)), [](int) { return true; });
+ assert(base(ret.begin()) == a + 5);
+ assert(ret.empty());
}
- {// Test with a range where no element satisfies the predicate
-
- {
- int a[] = {1, 2, 3, 4, 5};
- std::same_as<std::ranges::subrange<It>> auto ret = std::ranges::find_last_if_not(It(a), Sent(It(a + 5)), [](int) { return true; });
- assert(base(ret.begin()) == a + 5);
- assert(ret.empty());
- }
-
- {
- int a[] = {1, 2, 3, 4, 5};
- std::same_as<std::ranges::borrowed_subrange_t<int (&)[5]>> auto ret = std::ranges::find_last_if_not(a, [](int) { return true; });
- assert(base(ret.begin()) == a + 5);
- assert(ret.empty());
- }
-
+ {
+ int a[] = {1, 2, 3, 4, 5};
+ std::same_as<std::ranges::borrowed_subrange_t<int(&)[5]>> auto ret =
+ std::ranges::find_last_if_not(a, [](int) { return true; });
+ assert(base(ret.begin()) == a + 5);
+ assert(ret.empty());
}
-
+}
}
struct NonConstComparableValue {
@@ -160,163 +151,176 @@ constexpr bool test() {
{// check that projections are used properly and called with the reference to the element the iterator is pointing to
- {
- int a[] = {1, 2, 3, 4, 5};
- std::same_as<std::ranges::subrange<int *>> auto ret = std::ranges::find_last_if_not(a, a + 5, [&](int* i) { return i != a + 3; }, [](int& i) { return &i; });
- assert(ret.data() == a + 3);
- }
-
- {
- int a[] = {1, 2, 3, 4, 5};
- std::same_as<std::ranges::subrange<int *>> auto ret = std::ranges::find_last_if_not(a, [&](int* i) { return i != a + 3; }, [](int& i) { return &i; });
- assert(ret.data() == a + 3);
- }
+ {int a[] = {1, 2, 3, 4, 5};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if_not(
+ a, a + 5, [&](int* i) { return i != a + 3; }, [](int& i) { return &i; });
+ assert(ret.data() == a + 3);
+}
- }
+{
+ int a[] = {1, 2, 3, 4, 5};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if_not(
+ a, [&](int* i) { return i != a + 3; }, [](int& i) { return &i; });
+ assert(ret.data() == a + 3);
+}
+}
- {// check that the last element is returned
-
- {
- struct S{
- int comp;
- int other;
- };
-
- S a[] = {{0, 0}, {0, 2}, {0, 1}};
- std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last_if_not(a, [](int i) { return i != 0; }, &S::comp);
- assert(ret.data() == a + 2);
- assert(ret.data()->comp == 0);
- assert(ret.data()->other == 1);
- }
-
- {
- struct S {
- int comp;
- int other;
- };
-
- S a[] = {{0, 0}, {0, 2}, {0, 1}};
- std::same_as<std::ranges::subrange<S *>> auto ret = std::ranges::find_last_if_not(a, a + 3, [](int i) { return i != 0; }, &S::comp);
- assert(ret.data() == a + 2);
- assert(ret.data()->comp == 0);
- assert(ret.data()->other == 1);
- }
+{// check that the last element is returned
- }
+ {struct S{int comp;
+int other;
+}
+;
+
+S a[] = {{0, 0}, {0, 2}, {0, 1}};
+std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last_if_not(
+ a, [](int i) { return i != 0; }, &S::comp);
+assert(ret.data() == a + 2);
+assert(ret.data()->comp == 0);
+assert(ret.data()->other == 1);
+}
- {// check that end iterator is returned with no match
+{
+ struct S {
+ int comp;
+ int other;
+ };
+
+ S a[] = {{0, 0}, {0, 2}, {0, 1}};
+ std::same_as<std::ranges::subrange<S*>> auto ret = std::ranges::find_last_if_not(
+ a, a + 3, [](int i) { return i != 0; }, &S::comp);
+ assert(ret.data() == a + 2);
+ assert(ret.data()->comp == 0);
+ assert(ret.data()->other == 1);
+}
+}
- {
- int a[] = {1, 1, 1};
- std::same_as<std::ranges::subrange<int *>> auto ret = std::ranges::find_last_if_not(a, a + 3, [](int) { return false; });
- assert(ret.data() == a + 2);
- }
+{// check that end iterator is returned with no match
- {
- int a[] = {1, 1, 1};
- std::same_as<std::ranges::subrange<int *>> auto ret = std::ranges::find_last_if_not(a, [](int) { return false; });
- assert(ret.data() == a + 2);
- }
+ {int a[] = {1, 1, 1};
+std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if_not(a, a + 3, [](int) { return false; });
+assert(ret.data() == a + 2);
+}
- }
+{
+ int a[] = {1, 1, 1};
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if_not(a, [](int) { return false; });
+ assert(ret.data() == a + 2);
+}
+}
- {// check that ranges::dangling is returned
- [[maybe_unused]] std::same_as<std::ranges::dangling> auto ret =
- std::ranges::find_last_if_not(std::array{1, 2}, [](int) { return true; });
- }
+{ // check that ranges::dangling is returned
+ [[maybe_unused]] std::same_as<std::ranges::dangling> auto ret =
+ std::ranges::find_last_if_not(std::array{1, 2}, [](int) { return true; });
+}
- {// check that an iterator is returned with a borrowing range
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::subrange<int *>> auto ret = std::ranges::find_last_if_not(std::views::all(a), [](int) { return false; });
- assert(ret.data() == a + 3);
- assert(*ret.data() == 4);
- }
+{ // check that an iterator is returned with a borrowing range
+ int a[] = {1, 2, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret =
+ std::ranges::find_last_if_not(std::views::all(a), [](int) { return false; });
+ assert(ret.data() == a + 3);
+ assert(*ret.data() == 4);
+}
- {// check that std::invoke is used
+{// check that std::invoke is used
- {
- struct S {
- int i;
- };
+ {struct S{int i;
+}
+;
- S a[] = {S{1}, S{3}, S{2}};
- std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last_if_not(a, [](int) { return true; }, &S::i);
- assert(ret.data() == a + 3);
- }
+S a[] = {S{1}, S{3}, S{2}};
+std::same_as<std::ranges::borrowed_subrange_t<S (&)[3]>> auto ret = std::ranges::find_last_if_not(
+ a, [](int) { return true; }, &S::i);
+assert(ret.data() == a + 3);
+}
- {
- struct S {
- int i;
- };
+{
+ struct S {
+ int i;
+ };
- S a[] = {S{1}, S{3}, S{2}};
- std::same_as<std::ranges::subrange<S *>> auto ret = std::ranges::find_last_if_not(a, a + 3, [](int) { return true; }, &S::i);
- assert(ret.data() == a + 3);
- }
+ S a[] = {S{1}, S{3}, S{2}};
+ std::same_as<std::ranges::subrange<S*>> auto ret = std::ranges::find_last_if_not(
+ a, a + 3, [](int) { return true; }, &S::i);
+ assert(ret.data() == a + 3);
+}
+}
- }
+{// count projection and predicate invocation count
+
+ {int a[] = {1, 2, 3, 4};
+int predicate_count = 0;
+int projection_count = 0;
+std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if_not(
+ a,
+ a + 4,
+ [&](int i) {
+ ++predicate_count;
+ return i != 2;
+ },
+ [&](int i) {
+ ++projection_count;
+ return i;
+ });
+assert(ret.data() == a + 1);
+assert(*ret.data() == 2);
+assert(predicate_count == 4);
+assert(projection_count == 4);
+}
- {// count projection and predicate invocation count
-
- {
- int a[] = {1, 2, 3, 4};
- int predicate_count = 0;
- int projection_count = 0;
- std::same_as<std::ranges::subrange<int *>> auto ret = std::ranges::find_last_if_not(a,a + 4,
- [&](int i) { ++predicate_count; return i != 2; },
- [&](int i) { ++projection_count; return i; });
- assert(ret.data() == a + 1);
- assert(*ret.data() == 2);
- assert(predicate_count == 4);
- assert(projection_count == 4);
- }
-
- {
- int a[] = {1, 2, 3, 4};
- int predicate_count = 0;
- int projection_count = 0;
- std::same_as<std::ranges::subrange<int *>> auto ret = std::ranges::find_last_if_not(a,
- [&](int i) { ++predicate_count; return i != 2; },
- [&](int i) { ++projection_count; return i; });
- assert(ret.data() == a + 1);
- assert(*ret.data() == 2);
- assert(predicate_count == 4);
- assert(projection_count == 4);
- }
+{
+ int a[] = {1, 2, 3, 4};
+ int predicate_count = 0;
+ int projection_count = 0;
+ std::same_as<std::ranges::subrange<int*>> auto ret = std::ranges::find_last_if_not(
+ a,
+ [&](int i) {
+ ++predicate_count;
+ return i != 2;
+ },
+ [&](int i) {
+ ++projection_count;
+ return i;
+ });
+ assert(ret.data() == a + 1);
+ assert(*ret.data() == 2);
+ assert(predicate_count == 4);
+ assert(projection_count == 4);
+}
+}
- }
+{// check that the return type of `iter::operator*` doesn't change
+ {NonConstComparableValue a[] = {NonConstComparableValue{}};
+std::same_as<std::ranges::subrange<NonConstComparableValue*>> auto ret =
+ std::ranges::find_last_if_not(a, a + 1, [](auto&& e) { return e != NonConstComparableValue{}; });
+assert(ret.data() == a);
+}
- {// check that the return type of `iter::operator*` doesn't change
- {
- NonConstComparableValue a[] = {NonConstComparableValue{}};
- std::same_as<std::ranges::subrange<NonConstComparableValue *>> auto ret = std::ranges::find_last_if_not(a, a + 1, [](auto&& e) { return e != NonConstComparableValue{}; });
- assert(ret.data() == a);
- }
+{
+ NonConstComparableValue a[] = {NonConstComparableValue{}};
+ std::same_as<std::ranges::borrowed_subrange_t<NonConstComparableValue(&)[1]>> auto ret =
+ std::ranges::find_last_if_not(a, [](auto&& e) { return e != NonConstComparableValue{}; });
+ assert(ret.data() == a);
+}
+}
- {
- NonConstComparableValue a[] = {NonConstComparableValue{}};
- std::same_as<std::ranges::borrowed_subrange_t<NonConstComparableValue (&)[1]>> auto ret = std::ranges::find_last_if_not(a, [](auto&& e) { return e != NonConstComparableValue{}; });
- assert(ret.data() == a);
- }
+{ // check that the implicit conversion to bool works
+ {
+ int a[] = {1, 2, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret =
+ std::ranges::find_last_if_not(a, a + 4, [](const int& i) { return BooleanTestable{i != 3}; });
+ assert(ret.data() == a + 2);
}
-
- {// check that the implicit conversion to bool works
-
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::subrange<int *>> auto ret = std::ranges::find_last_if_not(a, a + 4, [](const int& i) { return BooleanTestable{i != 3}; });
- assert(ret.data() == a + 2);
- }
- {
- int a[] = {1, 2, 3, 4};
- std::same_as<std::ranges::subrange<int *>> auto ret = std::ranges::find_last_if_not(a, [](const int& b) { return BooleanTestable{b != 3}; });
- assert(ret.data() == a + 2);
- }
-
+ {
+ int a[] = {1, 2, 3, 4};
+ std::same_as<std::ranges::subrange<int*>> auto ret =
+ std::ranges::find_last_if_not(a, [](const int& b) { return BooleanTestable{b != 3}; });
+ assert(ret.data() == a + 2);
}
+}
- return true;
+return true;
}
int main(int, char**) {
diff --git a/libcxx/test/support/almost_satisfies_types.h b/libcxx/test/support/almost_satisfies_types.h
index 1444e5a89274..9d26dc9a2a52 100644
--- a/libcxx/test/support/almost_satisfies_types.h
+++ b/libcxx/test/support/almost_satisfies_types.h
@@ -85,8 +85,8 @@ static_assert(!std::ranges::input_range<InputRangeNotInputOrOutputIterator>);
// Example predicate that satisfies HasFindLastIfPred
class IndirectUnaryPredicate {
- public:
- bool operator()(int) const;
+public:
+ bool operator()(int) const;
};
static_assert(std::predicate<IndirectUnaryPredicate, int&>);
``````````
</details>
https://github.com/llvm/llvm-project/pull/67270
More information about the libcxx-commits
mailing list