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