• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
88 struct MyBool {
89   bool value;
MyBoolMyBool90   constexpr explicit MyBool(bool v) : value(v) {}
operator boolMyBool91   constexpr operator bool() const noexcept { return value; }
92 };
93 
94 struct ComparesToMyBool {
95   int value = 0;
96 };
operator ==(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)97 inline constexpr MyBool operator==(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
98   return MyBool(LHS.value == RHS.value);
99 }
operator !=(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)100 inline constexpr MyBool operator!=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
101   return MyBool(LHS.value != RHS.value);
102 }
operator <(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)103 inline constexpr MyBool operator<(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
104   return MyBool(LHS.value < RHS.value);
105 }
operator <=(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)106 inline constexpr MyBool operator<=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
107   return MyBool(LHS.value <= RHS.value);
108 }
operator >(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)109 inline constexpr MyBool operator>(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
110   return MyBool(LHS.value > RHS.value);
111 }
operator >=(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)112 inline constexpr MyBool operator>=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
113   return MyBool(LHS.value >= RHS.value);
114 }
115 
116 template <class T1, class T2>
test_equality_basic()117 void 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 
test_equality()156 void test_equality() {
157   test_equality_basic<int, long>();
158   test_equality_basic<ComparesToMyBool, int>();
159   test_equality_basic<int, ComparesToMyBool>();
160   test_equality_basic<ComparesToMyBool, ComparesToMyBool>();
161 #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 
196 template <class Var>
test_less(const Var & l,const Var & r,bool expect_less,bool expect_greater)197 constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
198                          bool expect_greater) {
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   static_assert(std::is_same_v<decltype(l >= r), bool>, "");
203 
204   return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
205          ((l > r) == expect_greater) && (!(l <= r) == expect_greater);
206 }
207 
208 template <class T1, class T2>
test_relational_basic()209 void test_relational_basic() {
210   { // same index, same value
211     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});
214     static_assert(test_less(v1, v2, false, false), "");
215   }
216   { // same index, value < other_value
217     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});
220     static_assert(test_less(v1, v2, true, false), "");
221   }
222   { // same index, value > other_value
223     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});
226     static_assert(test_less(v1, v2, false, true), "");
227   }
228   { // LHS.index() < RHS.index()
229     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});
232     static_assert(test_less(v1, v2, true, false), "");
233   }
234   { // LHS.index() > RHS.index()
235     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});
238     static_assert(test_less(v1, v2, false, true), "");
239   }
240 }
241 
test_relational()242 void 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>();
247 #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 
main()273 int main() {
274   test_equality();
275   test_relational();
276 }
277