]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #include <boost/config.hpp> |
2 | ||
3 | #if defined(BOOST_MSVC) | |
4 | ||
5 | #pragma warning(disable: 4786) // identifier truncated in debug info | |
6 | #pragma warning(disable: 4710) // function not inlined | |
7 | #pragma warning(disable: 4711) // function selected for automatic inline expansion | |
8 | #pragma warning(disable: 4514) // unreferenced inline removed | |
9 | #pragma warning(disable: 4355) // 'this' : used in base member initializer list | |
10 | ||
11 | #if (BOOST_MSVC >= 1310) | |
12 | #pragma warning(disable: 4675) // resolved overload found with Koenig lookup | |
13 | #endif | |
14 | ||
15 | #endif | |
16 | ||
92f5a8d4 TL |
17 | #if defined(__GNUC__) && __GNUC__ > 4 |
18 | # pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" | |
19 | #endif | |
20 | ||
7c673cae FG |
21 | // |
22 | // shared_ptr_basic_test.cpp | |
23 | // | |
24 | // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. | |
25 | // | |
26 | // Distributed under the Boost Software License, Version 1.0. (See | |
27 | // accompanying file LICENSE_1_0.txt or copy at | |
28 | // http://www.boost.org/LICENSE_1_0.txt) | |
29 | // | |
30 | ||
f67539c2 | 31 | #include <boost/core/lightweight_test.hpp> |
7c673cae FG |
32 | |
33 | #include <boost/shared_ptr.hpp> | |
34 | #include <boost/weak_ptr.hpp> | |
35 | ||
36 | int cnt = 0; | |
37 | ||
38 | struct X | |
39 | { | |
40 | X() | |
41 | { | |
42 | ++cnt; | |
43 | } | |
44 | ||
45 | ~X() // virtual destructor deliberately omitted | |
46 | { | |
47 | --cnt; | |
48 | } | |
49 | ||
50 | virtual int id() const | |
51 | { | |
52 | return 1; | |
53 | } | |
54 | ||
55 | private: | |
56 | ||
57 | X(X const &); | |
58 | X & operator= (X const &); | |
59 | }; | |
60 | ||
61 | struct Y: public X | |
62 | { | |
63 | Y() | |
64 | { | |
65 | ++cnt; | |
66 | } | |
67 | ||
68 | ~Y() | |
69 | { | |
70 | --cnt; | |
71 | } | |
72 | ||
73 | virtual int id() const | |
74 | { | |
75 | return 2; | |
76 | } | |
77 | ||
78 | private: | |
79 | ||
80 | Y(Y const &); | |
81 | Y & operator= (Y const &); | |
82 | }; | |
83 | ||
84 | int * get_object() | |
85 | { | |
86 | ++cnt; | |
87 | return &cnt; | |
88 | } | |
89 | ||
90 | void release_object(int * p) | |
91 | { | |
92 | BOOST_TEST(p == &cnt); | |
93 | --cnt; | |
94 | } | |
95 | ||
96 | template<class T> void test_is_X(boost::shared_ptr<T> const & p) | |
97 | { | |
98 | BOOST_TEST(p->id() == 1); | |
99 | BOOST_TEST((*p).id() == 1); | |
100 | } | |
101 | ||
102 | template<class T> void test_is_X(boost::weak_ptr<T> const & p) | |
103 | { | |
104 | BOOST_TEST(p.get() != 0); | |
105 | BOOST_TEST(p.get()->id() == 1); | |
106 | } | |
107 | ||
108 | template<class T> void test_is_Y(boost::shared_ptr<T> const & p) | |
109 | { | |
110 | BOOST_TEST(p->id() == 2); | |
111 | BOOST_TEST((*p).id() == 2); | |
112 | } | |
113 | ||
114 | template<class T> void test_is_Y(boost::weak_ptr<T> const & p) | |
115 | { | |
116 | boost::shared_ptr<T> q = p.lock(); | |
117 | BOOST_TEST(q.get() != 0); | |
118 | BOOST_TEST(q->id() == 2); | |
119 | } | |
120 | ||
121 | template<class T> void test_eq(T const & a, T const & b) | |
122 | { | |
123 | BOOST_TEST(a == b); | |
124 | BOOST_TEST(!(a != b)); | |
125 | BOOST_TEST(!(a < b)); | |
126 | BOOST_TEST(!(b < a)); | |
127 | } | |
128 | ||
129 | template<class T> void test_ne(T const & a, T const & b) | |
130 | { | |
131 | BOOST_TEST(!(a == b)); | |
132 | BOOST_TEST(a != b); | |
133 | BOOST_TEST(a < b || b < a); | |
134 | BOOST_TEST(!(a < b && b < a)); | |
135 | } | |
136 | ||
137 | template<class T, class U> void test_shared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b) | |
138 | { | |
139 | BOOST_TEST(!(a < b)); | |
140 | BOOST_TEST(!(b < a)); | |
141 | } | |
142 | ||
143 | template<class T, class U> void test_nonshared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b) | |
144 | { | |
145 | BOOST_TEST(a < b || b < a); | |
146 | BOOST_TEST(!(a < b && b < a)); | |
147 | } | |
148 | ||
149 | template<class T, class U> void test_eq2(T const & a, U const & b) | |
150 | { | |
151 | BOOST_TEST(a == b); | |
152 | BOOST_TEST(!(a != b)); | |
153 | } | |
154 | ||
155 | template<class T, class U> void test_ne2(T const & a, U const & b) | |
156 | { | |
157 | BOOST_TEST(!(a == b)); | |
158 | BOOST_TEST(a != b); | |
159 | } | |
160 | ||
161 | template<class T> void test_is_zero(boost::shared_ptr<T> const & p) | |
162 | { | |
163 | BOOST_TEST(!p); | |
164 | BOOST_TEST(p.get() == 0); | |
165 | } | |
166 | ||
167 | template<class T> void test_is_nonzero(boost::shared_ptr<T> const & p) | |
168 | { | |
169 | // p? true: false is used to test p in a boolean context. | |
170 | // BOOST_TEST(p) is not guaranteed to test the conversion, | |
171 | // as the macro might test !!p instead. | |
172 | BOOST_TEST(p? true: false); | |
173 | BOOST_TEST(p.get() != 0); | |
174 | } | |
175 | ||
176 | int main() | |
177 | { | |
178 | using namespace boost; | |
179 | ||
180 | { | |
181 | shared_ptr<X> p(new Y); | |
182 | shared_ptr<X> p2(new X); | |
183 | ||
184 | test_is_nonzero(p); | |
185 | test_is_nonzero(p2); | |
186 | test_is_Y(p); | |
187 | test_is_X(p2); | |
188 | test_ne(p, p2); | |
189 | ||
190 | { | |
191 | shared_ptr<X> q(p); | |
192 | test_eq(p, q); | |
193 | } | |
194 | ||
195 | #if !defined( BOOST_NO_RTTI ) | |
196 | shared_ptr<Y> p3 = dynamic_pointer_cast<Y>(p); | |
197 | shared_ptr<Y> p4 = dynamic_pointer_cast<Y>(p2); | |
198 | ||
199 | test_is_nonzero(p3); | |
200 | test_is_zero(p4); | |
201 | ||
202 | BOOST_TEST(p.use_count() == 2); | |
203 | BOOST_TEST(p2.use_count() == 1); | |
204 | BOOST_TEST(p3.use_count() == 2); | |
205 | ||
206 | test_is_Y(p3); | |
207 | test_eq2(p, p3); | |
208 | test_ne2(p2, p4); | |
209 | #endif | |
210 | ||
211 | shared_ptr<void> p5(p); | |
212 | ||
213 | test_is_nonzero(p5); | |
214 | test_eq2(p, p5); | |
215 | ||
216 | weak_ptr<X> wp1(p2); | |
217 | ||
218 | BOOST_TEST(!wp1.expired()); | |
219 | BOOST_TEST(wp1.use_count() != 0); | |
220 | ||
221 | p.reset(); | |
222 | p2.reset(); | |
223 | #if !defined( BOOST_NO_RTTI ) | |
224 | p3.reset(); | |
225 | p4.reset(); | |
226 | #endif | |
227 | ||
228 | test_is_zero(p); | |
229 | test_is_zero(p2); | |
230 | #if !defined( BOOST_NO_RTTI ) | |
231 | test_is_zero(p3); | |
232 | test_is_zero(p4); | |
233 | #endif | |
234 | ||
235 | BOOST_TEST(p5.use_count() == 1); | |
236 | ||
237 | BOOST_TEST(wp1.expired()); | |
238 | BOOST_TEST(wp1.use_count() == 0); | |
239 | ||
240 | try | |
241 | { | |
242 | shared_ptr<X> sp1(wp1); | |
243 | BOOST_ERROR("shared_ptr<X> sp1(wp1) failed to throw"); | |
244 | } | |
245 | catch(boost::bad_weak_ptr const &) | |
246 | { | |
247 | } | |
248 | ||
249 | test_is_zero(wp1.lock()); | |
250 | ||
251 | weak_ptr<X> wp2 = static_pointer_cast<X>(p5); | |
252 | ||
253 | BOOST_TEST(wp2.use_count() == 1); | |
254 | test_is_Y(wp2); | |
255 | test_nonshared(wp1, wp2); | |
256 | ||
257 | // Scoped to not affect the subsequent use_count() tests. | |
258 | { | |
259 | shared_ptr<X> sp2(wp2); | |
260 | test_is_nonzero(wp2.lock()); | |
261 | } | |
262 | ||
263 | #if !defined( BOOST_NO_RTTI ) | |
264 | weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(wp2.lock()); | |
265 | ||
266 | BOOST_TEST(wp3.use_count() == 1); | |
267 | test_shared(wp2, wp3); | |
268 | ||
269 | weak_ptr<X> wp4(wp3); | |
270 | ||
271 | BOOST_TEST(wp4.use_count() == 1); | |
272 | test_shared(wp2, wp4); | |
273 | #endif | |
274 | ||
275 | wp1 = p2; | |
276 | test_is_zero(wp1.lock()); | |
277 | ||
278 | #if !defined( BOOST_NO_RTTI ) | |
279 | wp1 = p4; | |
280 | wp1 = wp3; | |
281 | #endif | |
282 | wp1 = wp2; | |
283 | ||
284 | BOOST_TEST(wp1.use_count() == 1); | |
285 | test_shared(wp1, wp2); | |
286 | ||
287 | weak_ptr<X> wp5; | |
288 | ||
289 | bool b1 = wp1 < wp5; | |
290 | bool b2 = wp5 < wp1; | |
291 | ||
292 | p5.reset(); | |
293 | ||
294 | BOOST_TEST(wp1.use_count() == 0); | |
295 | BOOST_TEST(wp2.use_count() == 0); | |
296 | #if !defined( BOOST_NO_RTTI ) | |
297 | BOOST_TEST(wp3.use_count() == 0); | |
298 | #endif | |
299 | ||
300 | // Test operator< stability for std::set< weak_ptr<> > | |
301 | // Thanks to Joe Gottman for pointing this out | |
302 | ||
303 | BOOST_TEST(b1 == (wp1 < wp5)); | |
304 | BOOST_TEST(b2 == (wp5 < wp1)); | |
305 | ||
306 | { | |
307 | // note that both get_object and release_object deal with int* | |
308 | shared_ptr<void> p6(get_object(), release_object); | |
309 | } | |
310 | } | |
311 | ||
312 | BOOST_TEST(cnt == 0); | |
313 | ||
314 | return boost::report_errors(); | |
315 | } |