diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index 0ab075d..eddbb42 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -297,6 +297,8 @@ template T * get_pointer(intrusive_ptr const & p) BOOST_SP_NOEXCEPT return p.get(); } +// pointer casts + template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) { return static_cast(p.get()); @@ -312,6 +314,31 @@ template intrusive_ptr dynamic_pointer_cast(intrusive_ptr(p.get()); } +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + +template intrusive_ptr static_pointer_cast( intrusive_ptr && p ) BOOST_SP_NOEXCEPT +{ + return intrusive_ptr( static_cast( p.detach() ), false ); +} + +template intrusive_ptr const_pointer_cast( intrusive_ptr && p ) BOOST_SP_NOEXCEPT +{ + return intrusive_ptr( const_cast( p.detach() ), false ); +} + +template intrusive_ptr dynamic_pointer_cast( intrusive_ptr && p ) BOOST_SP_NOEXCEPT +{ + T * p2 = dynamic_cast( p.get() ); + + intrusive_ptr r( p2, false ); + + if( p2 ) p.detach(); + + return r; +} + +#endif // defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + // operator<< #if !defined(BOOST_NO_IOSTREAM) diff --git a/test/intrusive_ptr_move_test.cpp b/test/intrusive_ptr_move_test.cpp index 2f2f652..9079c88 100644 --- a/test/intrusive_ptr_move_test.cpp +++ b/test/intrusive_ptr_move_test.cpp @@ -41,7 +41,7 @@ class base { private: - boost::detail::atomic_count use_count_; + mutable boost::detail::atomic_count use_count_; base(base const &); base & operator=(base const &); @@ -69,24 +69,24 @@ public: #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) - inline friend void intrusive_ptr_add_ref(base * p) + inline friend void intrusive_ptr_add_ref(base const * p) { ++p->use_count_; } - inline friend void intrusive_ptr_release(base * p) + inline friend void intrusive_ptr_release(base const * p) { if(--p->use_count_ == 0) delete p; } #else - void add_ref() + void add_ref() const { ++use_count_; } - void release() + void release() const { if(--use_count_ == 0) delete this; } @@ -103,12 +103,12 @@ long base::instances = 0; namespace boost { -inline void intrusive_ptr_add_ref(N::base * p) +inline void intrusive_ptr_add_ref(N::base const * p) { p->add_ref(); } -inline void intrusive_ptr_release(N::base * p) +inline void intrusive_ptr_release(N::base const * p) { p->release(); } @@ -209,6 +209,58 @@ int main() BOOST_TEST( N::base::instances == 0 ); } + { + boost::intrusive_ptr px( new Y ); + + X * px2 = px.get(); + + boost::intrusive_ptr py = boost::static_pointer_cast( std::move( px ) ); + BOOST_TEST( py.get() == px2 ); + BOOST_TEST( px.get() == 0 ); + BOOST_TEST( py->use_count() == 1 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px( new X ); + + X const * px2 = px.get(); + + boost::intrusive_ptr px3 = boost::const_pointer_cast( std::move( px ) ); + BOOST_TEST( px3.get() == px2 ); + BOOST_TEST( px.get() == 0 ); + BOOST_TEST( px3->use_count() == 1 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px( new Y ); + + X * px2 = px.get(); + + boost::intrusive_ptr py = boost::dynamic_pointer_cast( std::move( px ) ); + BOOST_TEST( py.get() == px2 ); + BOOST_TEST( px.get() == 0 ); + BOOST_TEST( py->use_count() == 1 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px( new X ); + + X * px2 = px.get(); + + boost::intrusive_ptr py = boost::dynamic_pointer_cast( std::move( px ) ); + BOOST_TEST( py.get() == 0 ); + BOOST_TEST( px.get() == px2 ); + BOOST_TEST( px->use_count() == 1 ); + } + + BOOST_TEST( N::base::instances == 0 ); + return boost::report_errors(); }