1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
8 // Utility functions to test comparisons on containers.
10 #ifndef TEST_CONTAINER_COMPARISONS
11 #define TEST_CONTAINER_COMPARISONS
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() {
25 assert(testOrder(l1
, l2
, Order::equivalent
));
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
));
47 Container
<Elem
> l1
{1};
48 Container
<Elem
> l2
{1, 2};
49 assert(testOrder(l1
, l2
, Order::less
));
53 Container
<Elem
> l1
{1, 2};
54 Container
<Elem
> l2
{1};
55 assert(testOrder(l1
, l2
, Order::greater
));
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
>>);
87 // Implementation detail of `test_sequence_container_adaptor_spaceship`
88 template <template <typename
...> typename ContainerAdaptor
,
89 template <typename
...>
93 constexpr void test_sequence_container_adaptor_spaceship_with_type() {
97 ContainerAdaptor
<Elem
, Container
<Elem
>> ca1
{l1
};
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
));
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
));
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
));
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
,
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
>();
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
) {
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
));
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
));
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
));
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
));
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
));
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
));
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
{});
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
) {
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
));
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
));
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
));
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
{});