diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 3fbe00e..5e13c01 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -62,11 +62,6 @@ class enable_shared_from_raw; namespace detail { -struct static_cast_tag {}; -struct const_cast_tag {}; -struct dynamic_cast_tag {}; -struct polymorphic_cast_tag {}; - // sp_element, element_type template< class T > struct sp_element @@ -420,36 +415,6 @@ public: { } - template - shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag) - BOOST_NOEXCEPT : px(static_cast(r.px)), pn(r.pn) - { - } - - template - shared_ptr(shared_ptr const & r, boost::detail::const_cast_tag) - BOOST_NOEXCEPT : px(const_cast(r.px)), pn(r.pn) - { - } - - template - shared_ptr(shared_ptr const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) - { - if(px == 0) // need to allocate new counter -- the cast failed - { - pn = boost::detail::shared_count(); - } - } - - template - shared_ptr(shared_ptr const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) - { - if(px == 0) - { - boost::throw_exception(std::bad_cast()); - } - } - #ifndef BOOST_NO_AUTO_PTR template @@ -723,42 +688,44 @@ template inline void swap(shared_ptr & a, shared_ptr & b) BOOST_N a.swap(b); } -template shared_ptr static_pointer_cast(shared_ptr const & r) +template shared_ptr static_pointer_cast( shared_ptr const & r ) BOOST_NOEXCEPT { - return shared_ptr(r, boost::detail::static_cast_tag()); + (void) static_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = static_cast< E* >( r.get() ); + return shared_ptr( r, p ); } -template shared_ptr const_pointer_cast(shared_ptr const & r) +template shared_ptr const_pointer_cast( shared_ptr const & r ) BOOST_NOEXCEPT { - return shared_ptr(r, boost::detail::const_cast_tag()); + (void) const_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = const_cast< E* >( r.get() ); + return shared_ptr( r, p ); } -template shared_ptr dynamic_pointer_cast(shared_ptr const & r) +template shared_ptr dynamic_pointer_cast( shared_ptr const & r ) BOOST_NOEXCEPT { - return shared_ptr(r, boost::detail::dynamic_cast_tag()); + (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = dynamic_cast< E* >( r.get() ); + return p? shared_ptr( r, p ): shared_ptr(); } -// shared_*_cast names are deprecated. Use *_pointer_cast instead. - -template shared_ptr shared_static_cast(shared_ptr const & r) +template shared_ptr reinterpret_pointer_cast( shared_ptr const & r ) BOOST_NOEXCEPT { - return shared_ptr(r, boost::detail::static_cast_tag()); -} + (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); -template shared_ptr shared_dynamic_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::dynamic_cast_tag()); -} + typedef typename shared_ptr::element_type E; -template shared_ptr shared_polymorphic_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::polymorphic_cast_tag()); -} - -template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) -{ - BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); - return shared_static_cast(r); + E * p = reinterpret_cast< E* >( r.get() ); + return shared_ptr( r, p ); } // get_pointer() enables boost::mem_fn to recognize shared_ptr diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e3b41c0..2c95dd9 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -74,6 +74,7 @@ import testing ; [ compile sp_array_cv_test.cpp ] [ run sp_convertible_test.cpp ] [ run sp_array_n_test.cpp ] + [ run sp_array_cast_test.cpp ] [ compile-fail array_fail_spa_sp_c.cpp ] [ compile-fail array_fail_sp_spa_c.cpp ] diff --git a/test/sp_array_cast_test.cpp b/test/sp_array_cast_test.cpp new file mode 100644 index 0000000..5af7eb5 --- /dev/null +++ b/test/sp_array_cast_test.cpp @@ -0,0 +1,202 @@ +// +// sp_array_cast_test.cpp +// +// Copyright (c) 2012 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include + +struct X +{ +}; + +void static_cast_test() +{ + { + boost::shared_ptr pv; + + boost::shared_ptr pi = boost::static_pointer_cast( pv ); + BOOST_TEST( pi.get() == 0 ); + + boost::shared_ptr pi2 = boost::static_pointer_cast( pv ); + BOOST_TEST( pi2.get() == 0 ); + + boost::shared_ptr px = boost::static_pointer_cast( pv ); + BOOST_TEST( px.get() == 0 ); + + boost::shared_ptr px2 = boost::static_pointer_cast( pv ); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr pi( new int[2] ); + boost::shared_ptr pv( pi ); + + boost::shared_ptr pi2 = boost::static_pointer_cast( pv ); + BOOST_TEST(pi.get() == pi2.get()); + BOOST_TEST(!(pi < pi2 || pi2 < pi)); + + boost::shared_ptr pi3 = boost::static_pointer_cast( pv ); + BOOST_TEST(pi.get() == pi3.get()); + BOOST_TEST(!(pi < pi3 || pi3 < pi)); + + boost::shared_ptr pv2( pi3 ); + + boost::shared_ptr pi4 = boost::static_pointer_cast( pv2 ); + BOOST_TEST(pi.get() == pi4.get()); + BOOST_TEST(!(pi < pi4 || pi4 < pi)); + } + + { + boost::shared_ptr px( new X[4] ); + boost::shared_ptr pv( px ); + + boost::shared_ptr px2 = boost::static_pointer_cast( pv ); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + + boost::shared_ptr px3 = boost::static_pointer_cast( pv ); + BOOST_TEST(px.get() == px3.get()); + BOOST_TEST(!(px < px3 || px3 < px)); + + boost::shared_ptr pv2( px3 ); + + boost::shared_ptr px4 = boost::static_pointer_cast( pv2 ); + BOOST_TEST(px.get() == px4.get()); + BOOST_TEST(!(px < px4 || px4 < px)); + } +} + +void const_cast_test() +{ + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr px( new int[3] ); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + } + + { + boost::shared_ptr px( new int[3] ); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + } + + { + boost::shared_ptr px( new X[4] ); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + } + + { + boost::shared_ptr px( new X[4] ); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + } +} + +void reinterpret_cast_test() +{ + { + boost::shared_ptr pi; + BOOST_TEST( pi.get() == 0 ); + + boost::shared_ptr pi2 = boost::reinterpret_pointer_cast( pi ); + BOOST_TEST( pi2.get() == 0 ); + + boost::shared_ptr pi3 = boost::reinterpret_pointer_cast( pi2 ); + BOOST_TEST( pi3.get() == 0 ); + } + + { + boost::shared_ptr px; + BOOST_TEST( px.get() == 0 ); + + boost::shared_ptr px2 = boost::reinterpret_pointer_cast( px ); + BOOST_TEST( px2.get() == 0 ); + + boost::shared_ptr px3 = boost::reinterpret_pointer_cast( px2 ); + BOOST_TEST( px3.get() == 0 ); + } + + { + boost::shared_ptr pi( new int[2] ); + + boost::shared_ptr pi2 = boost::reinterpret_pointer_cast( pi ); + BOOST_TEST(pi.get() == pi2.get()); + BOOST_TEST(!(pi < pi2 || pi2 < pi)); + + boost::shared_ptr pi3 = boost::reinterpret_pointer_cast( pi2 ); + BOOST_TEST(pi.get() == pi3.get()); + BOOST_TEST(!(pi < pi3 || pi3 < pi)); + + boost::shared_ptr pi4 = boost::reinterpret_pointer_cast( pi3 ); + BOOST_TEST(pi.get() == pi4.get()); + BOOST_TEST(!(pi < pi4 || pi4 < pi)); + } + + { + boost::shared_ptr px( new X[4] ); + + boost::shared_ptr px2 = boost::reinterpret_pointer_cast( px ); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + + boost::shared_ptr px3 = boost::reinterpret_pointer_cast( px2 ); + BOOST_TEST(px.get() == px3.get()); + BOOST_TEST(!(px < px3 || px3 < px)); + + boost::shared_ptr px4 = boost::reinterpret_pointer_cast( px3 ); + BOOST_TEST(px.get() == px4.get()); + BOOST_TEST(!(px < px4 || px4 < px)); + } +} + +int main() +{ + static_cast_test(); + const_cast_test(); + reinterpret_cast_test(); + + return boost::report_errors(); +}