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