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