File: boost/shared_ptr.hpp
    1#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
    2#define BOOST_SHARED_PTR_HPP_INCLUDED
    3
    4//
    5//  shared_ptr.hpp
    6//
    7//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
    8//  Copyright (c) 2001-2007 Peter Dimov
    9//
   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)
   13//
   14//  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
   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// enable_shared_from_this support
   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 & /*pn*/, ... )
  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// rvalue auto_ptr support based on a technique by Dave Abrahams
  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} // namespace detail
  137
  138
  139//
  140//  shared_ptr
  141//
  142//  An enhanced relative of scoped_ptr with reference counted copy semantics.
  143//  The object pointed to is deleted when the last shared_ptr pointing to it
  144//  is destroyed or reset.
  145//
  146
  147template<class T> class shared_ptr
  148{
  149private:
  150
  151    // Borland 5.5.1 specific workaround
  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() // never throws in 1.30+
  162    {
  163    }
  164
  165    template<class Y>
  166    explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
  167    {
  168        boost::detail::sp_enable_shared_from_this( pn, p, p );
  169    }
  170
  171    //
  172    // Requirements: D's copy constructor must not throw
  173    //
  174    // shared_ptr will release p by calling d(p)
  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    // As above, but with allocator. A's copy constructor shall not throw.
  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//  generated copy constructor, assignment, destructor are fine...
  190
  191//  except that Borland C++ has a bug, and g++ with -Wsynth warns
  192#if defined(__BORLANDC__) || defined(__GNUC__)
  193
  194    shared_ptr & operator=(shared_ptr const & r) // never throws
  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) // may throw
  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) // never throws
  212    {
  213    }
  214
  215    // aliasing
  216    template< class Y >
  217    shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
  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) // never throws
  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// Move support
  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() // never throws in 1.30+
  342    {
  343        this_type().swap(*this);
  344    }
  345
  346    template<class Y> void reset(Y * p) // Y must be complete
  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 // never throws
  368    {
  369        BOOST_ASSERT(px != 0);
  370        return *px;
  371    }
  372
  373    T * operator-> () const // never throws
  374    {
  375        BOOST_ASSERT(px != 0);
  376        return px;
  377    }
  378    
  379    T * get() const // never throws
  380    {
  381        return px;
  382    }
  383
  384    // implicit conversion to "bool"
  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 // never throws
  423    {
  424        return px == 0? 0: &this_type::px;
  425    }
  426
  427#endif
  428
  429    // operator! is redundant, but some compilers need it
  430
  431    bool operator! () const // never throws
  432    {
  433        return px == 0;
  434    }
  435
  436    bool unique() const // never throws
  437    {
  438        return pn.unique();
  439    }
  440
  441    long use_count() const // never throws
  442    {
  443        return pn.use_count();
  444    }
  445
  446    void swap(shared_ptr<T> & other) // never throws
  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// Tasteless as this may seem, making all members public allows member templates
  463// to work in the absence of member template friends. (Matthew Langston)
  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;                     // contained pointer
  476    boost::detail::shared_count pn;    // reference counter
  477
  478};  // shared_ptr
  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// shared_*_cast names are deprecated. Use *_pointer_cast instead.
  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// get_pointer() enables boost::mem_fn to recognize shared_ptr
  550
  551template<class T> inline T * get_pointer(shared_ptr<T> const & p)
  552{
  553    return p.get();
  554}
  555
  556// operator<<
  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// in STLport's no-iostreams mode no iostream symbols can be used
  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// get_deleter
  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} // namespace boost
  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