xref: /llvm-project/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.special/swap.pass.cpp (revision 30dadaa2eb499395f5bef44b9e1a18db6360ad1f)
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