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 47struct MakeEmptyT { 48 MakeEmptyT() = default; 49 MakeEmptyT(MakeEmptyT &&) { throw 42; } 50 MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; } 51}; 52inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) { 53 assert(false); 54 return false; 55} 56inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) { 57 assert(false); 58 return false; 59} 60inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) { 61 assert(false); 62 return false; 63} 64inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) { 65 assert(false); 66 return false; 67} 68inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) { 69 assert(false); 70 return false; 71} 72inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) { 73 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> 161constexpr 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 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} 228