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 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> 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 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 224 int main() { 225 test_equality(); 226 test_relational(); 227 } 228