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