1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: c++03, c++11, c++14 11 12 // Throwing bad_variant_access is supported starting in macosx10.13 13 // XFAIL: with_system_cxx_lib=macosx10.12 && !no-exceptions 14 // XFAIL: with_system_cxx_lib=macosx10.11 && !no-exceptions 15 // XFAIL: with_system_cxx_lib=macosx10.10 && !no-exceptions 16 // XFAIL: with_system_cxx_lib=macosx10.9 && !no-exceptions 17 18 // <variant> 19 20 // template <size_t I, class... Types> 21 // constexpr variant_alternative_t<I, variant<Types...>>& 22 // get(variant<Types...>& v); 23 // template <size_t I, class... Types> 24 // constexpr variant_alternative_t<I, variant<Types...>>&& 25 // get(variant<Types...>&& v); 26 // template <size_t I, class... Types> 27 // constexpr variant_alternative_t<I, variant<Types...>> const& get(const 28 // variant<Types...>& v); 29 // template <size_t I, class... Types> 30 // constexpr variant_alternative_t<I, variant<Types...>> const&& get(const 31 // variant<Types...>&& v); 32 33 #include "test_macros.h" 34 #include "test_workarounds.h" 35 #include "variant_test_helpers.h" 36 #include <cassert> 37 #include <type_traits> 38 #include <utility> 39 #include <variant> 40 41 void test_const_lvalue_get() { 42 { 43 using V = std::variant<int, const long>; 44 constexpr V v(42); 45 #ifdef TEST_WORKAROUND_CONSTEXPR_IMPLIES_NOEXCEPT 46 ASSERT_NOEXCEPT(std::get<0>(v)); 47 #else 48 ASSERT_NOT_NOEXCEPT(std::get<0>(v)); 49 #endif 50 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); 51 static_assert(std::get<0>(v) == 42, ""); 52 } 53 { 54 using V = std::variant<int, const long>; 55 const V v(42); 56 ASSERT_NOT_NOEXCEPT(std::get<0>(v)); 57 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); 58 assert(std::get<0>(v) == 42); 59 } 60 { 61 using V = std::variant<int, const long>; 62 constexpr V v(42l); 63 #ifdef TEST_WORKAROUND_CONSTEXPR_IMPLIES_NOEXCEPT 64 ASSERT_NOEXCEPT(std::get<1>(v)); 65 #else 66 ASSERT_NOT_NOEXCEPT(std::get<1>(v)); 67 #endif 68 ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &); 69 static_assert(std::get<1>(v) == 42, ""); 70 } 71 { 72 using V = std::variant<int, const long>; 73 const V v(42l); 74 ASSERT_NOT_NOEXCEPT(std::get<1>(v)); 75 ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &); 76 assert(std::get<1>(v) == 42); 77 } 78 // FIXME: Remove these once reference support is reinstated 79 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES) 80 { 81 using V = std::variant<int &>; 82 int x = 42; 83 const V v(x); 84 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); 85 assert(&std::get<0>(v) == &x); 86 } 87 { 88 using V = std::variant<int &&>; 89 int x = 42; 90 const V v(std::move(x)); 91 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); 92 assert(&std::get<0>(v) == &x); 93 } 94 { 95 using V = std::variant<const int &&>; 96 int x = 42; 97 const V v(std::move(x)); 98 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); 99 assert(&std::get<0>(v) == &x); 100 } 101 #endif 102 } 103 104 void test_lvalue_get() { 105 { 106 using V = std::variant<int, const long>; 107 V v(42); 108 ASSERT_NOT_NOEXCEPT(std::get<0>(v)); 109 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); 110 assert(std::get<0>(v) == 42); 111 } 112 { 113 using V = std::variant<int, const long>; 114 V v(42l); 115 ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &); 116 assert(std::get<1>(v) == 42); 117 } 118 // FIXME: Remove these once reference support is reinstated 119 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES) 120 { 121 using V = std::variant<int &>; 122 int x = 42; 123 V v(x); 124 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); 125 assert(&std::get<0>(v) == &x); 126 } 127 { 128 using V = std::variant<const int &>; 129 int x = 42; 130 V v(x); 131 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); 132 assert(&std::get<0>(v) == &x); 133 } 134 { 135 using V = std::variant<int &&>; 136 int x = 42; 137 V v(std::move(x)); 138 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); 139 assert(&std::get<0>(v) == &x); 140 } 141 { 142 using V = std::variant<const int &&>; 143 int x = 42; 144 V v(std::move(x)); 145 ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); 146 assert(&std::get<0>(v) == &x); 147 } 148 #endif 149 } 150 151 void test_rvalue_get() { 152 { 153 using V = std::variant<int, const long>; 154 V v(42); 155 ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v))); 156 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&); 157 assert(std::get<0>(std::move(v)) == 42); 158 } 159 { 160 using V = std::variant<int, const long>; 161 V v(42l); 162 ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&); 163 assert(std::get<1>(std::move(v)) == 42); 164 } 165 // FIXME: Remove these once reference support is reinstated 166 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES) 167 { 168 using V = std::variant<int &>; 169 int x = 42; 170 V v(x); 171 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &); 172 assert(&std::get<0>(std::move(v)) == &x); 173 } 174 { 175 using V = std::variant<const int &>; 176 int x = 42; 177 V v(x); 178 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &); 179 assert(&std::get<0>(std::move(v)) == &x); 180 } 181 { 182 using V = std::variant<int &&>; 183 int x = 42; 184 V v(std::move(x)); 185 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&); 186 int &&xref = std::get<0>(std::move(v)); 187 assert(&xref == &x); 188 } 189 { 190 using V = std::variant<const int &&>; 191 int x = 42; 192 V v(std::move(x)); 193 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&); 194 const int &&xref = std::get<0>(std::move(v)); 195 assert(&xref == &x); 196 } 197 #endif 198 } 199 200 void test_const_rvalue_get() { 201 { 202 using V = std::variant<int, const long>; 203 const V v(42); 204 ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v))); 205 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&); 206 assert(std::get<0>(std::move(v)) == 42); 207 } 208 { 209 using V = std::variant<int, const long>; 210 const V v(42l); 211 ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&); 212 assert(std::get<1>(std::move(v)) == 42); 213 } 214 // FIXME: Remove these once reference support is reinstated 215 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES) 216 { 217 using V = std::variant<int &>; 218 int x = 42; 219 const V v(x); 220 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &); 221 assert(&std::get<0>(std::move(v)) == &x); 222 } 223 { 224 using V = std::variant<const int &>; 225 int x = 42; 226 const V v(x); 227 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &); 228 assert(&std::get<0>(std::move(v)) == &x); 229 } 230 { 231 using V = std::variant<int &&>; 232 int x = 42; 233 const V v(std::move(x)); 234 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&); 235 int &&xref = std::get<0>(std::move(v)); 236 assert(&xref == &x); 237 } 238 { 239 using V = std::variant<const int &&>; 240 int x = 42; 241 const V v(std::move(x)); 242 ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&); 243 const int &&xref = std::get<0>(std::move(v)); 244 assert(&xref == &x); 245 } 246 #endif 247 } 248 249 template <std::size_t I> using Idx = std::integral_constant<size_t, I>; 250 251 void test_throws_for_all_value_categories() { 252 #ifndef TEST_HAS_NO_EXCEPTIONS 253 using V = std::variant<int, long>; 254 V v0(42); 255 const V &cv0 = v0; 256 assert(v0.index() == 0); 257 V v1(42l); 258 const V &cv1 = v1; 259 assert(v1.index() == 1); 260 std::integral_constant<size_t, 0> zero; 261 std::integral_constant<size_t, 1> one; 262 auto test = [](auto idx, auto &&v) { 263 using Idx = decltype(idx); 264 try { 265 TEST_IGNORE_NODISCARD std::get<Idx::value>(std::forward<decltype(v)>(v)); 266 } catch (const std::bad_variant_access &) { 267 return true; 268 } catch (...) { /* ... */ 269 } 270 return false; 271 }; 272 { // lvalue test cases 273 assert(test(one, v0)); 274 assert(test(zero, v1)); 275 } 276 { // const lvalue test cases 277 assert(test(one, cv0)); 278 assert(test(zero, cv1)); 279 } 280 { // rvalue test cases 281 assert(test(one, std::move(v0))); 282 assert(test(zero, std::move(v1))); 283 } 284 { // const rvalue test cases 285 assert(test(one, std::move(cv0))); 286 assert(test(zero, std::move(cv1))); 287 } 288 #endif 289 } 290 291 int main(int, char**) { 292 test_const_lvalue_get(); 293 test_lvalue_get(); 294 test_rvalue_get(); 295 test_const_rvalue_get(); 296 test_throws_for_all_value_categories(); 297 298 return 0; 299 } 300