summaryrefslogtreecommitdiff
path: root/boost/ptr_container/detail/reversible_ptr_container.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/ptr_container/detail/reversible_ptr_container.hpp')
-rw-r--r--boost/ptr_container/detail/reversible_ptr_container.hpp203
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 );
}