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