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