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 "../../deleter.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 (ie std::move(x))
30 // 4 The constructor works for true temporaries (ie 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 struct A
41 {
42 static int count;
AA43 A() {++count;}
AA44 A(const A&) {++count;}
~AA45 virtual ~A() {--count;}
46 };
47
48 int A::count = 0;
49
50 template <class Expect>
sinkFunction(Expect)51 void sinkFunction(Expect)
52 {
53 }
54
55 typedef std::unique_ptr<A> APtrSource1;
56 typedef std::unique_ptr<A, Deleter<A> > APtrSource2;
57 typedef std::unique_ptr<A, NCDeleter<A>& > APtrSource3;
58
source1()59 APtrSource1 source1() {
60 return APtrSource1 (new A);
61 }
62
sink1(APtrSource1 p)63 void sink1(APtrSource1 p) {
64 assert(p.get() != nullptr);
65 }
66
source2()67 APtrSource2 source2() {
68 return APtrSource2(new A, Deleter<A>(5));
69 }
70
sink2(APtrSource2 p)71 void sink2(APtrSource2 p) {
72 assert(p.get() != nullptr);
73 assert(p.get_deleter().state() == 5);
74 }
75
source3()76 APtrSource3 source3() {
77 static NCDeleter<A> d(5);
78 return APtrSource3(new A, d);
79 }
80
sink3(APtrSource3 p)81 void sink3(APtrSource3 p) {
82 assert(p.get() != nullptr);
83 assert(p.get_deleter().state() == 5);
84 assert(&p.get_deleter() == &source3().get_deleter());
85 }
86
main()87 int main()
88 {
89 {
90 typedef std::unique_ptr<A> APtr;
91 APtr s(new A);
92 A* p = s.get();
93 APtr s2 = std::move(s);
94 assert(s2.get() == p);
95 assert(s.get() == 0);
96 assert(A::count == 1);
97 }
98 assert(A::count == 0);
99 {
100 typedef Deleter<A> MoveDel;
101 typedef std::unique_ptr<A, MoveDel> APtr;
102 MoveDel d(5);
103 APtr s(new A, std::move(d));
104 assert(d.state() == 0);
105 assert(s.get_deleter().state() == 5);
106 A* p = s.get();
107 APtr s2 = std::move(s);
108 assert(s2.get() == p);
109 assert(s.get() == 0);
110 assert(A::count == 1);
111 assert(s2.get_deleter().state() == 5);
112 assert(s.get_deleter().state() == 0);
113 }
114 assert(A::count == 0);
115 {
116 typedef NCDeleter<A> NonCopyDel;
117 typedef std::unique_ptr<A, NonCopyDel&> APtr;
118
119 NonCopyDel d;
120 APtr s(new A, d);
121 A* p = s.get();
122 APtr s2 = std::move(s);
123 assert(s2.get() == p);
124 assert(s.get() == 0);
125 assert(A::count == 1);
126 d.set_state(6);
127 assert(s2.get_deleter().state() == d.state());
128 assert(s.get_deleter().state() == d.state());
129 }
130 assert(A::count == 0);
131 {
132 sink1(source1());
133 assert(A::count == 0);
134 sink2(source2());
135 assert(A::count == 0);
136 sink3(source3());
137 assert(A::count == 0);
138 }
139 assert(A::count == 0);
140 }
141