]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/variant/compile.cc
65f4326c3975326fc35c2efef4bc1878973a6fc4
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / variant / compile.cc
1 // { dg-options "-std=gnu++17" }
2 // { dg-do compile }
3
4 // Copyright (C) 2016-2017 Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING3. If not see
19 // <http://www.gnu.org/licenses/>.
20
21 #include <variant>
22 #include <string>
23 #include <vector>
24
25 using namespace std;
26
27 struct AllDeleted
28 {
29 AllDeleted() = delete;
30 AllDeleted(const AllDeleted&) = delete;
31 AllDeleted(AllDeleted&&) = delete;
32 AllDeleted& operator=(const AllDeleted&) = delete;
33 AllDeleted& operator=(AllDeleted&&) = delete;
34 };
35
36 struct Empty
37 {
38 Empty() { };
39 Empty(const Empty&) { };
40 Empty(Empty&&) { };
41 Empty& operator=(const Empty&) { return *this; };
42 Empty& operator=(Empty&&) { return *this; };
43 };
44
45 struct DefaultNoexcept
46 {
47 DefaultNoexcept() noexcept = default;
48 DefaultNoexcept(const DefaultNoexcept&) noexcept = default;
49 DefaultNoexcept(DefaultNoexcept&&) noexcept = default;
50 DefaultNoexcept& operator=(const DefaultNoexcept&) noexcept = default;
51 DefaultNoexcept& operator=(DefaultNoexcept&&) noexcept = default;
52 };
53
54 struct MoveCtorOnly
55 {
56 MoveCtorOnly() noexcept = delete;
57 MoveCtorOnly(const DefaultNoexcept&) noexcept = delete;
58 MoveCtorOnly(DefaultNoexcept&&) noexcept { }
59 MoveCtorOnly& operator=(const DefaultNoexcept&) noexcept = delete;
60 MoveCtorOnly& operator=(DefaultNoexcept&&) noexcept = delete;
61 };
62
63 struct nonliteral
64 {
65 nonliteral() { }
66
67 bool operator<(const nonliteral&) const;
68 bool operator==(const nonliteral&) const;
69 };
70
71 void default_ctor()
72 {
73 static_assert(is_default_constructible_v<variant<int, string>>, "");
74 static_assert(is_default_constructible_v<variant<string, string>>, "");
75 static_assert(!is_default_constructible_v<variant<AllDeleted, string>>, "");
76 static_assert(is_default_constructible_v<variant<string, AllDeleted>>, "");
77
78 static_assert(noexcept(variant<int>()), "");
79 static_assert(!noexcept(variant<Empty>()), "");
80 static_assert(noexcept(variant<DefaultNoexcept>()), "");
81 }
82
83 void copy_ctor()
84 {
85 static_assert(is_copy_constructible_v<variant<int, string>>, "");
86 static_assert(!is_copy_constructible_v<variant<AllDeleted, string>>, "");
87
88 {
89 variant<int> a;
90 static_assert(!noexcept(variant<int>(a)), "");
91 }
92 {
93 variant<string> a;
94 static_assert(!noexcept(variant<string>(a)), "");
95 }
96 {
97 variant<int, string> a;
98 static_assert(!noexcept(variant<int, string>(a)), "");
99 }
100 {
101 variant<int, char> a;
102 static_assert(!noexcept(variant<int, char>(a)), "");
103 }
104 }
105
106 void move_ctor()
107 {
108 static_assert(is_move_constructible_v<variant<int, string>>, "");
109 static_assert(!is_move_constructible_v<variant<AllDeleted, string>>, "");
110 static_assert(!noexcept(variant<int, Empty>(declval<variant<int, Empty>>())), "");
111 static_assert(noexcept(variant<int, DefaultNoexcept>(declval<variant<int, DefaultNoexcept>>())), "");
112 }
113
114 void arbitrary_ctor()
115 {
116 static_assert(!is_constructible_v<variant<string, string>, const char*>, "");
117 static_assert(is_constructible_v<variant<int, string>, const char*>, "");
118 static_assert(noexcept(variant<int, Empty>(int{})), "");
119 static_assert(noexcept(variant<int, DefaultNoexcept>(int{})), "");
120 static_assert(!noexcept(variant<int, Empty>(Empty{})), "");
121 static_assert(noexcept(variant<int, DefaultNoexcept>(DefaultNoexcept{})), "");
122 }
123
124 void in_place_index_ctor()
125 {
126 variant<string, string> a(in_place_index<0>, "a");
127 variant<string, string> b(in_place_index<1>, {'a'});
128 }
129
130 void in_place_type_ctor()
131 {
132 variant<int, string, int> a(in_place_type<string>, "a");
133 variant<int, string, int> b(in_place_type<string>, {'a'});
134 static_assert(!is_constructible_v<variant<string, string>, in_place_type_t<string>, const char*>, "");
135 }
136
137 void dtor()
138 {
139 static_assert(is_destructible_v<variant<int, string>>, "");
140 static_assert(is_destructible_v<variant<AllDeleted, string>>, "");
141 }
142
143 void copy_assign()
144 {
145 static_assert(is_copy_assignable_v<variant<int, string>>, "");
146 static_assert(!is_copy_assignable_v<variant<AllDeleted, string>>, "");
147 {
148 variant<Empty> a;
149 static_assert(!noexcept(a = a), "");
150 }
151 {
152 variant<DefaultNoexcept> a;
153 static_assert(!noexcept(a = a), "");
154 }
155 }
156
157 void move_assign()
158 {
159 static_assert(is_move_assignable_v<variant<int, string>>, "");
160 static_assert(!is_move_assignable_v<variant<AllDeleted, string>>, "");
161 {
162 variant<Empty> a;
163 static_assert(!noexcept(a = std::move(a)), "");
164 }
165 {
166 variant<DefaultNoexcept> a;
167 static_assert(noexcept(a = std::move(a)), "");
168 }
169 }
170
171 void arbitrary_assign()
172 {
173 static_assert(!is_assignable_v<variant<string, string>, const char*>, "");
174 static_assert(is_assignable_v<variant<int, string>, const char*>, "");
175 static_assert(noexcept(variant<int, Empty>() = int{}), "");
176 static_assert(noexcept(variant<int, DefaultNoexcept>() = int{}), "");
177 static_assert(!noexcept(variant<int, Empty>() = Empty{}), "");
178 static_assert(noexcept(variant<int, DefaultNoexcept>() = DefaultNoexcept{}), "");
179 }
180
181 void test_get()
182 {
183 static_assert(is_same<decltype(get<0>(variant<int, string>())), int&&>::value, "");
184 static_assert(is_same<decltype(get<1>(variant<int, string>())), string&&>::value, "");
185 static_assert(is_same<decltype(get<1>(variant<int, const string>())), const string&&>::value, "");
186
187 static_assert(is_same<decltype(get<int>(variant<int, string>())), int&&>::value, "");
188 static_assert(is_same<decltype(get<string>(variant<int, string>())), string&&>::value, "");
189 static_assert(is_same<decltype(get<const string>(variant<int, const string>())), const string&&>::value, "");
190 }
191
192 void test_relational()
193 {
194 {
195 constexpr variant<int, nonliteral> a(42), b(43);
196 static_assert((a < b), "");
197 static_assert(!(a > b), "");
198 static_assert((a <= b), "");
199 static_assert(!(a == b), "");
200 static_assert((a != b), "");
201 static_assert(!(a >= b), "");
202 }
203 {
204 constexpr variant<int, nonliteral> a(42), b(42);
205 static_assert(!(a < b), "");
206 static_assert(!(a > b), "");
207 static_assert((a <= b), "");
208 static_assert((a == b), "");
209 static_assert(!(a != b), "");
210 static_assert((a >= b), "");
211 }
212 {
213 constexpr variant<int, nonliteral> a(43), b(42);
214 static_assert(!(a < b), "");
215 static_assert((a > b), "");
216 static_assert(!(a <= b), "");
217 static_assert(!(a == b), "");
218 static_assert((a != b), "");
219 static_assert((a >= b), "");
220 }
221 {
222 constexpr monostate a, b;
223 static_assert(!(a < b), "");
224 static_assert(!(a > b), "");
225 static_assert((a <= b), "");
226 static_assert((a == b), "");
227 static_assert(!(a != b), "");
228 static_assert((a >= b), "");
229 }
230 }
231
232 // Not swappable, and variant<C> not swappable via the generic std::swap.
233 struct C { };
234 void swap(C&, C&) = delete;
235
236 static_assert( !std::is_swappable_v<variant<C>> );
237 static_assert( !std::is_swappable_v<variant<int, C>> );
238 static_assert( !std::is_swappable_v<variant<C, int>> );
239
240 // Not swappable, and variant<D> not swappable via the generic std::swap.
241 struct D { D(D&&) = delete; };
242
243 static_assert( !std::is_swappable_v<variant<D>> );
244 static_assert( !std::is_swappable_v<variant<int, D>> );
245 static_assert( !std::is_swappable_v<variant<D, int>> );
246
247 void test_swap()
248 {
249 static_assert(is_swappable_v<variant<int, string>>, "");
250 static_assert(is_swappable_v<variant<MoveCtorOnly>>, "");
251 static_assert(!is_swappable_v<variant<AllDeleted>>, "");
252 }
253
254 void test_visit()
255 {
256 {
257 struct Visitor
258 {
259 void operator()(monostate) {}
260 void operator()(const int&) {}
261 };
262 struct CVisitor
263 {
264 void operator()(monostate) const {}
265 void operator()(const int&) const {}
266 };
267 }
268 {
269 struct Visitor
270 {
271 bool operator()(int, float) { return false; }
272 bool operator()(int, double) { return false; }
273 bool operator()(char, float) { return false; }
274 bool operator()(char, double) { return false; }
275 };
276 visit(Visitor(), variant<int, char>(), variant<float, double>());
277 }
278 {
279 struct Visitor
280 {
281 constexpr bool operator()(const int&) { return true; }
282 constexpr bool operator()(const nonliteral&) { return false; }
283 };
284 static_assert(visit(Visitor(), variant<int, nonliteral>(0)), "");
285 }
286 {
287 struct Visitor
288 {
289 constexpr bool operator()(const int&) { return true; }
290 constexpr bool operator()(const nonliteral&) { return false; }
291 };
292 static_assert(visit(Visitor(), variant<int, nonliteral>(0)), "");
293 }
294 }
295
296 void test_constexpr()
297 {
298 constexpr variant<int> a;
299 static_assert(holds_alternative<int>(a), "");
300 constexpr variant<int, char> b(in_place_index<0>, int{});
301 static_assert(holds_alternative<int>(b), "");
302 constexpr variant<int, char> c(in_place_type<int>, int{});
303 static_assert(holds_alternative<int>(c), "");
304 constexpr variant<int, char> d(in_place_index<1>, char{});
305 static_assert(holds_alternative<char>(d), "");
306 constexpr variant<int, char> e(in_place_type<char>, char{});
307 static_assert(holds_alternative<char>(e), "");
308 constexpr variant<int, char> f(char{});
309 static_assert(holds_alternative<char>(f), "");
310
311 {
312 struct literal {
313 constexpr literal() = default;
314 };
315
316 constexpr variant<literal, nonliteral> v{};
317 constexpr variant<literal, nonliteral> v1{in_place_type<literal>};
318 constexpr variant<literal, nonliteral> v2{in_place_index<0>};
319 }
320
321 {
322 constexpr variant<int> a(42);
323 static_assert(get<0>(a) == 42, "");
324 }
325 {
326 constexpr variant<int, nonliteral> a(42);
327 static_assert(get<0>(a) == 42, "");
328 }
329 {
330 constexpr variant<nonliteral, int> a(42);
331 static_assert(get<1>(a) == 42, "");
332 }
333 {
334 constexpr variant<int> a(42);
335 static_assert(get<int>(a) == 42, "");
336 }
337 {
338 constexpr variant<int, nonliteral> a(42);
339 static_assert(get<int>(a) == 42, "");
340 }
341 {
342 constexpr variant<nonliteral, int> a(42);
343 static_assert(get<int>(a) == 42, "");
344 }
345 {
346 constexpr variant<int> a(42);
347 static_assert(get<0>(std::move(a)) == 42, "");
348 }
349 {
350 constexpr variant<int, nonliteral> a(42);
351 static_assert(get<0>(std::move(a)) == 42, "");
352 }
353 {
354 constexpr variant<nonliteral, int> a(42);
355 static_assert(get<1>(std::move(a)) == 42, "");
356 }
357 {
358 constexpr variant<int> a(42);
359 static_assert(get<int>(std::move(a)) == 42, "");
360 }
361 {
362 constexpr variant<int, nonliteral> a(42);
363 static_assert(get<int>(std::move(a)) == 42, "");
364 }
365 {
366 constexpr variant<nonliteral, int> a(42);
367 static_assert(get<int>(std::move(a)) == 42, "");
368 }
369 }
370
371 void test_pr77641()
372 {
373 struct X {
374 constexpr X() { }
375 };
376
377 constexpr std::variant<X> v1 = X{};
378 }
379
380 namespace adl_trap
381 {
382 struct X {
383 X() = default;
384 X(int) { }
385 X(std::initializer_list<int>, const X&) { }
386 };
387 template<typename T> void move(T&) { }
388 template<typename T> void forward(T&) { }
389
390 struct Visitor {
391 template<typename T> void operator()(T&&) { }
392 };
393 }
394
395 void test_adl()
396 {
397 using adl_trap::X;
398 X x;
399 std::initializer_list<int> il;
400 adl_trap::Visitor vis;
401
402 std::variant<X> v0(x);
403 v0 = x;
404 v0.emplace<0>(x);
405 v0.emplace<0>(il, x);
406 visit(vis, v0);
407 variant<X> v1{in_place_index<0>, x};
408 variant<X> v2{in_place_type<X>, x};
409 variant<X> v3{in_place_index<0>, il, x};
410 variant<X> v4{in_place_type<X>, il, x};
411 }
412
413 void test_variant_alternative()
414 {
415 static_assert(is_same_v<variant_alternative_t<0, variant<int, string>>, int>, "");
416 static_assert(is_same_v<variant_alternative_t<1, variant<int, string>>, string>, "");
417
418 static_assert(is_same_v<variant_alternative_t<0, const variant<int>>, const int>, "");
419 static_assert(is_same_v<variant_alternative_t<0, volatile variant<int>>, volatile int>, "");
420 static_assert(is_same_v<variant_alternative_t<0, const volatile variant<int>>, const volatile int>, "");
421 }
422
423 template<typename V, typename T>
424 constexpr auto has_type_emplace(int) -> decltype((declval<V>().template emplace<T>(), true))
425 { return true; };
426
427 template<typename V, typename T>
428 constexpr bool has_type_emplace(...)
429 { return false; };
430
431 template<typename V, size_t N>
432 constexpr auto has_index_emplace(int) -> decltype((declval<V>().template emplace<N>(), true))
433 { return true; };
434
435 template<typename V, size_t T>
436 constexpr bool has_index_emplace(...)
437 { return false; };
438
439 void test_emplace()
440 {
441 static_assert(has_type_emplace<variant<int>, int>(0), "");
442 static_assert(!has_type_emplace<variant<long>, int>(0), "");
443 static_assert(has_index_emplace<variant<int>, 0>(0), "");
444 static_assert(!has_type_emplace<variant<AllDeleted>, AllDeleted>(0), "");
445 static_assert(!has_index_emplace<variant<AllDeleted>, 0>(0), "");
446 }