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