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