1 #ifndef BOOST_SHARED_PTR_132_HPP_INCLUDED
2 #define BOOST_SHARED_PTR_132_HPP_INCLUDED
7 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
8 // Copyright (c) 2001, 2002, 2003 Peter Dimov
10 // Distributed under the Boost Software License, Version 1.0. (See
11 // accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
14 // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
17 #include <boost/config.hpp> // for broken compiler workarounds
19 #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
20 #include <boost/serialization/detail/shared_ptr_nmt_132.hpp>
23 #include <boost/assert.hpp>
24 #include <boost/checked_delete.hpp>
25 #include <boost/serialization/throw_exception.hpp>
26 #include <boost/detail/workaround.hpp>
28 #include <boost/serialization/access.hpp>
29 #include <boost/serialization/detail/shared_count_132.hpp>
31 #include <memory> // for std::auto_ptr
32 #include <algorithm> // for std::swap
33 #include <functional> // for std::less
34 #include <typeinfo> // for std::bad_cast
35 #include <iosfwd> // for std::basic_ostream
37 #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
38 # pragma warning(push)
39 # 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 const_cast_tag
{};
52 struct dynamic_cast_tag
{};
53 struct polymorphic_cast_tag
{};
55 template<class T
> struct shared_ptr_traits
57 typedef T
& reference
;
60 template<> struct shared_ptr_traits
<void>
62 typedef void reference
;
65 #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
67 template<> struct shared_ptr_traits
<void const>
69 typedef void reference
;
72 template<> struct shared_ptr_traits
<void volatile>
74 typedef void reference
;
77 template<> struct shared_ptr_traits
<void const volatile>
79 typedef void reference
;
84 // enable_shared_from_this support
86 template<class T
, class Y
> void sp_enable_shared_from_this( shared_count
const & pn
, enable_shared_from_this
<T
> const * pe
, Y
const * px
)
88 if(pe
!= 0) pe
->_internal_weak_this
._internal_assign(const_cast<Y
*>(px
), pn
);
91 inline void sp_enable_shared_from_this( shared_count
const & /*pn*/, ... )
101 // An enhanced relative of scoped_ptr with reference counted copy semantics.
102 // The object pointed to is deleted when the last shared_ptr pointing to it
103 // is destroyed or reset.
106 template<class T
> class shared_ptr
109 // Borland 5.5.1 specific workaround
110 typedef shared_ptr
<T
> this_type
;
114 typedef T element_type
;
115 typedef T value_type
;
117 typedef BOOST_DEDUCED_TYPENAME
detail::shared_ptr_traits
<T
>::reference reference
;
119 shared_ptr(): px(0), pn() // never throws in 1.30+
123 #if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x564) )
125 explicit shared_ptr(Y
* p
): px(p
), pn(p
, boost::checked_deleter
<Y
>()) // Y must be complete
128 explicit shared_ptr(Y
* p
): px(p
), pn(p
, boost::checked_deleter
<Y
>()) // Y must be complete
131 detail::sp_enable_shared_from_this( pn
, p
, p
);
135 // Requirements: D's copy constructor must not throw
137 // shared_ptr will release p by calling d(p)
140 template<class Y
, class D
> shared_ptr(Y
* p
, D d
): px(p
), pn(p
, d
)
142 detail::sp_enable_shared_from_this( pn
, p
, p
);
145 // generated copy constructor, assignment, destructor are fine...
147 // except that Borland C++ has a bug, and g++ with -Wsynth warns
148 #if defined(__BORLANDC__) || defined(__GNUC__)
150 shared_ptr
& operator=(shared_ptr
const & r
) // never throws
153 pn
= r
.pn
; // shared_count::op= doesn't throw
160 explicit shared_ptr(weak_ptr
<Y
> const & r
): pn(r
.pn
) // may throw
162 // it is now safe to copy r.px, as pn(r.pn) did not throw
167 shared_ptr(shared_ptr
<Y
> const & r
): px(r
.px
), pn(r
.pn
) // never throws
172 shared_ptr(shared_ptr
<Y
> const & r
, detail::static_cast_tag
): px(static_cast<element_type
*>(r
.px
)), pn(r
.pn
)
177 shared_ptr(shared_ptr
<Y
> const & r
, detail::const_cast_tag
): px(const_cast<element_type
*>(r
.px
)), pn(r
.pn
)
182 shared_ptr(shared_ptr
<Y
> const & r
, detail::dynamic_cast_tag
): px(dynamic_cast<element_type
*>(r
.px
)), pn(r
.pn
)
184 if(px
== 0) // need to allocate new counter -- the cast failed
186 pn
= detail::shared_count();
191 shared_ptr(shared_ptr
<Y
> const & r
, detail::polymorphic_cast_tag
): px(dynamic_cast<element_type
*>(r
.px
)), pn(r
.pn
)
195 boost::serialization::throw_exception(std::bad_cast());
199 #ifndef BOOST_NO_AUTO_PTR
202 explicit shared_ptr(std::auto_ptr
<Y
> & r
): px(r
.get()), pn()
205 pn
= detail::shared_count(r
);
206 detail::sp_enable_shared_from_this( pn
, tmp
, tmp
);
211 #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
214 shared_ptr
& operator=(shared_ptr
<Y
> const & r
) // never throws
217 pn
= r
.pn
; // shared_count::op= doesn't throw
223 #ifndef BOOST_NO_AUTO_PTR
226 shared_ptr
& operator=(std::auto_ptr
<Y
> & r
)
228 this_type(r
).swap(*this);
234 void reset() // never throws in 1.30+
236 this_type().swap(*this);
239 template<class Y
> void reset(Y
* p
) // Y must be complete
241 BOOST_ASSERT(p
== 0 || p
!= px
); // catch self-reset errors
242 this_type(p
).swap(*this);
245 template<class Y
, class D
> void reset(Y
* p
, D d
)
247 this_type(p
, d
).swap(*this);
250 reference
operator* () const // never throws
252 BOOST_ASSERT(px
!= 0);
256 T
* operator-> () const // never throws
258 BOOST_ASSERT(px
!= 0);
262 T
* get() const // never throws
267 // implicit conversion to "bool"
269 #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
271 operator bool () const
276 #elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
277 typedef T
* (this_type::*unspecified_bool_type
)() const;
279 operator unspecified_bool_type() const // never throws
281 return px
== 0? 0: &this_type::get
;
286 typedef T
* this_type::*unspecified_bool_type
;
288 operator unspecified_bool_type() const // never throws
290 return px
== 0? 0: &this_type::px
;
295 // operator! is redundant, but some compilers need it
297 bool operator! () const // never throws
302 bool unique() const // never throws
307 long use_count() const // never throws
309 return pn
.use_count();
312 void swap(shared_ptr
<T
> & other
) // never throws
314 std::swap(px
, other
.px
);
318 template<class Y
> bool _internal_less(shared_ptr
<Y
> const & rhs
) const
323 void * _internal_get_deleter(std::type_info
const & ti
) const
325 return pn
.get_deleter(ti
);
328 // Tasteless as this may seem, making all members public allows member templates
329 // to work in the absence of member template friends. (Matthew Langston)
331 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
335 template<class Y
> friend class shared_ptr
;
336 template<class Y
> friend class weak_ptr
;
340 public: // for serialization
341 T
* px
; // contained pointer
342 detail::shared_count pn
; // reference counter
346 template<class T
, class U
> inline bool operator==(shared_ptr
<T
> const & a
, shared_ptr
<U
> const & b
)
348 return a
.get() == b
.get();
351 template<class T
, class U
> inline bool operator!=(shared_ptr
<T
> const & a
, shared_ptr
<U
> const & b
)
353 return a
.get() != b
.get();
356 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
358 // Resolve the ambiguity between our op!= and the one in rel_ops
360 template<class T
> inline bool operator!=(shared_ptr
<T
> const & a
, shared_ptr
<T
> const & b
)
362 return a
.get() != b
.get();
367 template<class T
, class U
> inline bool operator<(shared_ptr
<T
> const & a
, shared_ptr
<U
> const & b
)
369 return a
._internal_less(b
);
372 template<class T
> inline void swap(shared_ptr
<T
> & a
, shared_ptr
<T
> & b
)
377 template<class T
, class U
> shared_ptr
<T
> static_pointer_cast(shared_ptr
<U
> const & r
)
379 return shared_ptr
<T
>(r
, detail::static_cast_tag());
382 template<class T
, class U
> shared_ptr
<T
> const_pointer_cast(shared_ptr
<U
> const & r
)
384 return shared_ptr
<T
>(r
, detail::const_cast_tag());
387 template<class T
, class U
> shared_ptr
<T
> dynamic_pointer_cast(shared_ptr
<U
> const & r
)
389 return shared_ptr
<T
>(r
, detail::dynamic_cast_tag());
392 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
394 template<class T
, class U
> shared_ptr
<T
> shared_static_cast(shared_ptr
<U
> const & r
)
396 return shared_ptr
<T
>(r
, detail::static_cast_tag());
399 template<class T
, class U
> shared_ptr
<T
> shared_dynamic_cast(shared_ptr
<U
> const & r
)
401 return shared_ptr
<T
>(r
, detail::dynamic_cast_tag());
404 template<class T
, class U
> shared_ptr
<T
> shared_polymorphic_cast(shared_ptr
<U
> const & r
)
406 return shared_ptr
<T
>(r
, detail::polymorphic_cast_tag());
409 template<class T
, class U
> shared_ptr
<T
> shared_polymorphic_downcast(shared_ptr
<U
> const & r
)
411 BOOST_ASSERT(dynamic_cast<T
*>(r
.get()) == r
.get());
412 return shared_static_cast
<T
>(r
);
415 // get_pointer() enables boost::mem_fn to recognize shared_ptr
417 template<class T
> inline T
* get_pointer(shared_ptr
<T
> const & p
)
424 #if defined(__GNUC__) && (__GNUC__ < 3)
426 template<class Y
> std::ostream
& operator<< (std::ostream
& os
, shared_ptr
<Y
> const & p
)
434 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT)
435 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
436 using std::basic_ostream
;
437 template<class E
, class T
, class Y
> basic_ostream
<E
, T
> & operator<< (basic_ostream
<E
, T
> & os
, shared_ptr
<Y
> const & p
)
439 template<class E
, class T
, class Y
> std::basic_ostream
<E
, T
> & operator<< (std::basic_ostream
<E
, T
> & os
, shared_ptr
<Y
> const & p
)
448 // get_deleter (experimental)
450 #if (defined(__GNUC__) && (__GNUC__ < 3)) || (defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238))
452 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
453 // apparently EDG 2.38 also doesn't accept it
455 template<class D
, class T
> D
* get_deleter(shared_ptr
<T
> const & p
)
457 void const * q
= p
._internal_get_deleter(typeid(D
));
458 return const_cast<D
*>(static_cast<D
const *>(q
));
463 template<class D
, class T
> D
* get_deleter(shared_ptr
<T
> const & p
)
465 return static_cast<D
*>(p
._internal_get_deleter(typeid(D
)));
473 # pragma warning(pop)
476 #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
478 #endif // #ifndef BOOST_SHARED_PTR_132_HPP_INCLUDED