1101d1e9bSNikolas Klauser //===----------------------------------------------------------------------===//
2101d1e9bSNikolas Klauser //
3101d1e9bSNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4101d1e9bSNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
5101d1e9bSNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6101d1e9bSNikolas Klauser //
7101d1e9bSNikolas Klauser //===----------------------------------------------------------------------===//
8101d1e9bSNikolas Klauser
9101d1e9bSNikolas Klauser // <algorithm>
10101d1e9bSNikolas Klauser
11101d1e9bSNikolas Klauser // UNSUPPORTED: c++03, c++11, c++14, c++17
12101d1e9bSNikolas Klauser
13101d1e9bSNikolas Klauser // template<forward_iterator I, sentinel_for<I> S, class T,
14101d1e9bSNikolas Klauser // class Pred = ranges::equal_to, class Proj = identity>
15101d1e9bSNikolas Klauser // requires indirectly_comparable<I, const T*, Pred, Proj>
16101d1e9bSNikolas Klauser // constexpr subrange<I>
17101d1e9bSNikolas Klauser // ranges::search_n(I first, S last, iter_difference_t<I> count,
18101d1e9bSNikolas Klauser // const T& value, Pred pred = {}, Proj proj = {});
19101d1e9bSNikolas Klauser // template<forward_range R, class T, class Pred = ranges::equal_to,
20101d1e9bSNikolas Klauser // class Proj = identity>
21101d1e9bSNikolas Klauser // requires indirectly_comparable<iterator_t<R>, const T*, Pred, Proj>
22101d1e9bSNikolas Klauser // constexpr borrowed_subrange_t<R>
23101d1e9bSNikolas Klauser // ranges::search_n(R&& r, range_difference_t<R> count,
24101d1e9bSNikolas Klauser // const T& value, Pred pred = {}, Proj proj = {});
25101d1e9bSNikolas Klauser
26101d1e9bSNikolas Klauser #include <algorithm>
27101d1e9bSNikolas Klauser #include <array>
28101d1e9bSNikolas Klauser #include <ranges>
29101d1e9bSNikolas Klauser
30101d1e9bSNikolas Klauser #include "almost_satisfies_types.h"
31101d1e9bSNikolas Klauser #include "test_iterators.h"
32101d1e9bSNikolas Klauser
33101d1e9bSNikolas Klauser template <class Iter1, class Sent1 = Iter1>
34101d1e9bSNikolas Klauser concept HasSearchNIt = requires (Iter1 first1, Sent1 last1) {
35101d1e9bSNikolas Klauser std::ranges::search_n(first1, last1, 0, 0);
36101d1e9bSNikolas Klauser };
37101d1e9bSNikolas Klauser
38101d1e9bSNikolas Klauser static_assert(HasSearchNIt<int*>);
39101d1e9bSNikolas Klauser static_assert(!HasSearchNIt<ForwardIteratorNotDerivedFrom>);
40101d1e9bSNikolas Klauser static_assert(!HasSearchNIt<ForwardIteratorNotIncrementable>);
41101d1e9bSNikolas Klauser static_assert(!HasSearchNIt<int*, SentinelForNotSemiregular>);
42101d1e9bSNikolas Klauser static_assert(!HasSearchNIt<int*, SentinelForNotWeaklyEqualityComparableWith>);
43101d1e9bSNikolas Klauser static_assert(!HasSearchNIt<int**, int**>); // not indirectly comparable
44101d1e9bSNikolas Klauser
45101d1e9bSNikolas Klauser template <class Range1, class Range2 = UncheckedRange<int*>>
46101d1e9bSNikolas Klauser concept HasSearchNR = requires (Range1 range) {
47101d1e9bSNikolas Klauser std::ranges::search_n(range, 0, 0);
48101d1e9bSNikolas Klauser };
49101d1e9bSNikolas Klauser
50101d1e9bSNikolas Klauser static_assert(HasSearchNR<UncheckedRange<int*>>);
51101d1e9bSNikolas Klauser static_assert(!HasSearchNR<ForwardRangeNotDerivedFrom>);
52101d1e9bSNikolas Klauser static_assert(!HasSearchNR<ForwardIteratorNotIncrementable>);
53101d1e9bSNikolas Klauser static_assert(!HasSearchNR<ForwardRangeNotSentinelSemiregular>);
54101d1e9bSNikolas Klauser static_assert(!HasSearchNR<ForwardRangeNotSentinelEqualityComparableWith>);
55101d1e9bSNikolas Klauser static_assert(!HasSearchNR<UncheckedRange<int**>>); // not indirectly comparable
56101d1e9bSNikolas Klauser
57101d1e9bSNikolas Klauser template <class Iter, class Sent = Iter>
test_iterators()58101d1e9bSNikolas Klauser constexpr void test_iterators() {
59101d1e9bSNikolas Klauser { // simple test
60101d1e9bSNikolas Klauser {
61101d1e9bSNikolas Klauser int a[] = {1, 2, 3, 4, 5, 6};
62101d1e9bSNikolas Klauser std::same_as<std::ranges::subrange<Iter, Iter>> decltype(auto) ret =
63101d1e9bSNikolas Klauser std::ranges::search_n(Iter(a), Sent(Iter(a + 6)), 1, 3);
64101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 2);
65101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 3);
66101d1e9bSNikolas Klauser }
67101d1e9bSNikolas Klauser {
68101d1e9bSNikolas Klauser int a[] = {1, 2, 3, 4, 5, 6};
69101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 6)));
70101d1e9bSNikolas Klauser std::same_as<std::ranges::subrange<Iter, Iter>> decltype(auto) ret = std::ranges::search_n(range, 1, 3);
71101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 2);
72101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 3);
73101d1e9bSNikolas Klauser }
74101d1e9bSNikolas Klauser }
75101d1e9bSNikolas Klauser
76101d1e9bSNikolas Klauser { // matching part begins at the front
77101d1e9bSNikolas Klauser {
78101d1e9bSNikolas Klauser int a[] = {7, 7, 3, 7, 3, 6};
79101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a + 6)), 2, 7);
80101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
81101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 2);
82101d1e9bSNikolas Klauser }
83101d1e9bSNikolas Klauser {
84101d1e9bSNikolas Klauser int a[] = {7, 7, 3, 7, 3, 6};
85101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 6)));
86101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range, 2, 7);
87101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
88101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 2);
89101d1e9bSNikolas Klauser }
90101d1e9bSNikolas Klauser }
91101d1e9bSNikolas Klauser
92101d1e9bSNikolas Klauser { // matching part ends at the back
93101d1e9bSNikolas Klauser {
94101d1e9bSNikolas Klauser int a[] = {9, 3, 6, 4, 4};
95101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a + 5)), 2, 4);
96101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 3);
97101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 5);
98101d1e9bSNikolas Klauser }
99101d1e9bSNikolas Klauser {
100101d1e9bSNikolas Klauser int a[] = {9, 3, 6, 4, 4};
101101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 5)));
102101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range, 2, 4);
103101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 3);
104101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 5);
105101d1e9bSNikolas Klauser }
106101d1e9bSNikolas Klauser }
107101d1e9bSNikolas Klauser
108101d1e9bSNikolas Klauser { // pattern does not match
109101d1e9bSNikolas Klauser {
110101d1e9bSNikolas Klauser int a[] = {9, 3, 6, 4, 8};
111101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a + 5)), 1, 1);
112101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 5);
113101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 5);
114101d1e9bSNikolas Klauser }
115101d1e9bSNikolas Klauser {
116101d1e9bSNikolas Klauser int a[] = {9, 3, 6, 4, 8};
117101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 5)));
118101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range, 1, 1);
119101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 5);
120101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 5);
121101d1e9bSNikolas Klauser }
122101d1e9bSNikolas Klauser }
123101d1e9bSNikolas Klauser
124101d1e9bSNikolas Klauser { // range and pattern are identical
125101d1e9bSNikolas Klauser {
126101d1e9bSNikolas Klauser int a[] = {1, 1, 1, 1};
127101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a + 4)), 4, 1);
128101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
129101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 4);
130101d1e9bSNikolas Klauser }
131101d1e9bSNikolas Klauser {
132101d1e9bSNikolas Klauser int a[] = {1, 1, 1, 1};
133101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 4)));
134101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range, 4, 1);
135101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
136101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 4);
137101d1e9bSNikolas Klauser }
138101d1e9bSNikolas Klauser }
139101d1e9bSNikolas Klauser
140101d1e9bSNikolas Klauser { // pattern is longer than range
141101d1e9bSNikolas Klauser {
142101d1e9bSNikolas Klauser int a[] = {3, 3, 3};
143101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a + 3)), 4, 3);
144101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 3);
145101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 3);
146101d1e9bSNikolas Klauser }
147101d1e9bSNikolas Klauser {
148101d1e9bSNikolas Klauser int a[] = {3, 3, 3};
149101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 3)));
150101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range, 4, 3);
151101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 3);
152101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 3);
153101d1e9bSNikolas Klauser }
154101d1e9bSNikolas Klauser }
155101d1e9bSNikolas Klauser
156101d1e9bSNikolas Klauser { // pattern has zero length
157101d1e9bSNikolas Klauser {
158101d1e9bSNikolas Klauser int a[] = {6, 7, 8};
159101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a + 3)), 0, 7);
160101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
161101d1e9bSNikolas Klauser assert(base(ret.end()) == a);
162101d1e9bSNikolas Klauser }
163101d1e9bSNikolas Klauser {
164101d1e9bSNikolas Klauser int a[] = {6, 7, 8};
165101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 3)));
166101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range, 0, 7);
167101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
168101d1e9bSNikolas Klauser assert(base(ret.end()) == a);
169101d1e9bSNikolas Klauser }
170101d1e9bSNikolas Klauser }
171101d1e9bSNikolas Klauser
172101d1e9bSNikolas Klauser { // range has zero length
173101d1e9bSNikolas Klauser {
174*c000f754SStephan T. Lavavej std::array<int, 0> a = {};
175*c000f754SStephan T. Lavavej auto ret = std::ranges::search_n(Iter(a.data()), Sent(Iter(a.data())), 1, 1);
176*c000f754SStephan T. Lavavej assert(base(ret.begin()) == a.data());
177*c000f754SStephan T. Lavavej assert(base(ret.end()) == a.data());
178101d1e9bSNikolas Klauser }
179101d1e9bSNikolas Klauser {
180*c000f754SStephan T. Lavavej std::array<int, 0> a = {};
181*c000f754SStephan T. Lavavej auto range = std::ranges::subrange(Iter(a.data()), Sent(Iter(a.data())));
182101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range, 1, 1);
183*c000f754SStephan T. Lavavej assert(base(ret.begin()) == a.data());
184*c000f754SStephan T. Lavavej assert(base(ret.end()) == a.data());
185101d1e9bSNikolas Klauser }
186101d1e9bSNikolas Klauser }
187101d1e9bSNikolas Klauser
188101d1e9bSNikolas Klauser { // check that the first match is returned
189101d1e9bSNikolas Klauser {
190101d1e9bSNikolas Klauser int a[] = {6, 6, 8, 6, 6, 8, 6, 6, 8};
191101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a + 9)), 2, 6);
192101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
193101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 2);
194101d1e9bSNikolas Klauser }
195101d1e9bSNikolas Klauser {
196101d1e9bSNikolas Klauser int a[] = {6, 6, 8, 6, 6, 8, 6, 6, 8};
197101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 9)));
198101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range, 2, 6);
199101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
200101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 2);
201101d1e9bSNikolas Klauser }
202101d1e9bSNikolas Klauser }
203101d1e9bSNikolas Klauser
204101d1e9bSNikolas Klauser { // check that the predicate is used
205101d1e9bSNikolas Klauser {
206101d1e9bSNikolas Klauser int a[] = {1, 4, 4, 3, 6, 1};
207101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a + 6)),
208101d1e9bSNikolas Klauser 3,
209101d1e9bSNikolas Klauser 4,
210101d1e9bSNikolas Klauser [](int l, int r) { return l == r || l == 1; });
211101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
212101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 3);
213101d1e9bSNikolas Klauser }
214101d1e9bSNikolas Klauser {
215101d1e9bSNikolas Klauser int a[] = {1, 4, 4, 3, 6, 1};
216101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 6)));
217101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range, 3, 4, [](int l, int r) { return l == r || l == 1; });
218101d1e9bSNikolas Klauser assert(base(ret.begin()) == a);
219101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 3);
220101d1e9bSNikolas Klauser }
221101d1e9bSNikolas Klauser }
222101d1e9bSNikolas Klauser
223101d1e9bSNikolas Klauser { // check that the projections are used
224101d1e9bSNikolas Klauser {
225101d1e9bSNikolas Klauser int a[] = {1, 3, 1, 6, 5, 6};
226101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a + 6)),
227101d1e9bSNikolas Klauser 3,
228101d1e9bSNikolas Klauser 6,
229101d1e9bSNikolas Klauser {},
230101d1e9bSNikolas Klauser [](int i) { return i % 2 == 0 ? i : i + 1; });
231101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 3);
232101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 6);
233101d1e9bSNikolas Klauser }
234101d1e9bSNikolas Klauser {
235101d1e9bSNikolas Klauser int a[] = {1, 3, 1, 6, 5, 6};
236101d1e9bSNikolas Klauser auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 6)));
237101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(range,
238101d1e9bSNikolas Klauser 3,
239101d1e9bSNikolas Klauser 6,
240101d1e9bSNikolas Klauser {},
241101d1e9bSNikolas Klauser [](int i) { return i % 2 == 0 ? i : i + 1; });
242101d1e9bSNikolas Klauser assert(base(ret.begin()) == a + 3);
243101d1e9bSNikolas Klauser assert(base(ret.end()) == a + 6);
244101d1e9bSNikolas Klauser }
245101d1e9bSNikolas Klauser }
246101d1e9bSNikolas Klauser }
test()247101d1e9bSNikolas Klauser constexpr bool test() {
248101d1e9bSNikolas Klauser test_iterators<forward_iterator<int*>>();
249101d1e9bSNikolas Klauser test_iterators<forward_iterator<int*>, sized_sentinel<forward_iterator<int*>>>();
250101d1e9bSNikolas Klauser test_iterators<bidirectional_iterator<int*>>();
251101d1e9bSNikolas Klauser test_iterators<bidirectional_iterator<int*>, sized_sentinel<bidirectional_iterator<int*>>>();
252101d1e9bSNikolas Klauser test_iterators<random_access_iterator<int*>>();
253101d1e9bSNikolas Klauser test_iterators<random_access_iterator<int*>, sized_sentinel<random_access_iterator<int*>>>();
254101d1e9bSNikolas Klauser test_iterators<contiguous_iterator<int*>>();
255101d1e9bSNikolas Klauser test_iterators<contiguous_iterator<int*>, sized_sentinel<contiguous_iterator<int*>>>();
256101d1e9bSNikolas Klauser test_iterators<int*>();
257101d1e9bSNikolas Klauser
258101d1e9bSNikolas Klauser { // check that std::invoke is used
259101d1e9bSNikolas Klauser struct S {
260101d1e9bSNikolas Klauser int i;
261101d1e9bSNikolas Klauser
262101d1e9bSNikolas Klauser constexpr S identity() {
263101d1e9bSNikolas Klauser return *this;
264101d1e9bSNikolas Klauser }
265101d1e9bSNikolas Klauser
266101d1e9bSNikolas Klauser constexpr bool compare(int o) {
267101d1e9bSNikolas Klauser return i == o;
268101d1e9bSNikolas Klauser }
269101d1e9bSNikolas Klauser };
270101d1e9bSNikolas Klauser {
271101d1e9bSNikolas Klauser S a[] = {{1}, {2}, {3}, {4}};
272101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(a, a + 4, 1, 2, &S::compare, &S::identity);
273101d1e9bSNikolas Klauser assert(ret.begin() == a + 1);
274101d1e9bSNikolas Klauser assert(ret.end() == a + 2);
275101d1e9bSNikolas Klauser }
276101d1e9bSNikolas Klauser {
277101d1e9bSNikolas Klauser S a[] = {{1}, {2}, {3}, {4}};
278101d1e9bSNikolas Klauser auto ret = std::ranges::search_n(a, 1, 2, &S::compare, &S::identity);
279101d1e9bSNikolas Klauser assert(ret.begin() == a + 1);
280101d1e9bSNikolas Klauser assert(ret.end() == a + 2);
281101d1e9bSNikolas Klauser }
282101d1e9bSNikolas Klauser }
283101d1e9bSNikolas Klauser
284101d1e9bSNikolas Klauser { // check that std::ranges::dangling is returned
285101d1e9bSNikolas Klauser [[maybe_unused]] std::same_as<std::ranges::dangling> decltype(auto) ret =
286101d1e9bSNikolas Klauser std::ranges::search_n(std::array {1, 2, 3, 4}, 1, 0);
287101d1e9bSNikolas Klauser }
288101d1e9bSNikolas Klauser
289101d1e9bSNikolas Klauser return true;
290101d1e9bSNikolas Klauser }
291101d1e9bSNikolas Klauser
main(int,char **)292101d1e9bSNikolas Klauser int main(int, char**) {
293101d1e9bSNikolas Klauser test();
294101d1e9bSNikolas Klauser static_assert(test());
295101d1e9bSNikolas Klauser
296101d1e9bSNikolas Klauser return 0;
297101d1e9bSNikolas Klauser }
298