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