xref: /llvm-project/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp (revision 09e3a360581dc36d0820d3fb6da9bd7cfed87b5d)
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 // this test checks that the projections in the ranges algorithms aren't copied/moved
14 
15 #include <algorithm>
16 #include <cassert>
17 #include <cstddef>
18 #include <deque>
19 #include <type_traits>
20 
21 #include "test_macros.h"
22 
23 struct T {};
24 
25 struct Proj {
26     int *copies_;
27     constexpr explicit Proj(int *copies) : copies_(copies) {}
28     constexpr Proj(const Proj& rhs) : copies_(rhs.copies_) { *copies_ += 1; }
29     constexpr Proj& operator=(const Proj&) = default;
30     constexpr void* operator()(T) const { return nullptr; }
31 };
32 
33 struct Less {
34   constexpr bool operator()(void*, void*) const { return false; }
35 };
36 
37 struct Equal {
38   constexpr bool operator()(void*, void*) const { return true; }
39 };
40 
41 struct UnaryVoid {
42   constexpr void operator()(void*) const {}
43 };
44 
45 struct UnaryTrue {
46   constexpr bool operator()(void*) const { return true; }
47 };
48 
49 struct NullaryValue {
50   constexpr std::nullptr_t operator()() const { return nullptr; }
51 };
52 
53 struct UnaryTransform {
54   constexpr T operator()(void*) const { return T(); }
55 };
56 
57 struct BinaryTransform {
58   constexpr T operator()(void*, void*) const { return T(); }
59 };
60 
61 constexpr bool all_the_algorithms()
62 {
63     T a[10] = {};
64     T b[10] = {};
65     T half[5] = {};
66     T *first = a;
67     T *mid = a+5;
68     T *last = a+10;
69     T *first2 = b;
70     T *mid2 = b+5;
71     T *last2 = b+10;
72     void *value = nullptr;
73     int count = 1;
74 
75     int copies = 0;
76     (void)std::ranges::adjacent_find(first, last, Equal(), Proj(&copies)); assert(copies == 0);
77     (void)std::ranges::adjacent_find(a, Equal(), Proj(&copies)); assert(copies == 0);
78     (void)std::ranges::all_of(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
79     (void)std::ranges::all_of(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
80     (void)std::ranges::any_of(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
81     (void)std::ranges::any_of(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
82     (void)std::ranges::binary_search(first, last, value, Less(), Proj(&copies)); assert(copies == 0);
83     (void)std::ranges::binary_search(a, value, Less(), Proj(&copies)); assert(copies == 0);
84     (void)std::ranges::clamp(T(), T(), T(), Less(), Proj(&copies)); assert(copies == 0);
85 #if TEST_STD_VER >= 23
86     (void)std::ranges::contains(first, last, value, Proj(&copies));
87     assert(copies == 0);
88     (void)std::ranges::contains(a, value, Proj(&copies));
89     assert(copies == 0);
90     (void)std::ranges::contains_subrange(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies));
91     assert(copies == 0);
92     (void)std::ranges::contains_subrange(a, b, Equal(), Proj(&copies), Proj(&copies));
93     assert(copies == 0);
94 #endif
95     (void)std::ranges::count(first, last, value, Proj(&copies)); assert(copies == 0);
96     (void)std::ranges::count(a, value, Proj(&copies)); assert(copies == 0);
97     (void)std::ranges::count_if(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
98     (void)std::ranges::count_if(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
99     (void)std::ranges::copy_if(first, last, first2, UnaryTrue(), Proj(&copies)); assert(copies == 0);
100     (void)std::ranges::copy_if(a, first2, UnaryTrue(), Proj(&copies)); assert(copies == 0);
101 #if TEST_STD_VER >= 23
102     (void)std::ranges::ends_with(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
103     (void)std::ranges::ends_with(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
104 #endif
105     (void)std::ranges::equal(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
106     (void)std::ranges::equal(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
107     (void)std::ranges::equal_range(first, last, value, Less(), Proj(&copies)); assert(copies == 0);
108     (void)std::ranges::equal_range(a, value, Less(), Proj(&copies)); assert(copies == 0);
109     (void)std::ranges::find(first, last, value, Proj(&copies)); assert(copies == 0);
110     (void)std::ranges::find(a, value, Proj(&copies)); assert(copies == 0);
111     (void)std::ranges::find_end(first, last, first2, mid2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
112     (void)std::ranges::find_end(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
113     (void)std::ranges::find_first_of(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
114     (void)std::ranges::find_first_of(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
115     (void)std::ranges::find_if(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
116     (void)std::ranges::find_if(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
117     (void)std::ranges::find_if_not(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
118     (void)std::ranges::find_if_not(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
119 #if TEST_STD_VER >= 23
120     (void)std::ranges::find_last(first, last, value, Proj(&copies));
121     assert(copies == 0);
122     (void)std::ranges::find_last(a, value, Proj(&copies));
123     assert(copies == 0);
124     (void)std::ranges::find_last_if(first, last, UnaryTrue(), Proj(&copies));
125     assert(copies == 0);
126     (void)std::ranges::find_last_if(a, UnaryTrue(), Proj(&copies));
127     assert(copies == 0);
128     (void)std::ranges::find_last_if_not(first, last, UnaryTrue(), Proj(&copies));
129     assert(copies == 0);
130     (void)std::ranges::find_last_if_not(a, UnaryTrue(), Proj(&copies));
131     assert(copies == 0);
132 #endif
133     (void)std::ranges::for_each(first, last, UnaryVoid(), Proj(&copies)); assert(copies == 0);
134     (void)std::ranges::for_each(a, UnaryVoid(), Proj(&copies)); assert(copies == 0);
135     (void)std::ranges::for_each_n(first, count, UnaryVoid(), Proj(&copies)); assert(copies == 0);
136     (void)std::ranges::includes(first, last, first2, last2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
137     (void)std::ranges::includes(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
138     (void)std::ranges::is_heap(first, last, Less(), Proj(&copies)); assert(copies == 0);
139     (void)std::ranges::is_heap(a, Less(), Proj(&copies)); assert(copies == 0);
140     (void)std::ranges::is_heap_until(first, last, Less(), Proj(&copies)); assert(copies == 0);
141     (void)std::ranges::is_heap_until(a, Less(), Proj(&copies)); assert(copies == 0);
142     (void)std::ranges::is_partitioned(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
143     (void)std::ranges::is_partitioned(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
144     (void)std::ranges::is_permutation(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
145     (void)std::ranges::is_permutation(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
146     (void)std::ranges::is_sorted(first, last, Less(), Proj(&copies)); assert(copies == 0);
147     (void)std::ranges::is_sorted(a, Less(), Proj(&copies)); assert(copies == 0);
148     (void)std::ranges::is_sorted_until(first, last, Less(), Proj(&copies)); assert(copies == 0);
149     (void)std::ranges::is_sorted_until(a, Less(), Proj(&copies)); assert(copies == 0);
150     if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); }
151     if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); assert(copies == 0); }
152     (void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
153     (void)std::ranges::lexicographical_compare(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
154     (void)std::ranges::lower_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0);
155     (void)std::ranges::lower_bound(a, value, Less(), Proj(&copies)); assert(copies == 0);
156     (void)std::ranges::make_heap(first, last, Less(), Proj(&copies)); assert(copies == 0);
157     (void)std::ranges::make_heap(a, Less(), Proj(&copies)); assert(copies == 0);
158     (void)std::ranges::max(T(), T(), Less(), Proj(&copies)); assert(copies == 0);
159     (void)std::ranges::max({ T(), T() }, Less(), Proj(&copies)); assert(copies == 0);
160     (void)std::ranges::max(a, Less(), Proj(&copies)); assert(copies == 0);
161     (void)std::ranges::max_element(first, last, Less(), Proj(&copies)); assert(copies == 0);
162     (void)std::ranges::max_element(a, Less(), Proj(&copies)); assert(copies == 0);
163     (void)std::ranges::merge(first, mid, mid, last, first2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
164     (void)std::ranges::merge(half, half, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
165     (void)std::ranges::min(T(), T(), Less(), Proj(&copies)); assert(copies == 0);
166     (void)std::ranges::min({ T(), T() }, Less(), Proj(&copies)); assert(copies == 0);
167     (void)std::ranges::min(a, Less(), Proj(&copies)); assert(copies == 0);
168     (void)std::ranges::min_element(first, last, Less(), Proj(&copies)); assert(copies == 0);
169     (void)std::ranges::min_element(a, Less(), Proj(&copies)); assert(copies == 0);
170     (void)std::ranges::minmax(T(), T(), Less(), Proj(&copies)); assert(copies == 0);
171     (void)std::ranges::minmax({ T(), T() }, Less(), Proj(&copies)); assert(copies == 0);
172     (void)std::ranges::minmax(a, Less(), Proj(&copies)); assert(copies == 0);
173     (void)std::ranges::minmax_element(first, last, Less(), Proj(&copies)); assert(copies == 0);
174     (void)std::ranges::minmax_element(a, Less(), Proj(&copies)); assert(copies == 0);
175     (void)std::ranges::mismatch(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
176     (void)std::ranges::mismatch(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
177     (void)std::ranges::next_permutation(first, last, Less(), Proj(&copies)); assert(copies == 0);
178     (void)std::ranges::next_permutation(a, Less(), Proj(&copies)); assert(copies == 0);
179     (void)std::ranges::none_of(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
180     (void)std::ranges::none_of(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
181     (void)std::ranges::nth_element(first, mid, last, Less(), Proj(&copies)); assert(copies == 0);
182     (void)std::ranges::nth_element(a, mid, Less(), Proj(&copies)); assert(copies == 0);
183     (void)std::ranges::partial_sort(first, mid, last, Less(), Proj(&copies)); assert(copies == 0);
184     (void)std::ranges::partial_sort(a, mid, Less(), Proj(&copies)); assert(copies == 0);
185     (void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
186     (void)std::ranges::partial_sort_copy(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
187     (void)std::ranges::partition(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
188     (void)std::ranges::partition(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
189     (void)std::ranges::partition_copy(first, last, first2, last2, UnaryTrue(), Proj(&copies)); assert(copies == 0);
190     (void)std::ranges::partition_copy(a, first2, last2, UnaryTrue(), Proj(&copies)); assert(copies == 0);
191     (void)std::ranges::partition_point(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
192     (void)std::ranges::partition_point(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
193     (void)std::ranges::pop_heap(first, last, Less(), Proj(&copies)); assert(copies == 0);
194     (void)std::ranges::pop_heap(a, Less(), Proj(&copies)); assert(copies == 0);
195     (void)std::ranges::prev_permutation(first, last, Less(), Proj(&copies)); assert(copies == 0);
196     (void)std::ranges::prev_permutation(a, Less(), Proj(&copies)); assert(copies == 0);
197     (void)std::ranges::push_heap(first, last, Less(), Proj(&copies)); assert(copies == 0);
198     (void)std::ranges::push_heap(a, Less(), Proj(&copies)); assert(copies == 0);
199     (void)std::ranges::remove_copy(first, last, first2, value, Proj(&copies)); assert(copies == 0);
200     (void)std::ranges::remove_copy(a, first2, value, Proj(&copies)); assert(copies == 0);
201     (void)std::ranges::remove_copy_if(first, last, first2, UnaryTrue(), Proj(&copies)); assert(copies == 0);
202     (void)std::ranges::remove_copy_if(a, first2, UnaryTrue(), Proj(&copies)); assert(copies == 0);
203     (void)std::ranges::remove(first, last, value, Proj(&copies)); assert(copies == 0);
204     (void)std::ranges::remove(a, value, Proj(&copies)); assert(copies == 0);
205     (void)std::ranges::remove_if(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
206     (void)std::ranges::remove_if(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
207     (void)std::ranges::replace_copy(first, last, first2, value, T(), Proj(&copies)); assert(copies == 0);
208     (void)std::ranges::replace_copy(a, first2, value, T(), Proj(&copies)); assert(copies == 0);
209     (void)std::ranges::replace_copy_if(first, last, first2, UnaryTrue(), T(), Proj(&copies)); assert(copies == 0);
210     (void)std::ranges::replace_copy_if(a, first2, UnaryTrue(), T(), Proj(&copies)); assert(copies == 0);
211     (void)std::ranges::replace(first, last, value, T(), Proj(&copies)); assert(copies == 0);
212     (void)std::ranges::replace(a, value, T(), Proj(&copies)); assert(copies == 0);
213     (void)std::ranges::replace_if(first, last, UnaryTrue(), T(), Proj(&copies)); assert(copies == 0);
214     (void)std::ranges::replace_if(a, UnaryTrue(), T(), Proj(&copies)); assert(copies == 0);
215     (void)std::ranges::search(first, last, first2, mid2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
216     (void)std::ranges::search(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
217     (void)std::ranges::search_n(first, last, count, value, Equal(), Proj(&copies)); assert(copies == 0);
218     (void)std::ranges::search_n(a, count, value, Equal(), Proj(&copies)); assert(copies == 0);
219     (void)std::ranges::set_difference(first, mid, mid, last, first2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
220     (void)std::ranges::set_difference(a, b, first2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
221     (void)std::ranges::set_intersection(first, mid, mid, last, first2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
222     (void)std::ranges::set_intersection(a, b, first2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
223     (void)std::ranges::set_symmetric_difference(first, mid, mid, last, first2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
224     (void)std::ranges::set_symmetric_difference(a, b, first2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
225     (void)std::ranges::set_union(first, mid, mid, last, first2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
226     (void)std::ranges::set_union(a, b, first2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
227     (void)std::ranges::sort(first, last, Less(), Proj(&copies)); assert(copies == 0);
228     (void)std::ranges::sort(a, Less(), Proj(&copies)); assert(copies == 0);
229     (void)std::ranges::sort_heap(first, last, Less(), Proj(&copies)); assert(copies == 0);
230     (void)std::ranges::sort_heap(a, Less(), Proj(&copies)); assert(copies == 0);
231     if (!std::is_constant_evaluated()) { (void)std::ranges::stable_partition(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0); }
232     if (!std::is_constant_evaluated()) { (void)std::ranges::stable_partition(a, UnaryTrue(), Proj(&copies)); assert(copies == 0); }
233     if (!std::is_constant_evaluated()) { (void)std::ranges::stable_sort(first, last, Less(), Proj(&copies)); assert(copies == 0); }
234     if (!std::is_constant_evaluated()) { (void)std::ranges::stable_sort(a, Less(), Proj(&copies)); assert(copies == 0); }
235 #if TEST_STD_VER > 20
236     (void)std::ranges::starts_with(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
237     (void)std::ranges::starts_with(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0);
238 #endif
239     (void)std::ranges::transform(first, last, first2, UnaryTransform(), Proj(&copies)); assert(copies == 0);
240     (void)std::ranges::transform(a, first2, UnaryTransform(), Proj(&copies)); assert(copies == 0);
241     (void)std::ranges::transform(first, mid, mid, last, first2, BinaryTransform(), Proj(&copies), Proj(&copies)); assert(copies == 0);
242     (void)std::ranges::transform(a, b, first2, BinaryTransform(), Proj(&copies), Proj(&copies)); assert(copies == 0);
243     (void)std::ranges::unique(first, last, Equal(), Proj(&copies)); assert(copies == 0);
244     (void)std::ranges::unique(a, Equal(), Proj(&copies)); assert(copies == 0);
245     (void)std::ranges::unique_copy(first, last, first2, Equal(), Proj(&copies)); assert(copies == 0);
246     (void)std::ranges::unique_copy(a, first2, Equal(), Proj(&copies)); assert(copies == 0);
247     (void)std::ranges::upper_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0);
248     (void)std::ranges::upper_bound(a, value, Less(), Proj(&copies)); assert(copies == 0);
249 
250     return true;
251 }
252 
253 void test_deque() {
254   std::deque<T> d;
255   int copies  = 0;
256   void* value = nullptr;
257 
258   (void)std::ranges::find(d, value, Proj(&copies));
259   assert(copies == 0);
260 }
261 
262 int main(int, char**) {
263   test_deque();
264   all_the_algorithms();
265   static_assert(all_the_algorithms());
266 
267   return 0;
268 }
269