xref: /llvm-project/libcxx/test/std/utilities/any/any.class/any.cons/move.pass.cpp (revision ec350ad418a24f70c88758259c774a1e11c06d74)
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.
test_move_does_not_throw()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 
test_move_empty()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>
test_move()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 
main(int,char **)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