Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / support / test_container_comparisons.h
blob67165dcfdf4df7c46ded9a3699cb3077afa465cd
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 // Utility functions to test comparisons on containers.
10 #ifndef TEST_CONTAINER_COMPARISONS
11 #define TEST_CONTAINER_COMPARISONS
13 #include <functional>
14 #include <set>
16 #include "test_comparisons.h"
18 // Implementation detail of `test_sequence_container_spaceship`
19 template <template <typename...> typename Container, typename Elem, typename Order>
20 constexpr void test_sequence_container_spaceship_with_type() {
21 // Empty containers
23 Container<Elem> l1;
24 Container<Elem> l2;
25 assert(testOrder(l1, l2, Order::equivalent));
27 // Identical contents
29 Container<Elem> l1{1, 1};
30 Container<Elem> l2{1, 1};
31 assert(testOrder(l1, l2, Order::equivalent));
33 // Less, due to contained values
35 Container<Elem> l1{1, 1};
36 Container<Elem> l2{1, 2};
37 assert(testOrder(l1, l2, Order::less));
39 // Greater, due to contained values
41 Container<Elem> l1{1, 3};
42 Container<Elem> l2{1, 2};
43 assert(testOrder(l1, l2, Order::greater));
45 // Shorter list
47 Container<Elem> l1{1};
48 Container<Elem> l2{1, 2};
49 assert(testOrder(l1, l2, Order::less));
51 // Longer list
53 Container<Elem> l1{1, 2};
54 Container<Elem> l2{1};
55 assert(testOrder(l1, l2, Order::greater));
57 // Unordered
58 if constexpr (std::is_same_v<Elem, PartialOrder>) {
59 Container<Elem> l1{1, std::numeric_limits<int>::min()};
60 Container<Elem> l2{1, 2};
61 assert(testOrder(l1, l2, Order::unordered));
65 // Tests the `operator<=>` on sequence containers
66 template <template <typename...> typename Container>
67 constexpr bool test_sequence_container_spaceship() {
68 // The container should fulfill `std::three_way_comparable`
69 static_assert(std::three_way_comparable<Container<int>>);
71 // Test different comparison categories
72 test_sequence_container_spaceship_with_type<Container, int, std::strong_ordering>();
73 test_sequence_container_spaceship_with_type<Container, StrongOrder, std::strong_ordering>();
74 test_sequence_container_spaceship_with_type<Container, WeakOrder, std::weak_ordering>();
75 test_sequence_container_spaceship_with_type<Container, PartialOrder, std::partial_ordering>();
77 // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
78 test_sequence_container_spaceship_with_type<Container, LessAndEqComp, std::weak_ordering>();
80 // Thanks to SFINAE, the following is not a compiler error but returns `false`
81 struct NonComparable {};
82 static_assert(!std::three_way_comparable<Container<NonComparable>>);
84 return true;
87 // Implementation detail of `test_sequence_container_adaptor_spaceship`
88 template <template <typename...> typename ContainerAdaptor,
89 template <typename...>
90 typename Container,
91 typename Elem,
92 typename Order>
93 constexpr void test_sequence_container_adaptor_spaceship_with_type() {
94 // Empty containers
96 Container<Elem> l1;
97 ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
98 Container<Elem> l2;
99 ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
100 assert(testOrder(ca1, ca2, Order::equivalent));
102 // Identical contents
104 Container<Elem> l1{1, 1};
105 ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
106 Container<Elem> l2{1, 1};
107 ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
108 assert(testOrder(ca1, ca2, Order::equivalent));
110 // Less, due to contained values
112 Container<Elem> l1{1, 1};
113 ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
114 Container<Elem> l2{1, 2};
115 ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
116 assert(testOrder(ca1, ca2, Order::less));
118 // Greater, due to contained values
120 Container<Elem> l1{1, 3};
121 ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
122 Container<Elem> l2{1, 2};
123 ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
124 assert(testOrder(ca1, ca2, Order::greater));
126 // Shorter list
128 Container<Elem> l1{1};
129 ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
130 Container<Elem> l2{1, 2};
131 ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
132 assert(testOrder(ca1, ca2, Order::less));
134 // Longer list
136 Container<Elem> l1{1, 2};
137 ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
138 Container<Elem> l2{1};
139 ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
140 assert(testOrder(ca1, ca2, Order::greater));
142 // Unordered
143 if constexpr (std::is_same_v<Elem, PartialOrder>) {
144 Container<Elem> l1{1, std::numeric_limits<int>::min()};
145 ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
146 Container<Elem> l2{1, 2};
147 ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
148 assert(testOrder(ca1, ca2, Order::unordered));
152 // Tests the `operator<=>` on sequence container adaptors
153 template <template <typename...> typename ContainerAdaptor, template <typename...> typename Container>
154 constexpr bool test_sequence_container_adaptor_spaceship() {
155 // Thanks to SFINAE, the following is not a compiler error but returns `false`
156 struct NonComparable {};
157 static_assert(!std::three_way_comparable<ContainerAdaptor<NonComparable>>);
159 // The container should fulfill `std::three_way_comparable`
160 static_assert(std::three_way_comparable<ContainerAdaptor<int, Container<int>>>);
162 // Test different comparison categories
163 test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor, Container, int, std::strong_ordering>();
164 test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor, Container, StrongOrder, std::strong_ordering>();
165 test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor, Container, WeakOrder, std::weak_ordering>();
166 test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor,
167 Container,
168 PartialOrder,
169 std::partial_ordering>();
171 // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
172 test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor, Container, LessAndEqComp, std::weak_ordering>();
174 return true;
177 // Implementation detail of `test_ordered_map_container_spaceship`
178 template <template <typename...> typename Container, typename Key, typename Val, typename Order, typename Compare>
179 constexpr void test_ordered_map_container_spaceship_with_type(Compare comp) {
180 // Empty containers
182 Container<Key, Val, Compare> l1{{}, comp};
183 Container<Key, Val, Compare> l2{{}, comp};
184 assert(testOrder(l1, l2, Order::equivalent));
186 // Identical contents
188 Container<Key, Val, Compare> l1{{{1, 1}, {2, 1}}, comp};
189 Container<Key, Val, Compare> l2{{{1, 1}, {2, 1}}, comp};
190 assert(testOrder(l1, l2, Order::equivalent));
192 // Less, due to contained values
194 Container<Key, Val, Compare> l1{{{1, 1}, {2, 1}}, comp};
195 Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
196 assert(testOrder(l1, l2, Order::less));
198 // Greater, due to contained values
200 Container<Key, Val, Compare> l1{{{1, 1}, {2, 3}}, comp};
201 Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
202 assert(testOrder(l1, l2, Order::greater));
204 // Shorter list
206 Container<Key, Val, Compare> l1{{{1, 1}}, comp};
207 Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
208 assert(testOrder(l1, l2, Order::less));
210 // Longer list
212 Container<Key, Val, Compare> l1{{{1, 2}, {2, 2}}, comp};
213 Container<Key, Val, Compare> l2{{{1, 1}}, comp};
214 assert(testOrder(l1, l2, Order::greater));
216 // Unordered
217 if constexpr (std::is_same_v<Val, PartialOrder>) {
218 Container<Key, Val, Compare> l1{{{1, 1}, {2, std::numeric_limits<int>::min()}}, comp};
219 Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
220 assert(testOrder(l1, l2, Order::unordered));
223 // Identical contents
225 Container<Key, Val, Compare> l1{{{1, 1}, {2, 1}, {2, 2}}, comp};
226 Container<Key, Val, Compare> l2{{{1, 1}, {2, 1}, {2, 2}}, comp};
227 assert(testOrder(l1, l2, Order::equivalent));
229 Container<Key, Val, Compare> l3{{{1, 1}, {2, 1}, {2, 2}}, comp};
230 Container<Key, Val, Compare> l4{{{2, 1}, {2, 2}, {1, 1}}, comp};
231 assert(testOrder(l3, l4, Order::equivalent));
233 // Less, due to contained values
235 Container<Key, Val, Compare> l1{{{1, 1}, {2, 1}, {2, 1}}, comp};
236 Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}, {2, 2}}, comp};
237 assert(testOrder(l1, l2, Order::less));
239 Container<Key, Val, Compare> l3{{{1, 1}, {2, 1}, {2, 1}}, comp};
240 Container<Key, Val, Compare> l4{{{2, 2}, {2, 2}, {1, 1}}, comp};
241 assert(testOrder(l3, l4, Order::less));
243 // Greater, due to contained values
245 Container<Key, Val, Compare> l1{{{1, 1}, {2, 3}, {2, 3}}, comp};
246 Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}, {2, 2}}, comp};
247 assert(testOrder(l1, l2, Order::greater));
249 Container<Key, Val, Compare> l3{{{1, 1}, {2, 3}, {2, 3}}, comp};
250 Container<Key, Val, Compare> l4{{{2, 2}, {2, 2}, {1, 1}}, comp};
251 assert(testOrder(l3, l4, Order::greater));
253 // Shorter list
255 Container<Key, Val, Compare> l1{{{1, 1}, {2, 2}}, comp};
256 Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}, {2, 2}, {3, 1}}, comp};
257 assert(testOrder(l1, l2, Order::less));
259 Container<Key, Val, Compare> l3{{{1, 1}, {2, 2}}, comp};
260 Container<Key, Val, Compare> l4{{{3, 1}, {2, 2}, {2, 2}, {1, 1}}, comp};
261 assert(testOrder(l3, l4, Order::less));
263 // Longer list
265 Container<Key, Val, Compare> l1{{{1, 2}, {2, 2}, {2, 2}, {3, 1}}, comp};
266 Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
267 assert(testOrder(l1, l2, Order::greater));
269 Container<Key, Val, Compare> l3{{{1, 2}, {2, 2}, {2, 2}, {3, 1}}, comp};
270 Container<Key, Val, Compare> l4{{{2, 2}, {1, 1}}, comp};
271 assert(testOrder(l3, l4, Order::greater));
273 // Unordered
274 if constexpr (std::is_same_v<Val, PartialOrder>) {
275 Container<Key, Val, Compare> l1{{{1, 1}, {2, std::numeric_limits<int>::min()}, {2, 3}}, comp};
276 Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}, {2, 3}}, comp};
277 assert(testOrder(l1, l2, Order::unordered));
279 Container<Key, Val, Compare> l3{{{1, 1}, {2, std::numeric_limits<int>::min()}, {2, 3}}, comp};
280 Container<Key, Val, Compare> l4{{{2, 3}, {2, 2}, {1, 1}}, comp};
281 assert(testOrder(l3, l4, Order::unordered));
285 // Tests the `operator<=>` on ordered map containers
286 template <template <typename...> typename Container>
287 constexpr bool test_ordered_map_container_spaceship() {
288 // Thanks to SFINAE, the following is not a compiler error but returns `false`
289 struct NonComparable {};
290 static_assert(!std::three_way_comparable<Container<int, NonComparable>>);
292 // The container should fulfill `std::three_way_comparable`
293 static_assert(std::three_way_comparable<Container<int, int>>);
295 // Test different comparison categories
296 test_ordered_map_container_spaceship_with_type<Container, int, int, std::strong_ordering>(std::less{});
297 test_ordered_map_container_spaceship_with_type<Container, int, int, std::strong_ordering>(std::greater{});
298 test_ordered_map_container_spaceship_with_type<Container, int, StrongOrder, std::strong_ordering>(std::less{});
299 test_ordered_map_container_spaceship_with_type<Container, int, StrongOrder, std::strong_ordering>(std::greater{});
300 test_ordered_map_container_spaceship_with_type<Container, int, WeakOrder, std::weak_ordering>(std::less{});
301 test_ordered_map_container_spaceship_with_type<Container, int, WeakOrder, std::weak_ordering>(std::greater{});
302 test_ordered_map_container_spaceship_with_type<Container, int, PartialOrder, std::partial_ordering>(std ::less{});
303 test_ordered_map_container_spaceship_with_type<Container, int, PartialOrder, std::partial_ordering>(std ::greater{});
305 // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
306 test_ordered_map_container_spaceship_with_type<Container, int, LessAndEqComp, std::weak_ordering>(std::less{});
308 return true;
311 // Implementation detail of `test_ordered_set_container_spaceship`
312 template <template <typename...> typename Container, typename Elem, typename Order, typename Compare>
313 constexpr void test_ordered_set_spaceship_with_type(Compare comp) {
314 // Empty containers
316 Container<Elem, Compare> l1{{}, comp};
317 Container<Elem, Compare> l2{{}, comp};
318 assert(testOrder(l1, l2, Order::equivalent));
320 // Identical contents
322 Container<Elem, Compare> l1{{1, 1, 2}, comp};
323 Container<Elem, Compare> l2{{1, 1, 2}, comp};
324 assert(testOrder(l1, l2, Order::equivalent));
326 // Less, due to contained values
328 Container<Elem, Compare> l1{{1, 1, 2, 3}, comp};
329 Container<Elem, Compare> l2{{1, 2, 2, 4}, comp};
330 assert(testOrder(l1, l2, Order::less));
332 // Greater, due to contained values
334 Container<Elem, Compare> l1{{1, 2, 2, 4}, comp};
335 Container<Elem, Compare> l2{{1, 1, 2, 3}, comp};
336 assert(testOrder(l1, l2, Order::greater));
338 // Shorter list
340 Container<Elem, Compare> l1{{1, 1, 2, 2}, comp};
341 Container<Elem, Compare> l2{{1, 1, 2, 2, 3}, comp};
342 assert(testOrder(l1, l2, Order::less));
344 // Longer list
346 Container<Elem, Compare> l1{{1, 1, 2, 2, 3}, comp};
347 Container<Elem, Compare> l2{{1, 1, 2, 2}, comp};
348 assert(testOrder(l1, l2, Order::greater));
350 // Unordered
351 if constexpr (std::is_same_v< Container<Elem>, std::multiset<PartialOrder>>) {
352 if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::less{})>) {
353 Container<Elem, Compare> l1{{1, std::numeric_limits<int>::min()}, comp};
354 Container<Elem, Compare> l2{{1, 2}, comp};
355 assert(testOrder(l1, l2, Order::unordered));
357 if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::less{})>) {
358 Container<Elem, Compare> l1{{1, std::numeric_limits<int>::max()}, comp};
359 Container<Elem, Compare> l2{{1, 2}, comp};
360 assert(testOrder(l1, l2, Order::unordered));
363 if constexpr (std::is_same_v< Container<Elem>, std::set<PartialOrder>>) {
364 // Unodered values are not supported for `set`
365 if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::less{})>) {
366 Container<Elem, Compare> l1{{1, std::numeric_limits<int>::min()}, comp};
367 Container<Elem, Compare> l2{{1, 2}, comp};
368 assert(testOrder(l1, l2, Order::less));
370 if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::less{})>) {
371 Container<Elem, Compare> l1{{1, std::numeric_limits<int>::max()}, comp};
372 Container<Elem, Compare> l2{{1, 2}, comp};
373 assert(testOrder(l1, l2, Order::less));
376 if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::greater{})>) {
377 Container<Elem, Compare> l1{{1, std::numeric_limits<int>::min()}, comp};
378 Container<Elem, Compare> l2{{1, 2}, comp};
379 assert(testOrder(l1, l2, Order::less));
381 if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::greater{})>) {
382 Container<Elem, Compare> l1{{1, std::numeric_limits<int>::max()}, comp};
383 Container<Elem, Compare> l2{{1, 2}, comp};
384 assert(testOrder(l1, l2, Order::less));
388 // Tests the `operator<=>` on ordered set containers
389 template <template <typename...> typename Container>
390 constexpr bool test_ordered_set_container_spaceship() {
391 // Thanks to SFINAE, the following is not a compiler error but returns `false`
392 struct NonComparable {};
393 static_assert(!std::three_way_comparable<Container<NonComparable>>);
395 // The container should fulfill `std::three_way_comparable`
396 static_assert(std::three_way_comparable<Container<int>>);
398 // Test different comparison categories
399 test_ordered_set_spaceship_with_type<Container, int, std::strong_ordering>(std::less{});
400 test_ordered_set_spaceship_with_type<Container, int, std::strong_ordering>(std::greater{});
401 test_ordered_set_spaceship_with_type<Container, StrongOrder, std::strong_ordering>(std::less{});
402 test_ordered_set_spaceship_with_type<Container, StrongOrder, std::strong_ordering>(std::greater{});
403 test_ordered_set_spaceship_with_type<Container, WeakOrder, std::weak_ordering>(std::less{});
404 test_ordered_set_spaceship_with_type<Container, WeakOrder, std::weak_ordering>(std::greater{});
405 test_ordered_set_spaceship_with_type<Container, PartialOrder, std::partial_ordering>(std::less{});
406 test_ordered_set_spaceship_with_type<Container, PartialOrder, std::partial_ordering>(std::greater{});
408 // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
409 test_ordered_set_spaceship_with_type<Container, LessAndEqComp, std::weak_ordering>(std::less{});
411 return true;
414 #endif