#ifndef BOOST_SHARED_PTR_HPP_INCLUDED #define BOOST_SHARED_PTR_HPP_INCLUDED // // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // Copyright (c) 2001, 2002 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. // #include // for broken compiler workarounds #ifndef BOOST_MSVC6_MEMBER_TEMPLATES #include #else #include #include #include #include // for std::auto_ptr #include // for std::swap #include // for std::less #include // for std::bad_cast #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) # pragma warning(disable:4284) // odd return type for operator-> #endif namespace boost { namespace detail { struct static_cast_tag {}; struct dynamic_cast_tag {}; struct polymorphic_cast_tag {}; template struct shared_ptr_traits { typedef T & reference; }; template<> struct shared_ptr_traits { typedef void reference; }; class no_inheritance {}; template class shared_ptr; } // namespace detail template class weak_ptr; template class intrusive_ptr; // // shared_ptr // // An enhanced relative of scoped_ptr with reference counted copy semantics. // The object pointed to is deleted when the last shared_ptr pointing to it // is destroyed or reset. // // this might be useful elsewhere template class inherits : public T { protected: typedef T super; }; template class shared_ptr : public InheritancePolicy::super { private: // Borland 5.5.1 specific workarounds // typedef checked_deleter deleter; typedef shared_ptr this_type; typedef InheritancePolicy::super super; public: typedef T element_type; shared_ptr(): super () { } template explicit shared_ptr(Y * p): super (p) { } // // Requirements: D's copy constructor must not throw // // shared_ptr will release p by calling d(p) // template shared_ptr(Y * p, D d): super (p) { } // generated copy constructor, assignment, destructor are fine template explicit shared_ptr(weak_ptr const & r): super (p) // may throw { } template shared_ptr(shared_ptr const & r): super (r) // never throws { } template shared_ptr(intrusive_ptr const & r): super (r.get ()) // never throws { } template shared_ptr(shared_ptr const & r, detail::static_cast_tag): super (r, detail::static_cast_tag) { } template shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): super (r, detail::dynamic_cast_tag) { } template shared_ptr(shared_ptr const & r, detail::polymorphic_cast_tag): super (r, detail::polymorphic_cast_tag) { } #ifndef BOOST_NO_AUTO_PTR template explicit shared_ptr(std::auto_ptr & r): super (r) { } #endif #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) template shared_ptr & operator=(shared_ptr const & r) // never throws { // super::operator= (r); i forget, is this implicit? return *this; } #endif #ifndef BOOST_NO_AUTO_PTR template shared_ptr & operator=(std::auto_ptr & r) { // this_type(r).swap(*this);, again, implicit? return *this; } #endif void reset() { super::reset (); } template void reset(Y * p) // Y must be complete { super::reset (p); } template void reset(Y * p, D d) { super::reset (p, d); } typename detail::shared_ptr_traits::reference operator* () const // never throws { return static_cast::reference> (super::operator* ()); } T * operator-> () const // never throws { return static_cast (super::operator-> ()); } T * get() const // never throws { return static_cast (super::get ()); } bool unique() const // never throws { return super::unique (); } long use_count() const // never throws { return super::use_count (); } // implicit conversion to "bool" typedef long (this_type::*bool_type)() const; operator bool_type() const // never throws { return super::operator bool_type (); } bool operator! () const // never throws { return super::operator! (); } void swap(shared_ptr & other) // never throws { super::swap (other); } // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: template friend class shared_ptr; template friend class weak_ptr; #endif }; // shared_ptr template class shared_ptr { private: // Borland 5.5.1 specific workarounds // typedef checked_deleter deleter; typedef shared_ptr this_type; public: typedef T element_type; shared_ptr(): px(0), pn() { } template explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter(), p) // Y must be complete { } // // Requirements: D's copy constructor must not throw // // shared_ptr will release p by calling d(p) // template shared_ptr(Y * p, D d): px(p), pn(p, d) { } // generated copy constructor, assignment, destructor are fine template explicit shared_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // may throw { } template shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws { } template shared_ptr(intrusive_ptr const & r): px(r.get()), pn(r.get()) // never throws { } template shared_ptr(shared_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) { } template shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { if (px == 0) // need to allocate new counter -- the cast failed { pn = detail::shared_count(); } } template shared_ptr(shared_ptr const & r, detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { if (px == 0) { throw std::bad_cast(); } } #ifndef BOOST_NO_AUTO_PTR template explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn(r) { } #endif #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) template shared_ptr & operator=(shared_ptr const & r) // never throws { px = r.px; pn = r.pn; // shared_count::op= doesn't throw return *this; } #endif #ifndef BOOST_NO_AUTO_PTR template shared_ptr & operator=(std::auto_ptr & r) { this_type(r).swap(*this); return *this; } #endif void reset() { this_type().swap(*this); } template void reset(Y * p) // Y must be complete { BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors this_type(p).swap(*this); } template void reset(Y * p, D d) { this_type(p, d).swap(*this); } typename detail::shared_ptr_traits::reference operator* () const // never throws { BOOST_ASSERT(px != 0); return *px; } T * operator-> () const // never throws { BOOST_ASSERT(px != 0); return px; } T * get() const // never throws { return px; } bool unique() const // never throws { return pn.unique(); } long use_count() const // never throws { return pn.use_count(); } // implicit conversion to "bool" typedef long (this_type::*bool_type)() const; operator bool_type() const // never throws { return px == 0? 0: &this_type::use_count; } bool operator! () const // never throws { return px == 0; } void swap(shared_ptr & other) // never throws { std::swap(px, other.px); pn.swap(other.pn); } // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: template friend class shared_ptr; template friend class weak_ptr; #endif T * px; // contained pointer detail::shared_count pn; // reference counter }; // shared_ptr < no inheritance > // the inheritance policy needs to be considered here template inline bool operator==(shared_ptr const & a, shared_ptr const & b) { return a.get() == b.get(); } template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) { return a.get() != b.get(); } #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 // Resolve the ambiguity between our op!= and the one in rel_ops template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) { return a.get() != b.get(); } #endif template inline bool operator<(shared_ptr const & a, shared_ptr const & b) { return std::less()(a.get(), b.get()); } template inline void swap(shared_ptr & a, shared_ptr & b) { a.swap(b); } template shared_ptr shared_static_cast(shared_ptr const & r) { return shared_ptr(r, detail::static_cast_tag()); } template shared_ptr shared_dynamic_cast(shared_ptr const & r) { return shared_ptr(r, detail::dynamic_cast_tag()); } template shared_ptr shared_polymorphic_cast(shared_ptr const & r) { return shared_ptr(r, detail::polymorphic_cast_tag()); } template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) { BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); return shared_static_cast(r); } // get_pointer() enables boost::mem_fn to recognize shared_ptr template inline T * get_pointer(shared_ptr const & p) { return p.get(); } } // namespace boost #ifdef BOOST_MSVC # pragma warning(pop) #endif #endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED