diff options
Diffstat (limited to 'boost/ptr_container/detail/reversible_ptr_container.hpp')
-rw-r--r-- | boost/ptr_container/detail/reversible_ptr_container.hpp | 203 |
1 files changed, 110 insertions, 93 deletions
diff --git a/boost/ptr_container/detail/reversible_ptr_container.hpp b/boost/ptr_container/detail/reversible_ptr_container.hpp index 47c3903f46..930f468b6b 100644 --- a/boost/ptr_container/detail/reversible_ptr_container.hpp +++ b/boost/ptr_container/detail/reversible_ptr_container.hpp @@ -35,12 +35,14 @@ #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_pointer.hpp> #include <boost/type_traits/is_integral.hpp> +#include <boost/swap.hpp> #include <typeinfo> #include <memory> #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) #pragma warning(push) #pragma warning(disable:4127) +#pragma warning(disable:4224) // formal parameter was previously defined as a type. #endif namespace boost @@ -48,12 +50,32 @@ namespace boost namespace ptr_container_detail { + template< class Container > + struct dynamic_clone_deleter + { + dynamic_clone_deleter() { } + dynamic_clone_deleter( Container& cont ) : cont(&cont) { } + Container* cont; + + template< class T > + void operator()( const T* p ) const + { + // remark: static_move_ptr already test for null + cont->get_clone_allocator().deallocate_clone( p ); + } + }; + template< class CloneAllocator > - struct clone_deleter + struct static_clone_deleter { + static_clone_deleter() { } + template< class Dummy > + static_clone_deleter( const Dummy& ) { } + template< class T > void operator()( const T* p ) const { + // remark: static_move_ptr already test for null CloneAllocator::deallocate_clone( p ); } }; @@ -79,71 +101,26 @@ namespace ptr_container_detail class Config, class CloneAllocator > - class reversible_ptr_container + class reversible_ptr_container : CloneAllocator { private: BOOST_STATIC_CONSTANT( bool, allow_null = Config::allow_null ); - - typedef BOOST_DEDUCED_TYPENAME Config::value_type Ty_; - - template< bool allow_null_values > - struct null_clone_allocator - { - template< class Iter > - static Ty_* allocate_clone_from_iterator( Iter i ) - { - return allocate_clone( Config::get_const_pointer( i ) ); - } - - static Ty_* allocate_clone( const Ty_* x ) - { - if( allow_null_values ) - { - if( x == 0 ) - return 0; - } - else - { - BOOST_ASSERT( x != 0 && "Cannot insert clone of null!" ); - } - - Ty_* res = CloneAllocator::allocate_clone( *x ); - BOOST_ASSERT( typeid(*res) == typeid(*x) && - "CloneAllocator::allocate_clone() does not clone the " - "object properly. Check that new_clone() is implemented" - " correctly" ); - return res; - } - - static void deallocate_clone( const Ty_* x ) - { - if( allow_null_values ) - { - if( x == 0 ) - return; - } + BOOST_STATIC_CONSTANT( bool, is_clone_allocator_empty = sizeof(CloneAllocator) < sizeof(void*) ); - CloneAllocator::deallocate_clone( x ); - } - }; - - typedef BOOST_DEDUCED_TYPENAME Config::void_container_type Cont; -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - typedef null_clone_allocator<reversible_ptr_container::allow_null> - null_cloner_type; -#else - typedef null_clone_allocator<allow_null> null_cloner_type; -#endif - typedef clone_deleter<null_cloner_type> Deleter; - - Cont c_; + typedef BOOST_DEDUCED_TYPENAME Config::value_type Ty_; + typedef BOOST_DEDUCED_TYPENAME Config::void_container_type container_type; + typedef dynamic_clone_deleter<reversible_ptr_container> dynamic_deleter_type; + typedef static_clone_deleter<CloneAllocator> static_deleter_type; + + container_type c_; public: - Cont& base() { return c_; } + container_type& base() { return c_; } protected: // having this public could break encapsulation - const Cont& base() const { return c_; } + const container_type& base() const { return c_; } public: // typedefs + typedef Ty_ object_type; typedef Ty_* value_type; typedef Ty_* pointer; typedef Ty_& reference; @@ -157,23 +134,27 @@ namespace ptr_container_detail reverse_iterator; typedef boost::reverse_iterator< const_iterator > const_reverse_iterator; - typedef BOOST_DEDUCED_TYPENAME Cont::difference_type + typedef BOOST_DEDUCED_TYPENAME container_type::difference_type difference_type; - typedef BOOST_DEDUCED_TYPENAME Cont::size_type + typedef BOOST_DEDUCED_TYPENAME container_type::size_type size_type; typedef BOOST_DEDUCED_TYPENAME Config::allocator_type allocator_type; typedef CloneAllocator clone_allocator_type; - typedef ptr_container_detail::static_move_ptr<Ty_,Deleter> + typedef ptr_container_detail::static_move_ptr<Ty_, + BOOST_DEDUCED_TYPENAME boost::mpl::if_c<is_clone_allocator_empty, + static_deleter_type, + dynamic_deleter_type>::type + > auto_type; protected: - typedef ptr_container_detail::scoped_deleter<Ty_,null_cloner_type> + typedef ptr_container_detail::scoped_deleter<reversible_ptr_container> scoped_deleter; - typedef BOOST_DEDUCED_TYPENAME Cont::iterator + typedef BOOST_DEDUCED_TYPENAME container_type::iterator ptr_iterator; - typedef BOOST_DEDUCED_TYPENAME Cont::const_iterator + typedef BOOST_DEDUCED_TYPENAME container_type::const_iterator ptr_const_iterator; private: @@ -185,7 +166,7 @@ namespace ptr_container_detail void copy( const reversible_ptr_container& r ) { - copy( r.begin(), r.end() ); + this->copy( r.begin(), r.end() ); } void copy_clones_and_release( scoped_deleter& sd ) // nothrow @@ -200,8 +181,8 @@ namespace ptr_container_detail ForwardIterator last ) // strong { BOOST_ASSERT( first != last ); - scoped_deleter sd( first, last ); // strong - copy_clones_and_release( sd ); // nothrow + scoped_deleter sd( *this, first, last ); // strong + copy_clones_and_release( sd ); // nothrow } template< class ForwardIterator > @@ -209,13 +190,13 @@ namespace ptr_container_detail ForwardIterator last ) { BOOST_ASSERT( first != last ); - scoped_deleter sd( first, last ); + scoped_deleter sd( *this, first, last ); insert_clones_and_release( sd, end() ); } void remove_all() { - remove( begin(), end() ); + this->remove( begin(), end() ); } protected: @@ -241,20 +222,20 @@ namespace ptr_container_detail template< class U > void remove( U* ptr ) { - null_policy_deallocate_clone( ptr ); + this->deallocate_clone( ptr ); } template< class I > void remove( I i ) { - null_policy_deallocate_clone( Config::get_const_pointer(i) ); + this->deallocate_clone( Config::get_const_pointer(i) ); } template< class I > void remove( I first, I last ) { for( ; first != last; ++first ) - remove( first ); + this->remove( first ); } static void enforce_null_policy( const Ty_* x, const char* msg ) @@ -266,16 +247,44 @@ namespace ptr_container_detail } } - static Ty_* null_policy_allocate_clone( const Ty_* x ) + public: + Ty_* null_policy_allocate_clone( const Ty_* x ) { - return null_cloner_type::allocate_clone( x ); + if( allow_null ) + { + if( x == 0 ) + return 0; + } + else + { + BOOST_ASSERT( x != 0 && "Cannot insert clone of null!" ); + } + + Ty_* res = this->get_clone_allocator().allocate_clone( *x ); + BOOST_ASSERT( typeid(*res) == typeid(*x) && + "CloneAllocator::allocate_clone() does not clone the " + "object properly. Check that new_clone() is implemented" + " correctly" ); + return res; } - static void null_policy_deallocate_clone( const Ty_* x ) + template< class Iterator > + Ty_* null_policy_allocate_clone_from_iterator( Iterator i ) { - null_cloner_type::deallocate_clone( x ); + return this->null_policy_allocate_clone(Config::get_const_pointer(i)); } + + void null_policy_deallocate_clone( const Ty_* x ) + { + if( allow_null ) + { + if( x == 0 ) + return; + } + this->get_clone_allocator().deallocate_clone( x ); + } + private: template< class ForwardIterator > ForwardIterator advance( ForwardIterator begin, size_type n ) @@ -290,7 +299,7 @@ namespace ptr_container_detail { while( first != last ) { - insert( end(), null_cloner_type::allocate_clone_from_iterator(first) ); + insert( end(), this->allocate_clone_from_iterator(first) ); ++first; } } @@ -309,11 +318,11 @@ namespace ptr_container_detail if( first == last ) return; - scoped_deleter sd( first, last ); + scoped_deleter sd( *this, first, last ); insert_clones_and_release( sd ); } - public: // foundation! should be protected! + public: // foundation: should be protected, but public for poor compilers' sake. reversible_ptr_container() { } @@ -471,6 +480,16 @@ namespace ptr_container_detail { return c_.get_allocator(); } + + clone_allocator_type& get_clone_allocator() + { + return static_cast<clone_allocator_type&>(*this); + } + + const clone_allocator_type& get_clone_allocator() const + { + return static_cast<const clone_allocator_type&>(*this); + } public: // container requirements iterator begin() @@ -503,7 +522,8 @@ namespace ptr_container_detail void swap( reversible_ptr_container& r ) // nothrow { - c_.swap( r.c_ ); + boost::swap( get_clone_allocator(), r.get_clone_allocator() ); // nothrow + c_.swap( r.c_ ); // nothrow } size_type size() const // nothrow @@ -562,7 +582,7 @@ namespace ptr_container_detail { enforce_null_policy( x, "Null pointer in 'insert()'" ); - auto_type ptr( x ); // nothrow + auto_type ptr( x, *this ); // nothrow iterator res( c_.insert( before.base(), x ) ); // strong, commit ptr.release(); // nothrow return res; @@ -611,23 +631,21 @@ namespace ptr_container_detail BOOST_PTR_CONTAINER_THROW_EXCEPTION( empty(), bad_ptr_container_operation, "'release()' on empty container" ); - auto_type ptr( Config::get_pointer( where ) ); // nothrow - c_.erase( where.base() ); // nothrow + auto_type ptr( Config::get_pointer(where), *this ); // nothrow + c_.erase( where.base() ); // nothrow return boost::ptr_container_detail::move( ptr ); } auto_type replace( iterator where, Ty_* x ) // strong { BOOST_ASSERT( where != end() ); + enforce_null_policy( x, "Null pointer in 'replace()'" ); - enforce_null_policy( x, "Null pointer in 'replace()'" ); - - auto_type ptr( x ); - + auto_type ptr( x, *this ); BOOST_PTR_CONTAINER_THROW_EXCEPTION( empty(), bad_ptr_container_operation, "'replace()' on empty container" ); - auto_type old( Config::get_pointer( where ) ); // nothrow + auto_type old( Config::get_pointer(where), *this ); // nothrow const_cast<void*&>(*where.base()) = ptr.release(); return boost::ptr_container_detail::move( old ); } @@ -640,15 +658,14 @@ namespace ptr_container_detail auto_type replace( size_type idx, Ty_* x ) // strong { - enforce_null_policy( x, "Null pointer in 'replace()'" ); - - auto_type ptr( x ); - + enforce_null_policy( x, "Null pointer in 'replace()'" ); + + auto_type ptr( x, *this ); BOOST_PTR_CONTAINER_THROW_EXCEPTION( idx >= size(), bad_index, "'replace()' out of bounds" ); - auto_type old( static_cast<Ty_*>( c_[idx] ) ); // nothrow - c_[idx] = ptr.release(); // nothrow, commit + auto_type old( static_cast<Ty_*>(c_[idx]), *this ); // nothrow + c_[idx] = ptr.release(); // nothrow, commit return boost::ptr_container_detail::move( old ); } |