1 //
2 // sp_unique_ptr_test.cpp
3 //
4 // Copyright (c) 2012 Peter Dimov
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt
9 //
10
11 #include <boost/shared_ptr.hpp>
12 #include <boost/enable_shared_from_this.hpp>
13 #include <boost/core/lightweight_test.hpp>
14 #include <boost/type_traits/remove_reference.hpp>
15 #include <memory>
16 #include <utility>
17
18 #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
19
20 struct X: public boost::enable_shared_from_this< X >
21 {
22 static int instances;
23
XX24 X()
25 {
26 ++instances;
27 }
28
~XX29 ~X()
30 {
31 --instances;
32 }
33
34 private:
35
36 X( X const & );
37 X & operator=( X const & );
38 };
39
40 int X::instances = 0;
41
42 struct Y
43 {
44 static int instances;
45
46 bool deleted_;
47
YY48 Y(): deleted_( false )
49 {
50 ++instances;
51 }
52
~YY53 ~Y()
54 {
55 BOOST_TEST( deleted_ );
56 --instances;
57 }
58
59 private:
60
61 Y( Y const & );
62 Y & operator=( Y const & );
63 };
64
65 int Y::instances = 0;
66
67 struct YD
68 {
operator ()YD69 void operator()( Y* p ) const
70 {
71 if( p )
72 {
73 p->deleted_ = true;
74 delete p;
75 }
76 else
77 {
78 BOOST_ERROR( "YD::operator()(0) called" );
79 }
80 }
81 };
82
test_null_unique_ptr(std::unique_ptr<T,D> p1,std::unique_ptr<T,D> p2)83 template<class U, class T, class D> static void test_null_unique_ptr( std::unique_ptr<T, D> p1, std::unique_ptr<T, D> p2 )
84 {
85 BOOST_TEST( T::instances == 0 );
86
87 boost::shared_ptr<U> sp( std::move( p1 ) );
88
89 BOOST_TEST( sp.get() == 0 );
90 BOOST_TEST( sp.use_count() == 0 );
91
92 sp.reset( new T, typename boost::remove_reference<D>::type() );
93
94 BOOST_TEST( sp.get() != 0 );
95 BOOST_TEST( sp.use_count() == 1 );
96
97 BOOST_TEST( T::instances == 1 );
98
99 sp = std::move( p2 );
100
101 BOOST_TEST( sp.get() == 0 );
102 BOOST_TEST( sp.use_count() == 0 );
103
104 BOOST_TEST( T::instances == 0 );
105 }
106
main()107 int main()
108 {
109 {
110 BOOST_TEST( X::instances == 0 );
111
112 std::unique_ptr<X> p( new X );
113 BOOST_TEST( X::instances == 1 );
114
115 boost::shared_ptr<X> p2( std::move( p ) );
116 BOOST_TEST( X::instances == 1 );
117 BOOST_TEST( p.get() == 0 );
118
119 boost::shared_ptr<X> p3 = p2->shared_from_this();
120 BOOST_TEST( p2 == p3 );
121 BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
122
123 p2.reset();
124 p3.reset();
125 BOOST_TEST( X::instances == 0 );
126
127 p2 = std::unique_ptr<X>( new X );
128 BOOST_TEST( X::instances == 1 );
129
130 p2 = std::unique_ptr<X>( new X );
131 BOOST_TEST( X::instances == 1 );
132
133 p2.reset();
134 BOOST_TEST( X::instances == 0 );
135 }
136
137 {
138 BOOST_TEST( X::instances == 0 );
139
140 std::unique_ptr<X> p( new X );
141 BOOST_TEST( X::instances == 1 );
142
143 boost::shared_ptr<X const> p2( std::move( p ) );
144 BOOST_TEST( X::instances == 1 );
145 BOOST_TEST( p.get() == 0 );
146
147 boost::shared_ptr<X const> p3 = p2->shared_from_this();
148 BOOST_TEST( p2 == p3 );
149 BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
150
151 p2.reset();
152 p3.reset();
153 BOOST_TEST( X::instances == 0 );
154
155 p2 = std::unique_ptr<X>( new X );
156 BOOST_TEST( X::instances == 1 );
157
158 p2 = std::unique_ptr<X>( new X );
159 BOOST_TEST( X::instances == 1 );
160
161 p2.reset();
162 BOOST_TEST( X::instances == 0 );
163 }
164
165 {
166 BOOST_TEST( X::instances == 0 );
167
168 std::unique_ptr<X> p( new X );
169 BOOST_TEST( X::instances == 1 );
170
171 boost::shared_ptr<void> p2( std::move( p ) );
172 BOOST_TEST( X::instances == 1 );
173 BOOST_TEST( p.get() == 0 );
174
175 p2.reset();
176 BOOST_TEST( X::instances == 0 );
177
178 p2 = std::unique_ptr<X>( new X );
179 BOOST_TEST( X::instances == 1 );
180
181 p2 = std::unique_ptr<X>( new X );
182 BOOST_TEST( X::instances == 1 );
183
184 p2.reset();
185 BOOST_TEST( X::instances == 0 );
186 }
187
188 {
189 BOOST_TEST( Y::instances == 0 );
190
191 std::unique_ptr<Y, YD> p( new Y, YD() );
192 BOOST_TEST( Y::instances == 1 );
193
194 boost::shared_ptr<Y> p2( std::move( p ) );
195 BOOST_TEST( Y::instances == 1 );
196 BOOST_TEST( p.get() == 0 );
197
198 p2.reset();
199 BOOST_TEST( Y::instances == 0 );
200
201 p2 = std::unique_ptr<Y, YD>( new Y, YD() );
202 BOOST_TEST( Y::instances == 1 );
203
204 p2 = std::unique_ptr<Y, YD>( new Y, YD() );
205 BOOST_TEST( Y::instances == 1 );
206
207 p2.reset();
208 BOOST_TEST( Y::instances == 0 );
209 }
210
211 {
212 BOOST_TEST( Y::instances == 0 );
213
214 YD yd;
215
216 std::unique_ptr<Y, YD&> p( new Y, yd );
217 BOOST_TEST( Y::instances == 1 );
218
219 boost::shared_ptr<Y> p2( std::move( p ) );
220 BOOST_TEST( Y::instances == 1 );
221 BOOST_TEST( p.get() == 0 );
222
223 p2.reset();
224 BOOST_TEST( Y::instances == 0 );
225
226 p2 = std::unique_ptr<Y, YD&>( new Y, yd );
227 BOOST_TEST( Y::instances == 1 );
228
229 p2 = std::unique_ptr<Y, YD&>( new Y, yd );
230 BOOST_TEST( Y::instances == 1 );
231
232 p2.reset();
233 BOOST_TEST( Y::instances == 0 );
234 }
235
236 {
237 BOOST_TEST( Y::instances == 0 );
238
239 YD yd;
240
241 std::unique_ptr<Y, YD const&> p( new Y, yd );
242 BOOST_TEST( Y::instances == 1 );
243
244 boost::shared_ptr<Y> p2( std::move( p ) );
245 BOOST_TEST( Y::instances == 1 );
246 BOOST_TEST( p.get() == 0 );
247
248 p2.reset();
249 BOOST_TEST( Y::instances == 0 );
250
251 p2 = std::unique_ptr<Y, YD const&>( new Y, yd );
252 BOOST_TEST( Y::instances == 1 );
253
254 p2 = std::unique_ptr<Y, YD const&>( new Y, yd );
255 BOOST_TEST( Y::instances == 1 );
256
257 p2.reset();
258 BOOST_TEST( Y::instances == 0 );
259 }
260
261 {
262 test_null_unique_ptr<X>( std::unique_ptr<X>(), std::unique_ptr<X>() );
263 test_null_unique_ptr<X const>( std::unique_ptr<X>(), std::unique_ptr<X>() );
264 test_null_unique_ptr<void>( std::unique_ptr<X>(), std::unique_ptr<X>() );
265 test_null_unique_ptr<void const>( std::unique_ptr<X>(), std::unique_ptr<X>() );
266 }
267
268 {
269 test_null_unique_ptr<Y>( std::unique_ptr<Y, YD>( 0, YD() ), std::unique_ptr<Y, YD>( 0, YD() ) );
270 test_null_unique_ptr<Y const>( std::unique_ptr<Y, YD>( 0, YD() ), std::unique_ptr<Y, YD>( 0, YD() ) );
271 test_null_unique_ptr<void>( std::unique_ptr<Y, YD>( 0, YD() ), std::unique_ptr<Y, YD>( 0, YD() ) );
272 test_null_unique_ptr<void const>( std::unique_ptr<Y, YD>( 0, YD() ), std::unique_ptr<Y, YD>( 0, YD() ) );
273 }
274
275 {
276 YD yd;
277
278 test_null_unique_ptr<Y>( std::unique_ptr<Y, YD&>( 0, yd ), std::unique_ptr<Y, YD&>( 0, yd ) );
279 test_null_unique_ptr<Y const>( std::unique_ptr<Y, YD&>( 0, yd ), std::unique_ptr<Y, YD&>( 0, yd ) );
280 test_null_unique_ptr<void>( std::unique_ptr<Y, YD&>( 0, yd ), std::unique_ptr<Y, YD&>( 0, yd ) );
281 test_null_unique_ptr<void const>( std::unique_ptr<Y, YD&>( 0, yd ), std::unique_ptr<Y, YD&>( 0, yd ) );
282 }
283
284 return boost::report_errors();
285 }
286
287 #else // !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
288
main()289 int main()
290 {
291 return 0;
292 }
293
294 #endif
295