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 | // <utility> |
10 | |
11 | // template<class T> |
12 | // requires MoveAssignable<T> && MoveConstructible<T> |
13 | // void |
14 | // swap(T& a, T& b); |
15 | |
16 | #include <cassert> |
17 | #include <memory> |
18 | #include <type_traits> |
19 | #include <utility> |
20 | |
21 | #include "test_macros.h" |
22 | |
23 | #if TEST_STD_VER >= 11 |
24 | struct CopyOnly { |
25 | CopyOnly() {} |
26 | CopyOnly(CopyOnly const&) noexcept {} |
27 | CopyOnly& operator=(CopyOnly const&) { return *this; } |
28 | }; |
29 | |
30 | struct MoveOnly { |
31 | MoveOnly() {} |
32 | MoveOnly(MoveOnly&&) {} |
33 | MoveOnly& operator=(MoveOnly&&) noexcept { return *this; } |
34 | }; |
35 | |
36 | struct NoexceptMoveOnly { |
37 | NoexceptMoveOnly() {} |
38 | NoexceptMoveOnly(NoexceptMoveOnly&&) noexcept {} |
39 | NoexceptMoveOnly& operator=(NoexceptMoveOnly&&) noexcept { return *this; } |
40 | }; |
41 | |
42 | struct NotMoveConstructible { |
43 | NotMoveConstructible& operator=(NotMoveConstructible&&) { return *this; } |
44 | private: |
45 | NotMoveConstructible(NotMoveConstructible&&); |
46 | }; |
47 | |
48 | struct NotMoveAssignable { |
49 | NotMoveAssignable(NotMoveAssignable&&); |
50 | private: |
51 | NotMoveAssignable& operator=(NotMoveAssignable&&); |
52 | }; |
53 | |
54 | template <class Tp> |
55 | auto can_swap_test(int) -> decltype(std::swap(std::declval<Tp>(), std::declval<Tp>())); |
56 | |
57 | template <class Tp> |
58 | auto can_swap_test(...) -> std::false_type; |
59 | |
60 | template <class Tp> |
61 | constexpr bool can_swap() { |
62 | return std::is_same<decltype(can_swap_test<Tp>(0)), void>::value; |
63 | } |
64 | #endif |
65 | |
66 | #if TEST_STD_VER > 17 |
67 | constexpr bool test_swap_constexpr() |
68 | { |
69 | int i = 1; |
70 | int j = 2; |
71 | std::swap(i, j); |
72 | return i == 2 && j == 1; |
73 | } |
74 | #endif // TEST_STD_VER > 17 |
75 | |
76 | int main(int, char**) |
77 | { |
78 | |
79 | { |
80 | int i = 1; |
81 | int j = 2; |
82 | std::swap(a&: i, b&: j); |
83 | assert(i == 2); |
84 | assert(j == 1); |
85 | } |
86 | #if TEST_STD_VER >= 11 |
87 | { |
88 | |
89 | std::unique_ptr<int> i(new int(1)); |
90 | std::unique_ptr<int> j(new int(2)); |
91 | std::swap(i, j); |
92 | assert(*i == 2); |
93 | assert(*j == 1); |
94 | |
95 | } |
96 | { |
97 | // test that the swap |
98 | static_assert(can_swap<CopyOnly&>(), "" ); |
99 | static_assert(can_swap<MoveOnly&>(), "" ); |
100 | static_assert(can_swap<NoexceptMoveOnly&>(), "" ); |
101 | |
102 | static_assert(!can_swap<NotMoveConstructible&>(), "" ); |
103 | static_assert(!can_swap<NotMoveAssignable&>(), "" ); |
104 | |
105 | CopyOnly c; |
106 | MoveOnly m; |
107 | NoexceptMoveOnly nm; |
108 | static_assert(!noexcept(std::swap(c, c)), "" ); |
109 | static_assert(!noexcept(std::swap(m, m)), "" ); |
110 | static_assert(noexcept(std::swap(nm, nm)), "" ); |
111 | } |
112 | #endif |
113 | |
114 | #if TEST_STD_VER > 17 |
115 | static_assert(test_swap_constexpr()); |
116 | #endif // TEST_STD_VER > 17 |
117 | |
118 | return 0; |
119 | } |
120 | |