diff --git a/.travis.yml b/.travis.yml index 7cc89de..fb53d45 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,9 @@ branches: - develop install: - - git clone -b $TRAVIS_BRANCH https://github.com/boostorg/boost.git boost - - cd boost + - cd .. + - git clone -b $TRAVIS_BRANCH https://github.com/boostorg/boost.git boost-root + - cd boost-root - git submodule init libs/align - git submodule init libs/assert - git submodule init libs/atomic @@ -29,16 +30,13 @@ install: - git submodule init libs/move - git submodule init libs/predef - git submodule init libs/preprocessor - - git submodule init libs/smart_ptr - git submodule init libs/static_assert - git submodule init libs/throw_exception - git submodule init libs/type_traits - git submodule init tools/build - git submodule init tools/inspect - git submodule update - - cd libs/smart_ptr - - git checkout -q $TRAVIS_COMMIT - - cd ../.. + - cp -r $TRAVIS_BUILD_DIR/* libs/smart_ptr - ./bootstrap.sh - ./b2 headers @@ -46,3 +44,7 @@ script: - TOOLSET=gcc,clang - if [ $TRAVIS_OS_NAME == osx ]; then TOOLSET=clang; fi - ./b2 libs/smart_ptr/test toolset=$TOOLSET + +notifications: + email: + on_success: always diff --git a/appveyor.yml b/appveyor.yml index 1fbbf38..d35c12d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,8 +12,9 @@ branches: - develop install: - - git clone -b %APPVEYOR_REPO_BRANCH% https://github.com/boostorg/boost.git boost - - cd boost + - cd .. + - git clone -b %APPVEYOR_REPO_BRANCH% https://github.com/boostorg/boost.git boost-root + - cd boost-root - git submodule init libs/align - git submodule init libs/assert - git submodule init libs/atomic @@ -25,20 +26,17 @@ install: - git submodule init libs/move - git submodule init libs/predef - git submodule init libs/preprocessor - - git submodule init libs/smart_ptr - git submodule init libs/static_assert - git submodule init libs/throw_exception - git submodule init libs/type_traits - git submodule init tools/build - git submodule init tools/inspect - git submodule update - - cd libs\smart_ptr - - git checkout -q %APPVEYOR_REPO_COMMIT% - - cd ..\.. + - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\smart_ptr - bootstrap - b2 headers build: off test_script: - - b2 libs/smart_ptr/test toolset=msvc-9.0,msvc-10.0,msvc-11.0,msvc-12.0 + - b2 libs/smart_ptr/test toolset=msvc-9.0,msvc-10.0,msvc-11.0,msvc-14.0 diff --git a/include/boost/pointer_cast.hpp b/include/boost/pointer_cast.hpp index 6e532eb..5af4971 100644 --- a/include/boost/pointer_cast.hpp +++ b/include/boost/pointer_cast.hpp @@ -10,6 +10,8 @@ #ifndef BOOST_POINTER_CAST_HPP #define BOOST_POINTER_CAST_HPP +#include + namespace boost { //static_pointer_cast overload for raw pointers @@ -42,4 +44,78 @@ inline T* reinterpret_pointer_cast(U *ptr) } // namespace boost +#if !defined( BOOST_NO_CXX11_SMART_PTR ) + +#include +#include +#include + +namespace boost { + +//static_pointer_cast overload for std::shared_ptr +using std::static_pointer_cast; + +//dynamic_pointer_cast overload for std::shared_ptr +using std::dynamic_pointer_cast; + +//const_pointer_cast overload for std::shared_ptr +using std::const_pointer_cast; + +//reinterpret_pointer_cast overload for std::shared_ptr +template std::shared_ptr reinterpret_pointer_cast(const std::shared_ptr & r ) BOOST_NOEXCEPT +{ + (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename std::shared_ptr::element_type E; + + E * p = reinterpret_cast< E* >( r.get() ); + return std::shared_ptr( r, p ); +} + +//static_pointer_cast overload for std::unique_ptr +template std::unique_ptr static_pointer_cast( std::unique_ptr && r ) BOOST_NOEXCEPT +{ + (void) static_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename std::unique_ptr::element_type E; + + return std::unique_ptr( static_cast( r.release() ) ); +} + +//dynamic_pointer_cast overload for std::unique_ptr +template std::unique_ptr dynamic_pointer_cast( std::unique_ptr && r ) BOOST_NOEXCEPT +{ + (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); + + BOOST_STATIC_ASSERT_MSG( boost::has_virtual_destructor::value, "The target of dynamic_pointer_cast must have a virtual destructor." ); + + T * p = dynamic_cast( r.get() ); + if( p ) r.release(); + return std::unique_ptr( p ); +} + +//const_pointer_cast overload for std::unique_ptr +template std::unique_ptr const_pointer_cast( std::unique_ptr && r ) BOOST_NOEXCEPT +{ + (void) const_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename std::unique_ptr::element_type E; + + return std::unique_ptr( const_cast( r.release() ) ); +} + +//reinterpret_pointer_cast overload for std::unique_ptr +template std::unique_ptr reinterpret_pointer_cast( std::unique_ptr && r ) BOOST_NOEXCEPT +{ + (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename std::unique_ptr::element_type E; + + return std::unique_ptr( reinterpret_cast( r.release() ) ); +} + +} // namespace boost + +#endif // #if !defined( BOOST_NO_CXX11_SMART_PTR ) + #endif //BOOST_POINTER_CAST_HPP diff --git a/include/boost/smart_ptr/bad_weak_ptr.hpp b/include/boost/smart_ptr/bad_weak_ptr.hpp index 3e0a1b7..582fad8 100644 --- a/include/boost/smart_ptr/bad_weak_ptr.hpp +++ b/include/boost/smart_ptr/bad_weak_ptr.hpp @@ -36,6 +36,11 @@ namespace boost # pragma option push -pc #endif +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wweak-vtables" +#endif + class bad_weak_ptr: public std::exception { public: @@ -46,6 +51,10 @@ public: } }; +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + #if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 # pragma option pop #endif diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp index 8aefd44..6e4f71a 100644 --- a/include/boost/smart_ptr/detail/atomic_count.hpp +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -73,6 +73,9 @@ #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) # include +#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC ) +# include + #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined( __PATHSCALE__ ) # include diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index 0addf07..83ede23 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -44,6 +44,9 @@ #elif defined( BOOST_SP_HAS_CLANG_C11_ATOMICS ) # include +#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC ) +# include + #elif defined( __SNC__ ) # include @@ -65,7 +68,7 @@ #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) && !defined(__PATHSCALE__) && !defined( _AIX ) # include -#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__) +#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__) && !defined( __mips16 ) # include #elif defined( BOOST_SP_HAS_SYNC ) diff --git a/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp b/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp index c66b985..7598495 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp @@ -58,6 +58,11 @@ inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * } } +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wweak-vtables" +#endif + class sp_counted_base { private: @@ -133,6 +138,10 @@ public: } }; +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + } // namespace detail } // namespace boost diff --git a/include/boost/smart_ptr/detail/spinlock.hpp b/include/boost/smart_ptr/detail/spinlock.hpp index 19f93d7..0b618df 100644 --- a/include/boost/smart_ptr/detail/spinlock.hpp +++ b/include/boost/smart_ptr/detail/spinlock.hpp @@ -43,6 +43,9 @@ #elif defined( BOOST_SP_USE_PTHREADS ) # include +#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC ) +# include + #elif defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include diff --git a/include/boost/smart_ptr/make_shared_object.hpp b/include/boost/smart_ptr/make_shared_object.hpp index 62372fa..3bc78ee 100644 --- a/include/boost/smart_ptr/make_shared_object.hpp +++ b/include/boost/smart_ptr/make_shared_object.hpp @@ -13,6 +13,8 @@ // for documentation. #include +#include +#include #include #include #include @@ -338,466 +340,10 @@ template< class T, class A > typename boost::detail::sp_if_not_array< T >::type return boost::shared_ptr< T >( pt, pt2 ); } -#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) - -// For example MSVC 10.0 - -template< class T, class A1 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A, class A1 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A1, class A2 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A, class A1, class A2 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A1, class A2, class A3 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A, class A1, class A2, class A3 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A1, class A2, class A3, class A4 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A, class A1, class A2, class A3, class A4 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ), - boost::detail::sp_forward( a6 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ), - boost::detail::sp_forward( a6 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ), - boost::detail::sp_forward( a6 ), - boost::detail::sp_forward( a7 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ), - boost::detail::sp_forward( a6 ), - boost::detail::sp_forward( a7 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ), - boost::detail::sp_forward( a6 ), - boost::detail::sp_forward( a7 ), - boost::detail::sp_forward( a8 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ), - boost::detail::sp_forward( a6 ), - boost::detail::sp_forward( a7 ), - boost::detail::sp_forward( a8 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ), - boost::detail::sp_forward( a6 ), - boost::detail::sp_forward( a7 ), - boost::detail::sp_forward( a8 ), - boost::detail::sp_forward( a9 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - - boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); - - void * pv = pd->address(); - - ::new( pv ) T( - boost::detail::sp_forward( a1 ), - boost::detail::sp_forward( a2 ), - boost::detail::sp_forward( a3 ), - boost::detail::sp_forward( a4 ), - boost::detail::sp_forward( a5 ), - boost::detail::sp_forward( a6 ), - boost::detail::sp_forward( a7 ), - boost::detail::sp_forward( a8 ), - boost::detail::sp_forward( a9 ) - ); - - pd->set_initialized(); - - T * pt2 = static_cast< T* >( pv ); - - boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); - return boost::shared_ptr< T >( pt, pt2 ); -} - -#else // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) - // C++03 version template< class T, class A1 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1 ) +typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); @@ -805,7 +351,10 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1 ) void * pv = pd->address(); - ::new( pv ) T( a1 ); + ::new( pv ) T( + boost::forward( a1 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -815,7 +364,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1 ) } template< class T, class A, class A1 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1 ) +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); @@ -823,7 +372,10 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, void * pv = pd->address(); - ::new( pv ) T( a1 ); + ::new( pv ) T( + boost::forward( a1 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -833,7 +385,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, } template< class T, class A1, class A2 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2 ) +typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); @@ -841,7 +393,11 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A void * pv = pd->address(); - ::new( pv ) T( a1, a2 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -851,7 +407,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A } template< class T, class A, class A1, class A2 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2 ) +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); @@ -859,7 +415,11 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, void * pv = pd->address(); - ::new( pv ) T( a1, a2 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -869,7 +429,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, } template< class T, class A1, class A2, class A3 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2, A3 const & a3 ) +typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); @@ -877,7 +437,12 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -887,7 +452,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A } template< class T, class A, class A1, class A2, class A3 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 ) +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); @@ -895,7 +460,12 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -905,7 +475,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, } template< class T, class A1, class A2, class A3, class A4 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); @@ -913,7 +483,13 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -923,7 +499,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A } template< class T, class A, class A1, class A2, class A3, class A4 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); @@ -931,7 +507,13 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -941,7 +523,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, } template< class T, class A1, class A2, class A3, class A4, class A5 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); @@ -949,7 +531,14 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -959,7 +548,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A } template< class T, class A, class A1, class A2, class A3, class A4, class A5 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); @@ -967,7 +556,14 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -977,7 +573,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, } template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); @@ -985,7 +581,15 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5, a6 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ), + boost::forward( a6 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -995,7 +599,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); @@ -1003,7 +607,15 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5, a6 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ), + boost::forward( a6 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -1013,7 +625,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, } template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); @@ -1021,7 +633,16 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ), + boost::forward( a6 ), + boost::forward( a7 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -1031,7 +652,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); @@ -1039,7 +660,16 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ), + boost::forward( a6 ), + boost::forward( a7 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -1049,7 +679,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, } template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7, BOOST_FWD_REF(A8) a8 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); @@ -1057,7 +687,17 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ), + boost::forward( a6 ), + boost::forward( a7 ), + boost::forward( a8 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -1067,7 +707,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7, BOOST_FWD_REF(A8) a8 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); @@ -1075,7 +715,17 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ), + boost::forward( a6 ), + boost::forward( a7 ), + boost::forward( a8 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -1085,7 +735,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, } template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > -typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7, BOOST_FWD_REF(A8) a8, BOOST_FWD_REF(A9) a9 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); @@ -1093,7 +743,18 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ), + boost::forward( a6 ), + boost::forward( a7 ), + boost::forward( a8 ), + boost::forward( a9 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -1103,7 +764,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > -typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7, BOOST_FWD_REF(A8) a8, BOOST_FWD_REF(A9) a9 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); @@ -1111,7 +772,18 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, void * pv = pd->address(); - ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + ::new( pv ) T( + boost::forward( a1 ), + boost::forward( a2 ), + boost::forward( a3 ), + boost::forward( a4 ), + boost::forward( a5 ), + boost::forward( a6 ), + boost::forward( a7 ), + boost::forward( a8 ), + boost::forward( a9 ) + ); + pd->set_initialized(); T * pt2 = static_cast< T* >( pv ); @@ -1120,8 +792,6 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, return boost::shared_ptr< T >( pt, pt2 ); } -#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) - #endif // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) #undef BOOST_SP_MSD diff --git a/pointer_cast.html b/pointer_cast.html index 2ab0859..bf63043 100644 --- a/pointer_cast.html +++ b/pointer_cast.html @@ -2,16 +2,16 @@ pointer_cast - +

boost.png (6897 bytes)pointer_cast

+ width="277" align="middle" border="0" />pointer_cast

The pointer cast functions (boost::static_pointer_cast boost::dynamic_pointer_cast boost::reinterpret_pointer_cast boost::const_pointer_cast) - provide a way to write generic pointer castings for raw pointers. The functions - are defined in boost/pointer_cast.hpp.

-

There is test/example code in pointer_cast_test.cpp.

+ provide a way to write generic pointer castings for raw pointers, std::shared_ptr and std::unique_ptr. The functions + are defined in boost/pointer_cast.hpp.

+

There is test/example code in pointer_cast_test.cpp.

Rationale

Boost smart pointers usually overload those functions to provide a mechanism to emulate pointers casts. For example, boost::shared_ptr<...> implements @@ -20,15 +20,15 @@ template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const &r); -

Pointer cast functions from boost/pointer_cast.hpp +

Pointer cast functions from boost/pointer_cast.hpp are overloads of boost::static_pointer_cast, boost::dynamic_pointer_cast, boost::reinterpret_pointer_cast and boost::const_pointer_cast - for raw pointers. This way when developing pointer type independent classes, - for example, memory managers or shared memory compatible classes, the same code - can be used for raw and smart pointers.

-

Synopsis

-
-
+            for raw pointers, std::shared_ptr and std::unique_ptr. This way when developing
+            pointer type independent classes, for example, memory managers or shared memory compatible classes, the same
+            code can be used for raw and smart pointers.

+

Synopsis

+
+
 namespace boost {
 
 template<class T, class U>
@@ -46,15 +46,93 @@ inline T* const_pointer_cast(U *ptr)
 template<class T, class U>
 inline T* reinterpret_pointer_cast(U *ptr)
   { return reinterpret_cast<T*>(ptr); }
+
+template<class T, class U>
+inline std::shared_ptr<T> static_pointer_cast(std::shared_ptr<U> const& r);
+
+template<class T, class U>
+inline std::shared_ptr<T> dynamic_pointer_cast(std::shared_ptr<U> const& r);
+
+template<class T, class U>
+inline std::shared_ptr<T> const_pointer_cast(std::shared_ptr<U> const& r);
+
+template<class T, class U>
+inline std::shared_ptr<T> reinterpret_pointer_cast(std::shared_ptr<U> const& r);
+
+template<class T, class U>
+inline std::unique_ptr<T> static_pointer_cast(std::unique_ptr<U>&& r);
+
+template<class T, class U>
+inline std::unique_ptr<T> dynamic_pointer_cast(std::unique_ptr<U>&& r);
+
+template<class T, class U>
+inline std::unique_ptr<T> const_pointer_cast(std::unique_ptr<U>&& r);
+
+template<class T, class U>
+inline std::unique_ptr<T> reinterpret_pointer_cast(std::unique_ptr<U>&& r);
   
 } // namespace boost
-
-
-

As you can see from the above synopsis, the pointer cast functions are just - wrappers around standard C++ cast operators.

-

Example

-
-
+
+
+

As you can see from the above synopsis, the pointer cast functions for raw pointers are just + wrappers around standard C++ cast operators.

+ +

The pointer casts for std::shared_ptr are aliases of the corresponding standard + functions with the same names and equivalent to the + functions taking boost::shared_ptr.

+ +

The pointer casts for std::unique_ptr are documented below.

+ +

static_pointer_cast

+
template<class T, class U>
+  unique_ptr<T> static_pointer_cast(unique_ptr<U>&& r); // never throws
+
+

Requires: The expression static_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns: unique_ptr<T>( static_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

+

Throws: nothing.

+

Notes: the seemingly equivalent expression + unique_ptr<T>(static_cast<T*>(r.get())) + will eventually result in undefined behavior, attempting to delete the same + object twice.

+
+

const_pointer_cast

+
template<class T, class U>
+  unique_ptr<T> const_pointer_cast(unique_ptr<U>&& r); // never throws
+
+

Requires: The expression const_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns: unique_ptr<T>( const_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

+

Throws: nothing.

+
+

dynamic_pointer_cast

+
template<class T, class U>
+  unique_ptr<T> dynamic_pointer_cast(unique_ptr<U>&& r);
+
+

Requires: The expression dynamic_cast<T*>( (U*)0 ) + must be well-formed. T must have a virtual destructor.

+

Returns:

+
    +
  • + When dynamic_cast<typename unique_ptr<T>::element_type*>(r.get()) returns a nonzero value, + unique_ptr<T>(dynamic_cast<typename unique_ptr<T>::element_type*>(r.release()));
  • +
  • + Otherwise, unique_ptr<T>().
+

Throws: nothing.

+
+

reinterpret_pointer_cast

+
template<class T, class U>
+  unique_ptr<T> reinterpret_pointer_cast(unique_ptr<U>&& r); // never throws
+
+

Requires: The expression reinterpret_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns: unique_ptr<T>( reinterpret_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

+

Throws: nothing.

+
+ +

Example

+
+
 #include <boost/pointer_cast.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -79,28 +157,27 @@ void check_if_it_is_derived(const BasePtr &ptr)
 
 int main()
 {
-   // Create a raw and a shared_ptr
+   // Create a raw and a shared_ptr
 
    base *ptr = new derived;
    boost::shared_ptr<base> sptr(new derived);
    
-   // Check that base pointer points actually to derived class
+   // Check that base pointer points actually to derived class
 
    check_if_it_is_derived(ptr);
    check_if_it_is_derived(sptr);
    
-   // Ok!
+   // Ok!
    
    delete ptr;
    return 0;
-}
-
-

The example demonstrates how the generic pointer casts help us create pointer - independent code.

-
-

$Date$

+}
+
+

The example demonstrates how the generic pointer casts help us create pointer + independent code.

+

Copyright 2005 Ion Gaztaņaga. Use, modification, and distribution are subject to - the Boost Software License, Version 1.0. (See accompanying file - LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

+ the Boost Software License, Version 1.0. (See accompanying file + LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

diff --git a/shared_ptr.htm b/shared_ptr.htm index 5c756f8..1cd0bc4 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -222,7 +222,7 @@ void bad() shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws template<class T, class U> - shared_ptr<T> reinterpet_pointer_cast(shared_ptr<U> const & r); // never throws + shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r); // never throws template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d965bfd..7c31ce5 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -29,6 +29,7 @@ import testing ; [ compile-fail shared_ptr_compare_fail.cpp ] [ run shared_ptr_alloc2_test.cpp ] [ run pointer_cast_test.cpp ] + [ run cpp11_pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] [ run auto_ptr_rv_test.cpp ] [ run shared_ptr_alias_test.cpp ] @@ -47,6 +48,7 @@ import testing ; [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] [ run spinlock_pool_test.cpp ] [ run make_shared_test.cpp ] + [ run make_shared_move_emulation_test.cpp ] [ run make_shared_perfect_forwarding_test.cpp ] [ run shared_ptr_convertible_test.cpp ] [ run wp_convertible_test.cpp ] @@ -185,5 +187,19 @@ import testing ; [ run sp_hash_test2.cpp ] [ run sp_hash_test3.cpp ] + + [ run pointer_cast_test2.cpp ] + + [ compile-fail pointer_cast_st_fail.cpp ] + [ compile-fail pointer_cast_st_fail2.cpp ] + [ compile-fail pointer_cast_st_fail3.cpp ] + + [ compile-fail pointer_cast_co_fail.cpp ] + [ compile-fail pointer_cast_co_fail2.cpp ] + [ compile-fail pointer_cast_co_fail3.cpp ] + + [ compile-fail pointer_cast_dy_fail.cpp ] + [ compile-fail pointer_cast_dy_fail2.cpp ] + [ compile-fail pointer_cast_dy_fail3.cpp ] ; } diff --git a/test/cpp11_pointer_cast_test.cpp b/test/cpp11_pointer_cast_test.cpp new file mode 100644 index 0000000..a9361c3 --- /dev/null +++ b/test/cpp11_pointer_cast_test.cpp @@ -0,0 +1,224 @@ +// +// cpp11_pointer_cast_test.cpp - a test for boost/pointer_cast.hpp with std::shared_ptr and std::unique_ptr +// +// Copyright (c) 2016 Karolin Varner +// +// 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 +#include +#include +#include + +#include +#include +#include + +#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) \ + || defined( BOOST_NO_CXX11_HDR_FUNCTIONAL ) \ + || defined( BOOST_NO_CXX11_HDR_UTILITY ) \ + || defined( BOOST_NO_CXX11_LAMBDAS ) \ + || defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + +// We expect all the features or none of the features to be +// available, since we should be on C++11 +int main() { return 0; } + +#else + +namespace +{ + +// Let's create these inheritance relationship: +// +// base base2 +// | | +// derived +// | +// derived_derived +// + +class base +{ + public: + virtual ~base(){} + int filler [5]; +}; + +class base2 +{ +public: + + virtual ~base2(){} + int filler [5]; +}; + +class derived + : public base, public base2 +{ + int filler [5]; +}; + +class derived_derived + : public derived +{ + int filler [5]; +}; + +// And now some simple check functions + +#if !defined( BOOST_NO_RTTI ) + +template +bool check_dynamic_pointer_cast(const BasePtr &ptr) +{ + //Check that dynamic_pointer_cast versus dynamic_cast + return + //Correct cast with dynamic_pointer_cast + boost::get_pointer(boost::dynamic_pointer_cast(ptr)) == + //Correct cast with dynamic_cast + dynamic_cast(boost::get_pointer(ptr)) + && + //Incorrect cast with dynamic_pointer_cast + boost::get_pointer(boost::dynamic_pointer_cast(ptr)) == + //Incorrect cast with dynamic_cast + dynamic_cast(boost::get_pointer(ptr)); +} + +#endif + +template +bool check_static_pointer_cast(const BasePtr &ptr) +{ + return + //Cast base -> derived -> base2 using static_pointer_cast + boost::get_pointer( + boost::static_pointer_cast( + boost::static_pointer_cast(ptr))) == + //Now the same with static_cast + static_cast(static_cast(boost::get_pointer(ptr))); +} + +template +bool check_const_pointer_cast(const BasePtr &ptr) +{ + return + //Unconst and const again using const_pointer_cast + boost::get_pointer( + boost::const_pointer_cast + (boost::const_pointer_cast(ptr))) == + //Now the same with const_cast + const_cast(const_cast(boost::get_pointer(ptr))); +} + +template +void check_all_copy_casts(const BasePtr &ptr) +{ +#if !defined( BOOST_NO_RTTI ) + BOOST_TEST( check_dynamic_pointer_cast( ptr ) ); +#endif + BOOST_TEST( check_static_pointer_cast( ptr ) ); + BOOST_TEST( check_const_pointer_cast( ptr ) ); +} + + +#if !defined( BOOST_NO_RTTI ) + +template +bool check_dynamic_moving_pointer_cast(std::function f) +{ + BasePtr smart1 = f(), smart2 = f(); + derived* expect1 = dynamic_cast(boost::get_pointer(smart1)); + derived_derived* expect2 = dynamic_cast(boost::get_pointer(smart2)); + //Check that dynamic_pointer_cast versus dynamic_cast + return + //Correct cast with dynamic_pointer_cast + boost::get_pointer(boost::dynamic_pointer_cast( std::move(smart1) )) == expect1 + && + //Incorrect cast with dynamic_pointer_cast + boost::get_pointer(boost::dynamic_pointer_cast( std::move(smart2) )) == expect2; +} + +#endif + +template +bool check_static_moving_pointer_cast(std::function f) +{ + BasePtr smart = f(); + base2 *expect = static_cast(static_cast(boost::get_pointer(smart))); + + return + //Cast base -> derived -> base2 using static_pointer_cast + boost::get_pointer( + boost::static_pointer_cast( + boost::static_pointer_cast( std::move(smart) ))) == + //Now the same with static_cast + expect; +} + +template +bool check_const_moving_pointer_cast(std::function f) +{ + BasePtr smart = f(); + const base *expect = const_cast(const_cast(boost::get_pointer(smart))); + return + //Unconst and const again using const_pointer_cast + boost::get_pointer( + boost::const_pointer_cast + (boost::const_pointer_cast( std::move(smart) ))) == + //Now the same with const_cast + expect; +} + +template +void check_all_moving_casts(std::function f) { +#if !defined( BOOST_NO_RTTI ) + BOOST_TEST( check_dynamic_moving_pointer_cast( f ) ); +#endif + BOOST_TEST( check_static_moving_pointer_cast( f ) ); + BOOST_TEST( check_const_moving_pointer_cast( f ) ); +} + +} + +int main() +{ + + std::shared_ptr std_shared(new derived); + boost::shared_ptr boost_shared(new derived); + base *plain = boost_shared.get(); + + // plain & boost::shared_ptr moving pointer_cast checks; there + // is no specific handleing for those types at the moment; this + // test just makes sure they won't break when std::move() is used + // in generic code + + check_all_moving_casts>([&boost_shared]() { + return boost_shared; + }); + + check_all_moving_casts([plain]() { + return plain; + }); + + // std::shared_ptr casts + + check_all_copy_casts(std_shared); + check_all_moving_casts>([&std_shared]() { + return std_shared; + }); + + // std::unique_ptr casts + + check_all_moving_casts>([]() { + return std::unique_ptr(new derived); + }); + + return boost::report_errors(); +} +#endif diff --git a/test/make_shared_move_emulation_test.cpp b/test/make_shared_move_emulation_test.cpp new file mode 100644 index 0000000..c607e05 --- /dev/null +++ b/test/make_shared_move_emulation_test.cpp @@ -0,0 +1,81 @@ +// make_shared_move_emulation_test.cpp - a test of make_shared +// semi-perfect forwarding of constructor arguments when using a C++03 +// compiler with move emulation. +// Note the "semi": it means moving temporaries (real r-values) doesn't work. +// +// Copyright 2016 Giel van Schijndel +// +// 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 +#include +#include +#include + +class movearg +{ +private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(movearg) +public: + movearg() + {} + movearg(BOOST_RV_REF(movearg)) + {} + movearg& operator=(BOOST_RV_REF(movearg)) + { + return *this; + } +}; + +class ByVal +{ +public: + ByVal(movearg) {} +}; + +class ByRef +{ +public: + enum constructor_id + { + move_constructor, + const_ref_constructor + }; + + ByRef(BOOST_RV_REF(movearg)): constructed_by_(move_constructor) + {} + ByRef(const movearg &arg): constructed_by_(const_ref_constructor) + {} + + constructor_id constructed_by_; +}; + +int main() +{ + { + movearg a; + boost::shared_ptr< ByVal > x = boost::make_shared< ByVal >(boost::move(a)); + } + { + movearg a; + boost::shared_ptr< ByRef > x = boost::make_shared< ByRef >(boost::move(a)); + BOOST_TEST( x->constructed_by_ == ByRef::move_constructor); + } +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + { + boost::shared_ptr< ByVal > x = boost::make_shared< ByVal >(movearg()); + boost::shared_ptr< ByRef > y = boost::make_shared< ByRef >(movearg()); + BOOST_TEST( y->constructed_by_ == ByRef::move_constructor); + } +#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + { + const movearg ca; + boost::shared_ptr< ByRef > x = boost::make_shared< ByRef >(ca); + BOOST_TEST( x->constructed_by_ == ByRef::const_ref_constructor); + } + + return boost::report_errors(); +} diff --git a/test/pointer_cast_co_fail.cpp b/test/pointer_cast_co_fail.cpp new file mode 100644 index 0000000..d8960b2 --- /dev/null +++ b/test/pointer_cast_co_fail.cpp @@ -0,0 +1,18 @@ +// +// A negative test for unique_ptr const_cast +// +// Copyright 2016 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 + +int main() +{ + std::unique_ptr p1( new int ); + std::unique_ptr p2 = boost::const_pointer_cast( std::move( p1 ) ); +} diff --git a/test/pointer_cast_co_fail2.cpp b/test/pointer_cast_co_fail2.cpp new file mode 100644 index 0000000..7fa8e18 --- /dev/null +++ b/test/pointer_cast_co_fail2.cpp @@ -0,0 +1,18 @@ +// +// A negative test for unique_ptr const_cast +// +// Copyright 2016 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 + +int main() +{ + std::unique_ptr p1( new int[ 1 ] ); + std::unique_ptr p2 = boost::const_pointer_cast( std::move( p1 ) ); +} diff --git a/test/pointer_cast_co_fail3.cpp b/test/pointer_cast_co_fail3.cpp new file mode 100644 index 0000000..d8872c8 --- /dev/null +++ b/test/pointer_cast_co_fail3.cpp @@ -0,0 +1,29 @@ +// +// A negative test for unique_ptr const_cast +// +// Copyright 2016 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 B +{ + virtual ~B() + { + } +}; + +struct D: B +{ +}; + +int main() +{ + std::unique_ptr p1( new D[ 1 ] ); + std::unique_ptr p2 = boost::const_pointer_cast( std::move( p1 ) ); +} diff --git a/test/pointer_cast_dy_fail.cpp b/test/pointer_cast_dy_fail.cpp new file mode 100644 index 0000000..c6df69d --- /dev/null +++ b/test/pointer_cast_dy_fail.cpp @@ -0,0 +1,25 @@ +// +// A negative test for unique_ptr dynamic_cast +// +// Copyright 2016 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 B +{ + virtual ~B() + { + } +}; + +int main() +{ + std::unique_ptr p1( new B ); + std::unique_ptr p2 = boost::dynamic_pointer_cast( std::move( p1 ) ); +} diff --git a/test/pointer_cast_dy_fail2.cpp b/test/pointer_cast_dy_fail2.cpp new file mode 100644 index 0000000..223977a --- /dev/null +++ b/test/pointer_cast_dy_fail2.cpp @@ -0,0 +1,25 @@ +// +// A negative test for unique_ptr dynamic_cast +// +// Copyright 2016 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 B +{ + virtual ~B() + { + } +}; + +int main() +{ + std::unique_ptr p1( new B[ 1 ] ); + std::unique_ptr p2 = boost::dynamic_pointer_cast( std::move( p1 ) ); +} diff --git a/test/pointer_cast_dy_fail3.cpp b/test/pointer_cast_dy_fail3.cpp new file mode 100644 index 0000000..1ac52e7 --- /dev/null +++ b/test/pointer_cast_dy_fail3.cpp @@ -0,0 +1,29 @@ +// +// A negative test for unique_ptr dynamic_cast +// +// Copyright 2016 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 B +{ + virtual ~B() + { + } +}; + +struct D: B +{ +}; + +int main() +{ + std::unique_ptr p1( new D[ 1 ] ); + std::unique_ptr p2 = boost::dynamic_pointer_cast( std::move( p1 ) ); +} diff --git a/test/pointer_cast_st_fail.cpp b/test/pointer_cast_st_fail.cpp new file mode 100644 index 0000000..0fcf8c1 --- /dev/null +++ b/test/pointer_cast_st_fail.cpp @@ -0,0 +1,18 @@ +// +// A negative test for unique_ptr static_cast +// +// Copyright 2016 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 + +int main() +{ + std::unique_ptr p1( new int ); + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); +} diff --git a/test/pointer_cast_st_fail2.cpp b/test/pointer_cast_st_fail2.cpp new file mode 100644 index 0000000..3b227b9 --- /dev/null +++ b/test/pointer_cast_st_fail2.cpp @@ -0,0 +1,18 @@ +// +// A negative test for unique_ptr static_cast +// +// Copyright 2016 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 + +int main() +{ + std::unique_ptr p1( new int[ 1 ] ); + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); +} diff --git a/test/pointer_cast_st_fail3.cpp b/test/pointer_cast_st_fail3.cpp new file mode 100644 index 0000000..4ca6a89 --- /dev/null +++ b/test/pointer_cast_st_fail3.cpp @@ -0,0 +1,29 @@ +// +// A negative test for unique_ptr static_cast +// +// Copyright 2016 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 B +{ + virtual ~B() + { + } +}; + +struct D: B +{ +}; + +int main() +{ + std::unique_ptr p1( new D[ 1 ] ); + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); +} diff --git a/test/pointer_cast_test.cpp b/test/pointer_cast_test.cpp index bd25dd1..ae036fb 100644 --- a/test/pointer_cast_test.cpp +++ b/test/pointer_cast_test.cpp @@ -104,33 +104,25 @@ bool check_const_pointer_cast(const BasePtr &ptr) const_cast(const_cast(boost::get_pointer(ptr))); } +template +void check_all_casts(const BasePtr &ptr) +{ +#if !defined( BOOST_NO_RTTI ) + BOOST_TEST( check_dynamic_pointer_cast( ptr ) ); +#endif + BOOST_TEST( check_static_pointer_cast( ptr ) ); + BOOST_TEST( check_const_pointer_cast( ptr ) ); +} + } int main() { - { - // Try casts with shared_ptr + boost::shared_ptr boost_shared(new derived); + base *plain = boost_shared.get(); - boost::shared_ptr ptr(new derived); - -#if !defined( BOOST_NO_RTTI ) - BOOST_TEST( check_dynamic_pointer_cast( ptr ) ); -#endif - BOOST_TEST( check_static_pointer_cast( ptr ) ); - BOOST_TEST( check_const_pointer_cast( ptr ) ); - } - - { - // Try casts with raw pointer - - boost::scoped_ptr ptr(new derived); - -#if !defined( BOOST_NO_RTTI ) - BOOST_TEST( check_dynamic_pointer_cast( ptr.get() ) ); -#endif - BOOST_TEST( check_static_pointer_cast( ptr.get() ) ); - BOOST_TEST( check_const_pointer_cast( ptr.get() ) ); - } + check_all_casts(boost_shared); + check_all_casts(plain); return boost::report_errors(); } diff --git a/test/pointer_cast_test2.cpp b/test/pointer_cast_test2.cpp new file mode 100644 index 0000000..eb28a5d --- /dev/null +++ b/test/pointer_cast_test2.cpp @@ -0,0 +1,247 @@ +// +// pointer_cast_test2.cpp - a test for unique_ptr casts +// +// Copyright 2016 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 + +#if defined( BOOST_NO_CXX11_SMART_PTR ) + +int main() +{ + return 0; +} + +#else + +#include +#include +#include + +struct B1 +{ +}; + +struct D1: B1 +{ + ~D1() + { + } +}; + +static void test_static_cast() +{ + { + std::unique_ptr p1( new int ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new int ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new int[ 1 ] ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new int[ 1 ] ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new D1 ); + D1 * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + + std::unique_ptr p3 = boost::static_pointer_cast( std::move( p2 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p3.get(), q1 ); + } +} + +static void test_const_cast() +{ + { + std::unique_ptr p1( new int ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::const_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + + std::unique_ptr p3 = boost::const_pointer_cast( std::move( p2 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p3.get(), q1 ); + } + + { + std::unique_ptr p1( new int[ 1 ] ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::const_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + + std::unique_ptr p3 = boost::const_pointer_cast( std::move( p2 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p3.get(), q1 ); + } +} + +struct B2 +{ + virtual ~B2() + { + } +}; + +struct C2 +{ + virtual ~C2() + { + } +}; + +struct D2: B2, C2 +{ +}; + +static void test_dynamic_cast() +{ + { + std::unique_ptr p1( new D2 ); + D2 * q1 = p1.get(); + + std::unique_ptr p2 = boost::dynamic_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new D2 ); + B2 * q1 = p1.get(); + + std::unique_ptr p2 = boost::dynamic_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new B2 ); + B2 * q1 = p1.get(); + + std::unique_ptr p2 = boost::dynamic_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p1.get(), q1 ); + } + + { + D2 * q1 = new D2; + std::unique_ptr p1( q1 ); + + std::unique_ptr p2 = boost::dynamic_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } +} + +static void test_reinterpret_cast() +{ + { + std::unique_ptr p1( new int ); + void * q1 = p1.get(); + + std::unique_ptr p2 = boost::reinterpret_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + + p1 = boost::reinterpret_pointer_cast( std::move( p2 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p1.get(), q1 ); + } + + { + std::unique_ptr p1( new int ); + void * q1 = p1.get(); + + std::unique_ptr p2 = boost::reinterpret_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + + p1 = boost::reinterpret_pointer_cast( std::move( p2 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p1.get(), q1 ); + } + + { + std::unique_ptr p1( new int[ 1 ] ); + void * q1 = p1.get(); + + std::unique_ptr p2 = boost::reinterpret_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + + p1 = boost::reinterpret_pointer_cast( std::move( p2 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p1.get(), q1 ); + } +} + +int main() +{ + test_static_cast(); + test_const_cast(); + test_dynamic_cast(); + test_reinterpret_cast(); + + return boost::report_errors(); +} + +#endif