Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / std / utilities / variant / variant.relops / three_way.pass.cpp
blobc235967abcc9d8a4a6587b17443adde130c37cac
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
11 // <variant>
13 // template <class... Types> class variant;
15 // template <class... Types> requires (three_way_comparable<Types> && ...)
16 // constexpr std::common_comparison_category_t<
17 // std::compare_three_way_result_t<Types>...>
18 // operator<=>(const variant<Types...>& t, const variant<Types...>& u);
20 #include <cassert>
21 #include <limits>
22 #include <type_traits>
23 #include <utility>
24 #include <variant>
26 #include "test_macros.h"
27 #include "test_comparisons.h"
29 #ifndef TEST_HAS_NO_EXCEPTIONS
30 // MakeEmptyT throws in operator=(&&), so we can move to it to create valueless-by-exception variants.
31 struct MakeEmptyT {
32 MakeEmptyT() = default;
33 MakeEmptyT(MakeEmptyT&&) { throw 42; }
34 MakeEmptyT& operator=(MakeEmptyT&&) { throw 42; }
36 inline bool operator==(const MakeEmptyT&, const MakeEmptyT&) {
37 assert(false);
38 return false;
40 inline std::weak_ordering operator<=>(const MakeEmptyT&, const MakeEmptyT&) {
41 assert(false);
42 return std::weak_ordering::equivalent;
45 template <class Variant>
46 void makeEmpty(Variant& v) {
47 Variant v2(std::in_place_type<MakeEmptyT>);
48 try {
49 v = std::move(v2);
50 assert(false);
51 } catch (...) {
52 assert(v.valueless_by_exception());
56 void test_empty() {
58 using V = std::variant<int, MakeEmptyT>;
59 V v1;
60 V v2;
61 makeEmpty(v2);
62 assert(testOrder(v1, v2, std::weak_ordering::greater));
65 using V = std::variant<int, MakeEmptyT>;
66 V v1;
67 makeEmpty(v1);
68 V v2;
69 assert(testOrder(v1, v2, std::weak_ordering::less));
72 using V = std::variant<int, MakeEmptyT>;
73 V v1;
74 makeEmpty(v1);
75 V v2;
76 makeEmpty(v2);
77 assert(testOrder(v1, v2, std::weak_ordering::equivalent));
80 #endif // TEST_HAS_NO_EXCEPTIONS
82 template <class T1, class T2, class Order>
83 constexpr bool test_with_types() {
84 using V = std::variant<T1, T2>;
85 AssertOrderReturn<Order, V>();
86 { // same index, same value
87 constexpr V v1(std::in_place_index<0>, T1{1});
88 constexpr V v2(std::in_place_index<0>, T1{1});
89 assert(testOrder(v1, v2, Order::equivalent));
91 { // same index, value < other_value
92 constexpr V v1(std::in_place_index<0>, T1{0});
93 constexpr V v2(std::in_place_index<0>, T1{1});
94 assert(testOrder(v1, v2, Order::less));
96 { // same index, value > other_value
97 constexpr V v1(std::in_place_index<0>, T1{1});
98 constexpr V v2(std::in_place_index<0>, T1{0});
99 assert(testOrder(v1, v2, Order::greater));
101 { // LHS.index() < RHS.index()
102 constexpr V v1(std::in_place_index<0>, T1{0});
103 constexpr V v2(std::in_place_index<1>, T2{0});
104 assert(testOrder(v1, v2, Order::less));
106 { // LHS.index() > RHS.index()
107 constexpr V v1(std::in_place_index<1>, T2{0});
108 constexpr V v2(std::in_place_index<0>, T1{0});
109 assert(testOrder(v1, v2, Order::greater));
112 return true;
115 constexpr bool test_three_way() {
116 assert((test_with_types<int, double, std::partial_ordering>()));
117 assert((test_with_types<int, long, std::strong_ordering>()));
120 using V = std::variant<int, double>;
121 constexpr double nan = std::numeric_limits<double>::quiet_NaN();
123 constexpr V v1(std::in_place_type<int>, 1);
124 constexpr V v2(std::in_place_type<double>, nan);
125 assert(testOrder(v1, v2, std::partial_ordering::less));
128 constexpr V v1(std::in_place_type<double>, nan);
129 constexpr V v2(std::in_place_type<int>, 2);
130 assert(testOrder(v1, v2, std::partial_ordering::greater));
133 constexpr V v1(std::in_place_type<double>, nan);
134 constexpr V v2(std::in_place_type<double>, nan);
135 assert(testOrder(v1, v2, std::partial_ordering::unordered));
139 return true;
142 // SFINAE tests
143 template <class T, class U = T>
144 concept has_three_way_op = requires (T& t, U& u) { t <=> u; };
146 // std::three_way_comparable is a more stringent requirement that demands
147 // operator== and a few other things.
148 using std::three_way_comparable;
150 struct HasSimpleOrdering {
151 constexpr bool operator==(const HasSimpleOrdering&) const;
152 constexpr bool operator<(const HasSimpleOrdering&) const;
155 struct HasOnlySpaceship {
156 constexpr bool operator==(const HasOnlySpaceship&) const = delete;
157 constexpr std::weak_ordering operator<=>(const HasOnlySpaceship&) const;
160 struct HasFullOrdering {
161 constexpr bool operator==(const HasFullOrdering&) const;
162 constexpr std::weak_ordering operator<=>(const HasFullOrdering&) const;
165 // operator<=> must resolve the return types of all its union types'
166 // operator<=>s to determine its own return type, so it is detectable by SFINAE
167 static_assert(!has_three_way_op<HasSimpleOrdering>);
168 static_assert(!has_three_way_op<std::variant<int, HasSimpleOrdering>>);
170 static_assert(!three_way_comparable<HasSimpleOrdering>);
171 static_assert(!three_way_comparable<std::variant<int, HasSimpleOrdering>>);
173 static_assert(has_three_way_op<HasOnlySpaceship>);
174 static_assert(!has_three_way_op<std::variant<int, HasOnlySpaceship>>);
176 static_assert(!three_way_comparable<HasOnlySpaceship>);
177 static_assert(!three_way_comparable<std::variant<int, HasOnlySpaceship>>);
179 static_assert( has_three_way_op<HasFullOrdering>);
180 static_assert( has_three_way_op<std::variant<int, HasFullOrdering>>);
182 static_assert( three_way_comparable<HasFullOrdering>);
183 static_assert( three_way_comparable<std::variant<int, HasFullOrdering>>);
185 int main(int, char**) {
186 test_three_way();
187 static_assert(test_three_way());
189 #ifndef TEST_HAS_NO_EXCEPTIONS
190 test_empty();
191 #endif // TEST_HAS_NO_EXCEPTIONS
193 return 0;