]>
Commit | Line | Data |
---|---|---|
197c757c TS |
1 | // { dg-options "-std=gnu++17" } |
2 | // { dg-do compile } | |
3 | ||
8d9254fc | 4 | // Copyright (C) 2016-2020 Free Software Foundation, Inc. |
197c757c TS |
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 | ||
458ef690 TS |
54 | struct MoveCtorOnly |
55 | { | |
56 | MoveCtorOnly() noexcept = delete; | |
9d3e662d JW |
57 | MoveCtorOnly(const MoveCtorOnly&) noexcept = delete; |
58 | MoveCtorOnly(MoveCtorOnly&&) noexcept { } | |
59 | MoveCtorOnly& operator=(const MoveCtorOnly&) noexcept = delete; | |
60 | MoveCtorOnly& operator=(MoveCtorOnly&&) noexcept = delete; | |
458ef690 TS |
61 | }; |
62 | ||
9d3e662d JW |
63 | struct MoveCtorAndSwapOnly : MoveCtorOnly { }; |
64 | void swap(MoveCtorAndSwapOnly&, MoveCtorAndSwapOnly&) { } | |
65 | ||
5f00d0d5 JW |
66 | struct DeletedMoves |
67 | { | |
68 | DeletedMoves() = default; | |
69 | DeletedMoves(const DeletedMoves&) = default; | |
70 | DeletedMoves(DeletedMoves&&) = delete; | |
71 | DeletedMoves& operator=(const DeletedMoves&) = default; | |
72 | DeletedMoves& operator=(DeletedMoves&&) = delete; | |
73 | }; | |
74 | ||
9189f559 TS |
75 | struct nonliteral |
76 | { | |
77 | nonliteral() { } | |
78 | ||
79 | bool operator<(const nonliteral&) const; | |
d255829b | 80 | bool operator<=(const nonliteral&) const; |
9189f559 | 81 | bool operator==(const nonliteral&) const; |
d255829b TS |
82 | bool operator!=(const nonliteral&) const; |
83 | bool operator>=(const nonliteral&) const; | |
84 | bool operator>(const nonliteral&) const; | |
9189f559 TS |
85 | }; |
86 | ||
24b54628 VV |
87 | struct virtual_default_dtor { |
88 | virtual ~virtual_default_dtor() = default; | |
89 | }; | |
90 | ||
197c757c TS |
91 | void default_ctor() |
92 | { | |
990666d0 JW |
93 | static_assert(is_default_constructible_v<variant<int, string>>); |
94 | static_assert(is_default_constructible_v<variant<string, string>>); | |
95 | static_assert(!is_default_constructible_v<variant<AllDeleted, string>>); | |
96 | static_assert(is_default_constructible_v<variant<string, AllDeleted>>); | |
5f00d0d5 | 97 | static_assert(is_default_constructible_v<variant<DeletedMoves>>); |
990666d0 JW |
98 | |
99 | static_assert(noexcept(variant<int>())); | |
100 | static_assert(!noexcept(variant<Empty>())); | |
101 | static_assert(noexcept(variant<DefaultNoexcept>())); | |
24b54628 VV |
102 | { |
103 | variant<virtual_default_dtor> a; | |
104 | } | |
197c757c TS |
105 | } |
106 | ||
107 | void copy_ctor() | |
108 | { | |
990666d0 JW |
109 | static_assert(is_copy_constructible_v<variant<int, string>>); |
110 | static_assert(!is_copy_constructible_v<variant<AllDeleted, string>>); | |
111 | static_assert(is_trivially_copy_constructible_v<variant<int>>); | |
112 | static_assert(!is_trivially_copy_constructible_v<variant<std::string>>); | |
5f00d0d5 | 113 | static_assert(is_trivially_copy_constructible_v<variant<DeletedMoves>>); |
197c757c TS |
114 | |
115 | { | |
116 | variant<int> a; | |
990666d0 | 117 | static_assert(noexcept(variant<int>(a))); |
197c757c TS |
118 | } |
119 | { | |
120 | variant<string> a; | |
990666d0 | 121 | static_assert(!noexcept(variant<string>(a))); |
197c757c TS |
122 | } |
123 | { | |
124 | variant<int, string> a; | |
990666d0 | 125 | static_assert(!noexcept(variant<int, string>(a))); |
197c757c TS |
126 | } |
127 | { | |
128 | variant<int, char> a; | |
990666d0 | 129 | static_assert(noexcept(variant<int, char>(a))); |
197c757c TS |
130 | } |
131 | } | |
132 | ||
133 | void move_ctor() | |
134 | { | |
990666d0 JW |
135 | static_assert(is_move_constructible_v<variant<int, string>>); |
136 | static_assert(!is_move_constructible_v<variant<AllDeleted, string>>); | |
5f00d0d5 | 137 | static_assert(is_move_constructible_v<variant<int, DeletedMoves>>); // uses copy ctor |
990666d0 JW |
138 | static_assert(is_trivially_move_constructible_v<variant<int>>); |
139 | static_assert(!is_trivially_move_constructible_v<variant<std::string>>); | |
140 | static_assert(!noexcept(variant<int, Empty>(declval<variant<int, Empty>>()))); | |
141 | static_assert(noexcept(variant<int, DefaultNoexcept>(declval<variant<int, DefaultNoexcept>>()))); | |
197c757c TS |
142 | } |
143 | ||
144 | void arbitrary_ctor() | |
145 | { | |
990666d0 JW |
146 | static_assert(!is_constructible_v<variant<string, string>, const char*>); |
147 | static_assert(is_constructible_v<variant<int, string>, const char*>); | |
148 | static_assert(noexcept(variant<int, Empty>(int{}))); | |
149 | static_assert(noexcept(variant<int, DefaultNoexcept>(int{}))); | |
150 | static_assert(!noexcept(variant<int, Empty>(Empty{}))); | |
151 | static_assert(noexcept(variant<int, DefaultNoexcept>(DefaultNoexcept{}))); | |
d069df01 JW |
152 | |
153 | // P0608R3 disallow narrowing conversions and boolean conversions | |
ac781bc8 JW |
154 | static_assert(!is_constructible_v<variant<float>, int>); |
155 | static_assert(!is_constructible_v<variant<float, vector<int>>, int>); | |
156 | static_assert(is_constructible_v<variant<float, int>, char>); | |
157 | static_assert(!is_constructible_v<variant<float, char>, int>); | |
158 | static_assert(is_constructible_v<variant<float, long>, int>); | |
159 | struct big_int { big_int(int) { } }; | |
160 | static_assert(is_constructible_v<variant<float, big_int>, int>); | |
161 | ||
162 | static_assert(!is_constructible_v<variant<int>, unsigned>); | |
d069df01 JW |
163 | static_assert(!is_constructible_v<variant<bool>, int>); |
164 | static_assert(!is_constructible_v<variant<bool>, void*>); | |
c98fc4eb JW |
165 | |
166 | // P1957R2 Converting from T* to bool should be considered narrowing | |
167 | struct ConvertibleToBool | |
168 | { | |
169 | operator bool() const { return true; } | |
170 | }; | |
171 | static_assert(is_constructible_v<variant<bool>, ConvertibleToBool>); | |
172 | static_assert(is_constructible_v<variant<bool, int>, ConvertibleToBool>); | |
197c757c TS |
173 | } |
174 | ||
06715e1c JW |
175 | struct none { none() = delete; }; |
176 | struct any { template <typename T> any(T&&) {} }; | |
177 | ||
197c757c TS |
178 | void in_place_index_ctor() |
179 | { | |
627a2f59 VV |
180 | variant<string, string> a(in_place_index<0>, "a"); |
181 | variant<string, string> b(in_place_index<1>, {'a'}); | |
06715e1c JW |
182 | |
183 | static_assert(!is_constructible_v<variant<none, any>, std::in_place_index_t<0>>, "PR libstdc++/90165"); | |
197c757c TS |
184 | } |
185 | ||
186 | void in_place_type_ctor() | |
187 | { | |
627a2f59 VV |
188 | variant<int, string, int> a(in_place_type<string>, "a"); |
189 | variant<int, string, int> b(in_place_type<string>, {'a'}); | |
990666d0 | 190 | static_assert(!is_constructible_v<variant<string, string>, in_place_type_t<string>, const char*>); |
06715e1c | 191 | static_assert(!is_constructible_v<variant<none, any>, std::in_place_type_t<none>>, "PR libstdc++/90165"); |
197c757c TS |
192 | } |
193 | ||
197c757c TS |
194 | void dtor() |
195 | { | |
990666d0 JW |
196 | static_assert(is_destructible_v<variant<int, string>>); |
197 | static_assert(is_destructible_v<variant<AllDeleted, string>>); | |
197c757c TS |
198 | } |
199 | ||
200 | void copy_assign() | |
201 | { | |
990666d0 JW |
202 | static_assert(is_copy_assignable_v<variant<int, string>>); |
203 | static_assert(!is_copy_assignable_v<variant<AllDeleted, string>>); | |
204 | static_assert(is_trivially_copy_assignable_v<variant<int>>); | |
205 | static_assert(!is_trivially_copy_assignable_v<variant<string>>); | |
5f00d0d5 | 206 | static_assert(is_trivially_copy_assignable_v<variant<DeletedMoves>>); |
197c757c TS |
207 | { |
208 | variant<Empty> a; | |
990666d0 | 209 | static_assert(!noexcept(a = a)); |
197c757c TS |
210 | } |
211 | { | |
212 | variant<DefaultNoexcept> a; | |
990666d0 | 213 | static_assert(noexcept(a = a)); |
197c757c TS |
214 | } |
215 | } | |
216 | ||
217 | void move_assign() | |
218 | { | |
990666d0 JW |
219 | static_assert(is_move_assignable_v<variant<int, string>>); |
220 | static_assert(!is_move_assignable_v<variant<AllDeleted, string>>); | |
5f00d0d5 | 221 | static_assert(is_move_assignable_v<variant<int, DeletedMoves>>); // uses copy assignment |
990666d0 JW |
222 | static_assert(is_trivially_move_assignable_v<variant<int>>); |
223 | static_assert(!is_trivially_move_assignable_v<variant<string>>); | |
197c757c TS |
224 | { |
225 | variant<Empty> a; | |
990666d0 | 226 | static_assert(!noexcept(a = std::move(a))); |
197c757c TS |
227 | } |
228 | { | |
229 | variant<DefaultNoexcept> a; | |
990666d0 | 230 | static_assert(noexcept(a = std::move(a))); |
197c757c TS |
231 | } |
232 | } | |
233 | ||
234 | void arbitrary_assign() | |
235 | { | |
990666d0 JW |
236 | static_assert(!is_assignable_v<variant<string, string>, const char*>); |
237 | static_assert(is_assignable_v<variant<int, string>, const char*>); | |
238 | static_assert(noexcept(variant<int, Empty>() = int{})); | |
239 | static_assert(noexcept(variant<int, DefaultNoexcept>() = int{})); | |
240 | static_assert(!noexcept(variant<int, Empty>() = Empty{})); | |
241 | static_assert(noexcept(variant<int, DefaultNoexcept>() = DefaultNoexcept{})); | |
197c757c TS |
242 | } |
243 | ||
244 | void test_get() | |
245 | { | |
990666d0 JW |
246 | static_assert(is_same<decltype(get<0>(variant<int, string>())), int&&>::value); |
247 | static_assert(is_same<decltype(get<1>(variant<int, string>())), string&&>::value); | |
248 | static_assert(is_same<decltype(get<1>(variant<int, const string>())), const string&&>::value); | |
7b277e8b | 249 | |
990666d0 JW |
250 | static_assert(is_same<decltype(get<int>(variant<int, string>())), int&&>::value); |
251 | static_assert(is_same<decltype(get<string>(variant<int, string>())), string&&>::value); | |
252 | static_assert(is_same<decltype(get<const string>(variant<int, const string>())), const string&&>::value); | |
197c757c TS |
253 | } |
254 | ||
255 | void test_relational() | |
256 | { | |
257 | { | |
9189f559 | 258 | constexpr variant<int, nonliteral> a(42), b(43); |
990666d0 JW |
259 | static_assert((a < b)); |
260 | static_assert(!(a > b)); | |
261 | static_assert((a <= b)); | |
262 | static_assert(!(a == b)); | |
263 | static_assert((a != b)); | |
264 | static_assert(!(a >= b)); | |
197c757c TS |
265 | } |
266 | { | |
9189f559 | 267 | constexpr variant<int, nonliteral> a(42), b(42); |
990666d0 JW |
268 | static_assert(!(a < b)); |
269 | static_assert(!(a > b)); | |
270 | static_assert((a <= b)); | |
271 | static_assert((a == b)); | |
272 | static_assert(!(a != b)); | |
273 | static_assert((a >= b)); | |
9189f559 TS |
274 | } |
275 | { | |
276 | constexpr variant<int, nonliteral> a(43), b(42); | |
990666d0 JW |
277 | static_assert(!(a < b)); |
278 | static_assert((a > b)); | |
279 | static_assert(!(a <= b)); | |
280 | static_assert(!(a == b)); | |
281 | static_assert((a != b)); | |
282 | static_assert((a >= b)); | |
9189f559 TS |
283 | } |
284 | { | |
285 | constexpr monostate a, b; | |
990666d0 JW |
286 | static_assert(!(a < b)); |
287 | static_assert(!(a > b)); | |
288 | static_assert((a <= b)); | |
289 | static_assert((a == b)); | |
290 | static_assert(!(a != b)); | |
291 | static_assert((a >= b)); | |
197c757c TS |
292 | } |
293 | } | |
294 | ||
a2863bde VV |
295 | // Not swappable, and variant<C> not swappable via the generic std::swap. |
296 | struct C { }; | |
297 | void swap(C&, C&) = delete; | |
298 | ||
299 | static_assert( !std::is_swappable_v<variant<C>> ); | |
300 | static_assert( !std::is_swappable_v<variant<int, C>> ); | |
301 | static_assert( !std::is_swappable_v<variant<C, int>> ); | |
302 | ||
303 | // Not swappable, and variant<D> not swappable via the generic std::swap. | |
304 | struct D { D(D&&) = delete; }; | |
305 | ||
306 | static_assert( !std::is_swappable_v<variant<D>> ); | |
307 | static_assert( !std::is_swappable_v<variant<int, D>> ); | |
308 | static_assert( !std::is_swappable_v<variant<D, int>> ); | |
309 | ||
197c757c TS |
310 | void test_swap() |
311 | { | |
990666d0 JW |
312 | static_assert(is_swappable_v<variant<int, string>>); |
313 | static_assert(!is_swappable_v<variant<MoveCtorOnly>>); | |
314 | static_assert(is_swappable_v<variant<MoveCtorAndSwapOnly>>); | |
315 | static_assert(!is_swappable_v<variant<AllDeleted>>); | |
197c757c TS |
316 | } |
317 | ||
318 | void test_visit() | |
319 | { | |
320 | { | |
321 | struct Visitor | |
322 | { | |
323 | void operator()(monostate) {} | |
324 | void operator()(const int&) {} | |
325 | }; | |
326 | struct CVisitor | |
327 | { | |
328 | void operator()(monostate) const {} | |
329 | void operator()(const int&) const {} | |
330 | }; | |
197c757c TS |
331 | } |
332 | { | |
333 | struct Visitor | |
334 | { | |
335 | bool operator()(int, float) { return false; } | |
336 | bool operator()(int, double) { return false; } | |
337 | bool operator()(char, float) { return false; } | |
338 | bool operator()(char, double) { return false; } | |
339 | }; | |
340 | visit(Visitor(), variant<int, char>(), variant<float, double>()); | |
341 | } | |
b01af236 TS |
342 | { |
343 | struct Visitor | |
344 | { | |
345 | constexpr bool operator()(const int&) { return true; } | |
346 | constexpr bool operator()(const nonliteral&) { return false; } | |
347 | }; | |
990666d0 | 348 | static_assert(visit(Visitor(), variant<int, nonliteral>(0))); |
b01af236 TS |
349 | } |
350 | { | |
351 | struct Visitor | |
352 | { | |
353 | constexpr bool operator()(const int&) { return true; } | |
354 | constexpr bool operator()(const nonliteral&) { return false; } | |
355 | }; | |
990666d0 | 356 | static_assert(visit(Visitor(), variant<int, nonliteral>(0))); |
b01af236 | 357 | } |
7d5abe42 TS |
358 | // PR libstdc++/79513 |
359 | { | |
360 | std::variant<int> v [[gnu::unused]] (5); | |
361 | std::visit([](int&){}, v); | |
362 | std::visit([](int&&){}, std::move(v)); | |
363 | } | |
197c757c TS |
364 | } |
365 | ||
366 | void test_constexpr() | |
367 | { | |
368 | constexpr variant<int> a; | |
990666d0 | 369 | static_assert(holds_alternative<int>(a)); |
627a2f59 | 370 | constexpr variant<int, char> b(in_place_index<0>, int{}); |
990666d0 | 371 | static_assert(holds_alternative<int>(b)); |
627a2f59 | 372 | constexpr variant<int, char> c(in_place_type<int>, int{}); |
990666d0 | 373 | static_assert(holds_alternative<int>(c)); |
627a2f59 | 374 | constexpr variant<int, char> d(in_place_index<1>, char{}); |
990666d0 | 375 | static_assert(holds_alternative<char>(d)); |
627a2f59 | 376 | constexpr variant<int, char> e(in_place_type<char>, char{}); |
990666d0 | 377 | static_assert(holds_alternative<char>(e)); |
197c757c | 378 | constexpr variant<int, char> f(char{}); |
990666d0 | 379 | static_assert(holds_alternative<char>(f)); |
197c757c TS |
380 | |
381 | { | |
382 | struct literal { | |
383 | constexpr literal() = default; | |
384 | }; | |
385 | ||
197c757c | 386 | constexpr variant<literal, nonliteral> v{}; |
627a2f59 VV |
387 | constexpr variant<literal, nonliteral> v1{in_place_type<literal>}; |
388 | constexpr variant<literal, nonliteral> v2{in_place_index<0>}; | |
197c757c | 389 | } |
9189f559 TS |
390 | |
391 | { | |
392 | constexpr variant<int> a(42); | |
990666d0 | 393 | static_assert(get<0>(a) == 42); |
9189f559 TS |
394 | } |
395 | { | |
396 | constexpr variant<int, nonliteral> a(42); | |
990666d0 | 397 | static_assert(get<0>(a) == 42); |
9189f559 TS |
398 | } |
399 | { | |
400 | constexpr variant<nonliteral, int> a(42); | |
990666d0 | 401 | static_assert(get<1>(a) == 42); |
9189f559 TS |
402 | } |
403 | { | |
404 | constexpr variant<int> a(42); | |
990666d0 | 405 | static_assert(get<int>(a) == 42); |
9189f559 TS |
406 | } |
407 | { | |
408 | constexpr variant<int, nonliteral> a(42); | |
990666d0 | 409 | static_assert(get<int>(a) == 42); |
9189f559 TS |
410 | } |
411 | { | |
412 | constexpr variant<nonliteral, int> a(42); | |
990666d0 | 413 | static_assert(get<int>(a) == 42); |
9189f559 TS |
414 | } |
415 | { | |
416 | constexpr variant<int> a(42); | |
990666d0 | 417 | static_assert(get<0>(std::move(a)) == 42); |
9189f559 TS |
418 | } |
419 | { | |
420 | constexpr variant<int, nonliteral> a(42); | |
990666d0 | 421 | static_assert(get<0>(std::move(a)) == 42); |
9189f559 TS |
422 | } |
423 | { | |
424 | constexpr variant<nonliteral, int> a(42); | |
990666d0 | 425 | static_assert(get<1>(std::move(a)) == 42); |
9189f559 TS |
426 | } |
427 | { | |
428 | constexpr variant<int> a(42); | |
990666d0 | 429 | static_assert(get<int>(std::move(a)) == 42); |
9189f559 TS |
430 | } |
431 | { | |
432 | constexpr variant<int, nonliteral> a(42); | |
990666d0 | 433 | static_assert(get<int>(std::move(a)) == 42); |
9189f559 TS |
434 | } |
435 | { | |
436 | constexpr variant<nonliteral, int> a(42); | |
990666d0 | 437 | static_assert(get<int>(std::move(a)) == 42); |
9189f559 | 438 | } |
197c757c TS |
439 | } |
440 | ||
41501d1a TS |
441 | void test_pr77641() |
442 | { | |
443 | struct X { | |
444 | constexpr X() { } | |
445 | }; | |
446 | ||
447 | constexpr std::variant<X> v1 = X{}; | |
448 | } | |
64626fca JW |
449 | |
450 | namespace adl_trap | |
451 | { | |
452 | struct X { | |
453 | X() = default; | |
454 | X(int) { } | |
455 | X(std::initializer_list<int>, const X&) { } | |
456 | }; | |
457 | template<typename T> void move(T&) { } | |
458 | template<typename T> void forward(T&) { } | |
459 | ||
460 | struct Visitor { | |
461 | template<typename T> void operator()(T&&) { } | |
462 | }; | |
463 | } | |
464 | ||
465 | void test_adl() | |
466 | { | |
467 | using adl_trap::X; | |
64626fca | 468 | X x; |
64626fca JW |
469 | std::initializer_list<int> il; |
470 | adl_trap::Visitor vis; | |
471 | ||
472 | std::variant<X> v0(x); | |
473 | v0 = x; | |
474 | v0.emplace<0>(x); | |
475 | v0.emplace<0>(il, x); | |
476 | visit(vis, v0); | |
627a2f59 VV |
477 | variant<X> v1{in_place_index<0>, x}; |
478 | variant<X> v2{in_place_type<X>, x}; | |
479 | variant<X> v3{in_place_index<0>, il, x}; | |
480 | variant<X> v4{in_place_type<X>, il, x}; | |
64626fca | 481 | } |
3203ed5f | 482 | |
458ef690 TS |
483 | void test_variant_alternative() |
484 | { | |
990666d0 JW |
485 | static_assert(is_same_v<variant_alternative_t<0, variant<int, string>>, int>); |
486 | static_assert(is_same_v<variant_alternative_t<1, variant<int, string>>, string>); | |
3203ed5f | 487 | |
990666d0 JW |
488 | static_assert(is_same_v<variant_alternative_t<0, const variant<int>>, const int>); |
489 | static_assert(is_same_v<variant_alternative_t<0, volatile variant<int>>, volatile int>); | |
490 | static_assert(is_same_v<variant_alternative_t<0, const volatile variant<int>>, const volatile int>); | |
3203ed5f | 491 | } |
458ef690 TS |
492 | |
493 | template<typename V, typename T> | |
494 | constexpr auto has_type_emplace(int) -> decltype((declval<V>().template emplace<T>(), true)) | |
495 | { return true; }; | |
496 | ||
497 | template<typename V, typename T> | |
498 | constexpr bool has_type_emplace(...) | |
499 | { return false; }; | |
500 | ||
501 | template<typename V, size_t N> | |
502 | constexpr auto has_index_emplace(int) -> decltype((declval<V>().template emplace<N>(), true)) | |
503 | { return true; }; | |
504 | ||
505 | template<typename V, size_t T> | |
506 | constexpr bool has_index_emplace(...) | |
507 | { return false; }; | |
508 | ||
509 | void test_emplace() | |
510 | { | |
990666d0 JW |
511 | static_assert(has_type_emplace<variant<int>, int>(0)); |
512 | static_assert(!has_type_emplace<variant<long>, int>(0)); | |
513 | static_assert(has_index_emplace<variant<int>, 0>(0)); | |
514 | static_assert(!has_type_emplace<variant<AllDeleted>, AllDeleted>(0)); | |
515 | static_assert(!has_index_emplace<variant<AllDeleted>, 0>(0)); | |
47a468bd JW |
516 | static_assert(has_type_emplace<variant<int, AllDeleted>, int>(0)); |
517 | static_assert(has_index_emplace<variant<int, AllDeleted>, 0>(0)); | |
518 | static_assert(has_type_emplace<variant<int, vector<int>, AllDeleted>, vector<int>>(0)); | |
519 | static_assert(has_index_emplace<variant<int, vector<int>, AllDeleted>, 1>(0)); | |
520 | ||
521 | // The above tests only check the emplace members are available for | |
522 | // overload resolution. The following odr-uses will instantiate them: | |
523 | variant<int, vector<int>, AllDeleted> v; | |
524 | v.emplace<0>(1); | |
525 | v.emplace<int>(1); | |
526 | v.emplace<1>(1, 1); | |
527 | v.emplace<vector<int>>(1, 1); | |
528 | v.emplace<1>({1, 2, 3, 4}); | |
529 | v.emplace<vector<int>>({1, 2, 3, 4}); | |
458ef690 | 530 | } |
70503724 TS |
531 | |
532 | void test_triviality() | |
533 | { | |
534 | #define TEST_TEMPLATE(DT, CC, MC, CA, MA, CC_VAL, MC_VAL, CA_VAL, MA_VAL) \ | |
535 | { \ | |
536 | struct A \ | |
537 | { \ | |
538 | ~A() DT; \ | |
539 | A(const A&) CC; \ | |
540 | A(A&&) MC; \ | |
541 | A& operator=(const A&) CA; \ | |
542 | A& operator=(A&&) MA; \ | |
543 | }; \ | |
990666d0 JW |
544 | static_assert(CC_VAL == is_trivially_copy_constructible_v<variant<A>>); \ |
545 | static_assert(MC_VAL == is_trivially_move_constructible_v<variant<A>>); \ | |
546 | static_assert(CA_VAL == is_trivially_copy_assignable_v<variant<A>>); \ | |
547 | static_assert(MA_VAL == is_trivially_move_assignable_v<variant<A>>); \ | |
70503724 TS |
548 | } |
549 | TEST_TEMPLATE(=default, =default, =default, =default, =default, true, true, true, true) | |
98910bc2 PC |
550 | TEST_TEMPLATE(=default, =default, =default, =default, , true, true, true, false) |
551 | TEST_TEMPLATE(=default, =default, =default, , =default, true, true, false, true) | |
552 | TEST_TEMPLATE(=default, =default, =default, , , true, true, false, false) | |
038bc9bf | 553 | TEST_TEMPLATE(=default, =default, , =default, =default, true, false, true, false) |
98910bc2 | 554 | TEST_TEMPLATE(=default, =default, , =default, , true, false, true, false) |
038bc9bf | 555 | TEST_TEMPLATE(=default, =default, , , =default, true, false, false, false) |
98910bc2 | 556 | TEST_TEMPLATE(=default, =default, , , , true, false, false, false) |
038bc9bf JW |
557 | TEST_TEMPLATE(=default, , =default, =default, =default, false, true, false, true) |
558 | TEST_TEMPLATE(=default, , =default, =default, , false, true, false, false) | |
98910bc2 PC |
559 | TEST_TEMPLATE(=default, , =default, , =default, false, true, false, true) |
560 | TEST_TEMPLATE(=default, , =default, , , false, true, false, false) | |
038bc9bf JW |
561 | TEST_TEMPLATE(=default, , , =default, =default, false, false, false, false) |
562 | TEST_TEMPLATE(=default, , , =default, , false, false, false, false) | |
563 | TEST_TEMPLATE(=default, , , , =default, false, false, false, false) | |
98910bc2 PC |
564 | TEST_TEMPLATE(=default, , , , , false, false, false, false) |
565 | TEST_TEMPLATE( , =default, =default, =default, =default, false, false, false, false) | |
566 | TEST_TEMPLATE( , =default, =default, =default, , false, false, false, false) | |
567 | TEST_TEMPLATE( , =default, =default, , =default, false, false, false, false) | |
568 | TEST_TEMPLATE( , =default, =default, , , false, false, false, false) | |
569 | TEST_TEMPLATE( , =default, , =default, =default, false, false, false, false) | |
570 | TEST_TEMPLATE( , =default, , =default, , false, false, false, false) | |
571 | TEST_TEMPLATE( , =default, , , =default, false, false, false, false) | |
572 | TEST_TEMPLATE( , =default, , , , false, false, false, false) | |
573 | TEST_TEMPLATE( , , =default, =default, =default, false, false, false, false) | |
574 | TEST_TEMPLATE( , , =default, =default, , false, false, false, false) | |
575 | TEST_TEMPLATE( , , =default, , =default, false, false, false, false) | |
576 | TEST_TEMPLATE( , , =default, , , false, false, false, false) | |
577 | TEST_TEMPLATE( , , , =default, =default, false, false, false, false) | |
578 | TEST_TEMPLATE( , , , =default, , false, false, false, false) | |
579 | TEST_TEMPLATE( , , , , =default, false, false, false, false) | |
580 | TEST_TEMPLATE( , , , , , false, false, false, false) | |
70503724 TS |
581 | #undef TEST_TEMPLATE |
582 | ||
583 | #define TEST_TEMPLATE(CC, MC, CA, MA) \ | |
584 | { \ | |
585 | struct A \ | |
586 | { \ | |
587 | A(const A&) CC; \ | |
588 | A(A&&) MC; \ | |
589 | A& operator=(const A&) CA; \ | |
590 | A& operator=(A&&) MA; \ | |
591 | }; \ | |
990666d0 JW |
592 | static_assert(!is_trivially_copy_constructible_v<variant<AllDeleted, A>>); \ |
593 | static_assert(!is_trivially_move_constructible_v<variant<AllDeleted, A>>); \ | |
594 | static_assert(!is_trivially_copy_assignable_v<variant<AllDeleted, A>>); \ | |
595 | static_assert(!is_trivially_move_assignable_v<variant<AllDeleted, A>>); \ | |
70503724 TS |
596 | } |
597 | TEST_TEMPLATE(=default, =default, =default, =default) | |
98910bc2 PC |
598 | TEST_TEMPLATE(=default, =default, =default, ) |
599 | TEST_TEMPLATE(=default, =default, , =default) | |
600 | TEST_TEMPLATE(=default, =default, , ) | |
601 | TEST_TEMPLATE(=default, , =default, =default) | |
602 | TEST_TEMPLATE(=default, , =default, ) | |
603 | TEST_TEMPLATE(=default, , , =default) | |
604 | TEST_TEMPLATE(=default, , , ) | |
605 | TEST_TEMPLATE( , =default, =default, =default) | |
606 | TEST_TEMPLATE( , =default, =default, ) | |
607 | TEST_TEMPLATE( , =default, , =default) | |
608 | TEST_TEMPLATE( , =default, , ) | |
609 | TEST_TEMPLATE( , , =default, =default) | |
610 | TEST_TEMPLATE( , , =default, ) | |
611 | TEST_TEMPLATE( , , , =default) | |
612 | TEST_TEMPLATE( , , , ) | |
70503724 TS |
613 | #undef TEST_TEMPLATE |
614 | ||
990666d0 JW |
615 | static_assert(is_trivially_copy_constructible_v<variant<DefaultNoexcept, int, char, float, double>>); |
616 | static_assert(is_trivially_move_constructible_v<variant<DefaultNoexcept, int, char, float, double>>); | |
617 | static_assert(is_trivially_copy_assignable_v<variant<DefaultNoexcept, int, char, float, double>>); | |
618 | static_assert(is_trivially_move_assignable_v<variant<DefaultNoexcept, int, char, float, double>>); | |
70503724 | 619 | } |