xref: /llvm-project/libcxx/test/std/algorithms/ranges_robust_against_nonbool.compile.pass.cpp (revision 04760bfadb399cc4ded9b32bd523ec7703aa7462)
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 // <algorithm>
12 //
13 // Range algorithms that take predicates should support predicates that return a non-boolean value as long as the
14 // returned type is implicitly convertible to bool.
15 
16 #include <algorithm>
17 
18 #include <initializer_list>
19 #include <ranges>
20 
21 #include "boolean_testable.h"
22 #include "test_macros.h"
23 
24 using Value     = StrictComparable<int>;
25 using Iterator  = StrictBooleanIterator<Value*>;
26 using Range     = std::ranges::subrange<Iterator>;
27 auto pred1      = StrictUnaryPredicate;
28 auto pred2      = StrictBinaryPredicate;
29 auto projection = [](Value const& val) -> Value { return val; };
30 
31 void f(Iterator it, Range in, Iterator out, std::size_t n, Value const& val, std::initializer_list<Value> ilist) {
32   // Functions of the form (in, pred)
33   auto in_pred = [&](auto func, auto pred) {
34     (void)func(it, it, pred);
35     (void)func(in, pred);
36     (void)func(it, it, pred, projection);
37     (void)func(in, pred, projection);
38   };
39 
40   // Functions of the form (in, in, pred)
41   auto in_in_pred = [&](auto func, auto pred) {
42     (void)func(it, it, it, it, pred);
43     (void)func(in, in, pred);
44     (void)func(it, it, it, it, pred, projection);
45     (void)func(in, in, pred, projection);
46   };
47 
48   in_pred(std::ranges::any_of, pred1);
49   in_pred(std::ranges::all_of, pred1);
50 #if TEST_STD_VER >= 23
51   in_in_pred(std::ranges::ends_with, pred2);
52 #endif
53   in_pred(std::ranges::none_of, pred1);
54   in_pred(std::ranges::find_if, pred1);
55   in_pred(std::ranges::find_if_not, pred1);
56 #if TEST_STD_VER >= 23
57   in_pred(std::ranges::find_last_if, pred1);
58   in_pred(std::ranges::find_last_if_not, pred1);
59 #endif
60   in_in_pred(std::ranges::find_first_of, pred2);
61   in_pred(std::ranges::adjacent_find, pred2);
62   in_in_pred(std::ranges::mismatch, pred2);
63   in_in_pred(std::ranges::equal, pred2);
64   in_in_pred(std::ranges::lexicographical_compare, pred2);
65   in_pred(std::ranges::partition_point, pred1);
66   // lower_bound
67   {
68     (void)std::ranges::lower_bound(it, it, val, pred2);
69     (void)std::ranges::lower_bound(in, val, pred2);
70     (void)std::ranges::lower_bound(it, it, val, pred2, projection);
71     (void)std::ranges::lower_bound(in, val, pred2, projection);
72   }
73   // upper_bound
74   {
75     (void)std::ranges::upper_bound(it, it, val, pred2);
76     (void)std::ranges::upper_bound(in, val, pred2);
77     (void)std::ranges::upper_bound(it, it, val, pred2, projection);
78     (void)std::ranges::upper_bound(in, val, pred2, projection);
79   }
80   // equal_range
81   {
82     (void)std::ranges::equal_range(it, it, val, pred2);
83     (void)std::ranges::equal_range(in, val, pred2);
84     (void)std::ranges::equal_range(it, it, val, pred2, projection);
85     (void)std::ranges::equal_range(in, val, pred2, projection);
86   }
87   // binary_search
88   {
89     (void)std::ranges::binary_search(it, it, val, pred2);
90     (void)std::ranges::binary_search(in, val, pred2);
91     (void)std::ranges::binary_search(it, it, val, pred2, projection);
92     (void)std::ranges::binary_search(in, val, pred2, projection);
93   }
94   // min
95   {
96     (void)std::ranges::min(val, val, pred2);
97     (void)std::ranges::min(val, val, pred2, projection);
98     (void)std::ranges::min(ilist, pred2);
99     (void)std::ranges::min(ilist, pred2, projection);
100     (void)std::ranges::min(in, pred2);
101     (void)std::ranges::min(in, pred2, projection);
102   }
103   // max
104   {
105     (void)std::ranges::max(val, val, pred2);
106     (void)std::ranges::max(val, val, pred2, projection);
107     (void)std::ranges::max(ilist, pred2);
108     (void)std::ranges::max(ilist, pred2, projection);
109     (void)std::ranges::max(in, pred2);
110     (void)std::ranges::max(in, pred2, projection);
111   }
112   // minmax
113   {
114     (void)std::ranges::minmax(val, val, pred2);
115     (void)std::ranges::minmax(val, val, pred2, projection);
116     (void)std::ranges::minmax(ilist, pred2);
117     (void)std::ranges::minmax(ilist, pred2, projection);
118     (void)std::ranges::minmax(in, pred2);
119     (void)std::ranges::minmax(in, pred2, projection);
120   }
121 
122   in_pred(std::ranges::min_element, pred2);
123   in_pred(std::ranges::max_element, pred2);
124   in_pred(std::ranges::minmax_element, pred2);
125   in_pred(std::ranges::count_if, pred1);
126   in_in_pred(std::ranges::search, pred2);
127   // search_n
128   {
129     (void)std::ranges::search_n(it, it, n, val, pred2);
130     (void)std::ranges::search_n(in, n, val, pred2);
131     (void)std::ranges::search_n(it, it, n, val, pred2, projection);
132     (void)std::ranges::search_n(in, n, val, pred2, projection);
133   }
134   in_in_pred(std::ranges::find_end, pred2);
135   in_pred(std::ranges::is_partitioned, pred1);
136   in_pred(std::ranges::is_sorted, pred2);
137   in_pred(std::ranges::is_sorted_until, pred2);
138   in_in_pred(std::ranges::includes, pred2);
139   in_pred(std::ranges::is_heap, pred2);
140   in_pred(std::ranges::is_heap_until, pred2);
141   // clamp
142   {
143     (void)std::ranges::clamp(val, val, val);
144     (void)std::ranges::clamp(val, val, val, pred2);
145     (void)std::ranges::clamp(val, val, val, pred2, projection);
146   }
147   in_in_pred(std::ranges::is_permutation, pred2);
148   // copy_if
149   {
150     (void)std::ranges::copy_if(it, it, out, pred1);
151     (void)std::ranges::copy_if(in, out, pred1);
152     (void)std::ranges::copy_if(it, it, out, pred1, projection);
153     (void)std::ranges::copy_if(in, out, pred1, projection);
154   }
155   {
156     (void)std::ranges::remove_copy_if(it, it, out, pred1);
157     (void)std::ranges::remove_copy_if(in, out, pred1);
158     (void)std::ranges::remove_copy_if(it, it, out, pred1, projection);
159     (void)std::ranges::remove_copy_if(in, out, pred1, projection);
160   }
161   // remove_copy
162   {
163     (void)std::ranges::remove_copy(it, it, out, val);
164     (void)std::ranges::remove_copy(in, out, val);
165     (void)std::ranges::remove_copy(it, it, out, val, projection);
166     (void)std::ranges::remove_copy(in, out, val, projection);
167   }
168   // replace
169   {
170     (void)std::ranges::replace(it, it, val, val);
171     (void)std::ranges::replace(in, val, val);
172     (void)std::ranges::replace(it, it, val, val, projection);
173     (void)std::ranges::replace(in, val, val, projection);
174   }
175   // replace_if
176   {
177     (void)std::ranges::replace_if(it, it, pred1, val);
178     (void)std::ranges::replace_if(in, pred1, val);
179     (void)std::ranges::replace_if(it, it, pred1, val, projection);
180     (void)std::ranges::replace_if(in, pred1, val, projection);
181   }
182   // replace_copy_if
183   {
184     (void)std::ranges::replace_copy_if(it, it, out, pred1, val);
185     (void)std::ranges::replace_copy_if(in, out, pred1, val);
186     (void)std::ranges::replace_copy_if(it, it, out, pred1, val, projection);
187     (void)std::ranges::replace_copy_if(in, out, pred1, val, projection);
188   }
189   // replace_copy
190   {
191     (void)std::ranges::replace_copy(it, it, out, val, val);
192     (void)std::ranges::replace_copy(in, out, val, val);
193     (void)std::ranges::replace_copy(it, it, out, val, val, projection);
194     (void)std::ranges::replace_copy(in, out, val, val, projection);
195   }
196   // unique_copy
197   {
198     (void)std::ranges::unique_copy(it, it, out, pred2);
199     (void)std::ranges::unique_copy(in, out, pred2);
200     (void)std::ranges::unique_copy(it, it, out, pred2, projection);
201     (void)std::ranges::unique_copy(in, out, pred2, projection);
202   }
203   // partition_copy
204   {
205     (void)std::ranges::partition_copy(it, it, out, out, pred1);
206     (void)std::ranges::partition_copy(in, out, out, pred1);
207     (void)std::ranges::partition_copy(it, it, out, out, pred1, projection);
208     (void)std::ranges::partition_copy(in, out, out, pred1, projection);
209   }
210   in_in_pred(std::ranges::partial_sort_copy, pred2);
211 #if TEST_STD_VER > 20
212   in_in_pred(std::ranges::starts_with, pred2);
213 #endif
214   // merge
215   {
216     (void)std::ranges::merge(it, it, it, it, out, pred2);
217     (void)std::ranges::merge(in, in, out, pred2);
218     (void)std::ranges::merge(it, it, it, it, out, pred2, projection, projection);
219     (void)std::ranges::merge(in, in, out, pred2, projection, projection);
220   }
221   // set_difference
222   {
223     (void)std::ranges::set_difference(it, it, it, it, out, pred2);
224     (void)std::ranges::set_difference(in, in, out, pred2);
225     (void)std::ranges::set_difference(it, it, it, it, out, pred2, projection, projection);
226     (void)std::ranges::set_difference(in, in, out, pred2, projection, projection);
227   }
228   // set_intersection
229   {
230     (void)std::ranges::set_intersection(it, it, it, it, out, pred2);
231     (void)std::ranges::set_intersection(in, in, out, pred2);
232     (void)std::ranges::set_intersection(it, it, it, it, out, pred2, projection, projection);
233     (void)std::ranges::set_intersection(in, in, out, pred2, projection, projection);
234   }
235   // set_symmetric_difference
236   {
237     (void)std::ranges::set_symmetric_difference(it, it, it, it, out, pred2);
238     (void)std::ranges::set_symmetric_difference(in, in, out, pred2);
239     (void)std::ranges::set_symmetric_difference(it, it, it, it, out, pred2, projection, projection);
240     (void)std::ranges::set_symmetric_difference(in, in, out, pred2, projection, projection);
241   }
242   // set_union
243   {
244     (void)std::ranges::set_union(it, it, it, it, out, pred2);
245     (void)std::ranges::set_union(in, in, out, pred2);
246     (void)std::ranges::set_union(it, it, it, it, out, pred2, projection, projection);
247     (void)std::ranges::set_union(in, in, out, pred2, projection, projection);
248   }
249   in_pred(std::ranges::remove_if, pred1);
250   // remove
251   {
252     (void)std::ranges::remove(it, it, val);
253     (void)std::ranges::remove(it, it, val, projection);
254     (void)std::ranges::remove(in, val);
255     (void)std::ranges::remove(in, val, projection);
256   }
257   in_pred(std::ranges::unique, pred2);
258   in_pred(std::ranges::partition, pred1);
259   in_pred(std::ranges::stable_partition, pred1);
260   in_pred(std::ranges::sort, pred2);
261   in_pred(std::ranges::stable_sort, pred2);
262   // partial_sort
263   {
264     (void)std::ranges::partial_sort(it, it, it, pred2);
265     (void)std::ranges::partial_sort(in, it, pred2);
266     (void)std::ranges::partial_sort(it, it, it, pred2, projection);
267     (void)std::ranges::partial_sort(in, it, pred2, projection);
268   }
269   // nth_element
270   {
271     (void)std::ranges::nth_element(it, it, it, pred2);
272     (void)std::ranges::nth_element(in, it, pred2);
273     (void)std::ranges::nth_element(it, it, it, pred2, projection);
274     (void)std::ranges::nth_element(in, it, pred2, projection);
275   }
276   // inplace_merge
277   {
278     (void)std::ranges::inplace_merge(it, it, it, pred2);
279     (void)std::ranges::inplace_merge(in, it, pred2);
280     (void)std::ranges::inplace_merge(it, it, it, pred2, projection);
281     (void)std::ranges::inplace_merge(in, it, pred2, projection);
282   }
283   in_pred(std::ranges::make_heap, pred2);
284   in_pred(std::ranges::push_heap, pred2);
285   in_pred(std::ranges::pop_heap, pred2);
286   in_pred(std::ranges::sort_heap, pred2);
287   in_pred(std::ranges::prev_permutation, pred2);
288   in_pred(std::ranges::next_permutation, pred2);
289 }
290