1 //
2 // shared_from_raw_test2.cpp - based on esft_regtest.cpp
3 //
4 // Copyright (c) 2008, 2014 Peter Dimov
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 //
8 // See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt
10 //
11
12 #include <boost/smart_ptr/enable_shared_from_raw.hpp>
13 #include <boost/shared_ptr.hpp>
14 #include <boost/weak_ptr.hpp>
15 #include <boost/detail/lightweight_test.hpp>
16 #include <memory>
17 #include <string>
18
19 class X: public boost::enable_shared_from_raw
20 {
21 private:
22
23 int destroyed_;
24 int deleted_;
25 int expected_;
26
27 private:
28
29 X( X const& );
30 X& operator=( X const& );
31
32 public:
33
34 static int instances;
35
36 public:
37
X(int expected)38 explicit X( int expected ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
39 {
40 ++instances;
41 }
42
~X()43 ~X()
44 {
45 BOOST_TEST( deleted_ == expected_ );
46 BOOST_TEST( destroyed_ == 0 );
47 ++destroyed_;
48 --instances;
49 }
50
51 typedef void (*deleter_type)( X* );
52
deleter(X * px)53 static void deleter( X * px )
54 {
55 ++px->deleted_;
56 }
57
deleter2(X * px)58 static void deleter2( X * px )
59 {
60 ++px->deleted_;
61 delete px;
62 }
63 };
64
65 int X::instances = 0;
66
test()67 void test()
68 {
69 BOOST_TEST( X::instances == 0 );
70
71 {
72 X x( 0 );
73 BOOST_TEST( X::instances == 1 );
74 }
75
76 BOOST_TEST( X::instances == 0 );
77
78 {
79 std::auto_ptr<X> px( new X( 0 ) );
80 BOOST_TEST( X::instances == 1 );
81 }
82
83 BOOST_TEST( X::instances == 0 );
84
85 {
86 boost::shared_ptr<X> px( new X( 0 ) );
87 BOOST_TEST( X::instances == 1 );
88
89 boost::weak_ptr<X> wp( px );
90 BOOST_TEST( !wp.expired() );
91
92 px.reset();
93
94 BOOST_TEST( wp.expired() );
95 }
96
97 BOOST_TEST( X::instances == 0 );
98
99 {
100 X x( 1 );
101 boost::shared_ptr<X> px( &x, X::deleter );
102 BOOST_TEST( X::instances == 1 );
103
104 X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
105 BOOST_TEST( pd != 0 && *pd == X::deleter );
106
107 boost::weak_ptr<X> wp( px );
108 BOOST_TEST( !wp.expired() );
109
110 px.reset();
111
112 BOOST_TEST( wp.expired() );
113 }
114
115 BOOST_TEST( X::instances == 0 );
116
117 {
118 boost::shared_ptr<X> px( new X( 1 ), X::deleter2 );
119 BOOST_TEST( X::instances == 1 );
120
121 X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
122 BOOST_TEST( pd != 0 && *pd == X::deleter2 );
123
124 boost::weak_ptr<X> wp( px );
125 BOOST_TEST( !wp.expired() );
126
127 px.reset();
128
129 BOOST_TEST( wp.expired() );
130 }
131
132 BOOST_TEST( X::instances == 0 );
133 }
134
135 struct V: public boost::enable_shared_from_raw
136 {
~VV137 virtual ~V() {}
138 std::string m_;
139 };
140
141 struct V2
142 {
~V2V2143 virtual ~V2() {}
144 std::string m2_;
145 };
146
147 struct W: V2, V
148 {
149 };
150
test2()151 void test2()
152 {
153 boost::shared_ptr<W> p( new W );
154 }
155
test3()156 void test3()
157 {
158 V * p = new W;
159 boost::shared_ptr<void> pv( p );
160 BOOST_TEST( pv.get() == p );
161 BOOST_TEST( pv.use_count() == 1 );
162 }
163
164 struct null_deleter
165 {
operator ()null_deleter166 void operator()( void const* ) const {}
167 };
168
test4()169 void test4()
170 {
171 boost::shared_ptr<V> pv( new V );
172 boost::shared_ptr<V> pv2( pv.get(), null_deleter() );
173 BOOST_TEST( pv2.get() == pv.get() );
174 BOOST_TEST( pv2.use_count() == 1 );
175 }
176
test5()177 void test5()
178 {
179 V v;
180
181 boost::shared_ptr<V> p1( &v, null_deleter() );
182 BOOST_TEST( p1.get() == &v );
183 BOOST_TEST( p1.use_count() == 1 );
184
185 try
186 {
187 boost::shared_from_raw( p1.get() );
188 }
189 catch( ... )
190 {
191 BOOST_ERROR( "shared_from_raw( p1.get() ) failed" );
192 }
193
194 p1.reset();
195
196 boost::shared_ptr<V> p2( &v, null_deleter() );
197 BOOST_TEST( p2.get() == &v );
198 BOOST_TEST( p2.use_count() == 1 );
199
200 try
201 {
202 boost::shared_from_raw( p2.get() );
203 }
204 catch( ... )
205 {
206 BOOST_ERROR( "shared_from_raw( p2.get() ) failed" );
207 }
208 }
209
main()210 int main()
211 {
212 test();
213 test2();
214 test3();
215 test4();
216 test5();
217
218 return boost::report_errors();
219 }
220