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