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