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
test_const_lvalue_get()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
test_lvalue_get()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
test_rvalue_get()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
test_const_rvalue_get()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<size_t, I>;
238
test_throws_for_all_value_categories()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<size_t, 0> zero;
249 std::integral_constant<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
main(int,char **)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