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