/*============================================================================ KWSys - Kitware System Library Copyright 2000-2009 Kitware, Inc., Insight Software Consortium Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ #ifndef cmsys_auto_ptr_hxx #define cmsys_auto_ptr_hxx #include // The HP compiler and VS6 cannot handle the conversions necessary to use // auto_ptr_ref to pass an auto_ptr returned from one function // directly to another function as in use_auto_ptr(get_auto_ptr()). // We instead use const_cast to achieve the syntax on those platforms. // We do not use const_cast on other platforms to maintain the C++ // standard design and guarantee that if an auto_ptr is bound // to a reference-to-const then ownership will be maintained. #if defined(__HP_aCC) || (defined(_MSC_VER) && _MSC_VER <= 1200) # define cmsys_AUTO_PTR_REF 0 # define cmsys_AUTO_PTR_CONST const # define cmsys_AUTO_PTR_CAST(a) cast(a) #else # define cmsys_AUTO_PTR_REF 1 # define cmsys_AUTO_PTR_CONST # define cmsys_AUTO_PTR_CAST(a) a #endif // In C++11, clang will warn about using dynamic exception specifications // as they are deprecated. But as this class is trying to faithfully // mimic std::auto_ptr, we want to keep the 'throw()' decorations below. // So we suppress the warning. #if defined(__clang__) && defined(__has_warning) # if __has_warning("-Wdeprecated") # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdeprecated" # endif #endif namespace cmsys { template class auto_ptr; #if cmsys_AUTO_PTR_REF namespace detail { // The auto_ptr_ref template is supposed to be a private member of // auto_ptr but Borland 5.8 cannot handle it. Instead put it in // a private namespace. template struct auto_ptr_ref { Y* p_; // The extra constructor argument prevents implicit conversion to // auto_ptr_ref from auto_ptr through the constructor. Normally // this should be done with the explicit keyword but Borland 5.x // generates code in the conversion operator to call itself // infinately. auto_ptr_ref(Y* p, int): p_(p) {} }; } #endif /** C++98 Standard Section 20.4.5 - Template class auto_ptr. */ template class auto_ptr { #if !cmsys_AUTO_PTR_REF template static inline auto_ptr& cast(auto_ptr const& a) { return const_cast&>(a); } #endif /** The pointer to the object held. */ X* x_; public: /** The type of object held by the auto_ptr. */ typedef X element_type; /** Construct from an auto_ptr holding a compatible object. This transfers ownership to the newly constructed auto_ptr. */ template auto_ptr(auto_ptr cmsys_AUTO_PTR_CONST& a) throw(): x_(cmsys_AUTO_PTR_CAST(a).release()) { } /** Assign from an auto_ptr holding a compatible object. This transfers ownership to the left-hand-side of the assignment. */ template auto_ptr& operator=(auto_ptr cmsys_AUTO_PTR_CONST& a) throw() { this->reset(cmsys_AUTO_PTR_CAST(a).release()); return *this; } /** * Explicitly construct from a raw pointer. This is typically * called with the result of operator new. For example: * * auto_ptr ptr(new X()); */ explicit auto_ptr(X* p=0) throw(): x_(p) { } /** Construct from another auto_ptr holding an object of the same type. This transfers ownership to the newly constructed auto_ptr. */ auto_ptr(auto_ptr cmsys_AUTO_PTR_CONST& a) throw(): x_(cmsys_AUTO_PTR_CAST(a).release()) { } /** Assign from another auto_ptr holding an object of the same type. This transfers ownership to the newly constructed auto_ptr. */ auto_ptr& operator=(auto_ptr cmsys_AUTO_PTR_CONST& a) throw() { this->reset(cmsys_AUTO_PTR_CAST(a).release()); return *this; } /** Destruct and delete the object held. */ ~auto_ptr() throw() { // Assume object destructor is nothrow. delete this->x_; } /** Dereference and return a reference to the object held. */ X& operator*() const throw() { return *this->x_; } /** Return a pointer to the object held. */ X* operator->() const throw() { return this->x_; } /** Return a pointer to the object held. */ X* get() const throw() { return this->x_; } /** Return a pointer to the object held and reset to hold no object. This transfers ownership to the caller. */ X* release() throw() { X* x = this->x_; this->x_ = 0; return x; } /** Assume ownership of the given object. The object previously held is deleted. */ void reset(X* p=0) throw() { if(this->x_ != p) { // Assume object destructor is nothrow. delete this->x_; this->x_ = p; } } /** Convert to an auto_ptr holding an object of a compatible type. This transfers ownership to the returned auto_ptr. */ template operator auto_ptr() throw() { return auto_ptr(this->release()); } #if cmsys_AUTO_PTR_REF /** Construct from an auto_ptr_ref. This is used when the constructor argument is a call to a function returning an auto_ptr. */ auto_ptr(detail::auto_ptr_ref r) throw(): x_(r.p_) { } /** Assign from an auto_ptr_ref. This is used when a function returning an auto_ptr is passed on the right-hand-side of an assignment. */ auto_ptr& operator=(detail::auto_ptr_ref r) throw() { this->reset(r.p_); return *this; } /** Convert to an auto_ptr_ref. This is used when a function returning an auto_ptr is the argument to the constructor of another auto_ptr. */ template operator detail::auto_ptr_ref() throw() { return detail::auto_ptr_ref(this->release(), 1); } #endif }; } // namespace cmsys // Undo warning suppression. #if defined(__clang__) && defined(__has_warning) # if __has_warning("-Wdeprecated") # pragma clang diagnostic pop # endif #endif #endif