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