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