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