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