xref: /llvm-project/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/ranges_mismatch.pass.cpp (revision d05bada59205b9bcf1195a6eac7e09b721e3b79b)
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 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 
11 // template <input_iterator I1, sentinel_for<_I1> S1, input_iterator I2, sentinel_for<_I2> S2,
12 //           class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity>
13 //   requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
14 // constexpr mismatch_result<_I1, _I2>
15 // ranges::mismatch()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {})
16 
17 // template <input_range R1, input_range R2,
18 //           class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity>
19 //   requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>
20 // constexpr mismatch_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>>
21 // ranges::mismatch(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {})
22 
23 #include <algorithm>
24 #include <array>
25 #include <cassert>
26 #include <functional>
27 #include <ranges>
28 
29 #include "test_iterators.h"
30 
31 template <class Iter1, class Iter2>
test_iterators(Iter1 begin1,Iter1 end1,Iter2 begin2,Iter2 end2,int * expected1,int * expected2)32 constexpr void test_iterators(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2, int* expected1, int* expected2) {
33   using Expected = std::ranges::mismatch_result<Iter1, Iter2>;
34   std::same_as<Expected> auto ret = std::ranges::mismatch(std::move(begin1), sentinel_wrapper<Iter1>(std::move(end1)),
35                                                           std::move(begin2), sentinel_wrapper<Iter2>(std::move(end2)));
36   assert(base(ret.in1) == expected1);
37   assert(base(ret.in2) == expected2);
38 }
39 
40 template <class Iter1, class Iter2>
test_iters()41 constexpr void test_iters() {
42   int a[] = {1, 2, 3, 4, 5};
43   int b[] = {1, 2, 3, 5, 4};
44 
45   test_iterators(Iter1(a), Iter1(a + 5), Iter2(b), Iter2(b + 5), a + 3, b + 3);
46 }
47 
test()48 constexpr bool test() {
49   test_iters<cpp17_input_iterator<int*>, cpp17_input_iterator<int*>>();
50   test_iters<cpp17_input_iterator<int*>, cpp20_input_iterator<int*>>();
51   test_iters<cpp17_input_iterator<int*>, forward_iterator<int*>>();
52   test_iters<cpp17_input_iterator<int*>, bidirectional_iterator<int*>>();
53   test_iters<cpp17_input_iterator<int*>, random_access_iterator<int*>>();
54   test_iters<cpp17_input_iterator<int*>, contiguous_iterator<int*>>();
55   test_iters<cpp17_input_iterator<int*>, int*>();
56 
57   test_iters<cpp20_input_iterator<int*>, cpp17_input_iterator<int*>>();
58   test_iters<cpp20_input_iterator<int*>, cpp20_input_iterator<int*>>();
59   test_iters<cpp20_input_iterator<int*>, forward_iterator<int*>>();
60   test_iters<cpp20_input_iterator<int*>, bidirectional_iterator<int*>>();
61   test_iters<cpp20_input_iterator<int*>, random_access_iterator<int*>>();
62   test_iters<cpp20_input_iterator<int*>, contiguous_iterator<int*>>();
63   test_iters<cpp20_input_iterator<int*>, int*>();
64 
65   test_iters<forward_iterator<int*>, cpp17_input_iterator<int*>>();
66   test_iters<forward_iterator<int*>, cpp20_input_iterator<int*>>();
67   test_iters<forward_iterator<int*>, forward_iterator<int*>>();
68   test_iters<forward_iterator<int*>, bidirectional_iterator<int*>>();
69   test_iters<forward_iterator<int*>, random_access_iterator<int*>>();
70   test_iters<forward_iterator<int*>, contiguous_iterator<int*>>();
71   test_iters<forward_iterator<int*>, int*>();
72 
73   test_iters<bidirectional_iterator<int*>, cpp17_input_iterator<int*>>();
74   test_iters<bidirectional_iterator<int*>, cpp20_input_iterator<int*>>();
75   test_iters<bidirectional_iterator<int*>, forward_iterator<int*>>();
76   test_iters<bidirectional_iterator<int*>, bidirectional_iterator<int*>>();
77   test_iters<bidirectional_iterator<int*>, random_access_iterator<int*>>();
78   test_iters<bidirectional_iterator<int*>, contiguous_iterator<int*>>();
79   test_iters<bidirectional_iterator<int*>, int*>();
80 
81   test_iters<random_access_iterator<int*>, cpp17_input_iterator<int*>>();
82   test_iters<random_access_iterator<int*>, cpp20_input_iterator<int*>>();
83   test_iters<random_access_iterator<int*>, forward_iterator<int*>>();
84   test_iters<random_access_iterator<int*>, bidirectional_iterator<int*>>();
85   test_iters<random_access_iterator<int*>, random_access_iterator<int*>>();
86   test_iters<random_access_iterator<int*>, contiguous_iterator<int*>>();
87   test_iters<random_access_iterator<int*>, int*>();
88 
89   test_iters<contiguous_iterator<int*>, cpp17_input_iterator<int*>>();
90   test_iters<contiguous_iterator<int*>, cpp20_input_iterator<int*>>();
91   test_iters<contiguous_iterator<int*>, forward_iterator<int*>>();
92   test_iters<contiguous_iterator<int*>, bidirectional_iterator<int*>>();
93   test_iters<contiguous_iterator<int*>, random_access_iterator<int*>>();
94   test_iters<contiguous_iterator<int*>, contiguous_iterator<int*>>();
95   test_iters<contiguous_iterator<int*>, int*>();
96 
97   test_iters<int*, cpp17_input_iterator<int*>>();
98   test_iters<int*, cpp20_input_iterator<int*>>();
99   test_iters<int*, forward_iterator<int*>>();
100   test_iters<int*, bidirectional_iterator<int*>>();
101   test_iters<int*, random_access_iterator<int*>>();
102   test_iters<int*, contiguous_iterator<int*>>();
103   test_iters<int*, int*>();
104 
105   { // test with a range
106     std::array<int, 5> a = {1, 2, 3, 4, 5};
107     std::array<int, 5> b = {1, 2, 3, 5, 4};
108     using Expected = std::ranges::mismatch_result<std::array<int, 5>::iterator, std::array<int, 5>::iterator>;
109     std::same_as<Expected> auto ret = std::ranges::mismatch(a, b);
110     assert(ret.in1 == a.begin() + 3);
111     assert(ret.in2 == b.begin() + 3);
112   }
113 
114   { // test with non-iterator sentinel
115     int a[] = {1, 2, 3, 4, 5};
116     int b[] = {1, 2, 3, 5, 4};
117 
118     using Iter = int*;
119     using Sentinel = sentinel_wrapper<Iter>;
120     using Expected = std::ranges::mismatch_result<Iter, Iter>;
121 
122     std::same_as<Expected> auto r = std::ranges::mismatch(Iter(a), Sentinel(a + 5), Iter(b), Sentinel(b + 5));
123     assert(r.in1 == a + 3);
124     assert(r.in2 == b + 3);
125   }
126 
127   { // test with different array sizes
128     {
129       int a[] = {1, 2, 3};
130       int b[] = {1, 2};
131       test_iterators(a, a + 3, b, b + 2, a + 2, b + 2);
132       using Expected = std::ranges::mismatch_result<int*, int*>;
133       std::same_as<Expected> auto ret = std::ranges::mismatch(a, b);
134       assert(ret.in1 == a + 2);
135       assert(ret.in2 == b + 2);
136     }
137     {
138       int a[] = {1, 2};
139       int b[] = {1, 2, 3};
140       test_iterators(a, a + 2, b, b + 3, a + 2, b + 2);
141       using Expected = std::ranges::mismatch_result<int*, int*>;
142       std::same_as<Expected> auto ret = std::ranges::mismatch(a, b);
143       assert(ret.in1 == a + 2);
144       assert(ret.in2 == b + 2);
145     }
146   }
147 
148   { // test with borrowed ranges
149     int r1[] = {1, 2, 3, 4, 5};
150     int r2[] = {1, 2, 3, 5, 4};
151 
152     using Expected = std::ranges::mismatch_result<int*, int*>;
153     {
154       std::same_as<Expected> auto ret = std::ranges::mismatch(r1, std::views::all(r2));
155       assert(ret.in1 == r1 + 3);
156       assert(ret.in2 == r2 + 3);
157     }
158     {
159       std::same_as<Expected> auto ret = std::ranges::mismatch(std::views::all(r1), r2);
160       assert(ret.in1 == r1 + 3);
161       assert(ret.in2 == r2 + 3);
162     }
163     {
164       std::same_as<Expected> auto ret = std::ranges::mismatch(std::views::all(r1), std::views::all(r2));
165       assert(ret.in1 == r1 + 3);
166       assert(ret.in2 == r2 + 3);
167     }
168   }
169 
170   { // test structured bindings
171     int a[] = {1, 2, 3, 4};
172     int b[] = {1, 2, 4, 8, 16};
173     auto [ai, bi] = std::ranges::mismatch(a, b);
174     assert(ai == a + 2);
175     assert(bi == b + 2);
176     auto [aj, bj] = std::ranges::mismatch(a, a+4, b, b+5);
177     assert(aj == a + 2);
178     assert(bj == b + 2);
179   }
180 
181   { // test predicate
182     {
183       int a[] = {7, 6, 9, 3, 5, 1, 2, 4};
184       int b[] = {6, 5, 8, 2, 5, 1, 2, 4};
185       auto ret = std::ranges::mismatch(a, a + 8, b, b + 8, std::ranges::greater{});
186       assert(ret.in1 == a + 4);
187       assert(ret.in2 == b + 4);
188       assert(*ret.in1 == 5);
189       assert(*ret.in2 == 5);
190     }
191 
192     {
193       int a[] = {7, 6, 9, 3, 5, 1, 2, 4};
194       int b[] = {6, 5, 8, 2, 5, 1, 2, 4};
195       auto ret = std::ranges::mismatch(a, b, std::ranges::greater{});
196       assert(ret.in1 == a + 4);
197       assert(ret.in2 == b + 4);
198       assert(*ret.in1 == 5);
199       assert(*ret.in2 == 5);
200     }
201   }
202 
203   { // test projection
204     {
205       int a[] = {7, 6, 9, 3, 5, 1, 2, 4};
206       int b[] = {6, 5, 8, 2, 5, 1, 2, 4};
207       auto ret = std::ranges::mismatch(a, b,
208                                        std::ranges::greater{},
209                                        [](int i) { return i == 5 ? +100 : i; },
210                                        [](int i) { return i == 5 ? -100 : i; });
211       assert(ret.in1 == a + 5);
212       assert(ret.in2 == b + 5);
213       assert(*ret.in1 == 1);
214       assert(*ret.in2 == 1);
215     }
216     {
217       int a[] = {7, 6, 9, 3, 5, 1, 2, 4};
218       auto ret = std::ranges::mismatch(a, a,
219                                        std::less<double>{},
220                                        [](int i) { return i * 1.01; },
221                                        [c = 0](int i) mutable { return c++ < 5 ? i * 1.02 : i; });
222       assert(ret.in1 == a + 5);
223       assert(ret.in2 == a + 5);
224       assert(*ret.in1 == 1);
225       assert(*ret.in2 == 1);
226     }
227     {
228       int a[] = {7, 6, 9, 3, 5, 1, 2, 4};
229       int b[] = {6, 5, 8, 2, 5, 1, 2, 4};
230       auto ret = std::ranges::mismatch(a, a + 8, b, b + 8,
231                                        std::ranges::greater{},
232                                        [](int i) { return i == 5 ? +100 : i; },
233                                        [](int i) { return i == 5 ? -100 : i; });
234       assert(ret.in1 == a + 5);
235       assert(ret.in2 == b + 5);
236       assert(*ret.in1 == 1);
237       assert(*ret.in2 == 1);
238     }
239     {
240       int a[] = {7, 6, 9, 3, 5, 1, 2, 4};
241       auto ret = std::ranges::mismatch(a, a + 8, a, a + 8,
242                                        std::less<double>{},
243                                        [](int i) { return i * 1.01; },
244                                        [c = 0](int i) mutable { return c++ < 5 ? i * 1.02 : i; });
245       assert(ret.in1 == a + 5);
246       assert(ret.in2 == a + 5);
247       assert(*ret.in1 == 1);
248       assert(*ret.in2 == 1);
249     }
250   }
251 
252   { // test predicate and projection call count
253     {
254       int pred_count = 0;
255       int proj1_count = 0;
256       int proj2_count = 0;
257       int a[] = {7, 6, 9, 3, 5, 1, 2, 4};
258       auto ret = std::ranges::mismatch(a, a,
259                                        [&](int lhs, int rhs) { ++pred_count; return lhs == rhs; },
260                                        [&](int i) { ++proj1_count; return i; },
261                                        [&](int i) { ++proj2_count; return i; });
262       assert(ret.in1 == a + 8);
263       assert(ret.in2 == a + 8);
264       assert(pred_count == 8);
265       assert(proj1_count == 8);
266       assert(proj2_count == 8);
267     }
268     {
269       int pred_count = 0;
270       int proj1_count = 0;
271       int proj2_count = 0;
272       int a[] = {7, 6, 9, 3, 5, 1, 2, 4};
273       auto ret = std::ranges::mismatch(a, a + 8, a, a + 8,
274                                        [&](int lhs, int rhs) { ++pred_count; return lhs == rhs; },
275                                        [&](int i) { ++proj1_count; return i; },
276                                        [&](int i) { ++proj2_count; return i; });
277       assert(ret.in1 == a + 8);
278       assert(ret.in2 == a + 8);
279       assert(pred_count == 8);
280       assert(proj1_count == 8);
281       assert(proj2_count == 8);
282     }
283   }
284 
285   return true;
286 }
287 
main(int,char **)288 int main(int, char**) {
289   test();
290   static_assert(test());
291 
292   return 0;
293 }
294