// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #undef DLIB_SHARED_PTr_ABSTRACT_ #ifdef DLIB_SHARED_PTr_ABSTRACT_ #include "weak_ptr_abstract.h" #include <exception> namespace dlib { // ---------------------------------------------------------------------------------------- class bad_weak_ptr: public std::exception {} // ---------------------------------------------------------------------------------------- template < typename T > class shared_ptr { /*! INITIAL VALUE defined by constructors WHAT THIS OBJECT REPRESENTS This object represents a reference counted smart pointer. Each shared_ptr contains a pointer to some object and when the last shared_ptr that points to the object is destructed or reset() then the object is guaranteed to be deleted. This is an implementation of the std::tr1::shared_ptr template from the document ISO/IEC PDTR 19768, Proposed Draft Technical Report on C++ Library Extensions. The only deviation from that document is that this shared_ptr is declared inside the dlib namespace rather than std::tr1. THREAD SAFETY This object is not thread safe. Especially so since it is reference counted. So you should take care to not have two shared_ptr objects in different threads that point to the same object. If you want a thread safe version of this object you should use the dlib::shared_ptr_thread_safe object instead. !*/ public: typedef T element_type; shared_ptr( ); /*! ensures - #get() == 0 - #use_count() == 0 !*/ template<typename Y> explicit shared_ptr( Y* p ); /*! requires - p is convertible to a T* type pointer - p can be deleted by calling "delete p;" and doing so will not throw exceptions - p != 0 ensures - #get() == p - #use_count() == 1 - #*this object owns the pointer p throws - std::bad_alloc if this exception is thrown then "delete p;" is called !*/ template<typename Y, typename D> shared_ptr( Y* p, const D& d ); /*! requires - p is convertible to a T* type pointer - D is copy constructable (and the copy constructor of D doesn't throw) - p can be deleted by calling "d(p);" and doing so will not throw exceptions - p != 0 ensures - #get() == p - #use_count() == 1 - #*this object owns the pointer p throws - std::bad_alloc if this exception is thrown then "d(p);" is called !*/ shared_ptr( const shared_ptr& r ); /*! ensures - #get() == #r.get() - #use_count() == #r.use_count() - If r is empty, constructs an empty shared_ptr object; otherwise, constructs a shared_ptr object that shares ownership with r. !*/ template<typename Y> shared_ptr( const shared_ptr<Y>& r ); /*! requires - Y* is convertible to T* ensures - #get() == #r.get() - #use_count() == #r.use_count() - If r is empty, constructs an empty shared_ptr object; otherwise, constructs a shared_ptr object that shares ownership with r. !*/ template<typename Y> explicit shared_ptr( const weak_ptr<Y>& r ); /*! requires - Y* is convertible to T* ensures - #get() == #r.get() - #use_count() == #r.use_count() - If r is empty, constructs an empty shared_ptr object; otherwise, constructs a shared_ptr object that shares ownership with r. throws - bad_weak_ptr this exception is thrown if r.expired() == true !*/ template<typename Y> explicit shared_ptr( std::auto_ptr<Y>& r ); /*! requires - p.get() != 0 - p.release() is convertible to a T* type pointer - p.release() can be deleted by calling "delete p.release();" and doing so will not throw exceptions ensures - #get() == p.release() - #use_count() == 1 - #r.get() == 0 - #*this object owns the pointer p.release() throws - std::bad_alloc !*/ ~shared_ptr( ); /*! ensures - if (use_count() > 1) - this object destroys itself but otherwise has no effect (i.e. the pointer get() is still valid and shared between the remaining shared_ptr objects) - else if (use_count() == 1) - deletes the pointer get() by calling delete (or using the deleter passed to the constructor if one was passed in) - else - in this case get() == 0 so there is nothing to do so nothing occurs !*/ shared_ptr& operator= ( const shared_ptr& r ); /*! ensures - equivalent to shared_ptr(r).swap(*this). - returns #*this !*/ template<typename Y> shared_ptr& operator= ( const shared_ptr<Y>& r ); /*! requires - Y* is convertible to T* ensures - equivalent to shared_ptr(r).swap(*this). - returns #*this !*/ template<typename Y> shared_ptr& operator= ( std::auto_ptr<Y>& r ); /*! requires - p.get() != 0 - p.release() is convertible to a T* type pointer - p.release() can be deleted by calling "delete p.release();" and doing so will not throw exceptions ensures - equivalent to shared_ptr(r).swap(*this). - returns #*this !*/ void reset( ); /*! ensures - equivalent to shared_ptr().swap(*this) !*/ template<typename Y> void reset( Y* p ); /*! requires - p is convertible to a T* type pointer - p can be deleted by calling "delete p;" and doing so will not throw exceptions - p != 0 ensures - equivalent to shared_ptr(p).swap(*this) !*/ template<typename Y, typename D> void reset( Y* p, const D& d ); /*! requires - p is convertible to a T* type pointer - D is copy constructable (and the copy constructor of D doesn't throw) - p can be deleted by calling "d(p);" and doing so will not throw exceptions - p != 0 ensures - equivalent to shared_ptr(p,d).swap(*this) !*/ T* get( ) const; /*! ensures - returns the stored pointer !*/ T& operator*( ) const; /*! requires - get() != 0 ensures - returns a reference to *get() !*/ T* operator->( ) const; /*! requires - get() != 0 ensures - returns get() !*/ bool unique( ) const; /*! ensures - returns (use_count() == 1) !*/ long use_count( ) const; /*! ensures - The number of shared_ptr objects, *this included, that share ownership with *this, or 0 when *this is empty. !*/ operator bool( ) const; /*! ensures - returns (get() != 0) !*/ void swap( shared_ptr& b ); /*! ensures - swaps *this and item !*/ }; // ---------------------------------------------------------------------------------------- template<typename T, typename U> bool operator== ( const shared_ptr<T>& a, const shared_ptr<U>& b ); /*! ensures - returns a.get() == b.get() !*/ template<typename T, typename U> bool operator!= ( const shared_ptr<T>& a, const shared_ptr<U>& b ) { return a.get() != b.get(); } /*! ensures - returns a.get() != b.get() !*/ template<typename T, typename U> bool operator< ( const shared_ptr<T>& a, const shared_ptr<U>& b ); /*! ensures - Defines an operator< on shared_ptr types appropriate for use in the associative containers. !*/ template<typename T> void swap( shared_ptr<T>& a, shared_ptr<T>& b ) { a.swap(b); } /*! provides a global swap function !*/ template<typename T, typename U> shared_ptr<T> static_pointer_cast( const shared_ptr<U>& r ); /*! - if (r.get() == 0) then - returns shared_ptr<T>() - else - returns a shared_ptr<T> object that stores static_cast<T*>(r.get()) and shares ownership with r. !*/ template<typename T, typename U> shared_ptr<T> const_pointer_cast( const shared_ptr<U>& r ); /*! - if (r.get() == 0) then - returns shared_ptr<T>() - else - returns a shared_ptr<T> object that stores const_cast<T*>(r.get()) and shares ownership with r. !*/ template<typename T, typename U> shared_ptr<T> dynamic_pointer_cast( const shared_ptr<U>& r ); /*! ensures - if (dynamic_cast<T*>(r.get()) returns a nonzero value) then - returns a shared_ptr<T> object that stores a copy of dynamic_cast<T*>(r.get()) and shares ownership with r - else - returns an empty shared_ptr<T> object. !*/ template<typename E, typename T, typename Y> std::basic_ostream<E, T> & operator<< ( std::basic_ostream<E, T> & os, const shared_ptr<Y>& p ); /*! ensures - performs os << p.get() - returns os !*/ template<typename D, typename T> D* get_deleter( const shared_ptr<T>& p ); /*! ensures - if (*this owns a deleter d of type cv-unqualified D) then - returns &d - else - returns 0 !*/ // ---------------------------------------------------------------------------------------- } #endif // DLIB_SHARED_PTr_ABSTRACT_