Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / std / algorithms / alg.nonmodifying / alg.search / ranges.search.pass.cpp
blobb35729962492b12091698e8853ea2bed015a08d3
1 //===----------------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 // <algorithm>
11 // UNSUPPORTED: c++03, c++11, c++14, c++17
13 // template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2,
14 // sentinel_for<I2> S2, class Pred = ranges::equal_to,
15 // class Proj1 = identity, class Proj2 = identity>
16 // requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
17 // constexpr subrange<I1>
18 // ranges::search(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
19 // Proj1 proj1 = {}, Proj2 proj2 = {});
20 // template<forward_range R1, forward_range R2, class Pred = ranges::equal_to,
21 // class Proj1 = identity, class Proj2 = identity>
22 // requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>
23 // constexpr borrowed_subrange_t<R1>
24 // ranges::search(R1&& r1, R2&& r2, Pred pred = {},
25 // Proj1 proj1 = {}, Proj2 proj2 = {});
27 #include <algorithm>
28 #include <array>
29 #include <ranges>
31 #include "almost_satisfies_types.h"
32 #include "test_iterators.h"
34 template <class Iter1, class Sent1 = Iter1, class Iter2 = int*, class Sent2 = Iter2>
35 concept HasSearchIt = requires (Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2) {
36 std::ranges::search(first1, last1, first2, last2);
39 static_assert(HasSearchIt<int*>);
40 static_assert(!HasSearchIt<ForwardIteratorNotDerivedFrom>);
41 static_assert(!HasSearchIt<ForwardIteratorNotIncrementable>);
42 static_assert(!HasSearchIt<int*, SentinelForNotSemiregular>);
43 static_assert(!HasSearchIt<int*, int*, int**>); // not indirectly comparable
44 static_assert(!HasSearchIt<int*, SentinelForNotWeaklyEqualityComparableWith>);
45 static_assert(!HasSearchIt<int*, int*, ForwardIteratorNotDerivedFrom>);
46 static_assert(!HasSearchIt<int*, int*, ForwardIteratorNotIncrementable>);
47 static_assert(!HasSearchIt<int*, int*, int*, SentinelForNotSemiregular>);
48 static_assert(!HasSearchIt<int*, int*, int*, SentinelForNotWeaklyEqualityComparableWith>);
50 template <class Range1, class Range2 = UncheckedRange<int*>>
51 concept HasSearchR = requires (Range1 range1, Range2 range2) {
52 std::ranges::search(range1, range2);
55 static_assert(HasSearchR<UncheckedRange<int*>>);
56 static_assert(!HasSearchR<ForwardRangeNotDerivedFrom>);
57 static_assert(!HasSearchR<ForwardIteratorNotIncrementable>);
58 static_assert(!HasSearchR<ForwardRangeNotSentinelSemiregular>);
59 static_assert(!HasSearchR<ForwardRangeNotSentinelEqualityComparableWith>);
60 static_assert(!HasSearchR<UncheckedRange<int*>, UncheckedRange<int**>>); // not indirectly comparable
61 static_assert(!HasSearchR<UncheckedRange<int*>, ForwardRangeNotDerivedFrom>);
62 static_assert(!HasSearchR<UncheckedRange<int*>, ForwardRangeNotIncrementable>);
63 static_assert(!HasSearchR<UncheckedRange<int*>, ForwardRangeNotSentinelSemiregular>);
64 static_assert(!HasSearchR<UncheckedRange<int*>, ForwardRangeNotSentinelEqualityComparableWith>);
66 template <class Iter1, class Sent1, class Iter2, class Sent2 = Iter2>
67 constexpr void test_iterators() {
68 { // simple test
70 int a[] = {1, 2, 3, 4, 5, 6};
71 int p[] = {3, 4};
72 std::same_as<std::ranges::subrange<Iter1, Iter1>> decltype(auto) ret =
73 std::ranges::search(Iter1(a), Sent1(Iter1(a + 6)), Iter2(p), Sent2(Iter2(p + 2)));
74 assert(base(ret.begin()) == a + 2);
75 assert(base(ret.end()) == a + 4);
78 int a[] = {1, 2, 3, 4, 5, 6};
79 int p[] = {3, 4};
80 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
81 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
82 std::same_as<std::ranges::subrange<Iter1, Iter1>> decltype(auto) ret = std::ranges::search(range1, range2);
83 assert(base(ret.begin()) == a + 2);
84 assert(base(ret.end()) == a + 4);
88 { // matching part begins at the front
90 int a[] = {7, 5, 3, 7, 3, 6};
91 int p[] = {7, 5, 3};
92 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 6)), Iter2(p), Sent2(Iter2(p + 3)));
93 assert(base(ret.begin()) == a);
94 assert(base(ret.end()) == a + 3);
97 int a[] = {7, 5, 3, 7, 3, 6};
98 int p[] = {7, 5, 3};
99 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
100 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
101 auto ret = std::ranges::search(range1, range2);
102 assert(base(ret.begin()) == a);
103 assert(base(ret.end()) == a + 3);
107 { // matching part ends at the back
109 int a[] = {9, 3, 6, 4, 8};
110 int p[] = {4, 8};
111 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 5)), Iter2(p), Sent2(Iter2(p + 2)));
112 assert(base(ret.begin()) == a + 3);
113 assert(base(ret.end()) == a + 5);
116 int a[] = {9, 3, 6, 4, 8};
117 int p[] = {4, 8};
118 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
119 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
120 auto ret = std::ranges::search(range1, range2);
121 assert(base(ret.begin()) == a + 3);
122 assert(base(ret.end()) == a + 5);
126 { // pattern does not match
128 int a[] = {9, 3, 6, 4, 8};
129 int p[] = {1};
130 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 5)), Iter2(p), Sent2(Iter2(p + 1)));
131 assert(base(ret.begin()) == a + 5);
132 assert(base(ret.end()) == a + 5);
135 int a[] = {9, 3, 6, 4, 8};
136 int p[] = {1};
137 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
138 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
139 auto ret = std::ranges::search(range1, range2);
140 assert(base(ret.begin()) == a + 5);
141 assert(base(ret.end()) == a + 5);
145 { // range and pattern are identical
147 int a[] = {6, 7, 8, 9};
148 int p[] = {6, 7, 8, 9};
149 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 4)), Iter2(p), Sent2(Iter2(p + 4)));
150 assert(base(ret.begin()) == a);
151 assert(base(ret.end()) == a + 4);
154 int a[] = {6, 7, 8, 9};
155 int p[] = {6, 7, 8, 9};
156 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 4)));
157 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 4)));
158 auto ret = std::ranges::search(range1, range2);
159 assert(base(ret.begin()) == a);
160 assert(base(ret.end()) == a + 4);
164 { // pattern is longer than range
166 int a[] = {6, 7, 8};
167 int p[] = {6, 7, 8, 9};
168 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 3)), Iter2(p), Sent2(Iter2(p + 4)));
169 assert(base(ret.begin()) == a + 3);
170 assert(base(ret.end()) == a + 3);
173 int a[] = {6, 7, 8};
174 int p[] = {6, 7, 8, 9};
175 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 3)));
176 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 4)));
177 auto ret = std::ranges::search(range1, range2);
178 assert(base(ret.begin()) == a + 3);
179 assert(base(ret.end()) == a + 3);
183 { // pattern has zero length
185 int a[] = {6, 7, 8};
186 int p[] = {};
187 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 3)), Iter2(p), Sent2(Iter2(p)));
188 assert(base(ret.begin()) == a);
189 assert(base(ret.end()) == a);
192 int a[] = {6, 7, 8};
193 int p[] = {};
194 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 3)));
195 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p)));
196 auto ret = std::ranges::search(range1, range2);
197 assert(base(ret.begin()) == a);
198 assert(base(ret.end()) == a);
202 { // range has zero length
204 int a[] = {};
205 int p[] = {6, 7, 8};
206 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a)), Iter2(p), Sent2(Iter2(p + 3)));
207 assert(base(ret.begin()) == a);
208 assert(base(ret.end()) == a);
211 int a[] = {};
212 int p[] = {6, 7, 8};
213 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
214 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
215 auto ret = std::ranges::search(range1, range2);
216 assert(base(ret.begin()) == a);
217 assert(base(ret.end()) == a);
221 { // check that the first match is returned
223 int a[] = {6, 7, 8, 6, 7, 8, 6, 7, 8};
224 int p[] = {6, 7, 8};
225 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 9)), Iter2(p), Sent2(Iter2(p + 3)));
226 assert(base(ret.begin()) == a);
227 assert(base(ret.end()) == a + 3);
230 int a[] = {6, 7, 8, 6, 7, 8, 6, 7, 8};
231 int p[] = {6, 7, 8};
232 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 9)));
233 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
234 auto ret = std::ranges::search(range1, range2);
235 assert(base(ret.begin()) == a);
236 assert(base(ret.end()) == a + 3);
240 { // check that the predicate is used
242 int a[] = {1, 2, 8, 1, 5, 6};
243 int p[] = {7, 0, 4};
244 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 6)),
245 Iter2(p), Sent2(Iter2(p + 3)),
246 [](int l, int r) { return l > r; });
247 assert(base(ret.begin()) == a + 2);
248 assert(base(ret.end()) == a + 5);
251 int a[] = {1, 2, 8, 1, 5, 6};
252 int p[] = {7, 0, 4};
253 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
254 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
255 auto ret = std::ranges::search(range1, range2, [](int l, int r) { return l > r; });
256 assert(base(ret.begin()) == a + 2);
257 assert(base(ret.end()) == a + 5);
261 { // check that the projections are used
263 int a[] = {1, 3, 5, 1, 5, 6};
264 int p[] = {2, 3, 4};
265 auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 6)),
266 Iter2(p), Sent2(Iter2(p + 3)),
268 [](int i) { return i + 3; },
269 [](int i) { return i * 2; });
270 assert(base(ret.begin()) == a);
271 assert(base(ret.end()) == a + 3);
274 int a[] = {1, 3, 5, 1, 5, 6};
275 int p[] = {2, 3, 4};
276 auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
277 auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
278 auto ret = std::ranges::search(range1,
279 range2,
281 [](int i) { return i + 3; },
282 [](int i) { return i * 2; });
283 assert(base(ret.begin()) == a);
284 assert(base(ret.end()) == a + 3);
289 template <class Iter1, class Sent1 = Iter1>
290 constexpr void test_iterators2() {
291 test_iterators<Iter1, Sent1, forward_iterator<int*>>();
292 test_iterators<Iter1, Sent1, forward_iterator<int*>, sized_sentinel<forward_iterator<int*>>>();
293 test_iterators<Iter1, Sent1, bidirectional_iterator<int*>>();
294 test_iterators<Iter1, Sent1, bidirectional_iterator<int*>, sized_sentinel<bidirectional_iterator<int*>>>();
295 test_iterators<Iter1, Sent1, random_access_iterator<int*>>();
296 test_iterators<Iter1, Sent1, random_access_iterator<int*>, sized_sentinel<random_access_iterator<int*>>>();
297 test_iterators<Iter1, Sent1, contiguous_iterator<int*>>();
298 test_iterators<Iter1, Sent1, contiguous_iterator<int*>, sized_sentinel<contiguous_iterator<int*>>>();
299 test_iterators<Iter1, Sent1, int*>();
302 constexpr bool test() {
303 test_iterators2<forward_iterator<int*>>();
304 test_iterators2<forward_iterator<int*>, sized_sentinel<forward_iterator<int*>>>();
305 test_iterators2<bidirectional_iterator<int*>>();
306 test_iterators2<bidirectional_iterator<int*>, sized_sentinel<bidirectional_iterator<int*>>>();
307 test_iterators2<random_access_iterator<int*>>();
308 test_iterators2<random_access_iterator<int*>, sized_sentinel<random_access_iterator<int*>>>();
309 test_iterators2<contiguous_iterator<int*>>();
310 test_iterators2<contiguous_iterator<int*>, sized_sentinel<contiguous_iterator<int*>>>();
311 test_iterators2<int*>();
313 { // check that std::invoke is used
314 struct S {
315 int i;
317 constexpr S identity() {
318 return *this;
321 constexpr bool compare(const S& s) {
322 return i == s.i;
326 S a[] = {{1}, {2}, {3}, {4}};
327 S p[] = {{2}, {3}};
328 auto ret = std::ranges::search(a, a + 4, p, p + 2, &S::compare, &S::identity, &S::identity);
329 assert(ret.begin() == a + 1);
330 assert(ret.end() == a + 3);
333 S a[] = {{1}, {2}, {3}, {4}};
334 S p[] = {{2}, {3}};
335 auto ret = std::ranges::search(a, p, &S::compare, &S::identity, &S::identity);
336 assert(ret.begin() == a + 1);
337 assert(ret.end() == a + 3);
341 { // check that std::ranges::dangling is returned
342 [[maybe_unused]] std::same_as<std::ranges::dangling> decltype(auto) ret =
343 std::ranges::search(std::array {1, 2, 3, 4}, std::array {2, 3});
346 return true;
349 int main(int, char**) {
350 test();
351 static_assert(test());
353 return 0;