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