#ifndef BOOST_MAKE_SHARED_HPP_INCLUDED #define BOOST_MAKE_SHARED_HPP_INCLUDED // // make_shared.hpp // // Copyright (c) 2007 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) // // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. // #include #include #include #include #include #include namespace boost { namespace detail { template< std::size_t N, std::size_t A > struct sp_aligned_storage { union type { char data_[ N ]; typename boost::type_with_alignment< A >::type align_; }; }; template< class T > class sp_ms_deleter { private: typedef typename sp_aligned_storage< sizeof( T ), boost::alignment_of< T >::value >::type storage_type; bool initialized_; storage_type storage_; private: void destroy() { if( initialized_ ) { reinterpret_cast< T* >( storage_.data_ )->~T(); initialized_ = false; } } public: sp_ms_deleter(): initialized_( false ) { } ~sp_ms_deleter() { destroy(); } void operator()( T * ) { destroy(); } void * address() { return storage_.data_; } void set_initialized() { initialized_ = true; } }; } // namespace detail // Zero-argument versions // // Used even when variadic templates are available because of the new T() vs new T issue template< class T > boost::shared_ptr< T > make_shared() { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T(); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T(); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } // FIXME: boost doesn't seem to have a compiler agnostic replacement for __STRICT_ANSI__ #if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) && !defined( __STRICT_ANSI__ ) // Variadic templates, rvalue reference template< class T> T forward( T t ) { return t; } template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( forward( args )... ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( forward( args )... ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } #else // C++03 version template< class T, class A1 > boost::shared_ptr< T > make_shared( A1 const & a1 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( a1 ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } template< class T, class A, class A1 > boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( a1 ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } template< class T, class A1, class A2 > boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( a1, a2 ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } template< class T, class A, class A1, class A2 > boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( a1, a2 ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } template< class T, class A1, class A2, class A3 > boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( a1, a2, a3 ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } template< class T, class A, class A1, class A2, class A3 > boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( a1, a2, a3 ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } template< class T, class A1, class A2, class A3, class A4 > boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( a1, a2, a3, a4 ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } template< class T, class A, class A1, class A2, class A3, class A4 > boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); void * pv = pd->address(); new( pv ) T( a1, a2, a3, a4 ); pd->set_initialized(); return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); } #endif } // namespace boost #endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED