williamr@2: // (C) Copyright Thorsten Ottosen 2005. williamr@2: // (C) Copyright Jonathan Turkanis 2004. williamr@2: // (C) Copyright Daniel Wallin 2004. williamr@2: // Distributed under the Boost Software License, Version 1.0. (See accompanying williamr@2: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) williamr@2: williamr@2: // Implementation of the move_ptr from the "Move Proposal" williamr@2: // (http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1377.htm) williamr@2: // enhanced to support custom deleters and safe boolean conversions. williamr@2: // williamr@2: // The implementation is based on an implementation by Daniel Wallin, at williamr@2: // "http://aspn.activestate.com/ASPN/Mail/Message/Attachments/boost/ williamr@2: // 400DC271.1060903@student.umu.se/move_ptr.hpp". The current was adapted williamr@2: // by Jonathan Turkanis to incorporating ideas of Howard Hinnant and williamr@2: // Rani Sharoni. williamr@2: williamr@2: #ifndef BOOST_STATIC_MOVE_PTR_HPP_INCLUDED williamr@2: #define BOOST_STATIC_MOVE_PTR_HPP_INCLUDED williamr@2: williamr@2: #include // Member template friends, put size_t in std. williamr@2: #include // swap. williamr@2: #include // size_t williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #if defined(BOOST_MSVC) williamr@2: #pragma warning(push) williamr@2: #pragma warning(disable:4521) // Multiple copy constuctors. williamr@2: #endif williamr@2: williamr@2: namespace boost { namespace ptr_container_detail { williamr@2: williamr@2: williamr@2: template< typename T, williamr@2: typename Deleter = williamr@2: move_ptrs::default_deleter > williamr@2: class static_move_ptr williamr@2: { williamr@2: public: williamr@2: williamr@2: typedef typename remove_bounds::type element_type; williamr@2: typedef Deleter deleter_type; williamr@2: williamr@2: private: williamr@2: williamr@2: struct safe_bool_helper { int x; }; williamr@2: typedef int safe_bool_helper::* safe_bool; williamr@2: typedef boost::compressed_pair impl_type; williamr@2: williamr@2: public: williamr@2: typedef typename impl_type::second_reference deleter_reference; williamr@2: typedef typename impl_type::second_const_reference deleter_const_reference; williamr@2: williamr@2: // Constructors williamr@2: williamr@2: static_move_ptr() : impl_(0) { } williamr@2: williamr@2: static_move_ptr(const static_move_ptr& p) williamr@2: : impl_(p.get(), p.get_deleter()) williamr@2: { williamr@2: const_cast(p).release(); williamr@2: } williamr@2: williamr@2: #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) williamr@2: static_move_ptr( const move_ptrs::move_source >& src ) williamr@2: #else williamr@2: static_move_ptr( const move_ptrs::move_source& src ) williamr@2: #endif williamr@2: : impl_(src.ptr().get(), src.ptr().get_deleter()) williamr@2: { williamr@2: src.ptr().release(); williamr@2: } williamr@2: williamr@2: template williamr@2: explicit static_move_ptr(TT* tt) williamr@2: : impl_(tt, Deleter()) williamr@2: { } williamr@2: williamr@2: // Destructor williamr@2: williamr@2: ~static_move_ptr() { if (ptr()) get_deleter()(ptr()); } williamr@2: williamr@2: // Assignment williamr@2: williamr@2: static_move_ptr& operator=(static_move_ptr rhs) williamr@2: { williamr@2: rhs.swap(*this); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: // Smart pointer interface williamr@2: williamr@2: element_type* get() const { return ptr(); } williamr@2: williamr@2: element_type& operator*() williamr@2: { williamr@2: /*BOOST_STATIC_ASSERT(!is_array);*/ return *ptr(); williamr@2: } williamr@2: williamr@2: const element_type& operator*() const williamr@2: { williamr@2: /*BOOST_STATIC_ASSERT(!is_array);*/ return *ptr(); williamr@2: } williamr@2: williamr@2: element_type* operator->() williamr@2: { williamr@2: /*BOOST_STATIC_ASSERT(!is_array);*/ return ptr(); williamr@2: } williamr@2: williamr@2: const element_type* operator->() const williamr@2: { williamr@2: /*BOOST_STATIC_ASSERT(!is_array);*/ return ptr(); williamr@2: } williamr@2: williamr@2: williamr@2: element_type* release() williamr@2: { williamr@2: element_type* result = ptr(); williamr@2: ptr() = 0; williamr@2: return result; williamr@2: } williamr@2: williamr@2: void reset() williamr@2: { williamr@2: if (ptr()) get_deleter()(ptr()); williamr@2: ptr() = 0; williamr@2: } williamr@2: williamr@2: template williamr@2: void reset(TT* tt) williamr@2: { williamr@2: static_move_ptr(tt).swap(*this); williamr@2: } williamr@2: williamr@2: template williamr@2: void reset(TT* tt, DD dd) williamr@2: { williamr@2: static_move_ptr(tt, dd).swap(*this); williamr@2: } williamr@2: williamr@2: operator safe_bool() const { return ptr() ? &safe_bool_helper::x : 0; } williamr@2: williamr@2: void swap(static_move_ptr& p) { impl_.swap(p.impl_); } williamr@2: williamr@2: deleter_reference get_deleter() { return impl_.second(); } williamr@2: williamr@2: deleter_const_reference get_deleter() const { return impl_.second(); } williamr@2: private: williamr@2: template williamr@2: void check(const static_move_ptr& ptr) williamr@2: { williamr@2: typedef move_ptrs::is_smart_ptr_convertible convertible; williamr@2: BOOST_STATIC_ASSERT(convertible::value); williamr@2: } williamr@2: williamr@2: #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_NO_SFINAE) williamr@2: // give up on this behavior williamr@2: #else williamr@2: williamr@2: template struct cant_move_from_const; williamr@2: williamr@2: template williamr@2: struct cant_move_from_const< const static_move_ptr > { williamr@2: typedef typename static_move_ptr::error type; williamr@2: }; williamr@2: williamr@2: template williamr@2: static_move_ptr(Ptr&, typename cant_move_from_const::type = 0); williamr@2: williamr@2: williamr@2: public: williamr@2: static_move_ptr(static_move_ptr&); williamr@2: williamr@2: williamr@2: private: williamr@2: template williamr@2: static_move_ptr( static_move_ptr&, williamr@2: typename williamr@2: move_ptrs::enable_if_convertible< williamr@2: TT, T, static_move_ptr& williamr@2: >::type::type* = 0 ); williamr@2: williamr@2: #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING || BOOST_NO_SFINAE williamr@2: williamr@2: //#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS williamr@2: // template williamr@2: // friend class static_move_ptr; williamr@2: //#else williamr@2: public: williamr@2: //#endif williamr@2: typename impl_type::first_reference williamr@2: ptr() { return impl_.first(); } williamr@2: williamr@2: typename impl_type::first_const_reference williamr@2: ptr() const { return impl_.first(); } williamr@2: williamr@2: impl_type impl_; williamr@2: }; williamr@2: williamr@2: } // namespace ptr_container_detail williamr@2: } // End namespace boost. williamr@2: williamr@2: #if defined(BOOST_MSVC) williamr@2: #pragma warning(pop) // #pragma warning(disable:4251) williamr@2: #endif williamr@2: williamr@2: #endif // #ifndef BOOST_STATIC_MOVE_PTR_HPP_INCLUDED