1b5a84ae0SAdrian Vogelsgesang //===----------------------------------------------------------------------===//
2b5a84ae0SAdrian Vogelsgesang //
3b5a84ae0SAdrian Vogelsgesang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b5a84ae0SAdrian Vogelsgesang // See https://llvm.org/LICENSE.txt for license information.
5b5a84ae0SAdrian Vogelsgesang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b5a84ae0SAdrian Vogelsgesang //
7b5a84ae0SAdrian Vogelsgesang //===----------------------------------------------------------------------===//
8b5a84ae0SAdrian Vogelsgesang // Utility functions to test comparisons on containers.
9b5a84ae0SAdrian Vogelsgesang
10b5a84ae0SAdrian Vogelsgesang #ifndef TEST_CONTAINER_COMPARISONS
11b5a84ae0SAdrian Vogelsgesang #define TEST_CONTAINER_COMPARISONS
12b5a84ae0SAdrian Vogelsgesang
136614d36dSHristo Hristov #include <functional>
14f8b5ac34SHristo Hristov #include <set>
15f8b5ac34SHristo Hristov
16b5a84ae0SAdrian Vogelsgesang #include "test_comparisons.h"
17b5a84ae0SAdrian Vogelsgesang
18177cb103SLouis Dionne // Implementation detail of `test_sequence_container_spaceship`
19b5a84ae0SAdrian Vogelsgesang template <template <typename...> typename Container, typename Elem, typename Order>
test_sequence_container_spaceship_with_type()20177cb103SLouis Dionne constexpr void test_sequence_container_spaceship_with_type() {
21b5a84ae0SAdrian Vogelsgesang // Empty containers
22b5a84ae0SAdrian Vogelsgesang {
23b5a84ae0SAdrian Vogelsgesang Container<Elem> l1;
24b5a84ae0SAdrian Vogelsgesang Container<Elem> l2;
25b5a84ae0SAdrian Vogelsgesang assert(testOrder(l1, l2, Order::equivalent));
26b5a84ae0SAdrian Vogelsgesang }
27b5a84ae0SAdrian Vogelsgesang // Identical contents
28b5a84ae0SAdrian Vogelsgesang {
29b5a84ae0SAdrian Vogelsgesang Container<Elem> l1{1, 1};
30b5a84ae0SAdrian Vogelsgesang Container<Elem> l2{1, 1};
31b5a84ae0SAdrian Vogelsgesang assert(testOrder(l1, l2, Order::equivalent));
32b5a84ae0SAdrian Vogelsgesang }
33b5a84ae0SAdrian Vogelsgesang // Less, due to contained values
34b5a84ae0SAdrian Vogelsgesang {
35b5a84ae0SAdrian Vogelsgesang Container<Elem> l1{1, 1};
36b5a84ae0SAdrian Vogelsgesang Container<Elem> l2{1, 2};
37b5a84ae0SAdrian Vogelsgesang assert(testOrder(l1, l2, Order::less));
38b5a84ae0SAdrian Vogelsgesang }
39b5a84ae0SAdrian Vogelsgesang // Greater, due to contained values
40b5a84ae0SAdrian Vogelsgesang {
41b5a84ae0SAdrian Vogelsgesang Container<Elem> l1{1, 3};
42b5a84ae0SAdrian Vogelsgesang Container<Elem> l2{1, 2};
43b5a84ae0SAdrian Vogelsgesang assert(testOrder(l1, l2, Order::greater));
44b5a84ae0SAdrian Vogelsgesang }
45b5a84ae0SAdrian Vogelsgesang // Shorter list
46b5a84ae0SAdrian Vogelsgesang {
47b5a84ae0SAdrian Vogelsgesang Container<Elem> l1{1};
48b5a84ae0SAdrian Vogelsgesang Container<Elem> l2{1, 2};
49b5a84ae0SAdrian Vogelsgesang assert(testOrder(l1, l2, Order::less));
50b5a84ae0SAdrian Vogelsgesang }
51b5a84ae0SAdrian Vogelsgesang // Longer list
52b5a84ae0SAdrian Vogelsgesang {
53b5a84ae0SAdrian Vogelsgesang Container<Elem> l1{1, 2};
54b5a84ae0SAdrian Vogelsgesang Container<Elem> l2{1};
55b5a84ae0SAdrian Vogelsgesang assert(testOrder(l1, l2, Order::greater));
56b5a84ae0SAdrian Vogelsgesang }
57b5a84ae0SAdrian Vogelsgesang // Unordered
58b5a84ae0SAdrian Vogelsgesang if constexpr (std::is_same_v<Elem, PartialOrder>) {
59b5a84ae0SAdrian Vogelsgesang Container<Elem> l1{1, std::numeric_limits<int>::min()};
60b5a84ae0SAdrian Vogelsgesang Container<Elem> l2{1, 2};
61b5a84ae0SAdrian Vogelsgesang assert(testOrder(l1, l2, Order::unordered));
62b5a84ae0SAdrian Vogelsgesang }
63b5a84ae0SAdrian Vogelsgesang }
64b5a84ae0SAdrian Vogelsgesang
65177cb103SLouis Dionne // Tests the `operator<=>` on sequence containers
66b5a84ae0SAdrian Vogelsgesang template <template <typename...> typename Container>
test_sequence_container_spaceship()67177cb103SLouis Dionne constexpr bool test_sequence_container_spaceship() {
68254986d2SHristo Hristov // The container should fulfill `std::three_way_comparable`
69b5a84ae0SAdrian Vogelsgesang static_assert(std::three_way_comparable<Container<int>>);
70b5a84ae0SAdrian Vogelsgesang
71b5a84ae0SAdrian Vogelsgesang // Test different comparison categories
72177cb103SLouis Dionne test_sequence_container_spaceship_with_type<Container, int, std::strong_ordering>();
73177cb103SLouis Dionne test_sequence_container_spaceship_with_type<Container, StrongOrder, std::strong_ordering>();
74177cb103SLouis Dionne test_sequence_container_spaceship_with_type<Container, WeakOrder, std::weak_ordering>();
75177cb103SLouis Dionne test_sequence_container_spaceship_with_type<Container, PartialOrder, std::partial_ordering>();
76b5a84ae0SAdrian Vogelsgesang
77254986d2SHristo Hristov // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
78177cb103SLouis Dionne test_sequence_container_spaceship_with_type<Container, LessAndEqComp, std::weak_ordering>();
79b5a84ae0SAdrian Vogelsgesang
80b5a84ae0SAdrian Vogelsgesang // Thanks to SFINAE, the following is not a compiler error but returns `false`
81b5a84ae0SAdrian Vogelsgesang struct NonComparable {};
82b5a84ae0SAdrian Vogelsgesang static_assert(!std::three_way_comparable<Container<NonComparable>>);
83b5a84ae0SAdrian Vogelsgesang
84b5a84ae0SAdrian Vogelsgesang return true;
85b5a84ae0SAdrian Vogelsgesang }
86b5a84ae0SAdrian Vogelsgesang
87172d990cSHristo Hristov // Implementation detail of `test_sequence_container_adaptor_spaceship`
88172d990cSHristo Hristov template <template <typename...> typename ContainerAdaptor,
89172d990cSHristo Hristov template <typename...>
90172d990cSHristo Hristov typename Container,
91172d990cSHristo Hristov typename Elem,
92172d990cSHristo Hristov typename Order>
test_sequence_container_adaptor_spaceship_with_type()93172d990cSHristo Hristov constexpr void test_sequence_container_adaptor_spaceship_with_type() {
94172d990cSHristo Hristov // Empty containers
95172d990cSHristo Hristov {
96172d990cSHristo Hristov Container<Elem> l1;
97172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
98172d990cSHristo Hristov Container<Elem> l2;
99172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
100172d990cSHristo Hristov assert(testOrder(ca1, ca2, Order::equivalent));
101172d990cSHristo Hristov }
102172d990cSHristo Hristov // Identical contents
103172d990cSHristo Hristov {
104172d990cSHristo Hristov Container<Elem> l1{1, 1};
105172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
106172d990cSHristo Hristov Container<Elem> l2{1, 1};
107172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
108172d990cSHristo Hristov assert(testOrder(ca1, ca2, Order::equivalent));
109172d990cSHristo Hristov }
110172d990cSHristo Hristov // Less, due to contained values
111172d990cSHristo Hristov {
112172d990cSHristo Hristov Container<Elem> l1{1, 1};
113172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
114172d990cSHristo Hristov Container<Elem> l2{1, 2};
115172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
116172d990cSHristo Hristov assert(testOrder(ca1, ca2, Order::less));
117172d990cSHristo Hristov }
118172d990cSHristo Hristov // Greater, due to contained values
119172d990cSHristo Hristov {
120172d990cSHristo Hristov Container<Elem> l1{1, 3};
121172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
122172d990cSHristo Hristov Container<Elem> l2{1, 2};
123172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
124172d990cSHristo Hristov assert(testOrder(ca1, ca2, Order::greater));
125172d990cSHristo Hristov }
126172d990cSHristo Hristov // Shorter list
127172d990cSHristo Hristov {
128172d990cSHristo Hristov Container<Elem> l1{1};
129172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
130172d990cSHristo Hristov Container<Elem> l2{1, 2};
131172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
132172d990cSHristo Hristov assert(testOrder(ca1, ca2, Order::less));
133172d990cSHristo Hristov }
134172d990cSHristo Hristov // Longer list
135172d990cSHristo Hristov {
136172d990cSHristo Hristov Container<Elem> l1{1, 2};
137172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
138172d990cSHristo Hristov Container<Elem> l2{1};
139172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
140172d990cSHristo Hristov assert(testOrder(ca1, ca2, Order::greater));
141172d990cSHristo Hristov }
142172d990cSHristo Hristov // Unordered
143172d990cSHristo Hristov if constexpr (std::is_same_v<Elem, PartialOrder>) {
144172d990cSHristo Hristov Container<Elem> l1{1, std::numeric_limits<int>::min()};
145172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca1{l1};
146172d990cSHristo Hristov Container<Elem> l2{1, 2};
147172d990cSHristo Hristov ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
148172d990cSHristo Hristov assert(testOrder(ca1, ca2, Order::unordered));
149172d990cSHristo Hristov }
150172d990cSHristo Hristov }
151172d990cSHristo Hristov
152172d990cSHristo Hristov // Tests the `operator<=>` on sequence container adaptors
153172d990cSHristo Hristov template <template <typename...> typename ContainerAdaptor, template <typename...> typename Container>
test_sequence_container_adaptor_spaceship()154172d990cSHristo Hristov constexpr bool test_sequence_container_adaptor_spaceship() {
155172d990cSHristo Hristov // Thanks to SFINAE, the following is not a compiler error but returns `false`
156172d990cSHristo Hristov struct NonComparable {};
157172d990cSHristo Hristov static_assert(!std::three_way_comparable<ContainerAdaptor<NonComparable>>);
158172d990cSHristo Hristov
159172d990cSHristo Hristov // The container should fulfill `std::three_way_comparable`
160172d990cSHristo Hristov static_assert(std::three_way_comparable<ContainerAdaptor<int, Container<int>>>);
161172d990cSHristo Hristov
162172d990cSHristo Hristov // Test different comparison categories
163172d990cSHristo Hristov test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor, Container, int, std::strong_ordering>();
164172d990cSHristo Hristov test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor, Container, StrongOrder, std::strong_ordering>();
165172d990cSHristo Hristov test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor, Container, WeakOrder, std::weak_ordering>();
166172d990cSHristo Hristov test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor,
167172d990cSHristo Hristov Container,
168172d990cSHristo Hristov PartialOrder,
169172d990cSHristo Hristov std::partial_ordering>();
170172d990cSHristo Hristov
171172d990cSHristo Hristov // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
172172d990cSHristo Hristov test_sequence_container_adaptor_spaceship_with_type<ContainerAdaptor, Container, LessAndEqComp, std::weak_ordering>();
173172d990cSHristo Hristov
174172d990cSHristo Hristov return true;
175172d990cSHristo Hristov }
176172d990cSHristo Hristov
177bc47a195SHristo Hristov // Implementation detail of `test_ordered_map_container_spaceship`
1786614d36dSHristo Hristov template <template <typename...> typename Container, typename Key, typename Val, typename Order, typename Compare>
test_ordered_map_container_spaceship_with_type(Compare comp)1796614d36dSHristo Hristov constexpr void test_ordered_map_container_spaceship_with_type(Compare comp) {
180bc47a195SHristo Hristov // Empty containers
181bc47a195SHristo Hristov {
1826614d36dSHristo Hristov Container<Key, Val, Compare> l1{{}, comp};
1836614d36dSHristo Hristov Container<Key, Val, Compare> l2{{}, comp};
184bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::equivalent));
185bc47a195SHristo Hristov }
186bc47a195SHristo Hristov // Identical contents
187bc47a195SHristo Hristov {
1886614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}, {2, 1}}, comp};
1896614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 1}}, comp};
190bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::equivalent));
191bc47a195SHristo Hristov }
192bc47a195SHristo Hristov // Less, due to contained values
193bc47a195SHristo Hristov {
1946614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}, {2, 1}}, comp};
1956614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
196bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::less));
197bc47a195SHristo Hristov }
198bc47a195SHristo Hristov // Greater, due to contained values
199bc47a195SHristo Hristov {
2006614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}, {2, 3}}, comp};
2016614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
202bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::greater));
203bc47a195SHristo Hristov }
204bc47a195SHristo Hristov // Shorter list
205bc47a195SHristo Hristov {
2066614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}}, comp};
2076614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
208bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::less));
209bc47a195SHristo Hristov }
210bc47a195SHristo Hristov // Longer list
211bc47a195SHristo Hristov {
2126614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 2}, {2, 2}}, comp};
2136614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}}, comp};
214bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::greater));
215bc47a195SHristo Hristov }
216bc47a195SHristo Hristov // Unordered
217bc47a195SHristo Hristov if constexpr (std::is_same_v<Val, PartialOrder>) {
2186614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}, {2, std::numeric_limits<int>::min()}}, comp};
2196614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
220bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::unordered));
221bc47a195SHristo Hristov }
222bc47a195SHristo Hristov
223bc47a195SHristo Hristov // Identical contents
224bc47a195SHristo Hristov {
2256614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}, {2, 1}, {2, 2}}, comp};
2266614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 1}, {2, 2}}, comp};
227bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::equivalent));
2286614d36dSHristo Hristov
2296614d36dSHristo Hristov Container<Key, Val, Compare> l3{{{1, 1}, {2, 1}, {2, 2}}, comp};
2306614d36dSHristo Hristov Container<Key, Val, Compare> l4{{{2, 1}, {2, 2}, {1, 1}}, comp};
231bc47a195SHristo Hristov assert(testOrder(l3, l4, Order::equivalent));
232bc47a195SHristo Hristov }
233bc47a195SHristo Hristov // Less, due to contained values
234bc47a195SHristo Hristov {
2356614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}, {2, 1}, {2, 1}}, comp};
2366614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}, {2, 2}}, comp};
237bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::less));
2386614d36dSHristo Hristov
2396614d36dSHristo Hristov Container<Key, Val, Compare> l3{{{1, 1}, {2, 1}, {2, 1}}, comp};
2406614d36dSHristo Hristov Container<Key, Val, Compare> l4{{{2, 2}, {2, 2}, {1, 1}}, comp};
241bc47a195SHristo Hristov assert(testOrder(l3, l4, Order::less));
242bc47a195SHristo Hristov }
243bc47a195SHristo Hristov // Greater, due to contained values
244bc47a195SHristo Hristov {
2456614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}, {2, 3}, {2, 3}}, comp};
2466614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}, {2, 2}}, comp};
247bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::greater));
2486614d36dSHristo Hristov
2496614d36dSHristo Hristov Container<Key, Val, Compare> l3{{{1, 1}, {2, 3}, {2, 3}}, comp};
2506614d36dSHristo Hristov Container<Key, Val, Compare> l4{{{2, 2}, {2, 2}, {1, 1}}, comp};
251bc47a195SHristo Hristov assert(testOrder(l3, l4, Order::greater));
252bc47a195SHristo Hristov }
253bc47a195SHristo Hristov // Shorter list
254bc47a195SHristo Hristov {
2556614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}, {2, 2}}, comp};
2566614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}, {2, 2}, {3, 1}}, comp};
257bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::less));
2586614d36dSHristo Hristov
2596614d36dSHristo Hristov Container<Key, Val, Compare> l3{{{1, 1}, {2, 2}}, comp};
2606614d36dSHristo Hristov Container<Key, Val, Compare> l4{{{3, 1}, {2, 2}, {2, 2}, {1, 1}}, comp};
261bc47a195SHristo Hristov assert(testOrder(l3, l4, Order::less));
262bc47a195SHristo Hristov }
263bc47a195SHristo Hristov // Longer list
264bc47a195SHristo Hristov {
2656614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 2}, {2, 2}, {2, 2}, {3, 1}}, comp};
2666614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}}, comp};
267bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::greater));
2686614d36dSHristo Hristov
2696614d36dSHristo Hristov Container<Key, Val, Compare> l3{{{1, 2}, {2, 2}, {2, 2}, {3, 1}}, comp};
2706614d36dSHristo Hristov Container<Key, Val, Compare> l4{{{2, 2}, {1, 1}}, comp};
271bc47a195SHristo Hristov assert(testOrder(l3, l4, Order::greater));
272bc47a195SHristo Hristov }
273bc47a195SHristo Hristov // Unordered
274bc47a195SHristo Hristov if constexpr (std::is_same_v<Val, PartialOrder>) {
2756614d36dSHristo Hristov Container<Key, Val, Compare> l1{{{1, 1}, {2, std::numeric_limits<int>::min()}, {2, 3}}, comp};
2766614d36dSHristo Hristov Container<Key, Val, Compare> l2{{{1, 1}, {2, 2}, {2, 3}}, comp};
277bc47a195SHristo Hristov assert(testOrder(l1, l2, Order::unordered));
2786614d36dSHristo Hristov
2796614d36dSHristo Hristov Container<Key, Val, Compare> l3{{{1, 1}, {2, std::numeric_limits<int>::min()}, {2, 3}}, comp};
2806614d36dSHristo Hristov Container<Key, Val, Compare> l4{{{2, 3}, {2, 2}, {1, 1}}, comp};
281bc47a195SHristo Hristov assert(testOrder(l3, l4, Order::unordered));
282bc47a195SHristo Hristov }
283bc47a195SHristo Hristov }
284bc47a195SHristo Hristov
285f8b5ac34SHristo Hristov // Tests the `operator<=>` on ordered map containers
286bc47a195SHristo Hristov template <template <typename...> typename Container>
test_ordered_map_container_spaceship()287bc47a195SHristo Hristov constexpr bool test_ordered_map_container_spaceship() {
2886614d36dSHristo Hristov // Thanks to SFINAE, the following is not a compiler error but returns `false`
2896614d36dSHristo Hristov struct NonComparable {};
2906614d36dSHristo Hristov static_assert(!std::three_way_comparable<Container<int, NonComparable>>);
2916614d36dSHristo Hristov
292254986d2SHristo Hristov // The container should fulfill `std::three_way_comparable`
293bc47a195SHristo Hristov static_assert(std::three_way_comparable<Container<int, int>>);
294bc47a195SHristo Hristov
295bc47a195SHristo Hristov // Test different comparison categories
2966614d36dSHristo Hristov test_ordered_map_container_spaceship_with_type<Container, int, int, std::strong_ordering>(std::less{});
2976614d36dSHristo Hristov test_ordered_map_container_spaceship_with_type<Container, int, int, std::strong_ordering>(std::greater{});
2986614d36dSHristo Hristov test_ordered_map_container_spaceship_with_type<Container, int, StrongOrder, std::strong_ordering>(std::less{});
2996614d36dSHristo Hristov test_ordered_map_container_spaceship_with_type<Container, int, StrongOrder, std::strong_ordering>(std::greater{});
3006614d36dSHristo Hristov test_ordered_map_container_spaceship_with_type<Container, int, WeakOrder, std::weak_ordering>(std::less{});
3016614d36dSHristo Hristov test_ordered_map_container_spaceship_with_type<Container, int, WeakOrder, std::weak_ordering>(std::greater{});
3026614d36dSHristo Hristov test_ordered_map_container_spaceship_with_type<Container, int, PartialOrder, std::partial_ordering>(std ::less{});
3036614d36dSHristo Hristov test_ordered_map_container_spaceship_with_type<Container, int, PartialOrder, std::partial_ordering>(std ::greater{});
304bc47a195SHristo Hristov
305254986d2SHristo Hristov // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
3066614d36dSHristo Hristov test_ordered_map_container_spaceship_with_type<Container, int, LessAndEqComp, std::weak_ordering>(std::less{});
307bc47a195SHristo Hristov
308bc47a195SHristo Hristov return true;
309bc47a195SHristo Hristov }
310bc47a195SHristo Hristov
311f8b5ac34SHristo Hristov // Implementation detail of `test_ordered_set_container_spaceship`
312f8b5ac34SHristo Hristov template <template <typename...> typename Container, typename Elem, typename Order, typename Compare>
test_ordered_set_spaceship_with_type(Compare comp)313f8b5ac34SHristo Hristov constexpr void test_ordered_set_spaceship_with_type(Compare comp) {
314f8b5ac34SHristo Hristov // Empty containers
315f8b5ac34SHristo Hristov {
316f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{}, comp};
317f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{}, comp};
318f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::equivalent));
319f8b5ac34SHristo Hristov }
320f8b5ac34SHristo Hristov // Identical contents
321f8b5ac34SHristo Hristov {
322f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, 1, 2}, comp};
323f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 1, 2}, comp};
324f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::equivalent));
325f8b5ac34SHristo Hristov }
326f8b5ac34SHristo Hristov // Less, due to contained values
327f8b5ac34SHristo Hristov {
328f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, 1, 2, 3}, comp};
329f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 2, 2, 4}, comp};
330f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::less));
331f8b5ac34SHristo Hristov }
332f8b5ac34SHristo Hristov // Greater, due to contained values
333f8b5ac34SHristo Hristov {
334f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, 2, 2, 4}, comp};
335f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 1, 2, 3}, comp};
336f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::greater));
337f8b5ac34SHristo Hristov }
338f8b5ac34SHristo Hristov // Shorter list
339f8b5ac34SHristo Hristov {
340f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, 1, 2, 2}, comp};
341f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 1, 2, 2, 3}, comp};
342f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::less));
343f8b5ac34SHristo Hristov }
344f8b5ac34SHristo Hristov // Longer list
345f8b5ac34SHristo Hristov {
346f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, 1, 2, 2, 3}, comp};
347f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 1, 2, 2}, comp};
348f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::greater));
349f8b5ac34SHristo Hristov }
350f8b5ac34SHristo Hristov // Unordered
351f8b5ac34SHristo Hristov if constexpr (std::is_same_v< Container<Elem>, std::multiset<PartialOrder>>) {
352f8b5ac34SHristo Hristov if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::less{})>) {
353f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, std::numeric_limits<int>::min()}, comp};
354f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 2}, comp};
355f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::unordered));
356f8b5ac34SHristo Hristov }
357f8b5ac34SHristo Hristov if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::less{})>) {
358f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, std::numeric_limits<int>::max()}, comp};
359f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 2}, comp};
360f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::unordered));
361f8b5ac34SHristo Hristov }
362f8b5ac34SHristo Hristov }
363f8b5ac34SHristo Hristov if constexpr (std::is_same_v< Container<Elem>, std::set<PartialOrder>>) {
364*f5832babSStephan T. Lavavej // Unordered values are not supported for `set`
365f8b5ac34SHristo Hristov if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::less{})>) {
366f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, std::numeric_limits<int>::min()}, comp};
367f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 2}, comp};
368f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::less));
369f8b5ac34SHristo Hristov }
370f8b5ac34SHristo Hristov if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::less{})>) {
371f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, std::numeric_limits<int>::max()}, comp};
372f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 2}, comp};
373f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::less));
374f8b5ac34SHristo Hristov }
375f8b5ac34SHristo Hristov }
376f8b5ac34SHristo Hristov if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::greater{})>) {
377f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, std::numeric_limits<int>::min()}, comp};
378f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 2}, comp};
379f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::less));
380f8b5ac34SHristo Hristov }
381f8b5ac34SHristo Hristov if constexpr (std::is_same_v<Elem, PartialOrder> && std::is_same_v<Compare, decltype(std::greater{})>) {
382f8b5ac34SHristo Hristov Container<Elem, Compare> l1{{1, std::numeric_limits<int>::max()}, comp};
383f8b5ac34SHristo Hristov Container<Elem, Compare> l2{{1, 2}, comp};
384f8b5ac34SHristo Hristov assert(testOrder(l1, l2, Order::less));
385f8b5ac34SHristo Hristov }
386f8b5ac34SHristo Hristov }
387f8b5ac34SHristo Hristov
388f8b5ac34SHristo Hristov // Tests the `operator<=>` on ordered set containers
389f8b5ac34SHristo Hristov template <template <typename...> typename Container>
test_ordered_set_container_spaceship()390f8b5ac34SHristo Hristov constexpr bool test_ordered_set_container_spaceship() {
391f8b5ac34SHristo Hristov // Thanks to SFINAE, the following is not a compiler error but returns `false`
392f8b5ac34SHristo Hristov struct NonComparable {};
393f8b5ac34SHristo Hristov static_assert(!std::three_way_comparable<Container<NonComparable>>);
394f8b5ac34SHristo Hristov
395f8b5ac34SHristo Hristov // The container should fulfill `std::three_way_comparable`
396f8b5ac34SHristo Hristov static_assert(std::three_way_comparable<Container<int>>);
397f8b5ac34SHristo Hristov
398f8b5ac34SHristo Hristov // Test different comparison categories
399f8b5ac34SHristo Hristov test_ordered_set_spaceship_with_type<Container, int, std::strong_ordering>(std::less{});
400f8b5ac34SHristo Hristov test_ordered_set_spaceship_with_type<Container, int, std::strong_ordering>(std::greater{});
401f8b5ac34SHristo Hristov test_ordered_set_spaceship_with_type<Container, StrongOrder, std::strong_ordering>(std::less{});
402f8b5ac34SHristo Hristov test_ordered_set_spaceship_with_type<Container, StrongOrder, std::strong_ordering>(std::greater{});
403f8b5ac34SHristo Hristov test_ordered_set_spaceship_with_type<Container, WeakOrder, std::weak_ordering>(std::less{});
404f8b5ac34SHristo Hristov test_ordered_set_spaceship_with_type<Container, WeakOrder, std::weak_ordering>(std::greater{});
405f8b5ac34SHristo Hristov test_ordered_set_spaceship_with_type<Container, PartialOrder, std::partial_ordering>(std::less{});
406f8b5ac34SHristo Hristov test_ordered_set_spaceship_with_type<Container, PartialOrder, std::partial_ordering>(std::greater{});
407f8b5ac34SHristo Hristov
408f8b5ac34SHristo Hristov // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
409f8b5ac34SHristo Hristov test_ordered_set_spaceship_with_type<Container, LessAndEqComp, std::weak_ordering>(std::less{});
410f8b5ac34SHristo Hristov
411f8b5ac34SHristo Hristov return true;
412f8b5ac34SHristo Hristov }
413f8b5ac34SHristo Hristov
414b5a84ae0SAdrian Vogelsgesang #endif
415