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