1 #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
2 #define BOOST_SHARED_PTR_HPP_INCLUDED
7 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
8 // Copyright (c) 2001, 2002, 2003 Peter Dimov
10 // Permission to copy, use, modify, sell and distribute this software
11 // is granted provided this copyright notice appears in all copies.
12 // This software is provided "as is" without express or implied
13 // warranty, and with no claim as to its suitability for any purpose.
15 // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
18 #include <boost/config.hpp> // for broken compiler workarounds
20 #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
21 #include <boost/detail/shared_ptr_nmt.hpp>
24 #include <boost/assert.hpp>
25 #include <boost/checked_delete.hpp>
26 #include <boost/throw_exception.hpp>
27 #include <boost/detail/shared_count.hpp>
28 #include <boost/detail/workaround.hpp>
30 #include <memory> // for std::auto_ptr
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
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->
44 template<class T> class weak_ptr;
45 template<class T> class enable_shared_from_this;
50 struct static_cast_tag {};
51 struct dynamic_cast_tag {};
52 struct polymorphic_cast_tag {};
54 template<class T> struct shared_ptr_traits
56 typedef T & reference;
59 template<> struct shared_ptr_traits<void>
61 typedef void reference;
64 #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
66 template<> struct shared_ptr_traits<void const>
68 typedef void reference;
73 // enable_shared_from_this support
75 template<class T, class Y> void sp_enable_shared_from_this(boost::enable_shared_from_this<T> * pe, Y * px, shared_count const & pn)
77 if(pe != 0) pe->_internal_weak_this._internal_assign(px, pn);
80 inline void sp_enable_shared_from_this(void const *, void const *, shared_count const &)
90 // An enhanced relative of scoped_ptr with reference counted copy semantics.
91 // The object pointed to is deleted when the last shared_ptr pointing to it
92 // is destroyed or reset.
95 template<class T> class shared_ptr
99 // Borland 5.5.1 specific workaround
100 typedef shared_ptr<T> this_type;
104 typedef T element_type;
105 typedef T value_type;
107 typedef typename detail::shared_ptr_traits<T>::reference reference;
109 shared_ptr(): px(0), pn() // never throws in 1.30+
114 explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete
116 detail::sp_enable_shared_from_this(p, p, pn);
120 // Requirements: D's copy constructor must not throw
122 // shared_ptr will release p by calling d(p)
125 template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
127 detail::sp_enable_shared_from_this(p, p, pn);
130 // generated copy constructor, assignment, destructor are fine...
132 // except that Borland C++ has a bug, and g++ with -Wsynth warns
133 #if defined(__BORLANDC__) || defined(__GNUC__)
135 shared_ptr & operator=(shared_ptr const & r) // never throws
138 pn = r.pn; // shared_count::op= doesn't throw
145 explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
147 // it is now safe to copy r.px, as pn(r.pn) did not throw
152 shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
157 shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
162 shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
164 if(px == 0) // need to allocate new counter -- the cast failed
166 pn = detail::shared_count();
171 shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
175 boost::throw_exception(std::bad_cast());
179 #ifndef BOOST_NO_AUTO_PTR
182 explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
185 pn = detail::shared_count(r);
186 detail::sp_enable_shared_from_this(tmp, tmp, pn);
191 #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
194 shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
197 pn = r.pn; // shared_count::op= doesn't throw
203 #ifndef BOOST_NO_AUTO_PTR
206 shared_ptr & operator=(std::auto_ptr<Y> & r)
208 this_type(r).swap(*this);
214 void reset() // never throws in 1.30+
216 this_type().swap(*this);
219 template<class Y> void reset(Y * p) // Y must be complete
221 BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
222 this_type(p).swap(*this);
225 template<class Y, class D> void reset(Y * p, D d)
227 this_type(p, d).swap(*this);
230 reference operator* () const // never throws
232 BOOST_ASSERT(px != 0);
236 T * operator-> () const // never throws
238 BOOST_ASSERT(px != 0);
242 T * get() const // never throws
247 // implicit conversion to "bool"
249 typedef T * (this_type::*unspecified_bool_type)() const;
251 operator unspecified_bool_type() const // never throws
253 return px == 0? 0: &this_type::get;
256 // operator! is redundant, but some compilers need it
258 bool operator! () const // never throws
263 bool unique() const // never throws
268 long use_count() const // never throws
270 return pn.use_count();
273 void swap(shared_ptr<T> & other) // never throws
275 std::swap(px, other.px);
279 template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
284 void * _internal_get_deleter(std::type_info const & ti) const
286 return pn.get_deleter(ti);
289 // Tasteless as this may seem, making all members public allows member templates
290 // to work in the absence of member template friends. (Matthew Langston)
292 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
296 template<class Y> friend class shared_ptr;
297 template<class Y> friend class weak_ptr;
302 T * px; // contained pointer
303 detail::shared_count pn; // reference counter
307 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
309 return a.get() == b.get();
312 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
314 return a.get() != b.get();
317 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
319 // Resolve the ambiguity between our op!= and the one in rel_ops
321 template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
323 return a.get() != b.get();
328 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
330 return a._internal_less(b);
333 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
338 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
340 return shared_ptr<T>(r, detail::static_cast_tag());
343 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
345 return shared_ptr<T>(r, detail::dynamic_cast_tag());
348 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
350 template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
352 return shared_ptr<T>(r, detail::static_cast_tag());
355 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
357 return shared_ptr<T>(r, detail::dynamic_cast_tag());
360 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
362 return shared_ptr<T>(r, detail::polymorphic_cast_tag());
365 template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
367 BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
368 return shared_static_cast<T>(r);
371 // get_pointer() enables boost::mem_fn to recognize shared_ptr
373 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
380 #if defined(__GNUC__) && (__GNUC__ < 3)
382 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
390 # if BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT)
391 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
392 using std::basic_ostream;
393 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
395 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
404 // get_deleter (experimental)
406 #if defined(__GNUC__) && (__GNUC__ < 3)
408 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
410 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
412 void const * q = p._internal_get_deleter(typeid(D));
413 return const_cast<D *>(static_cast<D const *>(q));
418 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
420 return static_cast<D *>(p._internal_get_deleter(typeid(D)));
428 # pragma warning(pop)
431 #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
433 #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED