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 unique_ptr move ctor
14 
15 #include <memory>
16 #include <utility>
17 #include <cassert>
18 
19 #include "test_macros.h"
20 #include "unique_ptr_test_helper.h"
21 
22 //=============================================================================
23 // TESTING unique_ptr(unique_ptr&&)
24 //
25 // Concerns
26 //   1 The moved from pointer is empty and the new pointer stores the old value.
27 //   2 The only requirement on the deleter is that it is MoveConstructible
28 //     or a reference.
29 //   3 The constructor works for explicitly moved values (i.e. std::move(x))
30 //   4 The constructor works for true temporaries (e.g. a return value)
31 //
32 // Plan
33 //  1 Explicitly construct unique_ptr<T, D> for various deleter types 'D'.
34 //    check that the value and deleter have been properly moved. (C-1,2,3)
35 //
36 //  2 Use the expression 'sink(source())' to move construct a unique_ptr<T, D>
37 //    from a temporary. 'source' should return the unique_ptr by value and
38 //    'sink' should accept the unique_ptr by value. (C-1,2,4)
39 
40 template <class VT>
source1()41 std::unique_ptr<VT> source1() {
42   return std::unique_ptr<VT>(newValue<VT>(1));
43 }
44 
45 template <class VT>
source2()46 std::unique_ptr<VT, Deleter<VT> > source2() {
47   return std::unique_ptr<VT, Deleter<VT> >(newValue<VT>(1), Deleter<VT>(5));
48 }
49 
50 template <class VT>
source3()51 std::unique_ptr<VT, NCDeleter<VT>&> source3() {
52   static NCDeleter<VT> d(5);
53   return std::unique_ptr<VT, NCDeleter<VT>&>(newValue<VT>(1), d);
54 }
55 
56 template <class VT>
sink1(std::unique_ptr<VT> p)57 void sink1(std::unique_ptr<VT> p) {
58   assert(p.get() != nullptr);
59 }
60 
61 template <class VT>
sink2(std::unique_ptr<VT,Deleter<VT>> p)62 void sink2(std::unique_ptr<VT, Deleter<VT> > p) {
63   assert(p.get() != nullptr);
64   assert(p.get_deleter().state() == 5);
65 }
66 
67 template <class VT>
sink3(std::unique_ptr<VT,NCDeleter<VT> &> p)68 void sink3(std::unique_ptr<VT, NCDeleter<VT>&> p) {
69   assert(p.get() != nullptr);
70   assert(p.get_deleter().state() == 5);
71   assert(&p.get_deleter() == &source3<VT>().get_deleter());
72 }
73 
74 template <class ValueT>
test_sfinae()75 void test_sfinae() {
76   typedef std::unique_ptr<ValueT> U;
77   { // Ensure unique_ptr is non-copyable
78     static_assert((!std::is_constructible<U, U const&>::value), "");
79     static_assert((!std::is_constructible<U, U&>::value), "");
80   }
81 }
82 
83 template <bool IsArray>
test_basic()84 void test_basic() {
85   typedef typename std::conditional<!IsArray, A, A[]>::type VT;
86   const int expect_alive = IsArray ? 5 : 1;
87   {
88     typedef std::unique_ptr<VT> APtr;
89     APtr s(newValue<VT>(expect_alive));
90     A* p = s.get();
91     APtr s2 = std::move(s);
92     assert(s2.get() == p);
93     assert(s.get() == 0);
94     assert(A::count == expect_alive);
95   }
96   assert(A::count == 0);
97   {
98     typedef Deleter<VT> MoveDel;
99     typedef std::unique_ptr<VT, MoveDel> APtr;
100     MoveDel d(5);
101     APtr s(newValue<VT>(expect_alive), std::move(d));
102     assert(d.state() == 0);
103     assert(s.get_deleter().state() == 5);
104     A* p = s.get();
105     APtr s2 = std::move(s);
106     assert(s2.get() == p);
107     assert(s.get() == 0);
108     assert(A::count == expect_alive);
109     assert(s2.get_deleter().state() == 5);
110     assert(s.get_deleter().state() == 0);
111   }
112   assert(A::count == 0);
113   {
114     typedef NCDeleter<VT> NonCopyDel;
115     typedef std::unique_ptr<VT, NonCopyDel&> APtr;
116 
117     NonCopyDel d;
118     APtr s(newValue<VT>(expect_alive), d);
119     A* p = s.get();
120     APtr s2 = std::move(s);
121     assert(s2.get() == p);
122     assert(s.get() == 0);
123     assert(A::count == expect_alive);
124     d.set_state(6);
125     assert(s2.get_deleter().state() == d.state());
126     assert(s.get_deleter().state() == d.state());
127   }
128   assert(A::count == 0);
129   {
130     sink1<VT>(source1<VT>());
131     assert(A::count == 0);
132     sink2<VT>(source2<VT>());
133     assert(A::count == 0);
134     sink3<VT>(source3<VT>());
135     assert(A::count == 0);
136   }
137   assert(A::count == 0);
138 }
139 
140 template <class VT>
test_noexcept()141 void test_noexcept() {
142 #if TEST_STD_VER >= 11
143   {
144     typedef std::unique_ptr<VT> U;
145     static_assert(std::is_nothrow_move_constructible<U>::value, "");
146   }
147   {
148     typedef std::unique_ptr<VT, Deleter<VT> > U;
149     static_assert(std::is_nothrow_move_constructible<U>::value, "");
150   }
151   {
152     typedef std::unique_ptr<VT, NCDeleter<VT> &> U;
153     static_assert(std::is_nothrow_move_constructible<U>::value, "");
154   }
155   {
156     typedef std::unique_ptr<VT, const NCConstDeleter<VT> &> U;
157     static_assert(std::is_nothrow_move_constructible<U>::value, "");
158   }
159 #endif
160 }
161 
main(int,char **)162 int main(int, char**) {
163   {
164     test_basic</*IsArray*/ false>();
165     test_sfinae<int>();
166     test_noexcept<int>();
167   }
168   {
169     test_basic</*IsArray*/ true>();
170     test_sfinae<int[]>();
171     test_noexcept<int[]>();
172   }
173 
174   return 0;
175 }
176