relops.pass.cpp (8058B)
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; 49 MakeEmptyT(MakeEmptyT &&) { throw 42; } 50 MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; } 51 }; 52 inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) { 53 assert(false); 54 return false; 55 } 56 inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) { 57 assert(false); 58 return false; 59 } 60 inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) { 61 assert(false); 62 return false; 63 } 64 inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) { 65 assert(false); 66 return false; 67 } 68 inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) { 69 assert(false); 70 return false; 71 } 72 inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) { 73 assert(false); 74 return false; 75 } 76 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; 90 constexpr explicit MyBool(bool v) : value(v) {} 91 constexpr operator bool() const noexcept { return value; } 92 }; 93 94 struct ComparesToMyBool { 95 int value = 0; 96 }; 97 inline constexpr MyBool operator==(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept { 98 return MyBool(LHS.value == RHS.value); 99 } 100 inline constexpr MyBool operator!=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept { 101 return MyBool(LHS.value != RHS.value); 102 } 103 inline constexpr MyBool operator<(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept { 104 return MyBool(LHS.value < RHS.value); 105 } 106 inline constexpr MyBool operator<=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept { 107 return MyBool(LHS.value <= RHS.value); 108 } 109 inline constexpr MyBool operator>(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept { 110 return MyBool(LHS.value > RHS.value); 111 } 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> 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 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> 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> 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 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 273 int main() { 274 test_equality(); 275 test_relational(); 276 }