]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/detail/lightweight_test.hpp> | |
b32b8144 | 18 | #include <boost/config.hpp> |
7c673cae FG |
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 | ||
b32b8144 FG |
81 | #if !defined( BOOST_NO_AUTO_PTR ) |
82 | ||
7c673cae FG |
83 | { |
84 | std::auto_ptr<X> px( new X( 0 ) ); | |
85 | BOOST_TEST( X::instances == 1 ); | |
86 | } | |
87 | ||
b32b8144 FG |
88 | #endif |
89 | ||
7c673cae FG |
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>( 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>( 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 | } |