1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // UNSUPPORTED: c++03, c++11, c++14 |
10 | |
11 | // <any> |
12 | |
13 | // any(any &&) noexcept; |
14 | |
15 | #include <any> |
16 | #include <utility> |
17 | #include <type_traits> |
18 | #include <cassert> |
19 | |
20 | #include "any_helpers.h" |
21 | #include "count_new.h" |
22 | #include "test_macros.h" |
23 | |
24 | // Moves are always noexcept. The throws_on_move object |
25 | // must be stored dynamically so the pointer is moved and |
26 | // not the stored object. |
27 | void test_move_does_not_throw() |
28 | { |
29 | #if !defined(TEST_HAS_NO_EXCEPTIONS) |
30 | assert(throws_on_move::count == 0); |
31 | { |
32 | throws_on_move v(42); |
33 | std::any a = v; |
34 | assert(throws_on_move::count == 2); |
35 | // No allocations should be performed after this point. |
36 | DisableAllocationGuard g; ((void)g); |
37 | try { |
38 | const std::any a2 = std::move(a); |
39 | assertEmpty(a); |
40 | assertContains<throws_on_move>(a2, 42); |
41 | } catch (...) { |
42 | assert(false); |
43 | } |
44 | assert(throws_on_move::count == 1); |
45 | assertEmpty(a); |
46 | } |
47 | assert(throws_on_move::count == 0); |
48 | #endif |
49 | } |
50 | |
51 | void test_move_empty() { |
52 | DisableAllocationGuard g; ((void)g); // no allocations should be performed. |
53 | |
54 | std::any a1; |
55 | std::any a2 = std::move(a1); |
56 | |
57 | assertEmpty(a1); |
58 | assertEmpty(a2); |
59 | } |
60 | |
61 | template <class Type> |
62 | void test_move() { |
63 | assert(Type::count == 0); |
64 | Type::reset(); |
65 | { |
66 | std::any a = Type(42); |
67 | assert(Type::count == 1); |
68 | assert(Type::copied == 0); |
69 | assert(Type::moved == 1); |
70 | |
71 | // Moving should not perform allocations since it must be noexcept. |
72 | DisableAllocationGuard g; ((void)g); |
73 | |
74 | std::any a2 = std::move(a); |
75 | |
76 | assert(Type::moved == 1 || Type::moved == 2); // zero or more move operations can be performed. |
77 | assert(Type::copied == 0); // no copies can be performed. |
78 | assert(Type::count == 1 + a.has_value()); |
79 | assertContains<Type>(a2, 42); |
80 | LIBCPP_ASSERT(!a.has_value()); // Moves are always destructive. |
81 | if (a.has_value()) |
82 | assertContains<Type>(a, 0); |
83 | } |
84 | assert(Type::count == 0); |
85 | } |
86 | |
87 | int main(int, char**) |
88 | { |
89 | // noexcept test |
90 | static_assert(std::is_nothrow_move_constructible<std::any>::value); |
91 | |
92 | test_move<small>(); |
93 | test_move<large>(); |
94 | test_move_empty(); |
95 | test_move_does_not_throw(); |
96 | |
97 | return 0; |
98 | } |
99 | |