blob: 41a953552150e035dbe15223afcee286e058075e [file] [log] [blame]
Eric Fiselier80e66ac2016-11-23 01:02:51 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11// UNSUPPORTED: c++98, c++03, c++11, c++14
12
13// <variant>
14
15// template <class ...Types>
16// constexpr bool
17// operator==(variant<Types...> const&, variant<Types...> const&) noexcept;
18//
19// template <class ...Types>
20// constexpr bool
21// operator!=(variant<Types...> const&, variant<Types...> const&) noexcept;
22//
23// template <class ...Types>
24// constexpr bool
25// operator<(variant<Types...> const&, variant<Types...> const&) noexcept;
26//
27// template <class ...Types>
28// constexpr bool
29// operator>(variant<Types...> const&, variant<Types...> const&) noexcept;
30//
31// template <class ...Types>
32// constexpr bool
33// operator<=(variant<Types...> const&, variant<Types...> const&) noexcept;
34//
35// template <class ...Types>
36// constexpr bool
37// operator>=(variant<Types...> const&, variant<Types...> const&) noexcept;
38
39#include <cassert>
40#include <type_traits>
41#include <utility>
42#include <variant>
43
44#include "test_macros.h"
45
46#ifndef TEST_HAS_NO_EXCEPTIONS
47struct MakeEmptyT {
48 MakeEmptyT() = default;
49 MakeEmptyT(MakeEmptyT &&) { throw 42; }
50 MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
51};
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000052inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000053 assert(false);
54 return false;
55}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000056inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000057 assert(false);
58 return false;
59}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000060inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000061 assert(false);
62 return false;
63}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000064inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000065 assert(false);
66 return false;
67}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000068inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000069 assert(false);
70 return false;
71}
Eric Fiselier0d3d8de2016-12-02 23:00:05 +000072inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) {
Eric Fiselier80e66ac2016-11-23 01:02:51 +000073 assert(false);
74 return false;
75}
76
77template <class Variant> void makeEmpty(Variant &v) {
78 Variant v2(std::in_place_type<MakeEmptyT>);
79 try {
80 v = std::move(v2);
81 assert(false);
82 } catch (...) {
83 assert(v.valueless_by_exception());
84 }
85}
86#endif // TEST_HAS_NO_EXCEPTIONS
87
Eric Fiselier7dca3122018-09-19 17:53:21 +000088struct MyBool {
89 bool value;
90 constexpr explicit MyBool(bool v) : value(v) {}
91 constexpr operator bool() const noexcept { return value; }
92};
93
94struct ComparesToMyBool {
95 int value = 0;
96};
97inline constexpr MyBool operator==(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
98 return MyBool(LHS.value == RHS.value);
99}
100inline constexpr MyBool operator!=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
101 return MyBool(LHS.value != RHS.value);
102}
103inline constexpr MyBool operator<(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
104 return MyBool(LHS.value < RHS.value);
105}
106inline constexpr MyBool operator<=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
107 return MyBool(LHS.value <= RHS.value);
108}
109inline constexpr MyBool operator>(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
110 return MyBool(LHS.value > RHS.value);
111}
112inline constexpr MyBool operator>=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
113 return MyBool(LHS.value >= RHS.value);
114}
115
116template <class T1, class T2>
117void test_equality_basic() {
118 {
119 using V = std::variant<T1, T2>;
120 constexpr V v1(std::in_place_index<0>, T1{42});
121 constexpr V v2(std::in_place_index<0>, T1{42});
122 static_assert(v1 == v2, "");
123 static_assert(v2 == v1, "");
124 static_assert(!(v1 != v2), "");
125 static_assert(!(v2 != v1), "");
126 }
127 {
128 using V = std::variant<T1, T2>;
129 constexpr V v1(std::in_place_index<0>, T1{42});
130 constexpr V v2(std::in_place_index<0>, T1{43});
131 static_assert(!(v1 == v2), "");
132 static_assert(!(v2 == v1), "");
133 static_assert(v1 != v2, "");
134 static_assert(v2 != v1, "");
135 }
136 {
137 using V = std::variant<T1, T2>;
138 constexpr V v1(std::in_place_index<0>, T1{42});
139 constexpr V v2(std::in_place_index<1>, T2{42});
140 static_assert(!(v1 == v2), "");
141 static_assert(!(v2 == v1), "");
142 static_assert(v1 != v2, "");
143 static_assert(v2 != v1, "");
144 }
145 {
146 using V = std::variant<T1, T2>;
147 constexpr V v1(std::in_place_index<1>, T2{42});
148 constexpr V v2(std::in_place_index<1>, T2{42});
149 static_assert(v1 == v2, "");
150 static_assert(v2 == v1, "");
151 static_assert(!(v1 != v2), "");
152 static_assert(!(v2 != v1), "");
153 }
154}
155
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000156void test_equality() {
Eric Fiselier7dca3122018-09-19 17:53:21 +0000157 test_equality_basic<int, long>();
158 test_equality_basic<ComparesToMyBool, int>();
159 test_equality_basic<int, ComparesToMyBool>();
160 test_equality_basic<ComparesToMyBool, ComparesToMyBool>();
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000161#ifndef TEST_HAS_NO_EXCEPTIONS
162 {
163 using V = std::variant<int, MakeEmptyT>;
164 V v1;
165 V v2;
166 makeEmpty(v2);
167 assert(!(v1 == v2));
168 assert(!(v2 == v1));
169 assert(v1 != v2);
170 assert(v2 != v1);
171 }
172 {
173 using V = std::variant<int, MakeEmptyT>;
174 V v1;
175 makeEmpty(v1);
176 V v2;
177 assert(!(v1 == v2));
178 assert(!(v2 == v1));
179 assert(v1 != v2);
180 assert(v2 != v1);
181 }
182 {
183 using V = std::variant<int, MakeEmptyT>;
184 V v1;
185 makeEmpty(v1);
186 V v2;
187 makeEmpty(v2);
188 assert(v1 == v2);
189 assert(v2 == v1);
190 assert(!(v1 != v2));
191 assert(!(v2 != v1));
192 }
193#endif
194}
195
196template <class Var>
Eric Fiselier0d3d8de2016-12-02 23:00:05 +0000197constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000198 bool expect_greater) {
Eric Fiselier7dca3122018-09-19 17:53:21 +0000199 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 static_assert(std::is_same_v<decltype(l >= r), bool>, "");
203
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000204 return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
205 ((l > r) == expect_greater) && (!(l <= r) == expect_greater);
206}
207
Eric Fiselier7dca3122018-09-19 17:53:21 +0000208template <class T1, class T2>
209void test_relational_basic() {
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000210 { // same index, same value
Eric Fiselier7dca3122018-09-19 17:53:21 +0000211 using V = std::variant<T1, T2>;
212 constexpr V v1(std::in_place_index<0>, T1{1});
213 constexpr V v2(std::in_place_index<0>, T1{1});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000214 static_assert(test_less(v1, v2, false, false), "");
215 }
216 { // same index, value < other_value
Eric Fiselier7dca3122018-09-19 17:53:21 +0000217 using V = std::variant<T1, T2>;
218 constexpr V v1(std::in_place_index<0>, T1{0});
219 constexpr V v2(std::in_place_index<0>, T1{1});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000220 static_assert(test_less(v1, v2, true, false), "");
221 }
222 { // same index, value > other_value
Eric Fiselier7dca3122018-09-19 17:53:21 +0000223 using V = std::variant<T1, T2>;
224 constexpr V v1(std::in_place_index<0>, T1{1});
225 constexpr V v2(std::in_place_index<0>, T1{0});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000226 static_assert(test_less(v1, v2, false, true), "");
227 }
228 { // LHS.index() < RHS.index()
Eric Fiselier7dca3122018-09-19 17:53:21 +0000229 using V = std::variant<T1, T2>;
230 constexpr V v1(std::in_place_index<0>, T1{0});
231 constexpr V v2(std::in_place_index<1>, T2{0});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000232 static_assert(test_less(v1, v2, true, false), "");
233 }
234 { // LHS.index() > RHS.index()
Eric Fiselier7dca3122018-09-19 17:53:21 +0000235 using V = std::variant<T1, T2>;
236 constexpr V v1(std::in_place_index<1>, T2{0});
237 constexpr V v2(std::in_place_index<0>, T1{0});
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000238 static_assert(test_less(v1, v2, false, true), "");
239 }
Eric Fiselier7dca3122018-09-19 17:53:21 +0000240}
241
242void test_relational() {
243 test_relational_basic<int, long>();
244 test_relational_basic<ComparesToMyBool, int>();
245 test_relational_basic<int, ComparesToMyBool>();
246 test_relational_basic<ComparesToMyBool, ComparesToMyBool>();
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000247#ifndef TEST_HAS_NO_EXCEPTIONS
248 { // LHS.index() < RHS.index(), RHS is empty
249 using V = std::variant<int, MakeEmptyT>;
250 V v1;
251 V v2;
252 makeEmpty(v2);
253 assert(test_less(v1, v2, false, true));
254 }
255 { // LHS.index() > RHS.index(), LHS is empty
256 using V = std::variant<int, MakeEmptyT>;
257 V v1;
258 makeEmpty(v1);
259 V v2;
260 assert(test_less(v1, v2, true, false));
261 }
262 { // LHS.index() == RHS.index(), LHS and RHS are empty
263 using V = std::variant<int, MakeEmptyT>;
264 V v1;
265 makeEmpty(v1);
266 V v2;
267 makeEmpty(v2);
268 assert(test_less(v1, v2, false, false));
269 }
270#endif
271}
272
273int main() {
274 test_equality();
275 test_relational();
276}