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 // <memory>
10
11 // unique_ptr
12
13 // Test swap
14
15 #include <memory>
16 #include <cassert>
17
18 #include "test_macros.h"
19 #include "deleter_types.h"
20
21 struct A
22 {
23 int state_;
24 static int count;
AA25 TEST_CONSTEXPR_CXX23 A() : state_(0) {
26 if (!TEST_IS_CONSTANT_EVALUATED)
27 ++count;
28 }
AA29 TEST_CONSTEXPR_CXX23 explicit A(int i) : state_(i) {
30 if (!TEST_IS_CONSTANT_EVALUATED)
31 ++count;
32 }
AA33 TEST_CONSTEXPR_CXX23 A(const A& a) : state_(a.state_) {
34 if (!TEST_IS_CONSTANT_EVALUATED)
35 ++count;
36 }
operator =A37 TEST_CONSTEXPR_CXX23 A& operator=(const A& a) {
38 state_ = a.state_;
39 return *this;
40 }
~AA41 TEST_CONSTEXPR_CXX23 ~A() {
42 if (!TEST_IS_CONSTANT_EVALUATED)
43 --count;
44 }
45
operator ==(const A & x,const A & y)46 friend TEST_CONSTEXPR_CXX23 bool operator==(const A& x, const A& y) { return x.state_ == y.state_; }
47 };
48
49 int A::count = 0;
50
51 template <class T>
52 struct NonSwappableDeleter {
NonSwappableDeleterNonSwappableDeleter53 TEST_CONSTEXPR_CXX23 explicit NonSwappableDeleter(int) {}
operator =NonSwappableDeleter54 TEST_CONSTEXPR_CXX23 NonSwappableDeleter& operator=(NonSwappableDeleter const&) { return *this; }
operator ()NonSwappableDeleter55 TEST_CONSTEXPR_CXX23 void operator()(T*) const {}
56
57 private:
58 NonSwappableDeleter(NonSwappableDeleter const&);
59
60 };
61
test()62 TEST_CONSTEXPR_CXX23 bool test() {
63 {
64 A* p1 = new A(1);
65 std::unique_ptr<A, Deleter<A> > s1(p1, Deleter<A>(1));
66 A* p2 = new A(2);
67 std::unique_ptr<A, Deleter<A> > s2(p2, Deleter<A>(2));
68 assert(s1.get() == p1);
69 assert(*s1 == A(1));
70 assert(s1.get_deleter().state() == 1);
71 assert(s2.get() == p2);
72 assert(*s2 == A(2));
73 assert(s2.get_deleter().state() == 2);
74 swap(s1, s2);
75 assert(s1.get() == p2);
76 assert(*s1 == A(2));
77 assert(s1.get_deleter().state() == 2);
78 assert(s2.get() == p1);
79 assert(*s2 == A(1));
80 assert(s2.get_deleter().state() == 1);
81 if (!TEST_IS_CONSTANT_EVALUATED)
82 assert(A::count == 2);
83 }
84 if (!TEST_IS_CONSTANT_EVALUATED)
85 assert(A::count == 0);
86 {
87 A* p1 = new A[3];
88 std::unique_ptr<A[], Deleter<A[]> > s1(p1, Deleter<A[]>(1));
89 A* p2 = new A[3];
90 std::unique_ptr<A[], Deleter<A[]> > s2(p2, Deleter<A[]>(2));
91 assert(s1.get() == p1);
92 assert(s1.get_deleter().state() == 1);
93 assert(s2.get() == p2);
94 assert(s2.get_deleter().state() == 2);
95 swap(s1, s2);
96 assert(s1.get() == p2);
97 assert(s1.get_deleter().state() == 2);
98 assert(s2.get() == p1);
99 assert(s2.get_deleter().state() == 1);
100 if (!TEST_IS_CONSTANT_EVALUATED)
101 assert(A::count == 6);
102 }
103 if (!TEST_IS_CONSTANT_EVALUATED)
104 assert(A::count == 0);
105 #if TEST_STD_VER >= 11
106 {
107 // test that unique_ptr's specialized swap is disabled when the deleter
108 // is non-swappable. Instead we should pick up the generic swap(T, T)
109 // and perform 3 move constructions.
110 typedef NonSwappableDeleter<int> D;
111 D d(42);
112 int x = 42;
113 int y = 43;
114 std::unique_ptr<int, D&> p(&x, d);
115 std::unique_ptr<int, D&> p2(&y, d);
116 std::swap(p, p2);
117 }
118 #endif
119
120 return true;
121 }
122
main(int,char **)123 int main(int, char**) {
124 test();
125 #if TEST_STD_VER >= 23
126 static_assert(test());
127 #endif
128
129 return 0;
130 }
131