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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
13 // template <class ...Types>
15 // operator==(variant<Types...> const&, variant<Types...> const&) noexcept;
17 // template <class ...Types>
19 // operator!=(variant<Types...> const&, variant<Types...> const&) noexcept;
21 // template <class ...Types>
23 // operator<(variant<Types...> const&, variant<Types...> const&) noexcept;
25 // template <class ...Types>
27 // operator>(variant<Types...> const&, variant<Types...> const&) noexcept;
29 // template <class ...Types>
31 // operator<=(variant<Types...> const&, variant<Types...> const&) noexcept;
33 // template <class ...Types>
35 // operator>=(variant<Types...> const&, variant<Types...> const&) noexcept;
38 #include <type_traits>
42 #include "test_macros.h"
44 #ifndef TEST_HAS_NO_EXCEPTIONS
46 MakeEmptyT() = default;
47 MakeEmptyT(MakeEmptyT
&&) { throw 42; }
48 MakeEmptyT
&operator=(MakeEmptyT
&&) { throw 42; }
50 inline bool operator==(const MakeEmptyT
&, const MakeEmptyT
&) {
54 inline bool operator!=(const MakeEmptyT
&, const MakeEmptyT
&) {
58 inline bool operator<(const MakeEmptyT
&, const MakeEmptyT
&) {
62 inline bool operator<=(const MakeEmptyT
&, const MakeEmptyT
&) {
66 inline bool operator>(const MakeEmptyT
&, const MakeEmptyT
&) {
70 inline bool operator>=(const MakeEmptyT
&, const MakeEmptyT
&) {
75 template <class Variant
> void makeEmpty(Variant
&v
) {
76 Variant
v2(std::in_place_type
<MakeEmptyT
>);
81 assert(v
.valueless_by_exception());
84 #endif // TEST_HAS_NO_EXCEPTIONS
88 constexpr explicit MyBool(bool v
) : value(v
) {}
89 constexpr operator bool() const noexcept
{ return value
; }
92 struct ComparesToMyBool
{
95 inline constexpr MyBool
operator==(const ComparesToMyBool
& LHS
, const ComparesToMyBool
& RHS
) noexcept
{
96 return MyBool(LHS
.value
== RHS
.value
);
98 inline constexpr MyBool
operator!=(const ComparesToMyBool
& LHS
, const ComparesToMyBool
& RHS
) noexcept
{
99 return MyBool(LHS
.value
!= RHS
.value
);
101 inline constexpr MyBool
operator<(const ComparesToMyBool
& LHS
, const ComparesToMyBool
& RHS
) noexcept
{
102 return MyBool(LHS
.value
< RHS
.value
);
104 inline constexpr MyBool
operator<=(const ComparesToMyBool
& LHS
, const ComparesToMyBool
& RHS
) noexcept
{
105 return MyBool(LHS
.value
<= RHS
.value
);
107 inline constexpr MyBool
operator>(const ComparesToMyBool
& LHS
, const ComparesToMyBool
& RHS
) noexcept
{
108 return MyBool(LHS
.value
> RHS
.value
);
110 inline constexpr MyBool
operator>=(const ComparesToMyBool
& LHS
, const ComparesToMyBool
& RHS
) noexcept
{
111 return MyBool(LHS
.value
>= RHS
.value
);
114 template <class T1
, class T2
>
115 void test_equality_basic() {
117 using V
= std::variant
<T1
, T2
>;
118 constexpr V
v1(std::in_place_index
<0>, T1
{42});
119 constexpr V
v2(std::in_place_index
<0>, T1
{42});
120 static_assert(v1
== v2
, "");
121 static_assert(v2
== v1
, "");
122 static_assert(!(v1
!= v2
), "");
123 static_assert(!(v2
!= v1
), "");
126 using V
= std::variant
<T1
, T2
>;
127 constexpr V
v1(std::in_place_index
<0>, T1
{42});
128 constexpr V
v2(std::in_place_index
<0>, T1
{43});
129 static_assert(!(v1
== v2
), "");
130 static_assert(!(v2
== v1
), "");
131 static_assert(v1
!= v2
, "");
132 static_assert(v2
!= v1
, "");
135 using V
= std::variant
<T1
, T2
>;
136 constexpr V
v1(std::in_place_index
<0>, T1
{42});
137 constexpr V
v2(std::in_place_index
<1>, T2
{42});
138 static_assert(!(v1
== v2
), "");
139 static_assert(!(v2
== v1
), "");
140 static_assert(v1
!= v2
, "");
141 static_assert(v2
!= v1
, "");
144 using V
= std::variant
<T1
, T2
>;
145 constexpr V
v1(std::in_place_index
<1>, T2
{42});
146 constexpr V
v2(std::in_place_index
<1>, T2
{42});
147 static_assert(v1
== v2
, "");
148 static_assert(v2
== v1
, "");
149 static_assert(!(v1
!= v2
), "");
150 static_assert(!(v2
!= v1
), "");
154 void test_equality() {
155 test_equality_basic
<int, long>();
156 test_equality_basic
<ComparesToMyBool
, int>();
157 test_equality_basic
<int, ComparesToMyBool
>();
158 test_equality_basic
<ComparesToMyBool
, ComparesToMyBool
>();
159 #ifndef TEST_HAS_NO_EXCEPTIONS
161 using V
= std::variant
<int, MakeEmptyT
>;
171 using V
= std::variant
<int, MakeEmptyT
>;
181 using V
= std::variant
<int, MakeEmptyT
>;
195 constexpr bool test_less(const Var
&l
, const Var
&r
, bool expect_less
,
196 bool expect_greater
) {
197 static_assert(std::is_same_v
<decltype(l
< r
), bool>, "");
198 static_assert(std::is_same_v
<decltype(l
<= r
), bool>, "");
199 static_assert(std::is_same_v
<decltype(l
> r
), bool>, "");
200 static_assert(std::is_same_v
<decltype(l
>= r
), bool>, "");
202 return ((l
< r
) == expect_less
) && (!(l
>= r
) == expect_less
) &&
203 ((l
> r
) == expect_greater
) && (!(l
<= r
) == expect_greater
);
206 template <class T1
, class T2
>
207 void test_relational_basic() {
208 { // same index, same value
209 using V
= std::variant
<T1
, T2
>;
210 constexpr V
v1(std::in_place_index
<0>, T1
{1});
211 constexpr V
v2(std::in_place_index
<0>, T1
{1});
212 static_assert(test_less(v1
, v2
, false, false), "");
214 { // same index, value < other_value
215 using V
= std::variant
<T1
, T2
>;
216 constexpr V
v1(std::in_place_index
<0>, T1
{0});
217 constexpr V
v2(std::in_place_index
<0>, T1
{1});
218 static_assert(test_less(v1
, v2
, true, false), "");
220 { // same index, value > other_value
221 using V
= std::variant
<T1
, T2
>;
222 constexpr V
v1(std::in_place_index
<0>, T1
{1});
223 constexpr V
v2(std::in_place_index
<0>, T1
{0});
224 static_assert(test_less(v1
, v2
, false, true), "");
226 { // LHS.index() < RHS.index()
227 using V
= std::variant
<T1
, T2
>;
228 constexpr V
v1(std::in_place_index
<0>, T1
{0});
229 constexpr V
v2(std::in_place_index
<1>, T2
{0});
230 static_assert(test_less(v1
, v2
, true, false), "");
232 { // LHS.index() > RHS.index()
233 using V
= std::variant
<T1
, T2
>;
234 constexpr V
v1(std::in_place_index
<1>, T2
{0});
235 constexpr V
v2(std::in_place_index
<0>, T1
{0});
236 static_assert(test_less(v1
, v2
, false, true), "");
240 void test_relational() {
241 test_relational_basic
<int, long>();
242 test_relational_basic
<ComparesToMyBool
, int>();
243 test_relational_basic
<int, ComparesToMyBool
>();
244 test_relational_basic
<ComparesToMyBool
, ComparesToMyBool
>();
245 #ifndef TEST_HAS_NO_EXCEPTIONS
246 { // LHS.index() < RHS.index(), RHS is empty
247 using V
= std::variant
<int, MakeEmptyT
>;
251 assert(test_less(v1
, v2
, false, true));
253 { // LHS.index() > RHS.index(), LHS is empty
254 using V
= std::variant
<int, MakeEmptyT
>;
258 assert(test_less(v1
, v2
, true, false));
260 { // LHS.index() == RHS.index(), LHS and RHS are empty
261 using V
= std::variant
<int, MakeEmptyT
>;
266 assert(test_less(v1
, v2
, false, false));
271 int main(int, char**) {