File: boost/shared_ptr.hpp
1#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
2#define BOOST_SHARED_PTR_HPP_INCLUDED
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <boost/config.hpp> // for broken compiler workarounds
18
19#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
20#include <boost/detail/shared_ptr_nmt.hpp>
21#else
22
23#include <memory> // for std::auto_ptr
24
25#include <boost/assert.hpp>
26#include <boost/checked_delete.hpp>
27#include <boost/throw_exception.hpp>
28#include <boost/detail/shared_count.hpp>
29#include <boost/detail/workaround.hpp>
30
31#include <algorithm> // for std::swap
32#include <functional> // for std::less
33#include <typeinfo> // for std::bad_cast
34#include <iosfwd> // for std::basic_ostream
35
36#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
37# pragma warning(push)
38# pragma warning(disable:4284) // odd return type for operator->
39#endif
40
41namespace boost
42{
43
44template<class T> class weak_ptr;
45template<class T> class enable_shared_from_this;
46
47namespace detail
48{
49
50struct static_cast_tag {};
51struct const_cast_tag {};
52struct dynamic_cast_tag {};
53struct polymorphic_cast_tag {};
54
55template<class T> struct shared_ptr_traits
56{
57 typedef T & reference;
58};
59
60template<> struct shared_ptr_traits<void>
61{
62 typedef void reference;
63};
64
65#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
66
67template<> struct shared_ptr_traits<void const>
68{
69 typedef void reference;
70};
71
72template<> struct shared_ptr_traits<void volatile>
73{
74 typedef void reference;
75};
76
77template<> struct shared_ptr_traits<void const volatile>
78{
79 typedef void reference;
80};
81
82#endif
83
84
85
86template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this<T> const * pe, Y const * px )
87{
88 if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
89}
90
91#ifdef _MANAGED
92
93// Avoid C4793, ... causes native code generation
94
95struct sp_any_pointer
96{
97 template<class T> sp_any_pointer( T* ) {}
98};
99
100inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer )
101{
102}
103
104#else // _MANAGED
105
106#ifdef sgi
107// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed
108# pragma set woff 3506
109#endif
110
111inline void sp_enable_shared_from_this( shared_count const & , ... )
112{
113}
114
115#ifdef sgi
116# pragma reset woff 3506
117#endif
118
119#endif // _MANAGED
120
121#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
122
123
124
125template< class T, class R > struct sp_enable_if_auto_ptr
126{
127};
128
129template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
130{
131 typedef R type;
132};
133
134#endif
135
136}
137
138
139
140
141
142
143
144
145
146
147template<class T> class shared_ptr
148{
149private:
150
151
152 typedef shared_ptr<T> this_type;
153
154public:
155
156 typedef T element_type;
157 typedef T value_type;
158 typedef T * pointer;
159 typedef typename boost::detail::shared_ptr_traits<T>::reference reference;
160
161 shared_ptr(): px(0), pn()
162 {
163 }
164
165 template<class Y>
166 explicit shared_ptr( Y * p ): px( p ), pn( p )
167 {
168 boost::detail::sp_enable_shared_from_this( pn, p, p );
169 }
170
171
172
173
174
175
176
177 template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
178 {
179 boost::detail::sp_enable_shared_from_this( pn, p, p );
180 }
181
182
183
184 template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
185 {
186 boost::detail::sp_enable_shared_from_this( pn, p, p );
187 }
188
189
190
191
192#if defined(__BORLANDC__) || defined(__GNUC__)
193
194 shared_ptr & operator=(shared_ptr const & r) /
195 {
196 px = r.px;
197 pn = r.pn; // shared_count::op= doesn't throw
198 return *this;
199 }
200
201#endif
202
203 template<class Y>
204 explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn)
205 {
206 // it is now safe to copy r.px, as pn(r.pn) did not throw
207 px = r.px;
208 }
209
210 template<class Y>
211 shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn)
212 {
213 }
214
215
216 template< class Y >
217 shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn )
218 {
219 }
220
221 template<class Y>
222 shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
223 {
224 }
225
226 template<class Y>
227 shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
228 {
229 }
230
231 template<class Y>
232 shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
233 {
234 if(px == 0) // need to allocate new counter -- the cast failed
235 {
236 pn = boost::detail::shared_count();
237 }
238 }
239
240 template<class Y>
241 shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
242 {
243 if(px == 0)
244 {
245 boost::throw_exception(std::bad_cast());
246 }
247 }
248
249#ifndef BOOST_NO_AUTO_PTR
250
251 template<class Y>
252 explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
253 {
254 Y * tmp = r.get();
255 pn = boost::detail::shared_count(r);
256 boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
257 }
258
259#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
260
261 template<class Ap>
262 shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
263 {
264 typename Ap::element_type * tmp = r.get();
265 pn = boost::detail::shared_count( r );
266 boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
267 }
268
269
270#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
271
272#endif // BOOST_NO_AUTO_PTR
273
274#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
275
276 template<class Y>
277 shared_ptr & operator=(shared_ptr<Y> const & r) /
278 {
279 px = r.px;
280 pn = r.pn; // shared_count::op= doesn't throw
281 return *this;
282 }
283
284#endif
285
286#ifndef BOOST_NO_AUTO_PTR
287
288 template<class Y>
289 shared_ptr & operator=( std::auto_ptr<Y> & r )
290 {
291 this_type(r).swap(*this);
292 return *this;
293 }
294
295#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
296
297 template<class Ap>
298 typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
299 {
300 this_type( r ).swap( *this );
301 return *this;
302 }
303
304
305#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
306
307#endif // BOOST_NO_AUTO_PTR
308
309
310
311#if defined( BOOST_HAS_RVALUE_REFS )
312
313 shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws
314 {
315 pn.swap( r.pn );
316 r.px = 0;
317 }
318
319 template<class Y>
320 shared_ptr( shared_ptr<Y> && r ): px( r.px ), pn() // never throws
321 {
322 pn.swap( r.pn );
323 r.px = 0;
324 }
325
326 shared_ptr & operator=( shared_ptr && r ) // never throws
327 {
328 this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
329 return *this;
330 }
331
332 template<class Y>
333 shared_ptr & operator=( shared_ptr<Y> && r ) // never throws
334 {
335 this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
336 return *this;
337 }
338
339#endif
340
341 void reset()
342 {
343 this_type().swap(*this);
344 }
345
346 template<class Y> void reset(Y * p)
347 {
348 BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
349 this_type(p).swap(*this);
350 }
351
352 template<class Y, class D> void reset( Y * p, D d )
353 {
354 this_type( p, d ).swap( *this );
355 }
356
357 template<class Y, class D, class A> void reset( Y * p, D d, A a )
358 {
359 this_type( p, d, a ).swap( *this );
360 }
361
362 template<class Y> void reset( shared_ptr<Y> const & r, T * p )
363 {
364 this_type( r, p ).swap( *this );
365 }
366
367 reference operator* () const
368 {
369 BOOST_ASSERT(px != 0);
370 return *px;
371 }
372
373 T * operator-> () const
374 {
375 BOOST_ASSERT(px != 0);
376 return px;
377 }
378
379 T * get() const
380 {
381 return px;
382 }
383
384
385
386#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
387
388 operator bool () const
389 {
390 return px != 0;
391 }
392
393#elif defined( _MANAGED )
394
395 static void unspecified_bool( this_type*** )
396 {
397 }
398
399 typedef void (*unspecified_bool_type)( this_type*** );
400
401 operator unspecified_bool_type() const // never throws
402 {
403 return px == 0? 0: unspecified_bool;
404 }
405
406#elif \
407 ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
408 ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \
409 ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
410
411 typedef T * (this_type::*unspecified_bool_type)() const;
412
413 operator unspecified_bool_type() const // never throws
414 {
415 return px == 0? 0: &this_type::get;
416 }
417
418#else
419
420 typedef T * this_type::*unspecified_bool_type;
421
422 operator unspecified_bool_type() const
423 {
424 return px == 0? 0: &this_type::px;
425 }
426
427#endif
428
429
430
431 bool operator! () const
432 {
433 return px == 0;
434 }
435
436 bool unique() const
437 {
438 return pn.unique();
439 }
440
441 long use_count() const
442 {
443 return pn.use_count();
444 }
445
446 void swap(shared_ptr<T> & other)
447 {
448 std::swap(px, other.px);
449 pn.swap(other.pn);
450 }
451
452 template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
453 {
454 return pn < rhs.pn;
455 }
456
457 void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const
458 {
459 return pn.get_deleter( ti );
460 }
461
462
463
464
465#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
466
467private:
468
469 template<class Y> friend class shared_ptr;
470 template<class Y> friend class weak_ptr;
471
472
473#endif
474
475 T * px;
476 boost::detail::shared_count pn;
477
478};
479
480template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
481{
482 return a.get() == b.get();
483}
484
485template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
486{
487 return a.get() != b.get();
488}
489
490#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
491
492// Resolve the ambiguity between our op!= and the one in rel_ops
493
494template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
495{
496 return a.get() != b.get();
497}
498
499#endif
500
501template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
502{
503 return a._internal_less(b);
504}
505
506template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
507{
508 a.swap(b);
509}
510
511template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
512{
513 return shared_ptr<T>(r, boost::detail::static_cast_tag());
514}
515
516template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
517{
518 return shared_ptr<T>(r, boost::detail::const_cast_tag());
519}
520
521template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
522{
523 return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
524}
525
526
527
528template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
529{
530 return shared_ptr<T>(r, boost::detail::static_cast_tag());
531}
532
533template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
534{
535 return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
536}
537
538template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
539{
540 return shared_ptr<T>(r, boost::detail::polymorphic_cast_tag());
541}
542
543template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
544{
545 BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
546 return shared_static_cast<T>(r);
547}
548
549
550
551template<class T> inline T * get_pointer(shared_ptr<T> const & p)
552{
553 return p.get();
554}
555
556
557
558#if defined(__GNUC__) && (__GNUC__ < 3)
559
560template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
561{
562 os << p.get();
563 return os;
564}
565
566#else
567
568
569#ifndef _STLP_NO_IOSTREAMS
570
571# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
572// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
573using std::basic_ostream;
574template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
575# else
576template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
577# endif
578{
579 os << p.get();
580 return os;
581}
582
583#endif // _STLP_NO_IOSTREAMS
584
585#endif // __GNUC__ < 3
586
587
588
589#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
590 ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
591 ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
592
593// g++ 2.9x doesn't allow static_cast<X const *>(void *)
594// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
595
596template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
597{
598 void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
599 return const_cast<D *>(static_cast<D const *>(q));
600}
601
602#else
603
604template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
605{
606 return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
607}
608
609#endif
610
611}
612
613#ifdef BOOST_MSVC
614# pragma warning(pop)
615#endif
616
617#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
618
619#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED