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