blob: d5dd7cffac358daf5dc2671a61935d9dca81ad60 [file] [log] [blame]
Eric Fiselier80e66ac2016-11-23 01:02:51 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Chandler Carruth57b08b02019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselier80e66ac2016-11-23 01:02:51 +00007//
8//===----------------------------------------------------------------------===//
9
Louis Dionne31cbe0f2020-06-01 10:38:23 -040010// UNSUPPORTED: c++03, c++11, c++14
Eric Fiselier80e66ac2016-11-23 01:02:51 +000011
12// <variant>
13
14// template <class ...Types>
15// constexpr bool
16// operator==(variant<Types...> const&, variant<Types...> const&) noexcept;
17//
18// template <class ...Types>
19// constexpr bool
20// operator!=(variant<Types...> const&, variant<Types...> const&) noexcept;
21//
22// template <class ...Types>
23// constexpr bool
24// operator<(variant<Types...> const&, variant<Types...> const&) noexcept;
25//
26// template <class ...Types>
27// constexpr bool
28// operator>(variant<Types...> const&, variant<Types...> const&) noexcept;
29//
30// template <class ...Types>
31// constexpr bool
32// operator<=(variant<Types...> const&, variant<Types...> const&) noexcept;
33//
34// template <class ...Types>
35// constexpr bool
36// operator>=(variant<Types...> const&, variant<Types...> const&) noexcept;
37
38#include <cassert>
39#include <type_traits>
40#include <utility>
41#include <variant>
42
43#include "test_macros.h"
44
45#ifndef TEST_HAS_NO_EXCEPTIONS
46struct MakeEmptyT {
47 MakeEmptyT() = default;
48 MakeEmptyT(MakeEmptyT &&) { throw 42; }
49 MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
50};
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000051inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000052 assert(false);
53 return false;
54}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000055inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000056 assert(false);
57 return false;
58}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000059inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000060 assert(false);
61 return false;
62}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000063inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000064 assert(false);
65 return false;
66}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000067inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000068 assert(false);
69 return false;
70}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000071inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000072 assert(false);
73 return false;
74}
75
76template <class Variant> void makeEmpty(Variant &v) {
77 Variant v2(std::in_place_type<MakeEmptyT>);
78 try {
79 v = std::move(v2);
80 assert(false);
81 } catch (...) {
82 assert(v.valueless_by_exception());
83 }
84}
85#endif // TEST_HAS_NO_EXCEPTIONS
86
Eric Fiselier7dca3122018-09-19 17:53:21 +000087struct MyBool {
88 bool value;
89 constexpr explicit MyBool(bool v) : value(v) {}
90 constexpr operator bool() const noexcept { return value; }
91};
92
93struct ComparesToMyBool {
94 int value = 0;
95};
96inline constexpr MyBool operator==(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
97 return MyBool(LHS.value == RHS.value);
98}
99inline constexpr MyBool operator!=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
100 return MyBool(LHS.value != RHS.value);
101}
102inline constexpr MyBool operator<(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
103 return MyBool(LHS.value < RHS.value);
104}
105inline constexpr MyBool operator<=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
106 return MyBool(LHS.value <= RHS.value);
107}
108inline constexpr MyBool operator>(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
109 return MyBool(LHS.value > RHS.value);
110}
111inline constexpr MyBool operator>=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
112 return MyBool(LHS.value >= RHS.value);
113}
114
115template <class T1, class T2>
116void test_equality_basic() {
117 {
118 using V = std::variant<T1, T2>;
119 constexpr V v1(std::in_place_index<0>, T1{42});
120 constexpr V v2(std::in_place_index<0>, T1{42});
121 static_assert(v1 == v2, "");
122 static_assert(v2 == v1, "");
123 static_assert(!(v1 != v2), "");
124 static_assert(!(v2 != v1), "");
125 }
126 {
127 using V = std::variant<T1, T2>;
128 constexpr V v1(std::in_place_index<0>, T1{42});
129 constexpr V v2(std::in_place_index<0>, T1{43});
130 static_assert(!(v1 == v2), "");
131 static_assert(!(v2 == v1), "");
132 static_assert(v1 != v2, "");
133 static_assert(v2 != v1, "");
134 }
135 {
136 using V = std::variant<T1, T2>;
137 constexpr V v1(std::in_place_index<0>, T1{42});
138 constexpr V v2(std::in_place_index<1>, T2{42});
139 static_assert(!(v1 == v2), "");
140 static_assert(!(v2 == v1), "");
141 static_assert(v1 != v2, "");
142 static_assert(v2 != v1, "");
143 }
144 {
145 using V = std::variant<T1, T2>;
146 constexpr V v1(std::in_place_index<1>, T2{42});
147 constexpr V v2(std::in_place_index<1>, T2{42});
148 static_assert(v1 == v2, "");
149 static_assert(v2 == v1, "");
150 static_assert(!(v1 != v2), "");
151 static_assert(!(v2 != v1), "");
152 }
153}
154
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000155void test_equality() {
Eric Fiselier7dca3122018-09-19 17:53:21 +0000156 test_equality_basic<int, long>();
157 test_equality_basic<ComparesToMyBool, int>();
158 test_equality_basic<int, ComparesToMyBool>();
159 test_equality_basic<ComparesToMyBool, ComparesToMyBool>();
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000160#ifndef TEST_HAS_NO_EXCEPTIONS
161 {
162 using V = std::variant<int, MakeEmptyT>;
163 V v1;
164 V v2;
165 makeEmpty(v2);
166 assert(!(v1 == v2));
167 assert(!(v2 == v1));
168 assert(v1 != v2);
169 assert(v2 != v1);
170 }
171 {
172 using V = std::variant<int, MakeEmptyT>;
173 V v1;
174 makeEmpty(v1);
175 V v2;
176 assert(!(v1 == v2));
177 assert(!(v2 == v1));
178 assert(v1 != v2);
179 assert(v2 != v1);
180 }
181 {
182 using V = std::variant<int, MakeEmptyT>;
183 V v1;
184 makeEmpty(v1);
185 V v2;
186 makeEmpty(v2);
187 assert(v1 == v2);
188 assert(v2 == v1);
189 assert(!(v1 != v2));
190 assert(!(v2 != v1));
191 }
192#endif
193}
194
195template <class Var>
Eric Fiselier0d3d8de2016-12-02 23:00:05 +0000196constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000197 bool expect_greater) {
Eric Fiselier7dca3122018-09-19 17:53:21 +0000198 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>, "");
201 static_assert(std::is_same_v<decltype(l >= r), bool>, "");
202
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000203 return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
204 ((l > r) == expect_greater) && (!(l <= r) == expect_greater);
205}
206
Eric Fiselier7dca3122018-09-19 17:53:21 +0000207template <class T1, class T2>
208void test_relational_basic() {
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000209 { // same index, same value
Eric Fiselier7dca3122018-09-19 17:53:21 +0000210 using V = std::variant<T1, T2>;
211 constexpr V v1(std::in_place_index<0>, T1{1});
212 constexpr V v2(std::in_place_index<0>, T1{1});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000213 static_assert(test_less(v1, v2, false, false), "");
214 }
215 { // same index, value < other_value
Eric Fiselier7dca3122018-09-19 17:53:21 +0000216 using V = std::variant<T1, T2>;
217 constexpr V v1(std::in_place_index<0>, T1{0});
218 constexpr V v2(std::in_place_index<0>, T1{1});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000219 static_assert(test_less(v1, v2, true, false), "");
220 }
221 { // same index, value > other_value
Eric Fiselier7dca3122018-09-19 17:53:21 +0000222 using V = std::variant<T1, T2>;
223 constexpr V v1(std::in_place_index<0>, T1{1});
224 constexpr V v2(std::in_place_index<0>, T1{0});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000225 static_assert(test_less(v1, v2, false, true), "");
226 }
227 { // LHS.index() < RHS.index()
Eric Fiselier7dca3122018-09-19 17:53:21 +0000228 using V = std::variant<T1, T2>;
229 constexpr V v1(std::in_place_index<0>, T1{0});
230 constexpr V v2(std::in_place_index<1>, T2{0});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000231 static_assert(test_less(v1, v2, true, false), "");
232 }
233 { // LHS.index() > RHS.index()
Eric Fiselier7dca3122018-09-19 17:53:21 +0000234 using V = std::variant<T1, T2>;
235 constexpr V v1(std::in_place_index<1>, T2{0});
236 constexpr V v2(std::in_place_index<0>, T1{0});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000237 static_assert(test_less(v1, v2, false, true), "");
238 }
Eric Fiselier7dca3122018-09-19 17:53:21 +0000239}
240
241void test_relational() {
242 test_relational_basic<int, long>();
243 test_relational_basic<ComparesToMyBool, int>();
244 test_relational_basic<int, ComparesToMyBool>();
245 test_relational_basic<ComparesToMyBool, ComparesToMyBool>();
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000246#ifndef TEST_HAS_NO_EXCEPTIONS
247 { // LHS.index() < RHS.index(), RHS is empty
248 using V = std::variant<int, MakeEmptyT>;
249 V v1;
250 V v2;
251 makeEmpty(v2);
252 assert(test_less(v1, v2, false, true));
253 }
254 { // LHS.index() > RHS.index(), LHS is empty
255 using V = std::variant<int, MakeEmptyT>;
256 V v1;
257 makeEmpty(v1);
258 V v2;
259 assert(test_less(v1, v2, true, false));
260 }
261 { // LHS.index() == RHS.index(), LHS and RHS are empty
262 using V = std::variant<int, MakeEmptyT>;
263 V v1;
264 makeEmpty(v1);
265 V v2;
266 makeEmpty(v2);
267 assert(test_less(v1, v2, false, false));
268 }
269#endif
270}
271
JF Bastien2df59c52019-02-04 20:31:13 +0000272int main(int, char**) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000273 test_equality();
274 test_relational();
JF Bastien2df59c52019-02-04 20:31:13 +0000275
276 return 0;
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000277}