diff --git a/include/boost/smart_ptr/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp index eb39797..00e5cb1 100644 --- a/include/boost/smart_ptr/detail/sp_convertible.hpp +++ b/include/boost/smart_ptr/detail/sp_convertible.hpp @@ -48,6 +48,31 @@ template< class Y, class T > struct sp_convertible enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) }; }; +template< class Y, class T > struct sp_convertible< Y, T[] > +{ + enum _vt { value = false }; +}; + +template< class T > struct sp_convertible< T[], T[] > +{ + enum _vt { value = true }; +}; + +template< class T > struct sp_convertible< T[], T const [] > +{ + enum _vt { value = true }; +}; + +template< class T > struct sp_convertible< T[], T volatile [] > +{ + enum _vt { value = true }; +}; + +template< class T > struct sp_convertible< T[], T const volatile [] > +{ + enum _vt { value = true }; +}; + struct sp_empty { }; diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 2bd721a..7ca3ba8 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -205,8 +205,10 @@ template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R // sp_assert_convertible -template< class T > inline void sp_assert_convertible( T * ) +template< class Y, class T > inline void sp_assert_convertible() { + T* p = static_cast< Y* >( 0 ); + (void)p; } // pointer constructor helper @@ -221,7 +223,7 @@ template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn ) { - sp_assert_convertible< T[] >( static_cast< Y (*) [] >( 0 ) ); + sp_assert_convertible< Y[], T[] >(); boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn ); } @@ -239,7 +241,7 @@ template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ ) { - sp_assert_convertible< T[] >( static_cast< Y (*) [] >( 0 ) ); + sp_assert_convertible< Y[], T[] >(); } #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -309,7 +311,7 @@ public: template explicit shared_ptr( weak_ptr const & r ): pn( r.pn ) // may throw { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); // it is now safe to copy r.px, as pn(r.pn) did not throw px = r.px; @@ -336,7 +338,7 @@ public: #endif : px( r.px ), pn( r.pn ) // never throws { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); } // aliasing @@ -378,7 +380,7 @@ public: template explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); Y * tmp = r.get(); pn = boost::detail::shared_count(r); @@ -393,7 +395,7 @@ public: { typedef typename Ap::element_type Y; - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); Y * tmp = r.get(); pn = boost::detail::shared_count( r ); @@ -410,7 +412,7 @@ public: template< class Y, class D > shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn() { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); typename std::unique_ptr< Y, D >::pointer tmp = r.get(); pn = boost::detail::shared_count( r ); @@ -483,7 +485,7 @@ public: #endif : px( r.px ), pn() // never throws { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); pn.swap( r.pn ); r.px = 0; diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp index f33116b..62b6afe 100644 --- a/include/boost/smart_ptr/weak_ptr.hpp +++ b/include/boost/smart_ptr/weak_ptr.hpp @@ -83,7 +83,7 @@ public: #endif : px(r.lock().get()), pn(r.pn) // never throws { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); } #if defined( BOOST_HAS_RVALUE_REFS ) @@ -100,7 +100,7 @@ public: #endif : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); r.px = 0; } @@ -132,7 +132,7 @@ public: #endif : px( r.px ), pn( r.pn ) // never throws { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); } #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) @@ -140,7 +140,7 @@ public: template weak_ptr & operator=( weak_ptr const & r ) // never throws { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); px = r.lock().get(); pn = r.pn; @@ -162,7 +162,7 @@ public: template weak_ptr & operator=( shared_ptr const & r ) // never throws { - boost::detail::sp_assert_convertible< T >( static_cast< Y* >( 0 ) ); + boost::detail::sp_assert_convertible< Y, T >(); px = r.px; pn = r.pn; @@ -204,7 +204,7 @@ public: } template - void _internal_aliasing_assign(weak_ptr const & r, T * px2) + void _internal_aliasing_assign(weak_ptr const & r, element_type * px2) { px = px2; pn = r.pn; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c638d92..1fe79ab 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -71,6 +71,7 @@ import testing ; [ run owner_less_test.cpp ] [ run sp_unique_ptr_test.cpp ] [ run sp_array_test.cpp ] + [ compile sp_array_cv_test.cpp ] [ compile-fail array_fail_spa_sp_c.cpp ] [ compile-fail array_fail_sp_spa_c.cpp ] diff --git a/test/sp_array_cv_test.cpp b/test/sp_array_cv_test.cpp new file mode 100644 index 0000000..2bdc9b6 --- /dev/null +++ b/test/sp_array_cv_test.cpp @@ -0,0 +1,42 @@ +// +// sp_array_cv_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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr< X[] > px; + + boost::shared_ptr< X const[] > pcx( px ); + boost::shared_ptr< X volatile[] > pvx( px ); + + boost::shared_ptr< X const volatile[] > pcvx( px ); + boost::shared_ptr< X const volatile[] > pcvx2( pcx ); + boost::shared_ptr< X const volatile[] > pcvx3( pvx ); + + boost::shared_ptr< void > pv( px ); + + boost::shared_ptr< void const > pcv( px ); + boost::shared_ptr< void const > pcv2( pcx ); + + boost::shared_ptr< void volatile > pvv( px ); + boost::shared_ptr< void volatile > pvv2( pvx ); + + boost::shared_ptr< void const volatile > pcvv( px ); + boost::shared_ptr< void const volatile > pcvv2( pcx ); + boost::shared_ptr< void const volatile > pcvv3( pvx ); + boost::shared_ptr< void const volatile > pcvv4( pcvx ); + + return 0; +}