mirror of
https://github.com/boostorg/container.git
synced 2025-08-02 14:04:26 +02:00
Ticket #7114:Destructor not called when using emplace()
[SVN r79422]
This commit is contained in:
@@ -65,6 +65,44 @@ struct null_scoped_array_deallocator
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct scoped_destroy_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
typedef container_detail::integral_constant<unsigned,
|
||||
boost::container::container_detail::
|
||||
version<Allocator>::value> alloc_version;
|
||||
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
|
||||
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
|
||||
|
||||
scoped_destroy_deallocator(pointer p, Allocator& a)
|
||||
: m_ptr(p), m_alloc(a) {}
|
||||
|
||||
~scoped_destroy_deallocator()
|
||||
{
|
||||
if(m_ptr){
|
||||
AllocTraits::destroy(m_alloc, container_detail::to_raw_pointer(m_ptr));
|
||||
priv_deallocate(m_ptr, alloc_version());
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
|
||||
private:
|
||||
|
||||
void priv_deallocate(const pointer &p, allocator_v1)
|
||||
{ AllocTraits::deallocate(m_alloc, p, 1); }
|
||||
|
||||
void priv_deallocate(const pointer &p, allocator_v2)
|
||||
{ m_alloc.deallocate_one(p); }
|
||||
|
||||
pointer m_ptr;
|
||||
Allocator& m_alloc;
|
||||
};
|
||||
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
@@ -150,6 +188,27 @@ class scoped_destructor
|
||||
A &a_;
|
||||
};
|
||||
|
||||
|
||||
template<class A>
|
||||
class value_destructor
|
||||
{
|
||||
typedef boost::container::allocator_traits<A> AllocTraits;
|
||||
public:
|
||||
typedef typename A::value_type value_type;
|
||||
value_destructor(A &a, value_type &rv)
|
||||
: rv_(rv), a_(a)
|
||||
{}
|
||||
|
||||
~value_destructor()
|
||||
{
|
||||
AllocTraits::destroy(a_, &rv_);
|
||||
}
|
||||
|
||||
private:
|
||||
value_type &rv_;
|
||||
A &a_;
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
class allocator_destroyer
|
||||
{
|
||||
|
@@ -395,14 +395,13 @@ class flat_tree
|
||||
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
||||
stored_allocator_type &a = this->get_stored_allocator();
|
||||
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
|
||||
scoped_destructor<stored_allocator_type> d(a, &val);
|
||||
value_destructor<stored_allocator_type> d(a, val);
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret =
|
||||
priv_insert_unique_prepare(val, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, boost::move(val));
|
||||
}
|
||||
d.release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -413,13 +412,12 @@ class flat_tree
|
||||
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
||||
stored_allocator_type &a = this->get_stored_allocator();
|
||||
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
|
||||
scoped_destructor<stored_allocator_type> d(a, &val);
|
||||
value_destructor<stored_allocator_type> d(a, val);
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, boost::move(val));
|
||||
}
|
||||
d.release();
|
||||
return ret.first;
|
||||
}
|
||||
|
||||
@@ -430,10 +428,9 @@ class flat_tree
|
||||
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
||||
stored_allocator_type &a = this->get_stored_allocator();
|
||||
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
|
||||
scoped_destructor<stored_allocator_type> d(a, &val);
|
||||
value_destructor<stored_allocator_type> d(a, val);
|
||||
iterator i = this->upper_bound(KeyOfValue()(val));
|
||||
i = this->m_data.m_vect.insert(i, boost::move(val));
|
||||
d.release();
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -444,11 +441,10 @@ class flat_tree
|
||||
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
||||
stored_allocator_type &a = this->get_stored_allocator();
|
||||
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
|
||||
scoped_destructor<stored_allocator_type> d(a, &val);
|
||||
value_destructor<stored_allocator_type> d(a, val);
|
||||
insert_commit_data data;
|
||||
this->priv_insert_equal_prepare(hint, val, data);
|
||||
iterator i = priv_insert_commit(data, boost::move(val));
|
||||
d.release();
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -464,13 +460,12 @@ class flat_tree
|
||||
stored_allocator_type &a = this->get_stored_allocator(); \
|
||||
stored_allocator_traits::construct(a, &val \
|
||||
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
|
||||
scoped_destructor<stored_allocator_type> d(a, &val); \
|
||||
value_destructor<stored_allocator_type> d(a, val); \
|
||||
insert_commit_data data; \
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
|
||||
if(ret.second){ \
|
||||
ret.first = priv_insert_commit(data, boost::move(val)); \
|
||||
} \
|
||||
d.release(); \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
@@ -483,13 +478,12 @@ class flat_tree
|
||||
stored_allocator_type &a = this->get_stored_allocator(); \
|
||||
stored_allocator_traits::construct(a, &val \
|
||||
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
|
||||
scoped_destructor<stored_allocator_type> d(a, &val); \
|
||||
value_destructor<stored_allocator_type> d(a, val); \
|
||||
insert_commit_data data; \
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
|
||||
if(ret.second){ \
|
||||
ret.first = priv_insert_commit(data, boost::move(val)); \
|
||||
} \
|
||||
d.release(); \
|
||||
return ret.first; \
|
||||
} \
|
||||
\
|
||||
@@ -501,10 +495,9 @@ class flat_tree
|
||||
stored_allocator_type &a = this->get_stored_allocator(); \
|
||||
stored_allocator_traits::construct(a, &val \
|
||||
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
|
||||
scoped_destructor<stored_allocator_type> d(a, &val); \
|
||||
value_destructor<stored_allocator_type> d(a, val); \
|
||||
iterator i = this->upper_bound(KeyOfValue()(val)); \
|
||||
i = this->m_data.m_vect.insert(i, boost::move(val)); \
|
||||
d.release(); \
|
||||
return i; \
|
||||
} \
|
||||
\
|
||||
@@ -517,11 +510,10 @@ class flat_tree
|
||||
stored_allocator_type &a = this->get_stored_allocator(); \
|
||||
stored_allocator_traits::construct(a, &val \
|
||||
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
|
||||
scoped_destructor<stored_allocator_type> d(a, &val); \
|
||||
value_destructor<stored_allocator_type> d(a, val); \
|
||||
insert_commit_data data; \
|
||||
this->priv_insert_equal_prepare(hint, val, data); \
|
||||
iterator i = priv_insert_commit(data, boost::move(val)); \
|
||||
d.release(); \
|
||||
return i; \
|
||||
} \
|
||||
|
||||
|
@@ -745,12 +745,14 @@ class rbtree
|
||||
{
|
||||
value_type &v = p->get_data();
|
||||
insert_commit_data data;
|
||||
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(p, this->node_alloc());
|
||||
std::pair<iterator,bool> ret =
|
||||
this->insert_unique_check(KeyOfValue()(v), data);
|
||||
if(!ret.second){
|
||||
Destroyer(this->node_alloc())(p);
|
||||
return ret;
|
||||
}
|
||||
//No throw insertion part, release rollback
|
||||
destroy_deallocator.release();
|
||||
return std::pair<iterator,bool>
|
||||
( iterator(iiterator(this->icont().insert_unique_commit(*p, data)))
|
||||
, true );
|
||||
|
Reference in New Issue
Block a user