1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 // UNSUPPORTED: c++03, c++11, c++14, c++17
13 // template<input_iterator I, sentinel_for<I> S, class Proj = identity,
14 // indirect_unary_predicate<projected<I, Proj>> Pred>
15 // constexpr I ranges::find_if_not(I first, S last, Pred pred, Proj proj = {});
16 // template<input_range R, class Proj = identity,
17 // indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
18 // constexpr borrowed_iterator_t<R>
19 // ranges::find_if_not(R&& r, Pred pred, Proj proj = {});
26 #include "almost_satisfies_types.h"
27 #include "boolean_testable.h"
28 #include "test_iterators.h"
34 template <class It
, class Sent
= It
>
35 concept HasFindIfNotIt
= requires(It it
, Sent sent
) { std::ranges::find_if_not(it
, sent
, Predicate
{}); };
36 static_assert(HasFindIfNotIt
<int*>);
37 static_assert(!HasFindIfNotIt
<InputIteratorNotDerivedFrom
>);
38 static_assert(!HasFindIfNotIt
<InputIteratorNotIndirectlyReadable
>);
39 static_assert(!HasFindIfNotIt
<InputIteratorNotInputOrOutputIterator
>);
40 static_assert(!HasFindIfNotIt
<cpp20_input_iterator
<int*>, SentinelForNotSemiregular
>);
41 static_assert(!HasFindIfNotIt
<cpp20_input_iterator
<int*>, InputRangeNotSentinelEqualityComparableWith
>);
43 static_assert(!HasFindIfNotIt
<int*, int>);
44 static_assert(!HasFindIfNotIt
<int, int*>);
47 concept HasFindIfNotPred
= requires(int* it
, Pred pred
) {std::ranges::find_if_not(it
, it
, pred
); };
49 static_assert(!HasFindIfNotPred
<IndirectUnaryPredicateNotCopyConstructible
>);
50 static_assert(!HasFindIfNotPred
<IndirectUnaryPredicateNotPredicate
>);
53 concept HasFindIfNotR
= requires(R r
) { std::ranges::find_if_not(r
, Predicate
{}); };
54 static_assert(HasFindIfNotR
<std::array
<int, 0>>);
55 static_assert(!HasFindIfNotR
<int>);
56 static_assert(!HasFindIfNotR
<InputRangeNotDerivedFrom
>);
57 static_assert(!HasFindIfNotR
<InputRangeNotIndirectlyReadable
>);
58 static_assert(!HasFindIfNotR
<InputRangeNotInputOrOutputIterator
>);
59 static_assert(!HasFindIfNotR
<InputRangeNotSentinelSemiregular
>);
60 static_assert(!HasFindIfNotR
<InputRangeNotSentinelEqualityComparableWith
>);
62 template <class It
, class Sent
= It
>
63 constexpr void test_iterators() {
65 int a
[] = {1, 2, 3, 4};
66 std::same_as
<It
> auto ret
= std::ranges::find_if_not(It(a
), Sent(It(a
+ 4)), [c
= 0](int) mutable { return c
++ <= 2; });
67 assert(base(ret
) == a
+ 3);
71 int a
[] = {1, 2, 3, 4};
72 auto range
= std::ranges::subrange(It(a
), Sent(It(a
+ 4)));
73 std::same_as
<It
> auto ret
= std::ranges::find_if_not(range
, [c
= 0](int) mutable { return c
++ <= 2; });
74 assert(base(ret
) == a
+ 3);
79 struct NonConstComparableLValue
{
80 friend constexpr bool operator==(const NonConstComparableLValue
&, const NonConstComparableLValue
&) { return false; }
81 friend constexpr bool operator==(NonConstComparableLValue
&, NonConstComparableLValue
&) { return false; }
82 friend constexpr bool operator==(const NonConstComparableLValue
&, NonConstComparableLValue
&) { return false; }
83 friend constexpr bool operator==(NonConstComparableLValue
&, const NonConstComparableLValue
&) { return true; }
86 constexpr bool test() {
87 test_iterators
<int*>();
88 test_iterators
<const int*>();
89 test_iterators
<cpp20_input_iterator
<int*>, sentinel_wrapper
<cpp20_input_iterator
<int*>>>();
90 test_iterators
<bidirectional_iterator
<int*>>();
91 test_iterators
<forward_iterator
<int*>>();
92 test_iterators
<random_access_iterator
<int*>>();
93 test_iterators
<contiguous_iterator
<int*>>();
95 { // check that projections are used properly and that they are called with the iterator directly
97 int a
[] = {1, 2, 3, 4};
98 auto ret
= std::ranges::find_if_not(a
, a
+ 4, [&](int* i
) { return i
!= a
+ 3; }, [](int& i
) { return &i
; });
102 int a
[] = {1, 2, 3, 4};
103 auto ret
= std::ranges::find_if_not(a
, [&](int* i
) { return i
!= a
+ 3; }, [](int& i
) { return &i
; });
104 assert(ret
== a
+ 3);
109 // check that the first element is returned
115 S a
[] = { {0, 0}, {0, 2}, {0, 1} };
116 auto ret
= std::ranges::find_if_not(a
, [](int i
){ return i
!= 0; }, &S::comp
);
118 assert(ret
->comp
== 0);
119 assert(ret
->other
== 0);
126 S a
[] = { {0, 0}, {0, 2}, {0, 1} };
127 auto ret
= std::ranges::find_if_not(a
, a
+ 3, [](int i
) { return i
!= 0; }, &S::comp
);
129 assert(ret
->comp
== 0);
130 assert(ret
->other
== 0);
135 // check that end + 1 iterator is returned with no match
138 auto ret
= std::ranges::find_if(a
, a
+ 3, [](int) { return false; });
139 assert(ret
== a
+ 3);
143 auto ret
= std::ranges::find_if(a
, [](int){ return false; });
144 assert(ret
== a
+ 3);
148 { // check that ranges::dangling is returned
149 [[maybe_unused
]] std::same_as
<std::ranges::dangling
> auto ret
=
150 std::ranges::find_if_not(std::array
{1, 2}, [](int){ return true; });
153 { // check that an iterator is returned with a borrowing range
154 int a
[] = {1, 2, 3, 4};
155 std::same_as
<int*> auto ret
= std::ranges::find_if_not(std::views::all(a
), [](int){ return false; });
160 { // check that std::invoke is used
162 S a
[] = { S
{1}, S
{3}, S
{2} };
163 std::same_as
<S
*> auto ret
= std::ranges::find_if_not(a
, [](int) { return true; }, &S::i
);
164 assert(ret
== a
+ 3);
167 { // count projection and predicate invocation count
169 int a
[] = {1, 2, 3, 4};
170 int predicate_count
= 0;
171 int projection_count
= 0;
172 auto ret
= std::ranges::find_if_not(a
, a
+ 4,
173 [&](int i
) { ++predicate_count
; return i
!= 2; },
174 [&](int i
) { ++projection_count
; return i
; });
175 assert(ret
== a
+ 1);
177 assert(predicate_count
== 2);
178 assert(projection_count
== 2);
181 int a
[] = {1, 2, 3, 4};
182 int predicate_count
= 0;
183 int projection_count
= 0;
184 auto ret
= std::ranges::find_if_not(a
,
185 [&](int i
) { ++predicate_count
; return i
!= 2; },
186 [&](int i
) { ++projection_count
; return i
; });
187 assert(ret
== a
+ 1);
189 assert(predicate_count
== 2);
190 assert(projection_count
== 2);
194 { // check that the return type of `iter::operator*` doesn't change
196 NonConstComparableLValue a
[] = { NonConstComparableLValue
{} };
197 auto ret
= std::ranges::find_if_not(a
, a
+ 1, [](auto&& e
) { return e
!= NonConstComparableLValue
{}; });
201 NonConstComparableLValue a
[] = { NonConstComparableLValue
{} };
202 auto ret
= std::ranges::find_if_not(a
, [](auto&& e
) { return e
!= NonConstComparableLValue
{}; });
208 // check that an empty range works
210 std::array
<int ,0> a
= {};
211 auto ret
= std::ranges::find_if_not(a
.begin(), a
.end(), [](int) { return true; });
212 assert(ret
== a
.begin());
215 std::array
<int, 0> a
= {};
216 auto ret
= std::ranges::find_if_not(a
, [](int) { return true; });
217 assert(ret
== a
.begin());
222 // check that the implicit conversion to bool works
224 int a
[] = {1, 2, 3, 4};
225 auto ret
= std::ranges::find_if_not(a
, a
+ 4, [](const int& i
) { return BooleanTestable
{i
!= 3}; });
226 assert(ret
== a
+ 2);
229 int a
[] = {1, 2, 3, 4};
230 auto ret
= std::ranges::find_if_not(a
, [](const int& b
) { return BooleanTestable
{b
!= 3}; });
231 assert(ret
== a
+ 2);
238 int main(int, char**) {
240 static_assert(test());