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