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