1 // -*- 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
47 struct MakeEmptyT {
48 MakeEmptyT() = default;
MakeEmptyTMakeEmptyT49 MakeEmptyT(MakeEmptyT &&) { throw 42; }
operator =MakeEmptyT50 MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
51 };
operator ==(const MakeEmptyT &,const MakeEmptyT &)52 inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) {
53 assert(false);
54 return false;
55 }
operator !=(const MakeEmptyT &,const MakeEmptyT &)56 inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) {
57 assert(false);
58 return false;
59 }
operator <(const MakeEmptyT &,const MakeEmptyT &)60 inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) {
61 assert(false);
62 return false;
63 }
operator <=(const MakeEmptyT &,const MakeEmptyT &)64 inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) {
65 assert(false);
66 return false;
67 }
operator >(const MakeEmptyT &,const MakeEmptyT &)68 inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) {
69 assert(false);
70 return false;
71 }
operator >=(const MakeEmptyT &,const MakeEmptyT &)72 inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) {
73 assert(false);
74 return false;
75 }
76
makeEmpty(Variant & v)77 template <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
test_equality()88 void 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
160 template <class Var>
test_less(const Var & l,const Var & r,bool expect_less,bool expect_greater)161 constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
162 bool expect_greater) {
163 return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
164 ((l > r) == expect_greater) && (!(l <= r) == expect_greater);
165 }
166
test_relational()167 void 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
main()224 int main() {
225 test_equality();
226 test_relational();
227 }
228