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