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