blob: 4337b4bdbbd7276923c77a683dc983aca01abbfd [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
88void test_equality() {
89 {
90 using V = std::variant<int, long>;
91 constexpr V v1(42);
92 constexpr V v2(42);
93 static_assert(v1 == v2, "");
94 static_assert(v2 == v1, "");
95 static_assert(!(v1 != v2), "");
96 static_assert(!(v2 != v1), "");
97 }
98 {
99 using V = std::variant<int, long>;
100 constexpr V v1(42);
101 constexpr V v2(43);
102 static_assert(!(v1 == v2), "");
103 static_assert(!(v2 == v1), "");
104 static_assert(v1 != v2, "");
105 static_assert(v2 != v1, "");
106 }
107 {
108 using V = std::variant<int, long>;
109 constexpr V v1(42);
110 constexpr V v2(42l);
111 static_assert(!(v1 == v2), "");
112 static_assert(!(v2 == v1), "");
113 static_assert(v1 != v2, "");
114 static_assert(v2 != v1, "");
115 }
116 {
117 using V = std::variant<int, long>;
118 constexpr V v1(42l);
119 constexpr V v2(42l);
120 static_assert(v1 == v2, "");
121 static_assert(v2 == v1, "");
122 static_assert(!(v1 != v2), "");
123 static_assert(!(v2 != v1), "");
124 }
125#ifndef TEST_HAS_NO_EXCEPTIONS
126 {
127 using V = std::variant<int, MakeEmptyT>;
128 V v1;
129 V v2;
130 makeEmpty(v2);
131 assert(!(v1 == v2));
132 assert(!(v2 == v1));
133 assert(v1 != v2);
134 assert(v2 != v1);
135 }
136 {
137 using V = std::variant<int, MakeEmptyT>;
138 V v1;
139 makeEmpty(v1);
140 V v2;
141 assert(!(v1 == v2));
142 assert(!(v2 == v1));
143 assert(v1 != v2);
144 assert(v2 != v1);
145 }
146 {
147 using V = std::variant<int, MakeEmptyT>;
148 V v1;
149 makeEmpty(v1);
150 V v2;
151 makeEmpty(v2);
152 assert(v1 == v2);
153 assert(v2 == v1);
154 assert(!(v1 != v2));
155 assert(!(v2 != v1));
156 }
157#endif
158}
159
160template <class Var>
Eric Fiselier0d3d8de2016-12-02 23:00:05 +0000161constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
Eric Fiselier80e66ac2016-11-23 01:02:51 +0000162 bool expect_greater) {
163 return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
164 ((l > r) == expect_greater) && (!(l <= r) == expect_greater);
165}
166
167void test_relational() {
168 { // same index, same value
169 using V = std::variant<int, long>;
170 constexpr V v1(1);
171 constexpr V v2(1);
172 static_assert(test_less(v1, v2, false, false), "");
173 }
174 { // same index, value < other_value
175 using V = std::variant<int, long>;
176 constexpr V v1(0);
177 constexpr V v2(1);
178 static_assert(test_less(v1, v2, true, false), "");
179 }
180 { // same index, value > other_value
181 using V = std::variant<int, long>;
182 constexpr V v1(1);
183 constexpr V v2(0);
184 static_assert(test_less(v1, v2, false, true), "");
185 }
186 { // LHS.index() < RHS.index()
187 using V = std::variant<int, long>;
188 constexpr V v1(0);
189 constexpr V v2(0l);
190 static_assert(test_less(v1, v2, true, false), "");
191 }
192 { // LHS.index() > RHS.index()
193 using V = std::variant<int, long>;
194 constexpr V v1(0l);
195 constexpr V v2(0);
196 static_assert(test_less(v1, v2, false, true), "");
197 }
198#ifndef TEST_HAS_NO_EXCEPTIONS
199 { // LHS.index() < RHS.index(), RHS is empty
200 using V = std::variant<int, MakeEmptyT>;
201 V v1;
202 V v2;
203 makeEmpty(v2);
204 assert(test_less(v1, v2, false, true));
205 }
206 { // LHS.index() > RHS.index(), LHS is empty
207 using V = std::variant<int, MakeEmptyT>;
208 V v1;
209 makeEmpty(v1);
210 V v2;
211 assert(test_less(v1, v2, true, false));
212 }
213 { // LHS.index() == RHS.index(), LHS and RHS are empty
214 using V = std::variant<int, MakeEmptyT>;
215 V v1;
216 makeEmpty(v1);
217 V v2;
218 makeEmpty(v2);
219 assert(test_less(v1, v2, false, false));
220 }
221#endif
222}
223
224int main() {
225 test_equality();
226 test_relational();
227}