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