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/detail/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