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 //===----------------------------------------------------------------------===//
8 
9 // <algorithm>
10 
11 // UNSUPPORTED: c++03, c++11, c++14, c++17
12 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
13 
14 // template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2,
15 //          sentinel_for<I2> S2, class Pred = ranges::equal_to,
16 //          class Proj1 = identity, class Proj2 = identity>
17 //   requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
18 //   constexpr subrange<I1>
19 //     ranges::search(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
20 //                    Proj1 proj1 = {}, Proj2 proj2 = {});
21 // template<forward_range R1, forward_range R2, class Pred = ranges::equal_to,
22 //          class Proj1 = identity, class Proj2 = identity>
23 //   requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>
24 //   constexpr borrowed_subrange_t<R1>
25 //     ranges::search(R1&& r1, R2&& r2, Pred pred = {},
26 //                    Proj1 proj1 = {}, Proj2 proj2 = {});
27 
28 #include <algorithm>
29 #include <array>
30 #include <ranges>
31 
32 #include "almost_satisfies_types.h"
33 #include "test_iterators.h"
34 
35 template <class Iter1, class Sent1 = Iter1, class Iter2 = int*, class Sent2 = Iter2>
36 concept HasSearchIt = requires (Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2) {
37   std::ranges::search(first1, last1, first2, last2);
38 };
39 
40 static_assert(HasSearchIt<int*>);
41 static_assert(!HasSearchIt<ForwardIteratorNotDerivedFrom>);
42 static_assert(!HasSearchIt<ForwardIteratorNotIncrementable>);
43 static_assert(!HasSearchIt<int*, SentinelForNotSemiregular>);
44 static_assert(!HasSearchIt<int*, int*, int**>); // not indirectly comparable
45 static_assert(!HasSearchIt<int*, SentinelForNotWeaklyEqualityComparableWith>);
46 static_assert(!HasSearchIt<int*, int*, ForwardIteratorNotDerivedFrom>);
47 static_assert(!HasSearchIt<int*, int*, ForwardIteratorNotIncrementable>);
48 static_assert(!HasSearchIt<int*, int*, int*, SentinelForNotSemiregular>);
49 static_assert(!HasSearchIt<int*, int*, int*, SentinelForNotWeaklyEqualityComparableWith>);
50 
51 template <class Range1, class Range2 = UncheckedRange<int*>>
52 concept HasSearchR = requires (Range1 range1, Range2 range2) {
53   std::ranges::search(range1, range2);
54 };
55 
56 static_assert(HasSearchR<UncheckedRange<int*>>);
57 static_assert(!HasSearchR<ForwardRangeNotDerivedFrom>);
58 static_assert(!HasSearchR<ForwardIteratorNotIncrementable>);
59 static_assert(!HasSearchR<ForwardRangeNotSentinelSemiregular>);
60 static_assert(!HasSearchR<ForwardRangeNotSentinelEqualityComparableWith>);
61 static_assert(!HasSearchR<UncheckedRange<int*>, UncheckedRange<int**>>); // not indirectly comparable
62 static_assert(!HasSearchR<UncheckedRange<int*>, ForwardRangeNotDerivedFrom>);
63 static_assert(!HasSearchR<UncheckedRange<int*>, ForwardRangeNotIncrementable>);
64 static_assert(!HasSearchR<UncheckedRange<int*>, ForwardRangeNotSentinelSemiregular>);
65 static_assert(!HasSearchR<UncheckedRange<int*>, ForwardRangeNotSentinelEqualityComparableWith>);
66 
67 template <class Iter1, class Sent1, class Iter2, class Sent2 = Iter2>
test_iterators()68 constexpr void test_iterators() {
69   { // simple test
70     {
71       int a[] = {1, 2, 3, 4, 5, 6};
72       int p[] = {3, 4};
73       std::same_as<std::ranges::subrange<Iter1, Iter1>> decltype(auto) ret =
74           std::ranges::search(Iter1(a), Sent1(Iter1(a + 6)), Iter2(p), Sent2(Iter2(p + 2)));
75       assert(base(ret.begin()) == a + 2);
76       assert(base(ret.end()) == a + 4);
77     }
78     {
79       int a[] = {1, 2, 3, 4, 5, 6};
80       int p[] = {3, 4};
81       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
82       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
83       std::same_as<std::ranges::subrange<Iter1, Iter1>> decltype(auto) ret = std::ranges::search(range1, range2);
84       assert(base(ret.begin()) == a + 2);
85       assert(base(ret.end()) == a + 4);
86     }
87   }
88 
89   { // matching part begins at the front
90     {
91       int a[] = {7, 5, 3, 7, 3, 6};
92       int p[] = {7, 5, 3};
93       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 6)), Iter2(p), Sent2(Iter2(p + 3)));
94       assert(base(ret.begin()) == a);
95       assert(base(ret.end()) == a + 3);
96     }
97     {
98       int a[] = {7, 5, 3, 7, 3, 6};
99       int p[] = {7, 5, 3};
100       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
101       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
102       auto ret = std::ranges::search(range1, range2);
103       assert(base(ret.begin()) == a);
104       assert(base(ret.end()) == a + 3);
105     }
106   }
107 
108   { // matching part ends at the back
109     {
110       int a[] = {9, 3, 6, 4, 8};
111       int p[] = {4, 8};
112       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 5)), Iter2(p), Sent2(Iter2(p + 2)));
113       assert(base(ret.begin()) == a + 3);
114       assert(base(ret.end()) == a + 5);
115     }
116     {
117       int a[] = {9, 3, 6, 4, 8};
118       int p[] = {4, 8};
119       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
120       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
121       auto ret = std::ranges::search(range1, range2);
122       assert(base(ret.begin()) == a + 3);
123       assert(base(ret.end()) == a + 5);
124     }
125   }
126 
127   { // pattern does not match
128     {
129       int a[] = {9, 3, 6, 4, 8};
130       int p[] = {1};
131       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 5)), Iter2(p), Sent2(Iter2(p + 1)));
132       assert(base(ret.begin()) == a + 5);
133       assert(base(ret.end()) == a + 5);
134     }
135     {
136       int a[] = {9, 3, 6, 4, 8};
137       int p[] = {1};
138       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
139       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
140       auto ret = std::ranges::search(range1, range2);
141       assert(base(ret.begin()) == a + 5);
142       assert(base(ret.end()) == a + 5);
143     }
144   }
145 
146   { // range and pattern are identical
147     {
148       int a[] = {6, 7, 8, 9};
149       int p[] = {6, 7, 8, 9};
150       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 4)), Iter2(p), Sent2(Iter2(p + 4)));
151       assert(base(ret.begin()) == a);
152       assert(base(ret.end()) == a + 4);
153     }
154     {
155       int a[] = {6, 7, 8, 9};
156       int p[] = {6, 7, 8, 9};
157       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 4)));
158       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 4)));
159       auto ret = std::ranges::search(range1, range2);
160       assert(base(ret.begin()) == a);
161       assert(base(ret.end()) == a + 4);
162     }
163   }
164 
165   { // pattern is longer than range
166     {
167       int a[] = {6, 7, 8};
168       int p[] = {6, 7, 8, 9};
169       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 3)), Iter2(p), Sent2(Iter2(p + 4)));
170       assert(base(ret.begin()) == a + 3);
171       assert(base(ret.end()) == a + 3);
172     }
173     {
174       int a[] = {6, 7, 8};
175       int p[] = {6, 7, 8, 9};
176       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 3)));
177       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 4)));
178       auto ret = std::ranges::search(range1, range2);
179       assert(base(ret.begin()) == a + 3);
180       assert(base(ret.end()) == a + 3);
181     }
182   }
183 
184   { // pattern has zero length
185     {
186       int a[] = {6, 7, 8};
187       int p[] = {};
188       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 3)), Iter2(p), Sent2(Iter2(p)));
189       assert(base(ret.begin()) == a);
190       assert(base(ret.end()) == a);
191     }
192     {
193       int a[] = {6, 7, 8};
194       int p[] = {};
195       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 3)));
196       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p)));
197       auto ret = std::ranges::search(range1, range2);
198       assert(base(ret.begin()) == a);
199       assert(base(ret.end()) == a);
200     }
201   }
202 
203   { // range has zero length
204     {
205       int a[] = {};
206       int p[] = {6, 7, 8};
207       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a)), Iter2(p), Sent2(Iter2(p + 3)));
208       assert(base(ret.begin()) == a);
209       assert(base(ret.end()) == a);
210     }
211     {
212       int a[] = {};
213       int p[] = {6, 7, 8};
214       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
215       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
216       auto ret = std::ranges::search(range1, range2);
217       assert(base(ret.begin()) == a);
218       assert(base(ret.end()) == a);
219     }
220   }
221 
222   { // check that the first match is returned
223     {
224       int a[] = {6, 7, 8, 6, 7, 8, 6, 7, 8};
225       int p[] = {6, 7, 8};
226       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 9)), Iter2(p), Sent2(Iter2(p + 3)));
227       assert(base(ret.begin()) == a);
228       assert(base(ret.end()) == a + 3);
229     }
230     {
231       int a[] = {6, 7, 8, 6, 7, 8, 6, 7, 8};
232       int p[] = {6, 7, 8};
233       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 9)));
234       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
235       auto ret = std::ranges::search(range1, range2);
236       assert(base(ret.begin()) == a);
237       assert(base(ret.end()) == a + 3);
238     }
239   }
240 
241   { // check that the predicate is used
242     {
243       int a[] = {1, 2, 8, 1, 5, 6};
244       int p[] = {7, 0, 4};
245       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 6)),
246                                      Iter2(p), Sent2(Iter2(p + 3)),
247                                      [](int l, int r) { return l > r; });
248       assert(base(ret.begin()) == a + 2);
249       assert(base(ret.end()) == a + 5);
250     }
251     {
252       int a[] = {1, 2, 8, 1, 5, 6};
253       int p[] = {7, 0, 4};
254       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
255       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
256       auto ret = std::ranges::search(range1, range2, [](int l, int r) { return l > r; });
257       assert(base(ret.begin()) == a + 2);
258       assert(base(ret.end()) == a + 5);
259     }
260   }
261 
262   { // check that the projections are used
263     {
264       int a[] = {1, 3, 5, 1, 5, 6};
265       int p[] = {2, 3, 4};
266       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 6)),
267                                      Iter2(p), Sent2(Iter2(p + 3)),
268                                      {},
269                                      [](int i) { return i + 3; },
270                                      [](int i) { return i * 2; });
271       assert(base(ret.begin()) == a);
272       assert(base(ret.end()) == a + 3);
273     }
274     {
275       int a[] = {1, 3, 5, 1, 5, 6};
276       int p[] = {2, 3, 4};
277       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
278       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
279       auto ret = std::ranges::search(range1,
280                                      range2,
281                                      {},
282                                      [](int i) { return i + 3; },
283                                      [](int i) { return i * 2; });
284       assert(base(ret.begin()) == a);
285       assert(base(ret.end()) == a + 3);
286     }
287   }
288 }
289 
290 template <class Iter1, class Sent1 = Iter1>
test_iterators2()291 constexpr void test_iterators2() {
292   test_iterators<Iter1, Sent1, forward_iterator<int*>>();
293   test_iterators<Iter1, Sent1, forward_iterator<int*>, sized_sentinel<forward_iterator<int*>>>();
294   test_iterators<Iter1, Sent1, bidirectional_iterator<int*>>();
295   test_iterators<Iter1, Sent1, bidirectional_iterator<int*>, sized_sentinel<bidirectional_iterator<int*>>>();
296   test_iterators<Iter1, Sent1, random_access_iterator<int*>>();
297   test_iterators<Iter1, Sent1, random_access_iterator<int*>, sized_sentinel<random_access_iterator<int*>>>();
298   test_iterators<Iter1, Sent1, contiguous_iterator<int*>>();
299   test_iterators<Iter1, Sent1, contiguous_iterator<int*>, sized_sentinel<contiguous_iterator<int*>>>();
300   test_iterators<Iter1, Sent1, int*>();
301 }
302 
test()303 constexpr bool test() {
304   test_iterators2<forward_iterator<int*>>();
305   test_iterators2<forward_iterator<int*>, sized_sentinel<forward_iterator<int*>>>();
306   test_iterators2<bidirectional_iterator<int*>>();
307   test_iterators2<bidirectional_iterator<int*>, sized_sentinel<bidirectional_iterator<int*>>>();
308   test_iterators2<random_access_iterator<int*>>();
309   test_iterators2<random_access_iterator<int*>, sized_sentinel<random_access_iterator<int*>>>();
310   test_iterators2<contiguous_iterator<int*>>();
311   test_iterators2<contiguous_iterator<int*>, sized_sentinel<contiguous_iterator<int*>>>();
312   test_iterators2<int*>();
313 
314   { // check that std::invoke is used
315     struct S {
316       int i;
317 
318       constexpr S identity() {
319         return *this;
320       }
321 
322       constexpr bool compare(const S& s) {
323         return i == s.i;
324       }
325     };
326     {
327       S a[] = {{1}, {2}, {3}, {4}};
328       S p[] = {{2}, {3}};
329       auto ret = std::ranges::search(a, a + 4, p, p + 2, &S::compare, &S::identity, &S::identity);
330       assert(ret.begin() == a + 1);
331       assert(ret.end() == a + 3);
332     }
333     {
334       S a[] = {{1}, {2}, {3}, {4}};
335       S p[] = {{2}, {3}};
336       auto ret = std::ranges::search(a, p, &S::compare, &S::identity, &S::identity);
337       assert(ret.begin() == a + 1);
338       assert(ret.end() == a + 3);
339     }
340   }
341 
342   { // check that std::ranges::dangling is returned
343     [[maybe_unused]] std::same_as<std::ranges::dangling> decltype(auto) ret =
344         std::ranges::search(std::array {1, 2, 3, 4}, std::array {2, 3});
345   }
346 
347   return true;
348 }
349 
main(int,char **)350 int main(int, char**) {
351   test();
352   static_assert(test());
353 
354   return 0;
355 }
356