Use normal emplace implementation for emplace_hint and insert with hint.

There's a bug in the emplace_hint implementation for unordered
containers with equivalent keys. Since my tests missed it, I'm just
going to use the normal emplace implementation until I write better
tests.

[SVN r57005]
This commit is contained in:
Daniel James
2009-10-19 19:24:33 +00:00
parent 6c24cccf96
commit 8d4b503e56
4 changed files with 20 additions and 91 deletions

View File

@ -96,36 +96,6 @@ namespace boost { namespace unordered_detail {
}
}
template <class H, class P, class A, class K>
inline BOOST_DEDUCED_TYPENAME
hash_equivalent_table<H, P, A, K>::iterator_base
hash_equivalent_table<H, P, A, K>
::emplace_hint_impl(iterator_base const& it, node_constructor& a)
{
// equal can throw, but with no effects
if (!it.node_ || !equal(get_key(a.value()), *it)) {
// Use the standard emplace if the iterator doesn't point
// to a matching key.
return emplace_impl(a);
}
else {
// Find the first node in the group - so that the node
// will be added at the end of the group.
node_ptr start = node::first_in_group(it.node_);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
bucket_ptr bucket = this->reserve_for_insert(this->size_ + 1) ?
get_bucket(this->bucket_index(get_key(a.value()))) :
it.bucket_;
// Nothing after this point can throw
return iterator_base(bucket, add_node(a, bucket, start));
}
}
template <class H, class P, class A, class K>
inline void hash_equivalent_table<H, P, A, K>
::emplace_impl_no_rehash(node_constructor& a)
@ -156,25 +126,6 @@ namespace boost { namespace unordered_detail {
return emplace_impl(a);
}
// Emplace (equivalent key containers)
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
// if hash function throws, basic exception safety
// strong otherwise
template <class H, class P, class A, class K>
template <class... Args>
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
hash_equivalent_table<H, P, A, K>
::emplace_hint(iterator_base const& it, Args&&... args)
{
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(*this);
a.construct(std::forward<Args>(args)...);
return emplace_hint_impl(it, a);
}
#else
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
@ -187,18 +138,6 @@ namespace boost { namespace unordered_detail {
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
return emplace_impl(a); \
} \
\
template <class H, class P, class A, class K> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base \
hash_equivalent_table<H, P, A, K> \
::emplace_hint(iterator_base const& it, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
return emplace_hint_impl(it, a); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,

View File

@ -710,8 +710,6 @@ namespace boost { namespace unordered_detail {
// Insert methods
iterator_base emplace_impl(node_constructor& a);
iterator_base emplace_hint_impl(iterator_base const& it,
node_constructor& a);
void emplace_impl_no_rehash(node_constructor& a);
// equals
@ -725,18 +723,12 @@ namespace boost { namespace unordered_detail {
template <class... Args>
iterator_base emplace(Args&&... args);
template <class... Args>
iterator_base emplace_hint(iterator_base const& it, Args&&... args);
#else
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
iterator_base emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
\
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
iterator_base emplace_hint(iterator_base const& it, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
iterator_base emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_INSERT_IMPL, _)

View File

@ -311,7 +311,7 @@ namespace boost
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
iterator emplace_hint(const_iterator hint, \
iterator emplace_hint(const_iterator, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
) \
{ \
@ -332,7 +332,7 @@ namespace boost
table_.emplace(obj));
}
iterator insert(const_iterator hint, const value_type& obj)
iterator insert(const_iterator, const value_type& obj)
{
return iterator(table_.emplace(obj).first);
}
@ -776,10 +776,9 @@ namespace boost
}
template <class... Args>
iterator emplace_hint(const_iterator hint, Args&&... args)
iterator emplace_hint(const_iterator, Args&&... args)
{
return iterator(table_.emplace_hint(get(hint),
std::forward<Args>(args)...));
return iterator(table_.emplace(std::forward<Args>(args)...));
}
#else
@ -788,10 +787,10 @@ namespace boost
return iterator(table_.emplace(v));
}
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
value_type const& v = value_type())
{
return iterator(table_.emplace_hint(get(hint), v));
return iterator(table_.emplace(v));
}
@ -812,11 +811,11 @@ namespace boost
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
iterator emplace_hint(const_iterator hint, \
iterator emplace_hint(const_iterator, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
) \
{ \
return iterator(table_.emplace_hint(get(hint), \
return iterator(table_.emplace( \
BOOST_UNORDERED_CALL_PARAMS(z, n) \
)); \
}
@ -833,9 +832,9 @@ namespace boost
return iterator(table_.emplace(obj));
}
iterator insert(const_iterator hint, const value_type& obj)
iterator insert(const_iterator, const value_type& obj)
{
return iterator(table_.emplace_hint(get(hint), obj));
return iterator(table_.emplace(obj));
}
template <class InputIt>

View File

@ -326,7 +326,7 @@ namespace boost
table_.emplace(obj));
}
iterator insert(const_iterator hint, const value_type& obj)
iterator insert(const_iterator, const value_type& obj)
{
return iterator(table_.emplace(obj).first);
}
@ -735,10 +735,9 @@ namespace boost
}
template <class... Args>
iterator emplace_hint(const_iterator hint, Args&&... args)
iterator emplace_hint(const_iterator, Args&&... args)
{
return iterator(table_.emplace_hint(get(hint),
std::forward<Args>(args)...));
return iterator(table_.emplace(std::forward<Args>(args)...));
}
#else
@ -747,10 +746,10 @@ namespace boost
return iterator(table_.emplace(v));
}
iterator emplace_hint(const_iterator hint,
iterator emplace_hint(const_iterator,
value_type const& v = value_type())
{
return iterator(table_.emplace_hint(get(hint), v));
return iterator(table_.emplace(v));
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
@ -768,11 +767,11 @@ namespace boost
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
iterator emplace_hint(const_iterator hint, \
iterator emplace_hint(const_iterator, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
) \
{ \
return iterator(table_.emplace_hint(get(hint), \
return iterator(table_.emplace( \
BOOST_UNORDERED_CALL_PARAMS(z, n) \
)); \
}
@ -789,9 +788,9 @@ namespace boost
return iterator(table_.emplace(obj));
}
iterator insert(const_iterator hint, const value_type& obj)
iterator insert(const_iterator, const value_type& obj)
{
return iterator(table_.emplace_hint(get(hint), obj));
return iterator(table_.emplace(obj));
}
template <class InputIt>