Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/smart_ptr/shared_ptr.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
0002 #define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
0003 
0004 //
0005 //  shared_ptr.hpp
0006 //
0007 //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
0008 //  Copyright (c) 2001-2008 Peter Dimov
0009 //
0010 //  Distributed under the Boost Software License, Version 1.0. (See
0011 //  accompanying file LICENSE_1_0.txt or copy at
0012 //  http://www.boost.org/LICENSE_1_0.txt)
0013 //
0014 //  See http://www.boost.org/libs/smart_ptr/ for documentation.
0015 //
0016 
0017 #include <boost/smart_ptr/detail/shared_count.hpp>
0018 #include <boost/smart_ptr/detail/sp_convertible.hpp>
0019 #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
0020 #include <boost/smart_ptr/detail/sp_noexcept.hpp>
0021 #include <boost/core/checked_delete.hpp>
0022 #include <boost/throw_exception.hpp>
0023 #include <boost/assert.hpp>
0024 #include <boost/config.hpp>
0025 #include <boost/config/workaround.hpp>
0026 
0027 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
0028 #include <boost/smart_ptr/detail/spinlock_pool.hpp>
0029 #endif
0030 
0031 #include <algorithm>            // for std::swap
0032 #include <functional>           // for std::less
0033 #include <typeinfo>             // for std::bad_cast
0034 #include <cstddef>              // for std::size_t
0035 #include <memory>               // for std::auto_ptr
0036 #include <iosfwd>               // for std::basic_ostream
0037 
0038 #if defined( BOOST_SP_DISABLE_DEPRECATED )
0039 #pragma GCC diagnostic push
0040 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0041 #endif
0042 
0043 namespace boost
0044 {
0045 
0046 template<class T> class shared_ptr;
0047 template<class T> class weak_ptr;
0048 template<class T> class enable_shared_from_this;
0049 class enable_shared_from_raw;
0050 
0051 namespace movelib
0052 {
0053 
0054     template< class T, class D > class unique_ptr;
0055 
0056 } // namespace movelib
0057 
0058 namespace detail
0059 {
0060 
0061 // sp_element, element_type
0062 
0063 template< class T > struct sp_element
0064 {
0065     typedef T type;
0066 };
0067 
0068 template< class T > struct sp_element< T[] >
0069 {
0070     typedef T type;
0071 };
0072 
0073 template< class T, std::size_t N > struct sp_element< T[N] >
0074 {
0075     typedef T type;
0076 };
0077 
0078 // sp_dereference, return type of operator*
0079 
0080 template< class T > struct sp_dereference
0081 {
0082     typedef T & type;
0083 };
0084 
0085 template<> struct sp_dereference< void >
0086 {
0087     typedef void type;
0088 };
0089 
0090 template<> struct sp_dereference< void const >
0091 {
0092     typedef void type;
0093 };
0094 
0095 template<> struct sp_dereference< void volatile >
0096 {
0097     typedef void type;
0098 };
0099 
0100 template<> struct sp_dereference< void const volatile >
0101 {
0102     typedef void type;
0103 };
0104 
0105 template< class T > struct sp_dereference< T[] >
0106 {
0107     typedef void type;
0108 };
0109 
0110 template< class T, std::size_t N > struct sp_dereference< T[N] >
0111 {
0112     typedef void type;
0113 };
0114 
0115 // sp_member_access, return type of operator->
0116 
0117 template< class T > struct sp_member_access
0118 {
0119     typedef T * type;
0120 };
0121 
0122 template< class T > struct sp_member_access< T[] >
0123 {
0124     typedef void type;
0125 };
0126 
0127 template< class T, std::size_t N > struct sp_member_access< T[N] >
0128 {
0129     typedef void type;
0130 };
0131 
0132 // sp_array_access, return type of operator[]
0133 
0134 template< class T > struct sp_array_access
0135 {
0136     typedef void type;
0137 };
0138 
0139 template< class T > struct sp_array_access< T[] >
0140 {
0141     typedef T & type;
0142 };
0143 
0144 template< class T, std::size_t N > struct sp_array_access< T[N] >
0145 {
0146     typedef T & type;
0147 };
0148 
0149 // sp_extent, for operator[] index check
0150 
0151 template< class T > struct sp_extent
0152 {
0153     enum _vt { value = 0 };
0154 };
0155 
0156 template< class T, std::size_t N > struct sp_extent< T[N] >
0157 {
0158     enum _vt { value = N };
0159 };
0160 
0161 // enable_shared_from_this support
0162 
0163 template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
0164 {
0165     if( pe != 0 )
0166     {
0167         pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
0168     }
0169 }
0170 
0171 template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
0172 
0173 #ifdef _MANAGED
0174 
0175 // Avoid C4793, ... causes native code generation
0176 
0177 struct sp_any_pointer
0178 {
0179     template<class T> sp_any_pointer( T* ) {}
0180 };
0181 
0182 inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
0183 {
0184 }
0185 
0186 #else // _MANAGED
0187 
0188 inline void sp_enable_shared_from_this( ... )
0189 {
0190 }
0191 
0192 #endif // _MANAGED
0193 
0194 // sp_assert_convertible
0195 
0196 template< class Y, class T > inline void sp_assert_convertible() noexcept
0197 {
0198     static_assert( sp_convertible< Y, T >::value, "incompatible pointer type" );
0199 }
0200 
0201 // pointer constructor helper
0202 
0203 template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
0204 {
0205     boost::detail::shared_count( p ).swap( pn );
0206     boost::detail::sp_enable_shared_from_this( ppx, p, p );
0207 }
0208 
0209 template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
0210 {
0211     sp_assert_convertible< Y[], T[] >();
0212     boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
0213 }
0214 
0215 template< class T, std::size_t N, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
0216 {
0217     sp_assert_convertible< Y[N], T[N] >();
0218     boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
0219 }
0220 
0221 // deleter constructor helper
0222 
0223 template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
0224 {
0225     boost::detail::sp_enable_shared_from_this( ppx, p, p );
0226 }
0227 
0228 template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
0229 {
0230     sp_assert_convertible< Y[], T[] >();
0231 }
0232 
0233 template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
0234 {
0235     sp_assert_convertible< Y[N], T[N] >();
0236 }
0237 
0238 struct sp_internal_constructor_tag
0239 {
0240 };
0241 
0242 } // namespace detail
0243 
0244 
0245 //
0246 //  shared_ptr
0247 //
0248 //  An enhanced relative of scoped_ptr with reference counted copy semantics.
0249 //  The object pointed to is deleted when the last shared_ptr pointing to it
0250 //  is destroyed or reset.
0251 //
0252 
0253 template<class T> class shared_ptr
0254 {
0255 private:
0256 
0257     // Borland 5.5.1 specific workaround
0258     typedef shared_ptr<T> this_type;
0259 
0260 public:
0261 
0262     typedef typename boost::detail::sp_element< T >::type element_type;
0263 
0264     constexpr shared_ptr() noexcept : px( 0 ), pn()
0265     {
0266     }
0267 
0268     constexpr shared_ptr( std::nullptr_t ) noexcept : px( 0 ), pn()
0269     {
0270     }
0271 
0272     constexpr shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count const & pn_ ) noexcept : px( px_ ), pn( pn_ )
0273     {
0274     }
0275 
0276     constexpr shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count && pn_ ) noexcept : px( px_ ), pn( std::move( pn_ ) )
0277     {
0278     }
0279 
0280     template<class Y>
0281     explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
0282     {
0283         boost::detail::sp_pointer_construct( this, p, pn );
0284     }
0285 
0286     //
0287     // Requirements: D's copy/move constructors must not throw
0288     //
0289     // shared_ptr will release p by calling d(p)
0290     //
0291 
0292     template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, static_cast< D&& >( d ) )
0293     {
0294         boost::detail::sp_deleter_construct( this, p );
0295     }
0296 
0297     template<class D> shared_ptr( std::nullptr_t p, D d ): px( p ), pn( p, static_cast< D&& >( d ) )
0298     {
0299     }
0300 
0301     // As above, but with allocator. A's copy constructor shall not throw.
0302 
0303     template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a )
0304     {
0305         boost::detail::sp_deleter_construct( this, p );
0306     }
0307 
0308     template<class D, class A> shared_ptr( std::nullptr_t p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a )
0309     {
0310     }
0311 
0312 //  generated copy constructor, destructor are fine...
0313 // ... except in C++0x, move disables the implicit copy
0314 
0315     shared_ptr( shared_ptr const & r ) noexcept : px( r.px ), pn( r.pn )
0316     {
0317     }
0318 
0319     template<class Y>
0320     explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
0321     {
0322         boost::detail::sp_assert_convertible< Y, T >();
0323 
0324         // it is now safe to copy r.px, as pn(r.pn) did not throw
0325         px = r.px;
0326     }
0327 
0328     template<class Y>
0329     shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
0330     noexcept : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
0331     {
0332         if( !pn.empty() )
0333         {
0334             px = r.px;
0335         }
0336     }
0337 
0338     template<class Y>
0339     shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
0340     noexcept : px( r.px ), pn( r.pn )
0341     {
0342         boost::detail::sp_assert_convertible< Y, T >();
0343     }
0344 
0345     // aliasing
0346     template< class Y >
0347     shared_ptr( shared_ptr<Y> const & r, element_type * p ) noexcept : px( p ), pn( r.pn )
0348     {
0349     }
0350 
0351 #ifndef BOOST_NO_AUTO_PTR
0352 
0353     template<class Y>
0354     explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
0355     {
0356         boost::detail::sp_assert_convertible< Y, T >();
0357 
0358         Y * tmp = r.get();
0359         pn = boost::detail::shared_count( r );
0360 
0361         boost::detail::sp_deleter_construct( this, tmp );
0362     }
0363 
0364     template<class Y>
0365     shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn()
0366     {
0367         boost::detail::sp_assert_convertible< Y, T >();
0368 
0369         Y * tmp = r.get();
0370         pn = boost::detail::shared_count( r );
0371 
0372         boost::detail::sp_deleter_construct( this, tmp );
0373     }
0374 
0375 #endif // BOOST_NO_AUTO_PTR
0376 
0377     template< class Y, class D >
0378     shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
0379     {
0380         boost::detail::sp_assert_convertible< Y, T >();
0381 
0382         typename std::unique_ptr< Y, D >::pointer tmp = r.get();
0383 
0384         if( tmp != 0 )
0385         {
0386             pn = boost::detail::shared_count( r );
0387             boost::detail::sp_deleter_construct( this, tmp );
0388         }
0389     }
0390 
0391     template< class Y, class D >
0392     shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn()
0393     {
0394         boost::detail::sp_assert_convertible< Y, T >();
0395 
0396         typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get();
0397 
0398         if( tmp != 0 )
0399         {
0400             pn = boost::detail::shared_count( r );
0401             boost::detail::sp_deleter_construct( this, tmp );
0402         }
0403     }
0404 
0405     // assignment
0406 
0407     shared_ptr & operator=( shared_ptr const & r ) noexcept
0408     {
0409         this_type(r).swap(*this);
0410         return *this;
0411     }
0412 
0413     template<class Y>
0414     shared_ptr & operator=(shared_ptr<Y> const & r) noexcept
0415     {
0416         this_type(r).swap(*this);
0417         return *this;
0418     }
0419 
0420 #ifndef BOOST_NO_AUTO_PTR
0421 
0422     template<class Y>
0423     shared_ptr & operator=( std::auto_ptr<Y> & r )
0424     {
0425         this_type( r ).swap( *this );
0426         return *this;
0427     }
0428 
0429     template<class Y>
0430     shared_ptr & operator=( std::auto_ptr<Y> && r )
0431     {
0432         this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this );
0433         return *this;
0434     }
0435 
0436 #endif // BOOST_NO_AUTO_PTR
0437 
0438     template<class Y, class D>
0439     shared_ptr & operator=( std::unique_ptr<Y, D> && r )
0440     {
0441         this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this);
0442         return *this;
0443     }
0444 
0445     template<class Y, class D>
0446     shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r )
0447     {
0448         // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this );
0449 
0450         boost::detail::sp_assert_convertible< Y, T >();
0451 
0452         typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get();
0453 
0454         shared_ptr tmp;
0455 
0456         if( p != 0 )
0457         {
0458             tmp.px = p;
0459             tmp.pn = boost::detail::shared_count( r );
0460 
0461             boost::detail::sp_deleter_construct( &tmp, p );
0462         }
0463 
0464         tmp.swap( *this );
0465 
0466         return *this;
0467     }
0468 
0469 // Move support
0470 
0471     shared_ptr( shared_ptr && r ) noexcept : px( r.px ), pn( static_cast< boost::detail::shared_count && >( r.pn ) )
0472     {
0473         r.px = 0;
0474     }
0475 
0476     template<class Y>
0477     shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
0478     noexcept : px( r.px ), pn( static_cast< boost::detail::shared_count && >( r.pn ) )
0479     {
0480         boost::detail::sp_assert_convertible< Y, T >();
0481         r.px = 0;
0482     }
0483 
0484     shared_ptr & operator=( shared_ptr && r ) noexcept
0485     {
0486         this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
0487         return *this;
0488     }
0489 
0490     template<class Y>
0491     shared_ptr & operator=( shared_ptr<Y> && r ) noexcept
0492     {
0493         this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
0494         return *this;
0495     }
0496 
0497     // aliasing move
0498     template<class Y>
0499     shared_ptr( shared_ptr<Y> && r, element_type * p ) noexcept : px( p ), pn()
0500     {
0501         pn.swap( r.pn );
0502         r.px = 0;
0503     }
0504 
0505     shared_ptr & operator=( std::nullptr_t ) noexcept
0506     {
0507         this_type().swap(*this);
0508         return *this;
0509     }
0510 
0511     void reset() noexcept
0512     {
0513         this_type().swap(*this);
0514     }
0515 
0516     template<class Y> void reset( Y * p ) // Y must be complete
0517     {
0518         BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
0519         this_type( p ).swap( *this );
0520     }
0521 
0522     template<class Y, class D> void reset( Y * p, D d )
0523     {
0524         this_type( p, static_cast< D&& >( d ) ).swap( *this );
0525     }
0526 
0527     template<class Y, class D, class A> void reset( Y * p, D d, A a )
0528     {
0529         this_type( p, static_cast< D&& >( d ), a ).swap( *this );
0530     }
0531 
0532     template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) noexcept
0533     {
0534         this_type( r, p ).swap( *this );
0535     }
0536 
0537     template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) noexcept
0538     {
0539         this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this );
0540     }
0541 
0542     typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT_WITH_ASSERT
0543     {
0544         BOOST_ASSERT( px != 0 );
0545         return *px;
0546     }
0547     
0548     typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT_WITH_ASSERT
0549     {
0550         BOOST_ASSERT( px != 0 );
0551         return px;
0552     }
0553     
0554     typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT
0555     {
0556         BOOST_ASSERT( px != 0 );
0557         BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
0558 
0559         return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
0560     }
0561 
0562     element_type * get() const noexcept
0563     {
0564         return px;
0565     }
0566 
0567     explicit operator bool () const noexcept
0568     {
0569         return px != 0;
0570     }
0571 
0572     bool unique() const noexcept
0573     {
0574         return pn.unique();
0575     }
0576 
0577     long use_count() const noexcept
0578     {
0579         return pn.use_count();
0580     }
0581 
0582     void swap( shared_ptr & other ) noexcept
0583     {
0584         std::swap(px, other.px);
0585         pn.swap(other.pn);
0586     }
0587 
0588     template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const noexcept
0589     {
0590         return pn < rhs.pn;
0591     }
0592 
0593     template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const noexcept
0594     {
0595         return pn < rhs.pn;
0596     }
0597 
0598     template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const noexcept
0599     {
0600         return pn == rhs.pn;
0601     }
0602 
0603     template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const noexcept
0604     {
0605         return pn == rhs.pn;
0606     }
0607 
0608     std::size_t owner_hash_value() const noexcept
0609     {
0610         return pn.hash_value();
0611     }
0612 
0613     void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const noexcept
0614     {
0615         return pn.get_deleter( ti );
0616     }
0617 
0618     void * _internal_get_local_deleter( boost::detail::sp_typeinfo_ const & ti ) const noexcept
0619     {
0620         return pn.get_local_deleter( ti );
0621     }
0622 
0623     void * _internal_get_untyped_deleter() const noexcept
0624     {
0625         return pn.get_untyped_deleter();
0626     }
0627 
0628     bool _internal_equiv( shared_ptr const & r ) const noexcept
0629     {
0630         return px == r.px && pn == r.pn;
0631     }
0632 
0633     boost::detail::shared_count _internal_count() const noexcept
0634     {
0635         return pn;
0636     }
0637 
0638 private:
0639 
0640     template<class Y> friend class shared_ptr;
0641     template<class Y> friend class weak_ptr;
0642 
0643 
0644     element_type * px;                 // contained pointer
0645     boost::detail::shared_count pn;    // reference counter
0646 
0647 };  // shared_ptr
0648 
0649 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept
0650 {
0651     return a.get() == b.get();
0652 }
0653 
0654 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept
0655 {
0656     return a.get() != b.get();
0657 }
0658 
0659 template<class T> inline bool operator==( shared_ptr<T> const & p, std::nullptr_t ) noexcept
0660 {
0661     return p.get() == 0;
0662 }
0663 
0664 template<class T> inline bool operator==( std::nullptr_t, shared_ptr<T> const & p ) noexcept
0665 {
0666     return p.get() == 0;
0667 }
0668 
0669 template<class T> inline bool operator!=( shared_ptr<T> const & p, std::nullptr_t ) noexcept
0670 {
0671     return p.get() != 0;
0672 }
0673 
0674 template<class T> inline bool operator!=( std::nullptr_t, shared_ptr<T> const & p ) noexcept
0675 {
0676     return p.get() != 0;
0677 }
0678 
0679 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept
0680 {
0681     return a.owner_before( b );
0682 }
0683 
0684 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept
0685 {
0686     a.swap(b);
0687 }
0688 
0689 template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) noexcept
0690 {
0691     (void) static_cast< T* >( static_cast< U* >( 0 ) );
0692 
0693     typedef typename shared_ptr<T>::element_type E;
0694 
0695     E * p = static_cast< E* >( r.get() );
0696     return shared_ptr<T>( r, p );
0697 }
0698 
0699 template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) noexcept
0700 {
0701     (void) const_cast< T* >( static_cast< U* >( 0 ) );
0702 
0703     typedef typename shared_ptr<T>::element_type E;
0704 
0705     E * p = const_cast< E* >( r.get() );
0706     return shared_ptr<T>( r, p );
0707 }
0708 
0709 template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) noexcept
0710 {
0711     (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
0712 
0713     typedef typename shared_ptr<T>::element_type E;
0714 
0715     E * p = dynamic_cast< E* >( r.get() );
0716     return p? shared_ptr<T>( r, p ): shared_ptr<T>();
0717 }
0718 
0719 template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) noexcept
0720 {
0721     (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
0722 
0723     typedef typename shared_ptr<T>::element_type E;
0724 
0725     E * p = reinterpret_cast< E* >( r.get() );
0726     return shared_ptr<T>( r, p );
0727 }
0728 
0729 template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) noexcept
0730 {
0731     (void) static_cast< T* >( static_cast< U* >( 0 ) );
0732 
0733     typedef typename shared_ptr<T>::element_type E;
0734 
0735     E * p = static_cast< E* >( r.get() );
0736     return shared_ptr<T>( std::move(r), p );
0737 }
0738 
0739 template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) noexcept
0740 {
0741     (void) const_cast< T* >( static_cast< U* >( 0 ) );
0742 
0743     typedef typename shared_ptr<T>::element_type E;
0744 
0745     E * p = const_cast< E* >( r.get() );
0746     return shared_ptr<T>( std::move(r), p );
0747 }
0748 
0749 template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) noexcept
0750 {
0751     (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
0752 
0753     typedef typename shared_ptr<T>::element_type E;
0754 
0755     E * p = dynamic_cast< E* >( r.get() );
0756     return p? shared_ptr<T>( std::move(r), p ): shared_ptr<T>();
0757 }
0758 
0759 template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) noexcept
0760 {
0761     (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
0762 
0763     typedef typename shared_ptr<T>::element_type E;
0764 
0765     E * p = reinterpret_cast< E* >( r.get() );
0766     return shared_ptr<T>( std::move(r), p );
0767 }
0768 
0769 // get_pointer() enables boost::mem_fn to recognize shared_ptr
0770 
0771 template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) noexcept
0772 {
0773     return p.get();
0774 }
0775 
0776 // operator<<
0777 
0778 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
0779 {
0780     os << p.get();
0781     return os;
0782 }
0783 
0784 // get_deleter
0785 
0786 namespace detail
0787 {
0788 
0789 template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) noexcept
0790 {
0791     return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID_(D)) );
0792 }
0793 
0794 template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) noexcept;
0795 template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) noexcept;
0796 
0797 class esft2_deleter_wrapper
0798 {
0799 private:
0800 
0801     shared_ptr<void const volatile> deleter_;
0802 
0803 public:
0804 
0805     esft2_deleter_wrapper() noexcept
0806     {
0807     }
0808 
0809     template< class T > void set_deleter( shared_ptr<T> const & deleter ) noexcept
0810     {
0811         deleter_ = deleter;
0812     }
0813 
0814     template<typename D> D* get_deleter() const noexcept
0815     {
0816         return boost::detail::basic_get_deleter<D>( deleter_ );
0817     }
0818 
0819     template< class T> void operator()( T* ) BOOST_SP_NOEXCEPT_WITH_ASSERT
0820     {
0821         BOOST_ASSERT( deleter_.use_count() <= 1 );
0822         deleter_.reset();
0823     }
0824 };
0825 
0826 } // namespace detail
0827 
0828 template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) noexcept
0829 {
0830     D * d = boost::detail::basic_get_deleter<D>( p );
0831 
0832     if( d == 0 )
0833     {
0834         d = boost::detail::basic_get_local_deleter( d, p );
0835     }
0836 
0837     if( d == 0 )
0838     {
0839         boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
0840 // The following get_deleter method call is fully qualified because
0841 // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
0842         if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
0843     }
0844 
0845     return d;
0846 }
0847 
0848 // atomic access
0849 
0850 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
0851 
0852 template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) noexcept
0853 {
0854     return false;
0855 }
0856 
0857 template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept
0858 {
0859     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
0860     return *p;
0861 }
0862 
0863 template<class T, class M> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ M ) noexcept
0864 {
0865     return atomic_load( p );
0866 }
0867 
0868 template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept
0869 {
0870     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
0871     p->swap( r );
0872 }
0873 
0874 template<class T, class M> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) noexcept
0875 {
0876     atomic_store( p, r ); // std::move( r )
0877 }
0878 
0879 template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept
0880 {
0881     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
0882 
0883     sp.lock();
0884     p->swap( r );
0885     sp.unlock();
0886 
0887     return r; // return std::move( r )
0888 }
0889 
0890 template<class T, class M> shared_ptr<T> inline atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) noexcept
0891 {
0892     return atomic_exchange( p, r ); // std::move( r )
0893 }
0894 
0895 template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept
0896 {
0897     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
0898 
0899     sp.lock();
0900 
0901     if( p->_internal_equiv( *v ) )
0902     {
0903         p->swap( w );
0904 
0905         sp.unlock();
0906 
0907         return true;
0908     }
0909     else
0910     {
0911         shared_ptr<T> tmp( *p );
0912 
0913         sp.unlock();
0914 
0915         tmp.swap( *v );
0916         return false;
0917     }
0918 }
0919 
0920 template<class T, class M> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ M, /*memory_order failure*/ M ) noexcept
0921 {
0922     return atomic_compare_exchange( p, v, w ); // std::move( w )
0923 }
0924 
0925 #endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
0926 
0927 // hash_value
0928 
0929 template< class T > struct hash;
0930 
0931 template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) noexcept
0932 {
0933     return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() );
0934 }
0935 
0936 } // namespace boost
0937 
0938 // std::hash
0939 
0940 namespace std
0941 {
0942 
0943 template<class T> struct hash< ::boost::shared_ptr<T> >
0944 {
0945     std::size_t operator()( ::boost::shared_ptr<T> const & p ) const noexcept
0946     {
0947         return std::hash< typename ::boost::shared_ptr<T>::element_type* >()( p.get() );
0948     }
0949 };
0950 
0951 } // namespace std
0952 
0953 #include <boost/smart_ptr/detail/local_sp_deleter.hpp>
0954 
0955 namespace boost
0956 {
0957 
0958 namespace detail
0959 {
0960 
0961 template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) noexcept
0962 {
0963     return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) );
0964 }
0965 
0966 template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) noexcept
0967 {
0968     return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) );
0969 }
0970 
0971 } // namespace detail
0972 
0973 #if defined(__cpp_deduction_guides)
0974 
0975 template<class T> shared_ptr( weak_ptr<T> ) -> shared_ptr<T>;
0976 template<class T, class D> shared_ptr( std::unique_ptr<T, D> ) -> shared_ptr<T>;
0977 
0978 #endif
0979 
0980 } // namespace boost
0981 
0982 #if defined( BOOST_SP_DISABLE_DEPRECATED )
0983 #pragma GCC diagnostic pop
0984 #endif
0985 
0986 #endif  // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED