Implemented unique associative containers' equal_range using lower_bound_range which is more efficient with heavy comparison functions.

Updated benchmark to avoid measuring redundant operations in searches.
This commit is contained in:
Ion Gaztañaga
2014-01-20 13:20:02 +01:00
parent abc50c7275
commit a4b839628a
6 changed files with 90 additions and 36 deletions
@@ -743,6 +743,12 @@ class flat_tree
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
{ return this->priv_equal_range(this->cbegin(), this->cend(), k); }
std::pair<iterator, iterator> lower_bound_range(const key_type& k)
{ return this->priv_lower_bound_range(this->begin(), this->end(), k); }
std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
{ return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
size_type capacity() const
{ return this->m_data.m_vect.capacity(); }
@@ -958,6 +964,18 @@ class flat_tree
return std::pair<RanIt, RanIt>(first, first);
}
template<class RanIt>
std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const key_type& k) const
{
const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
if(lb != last && static_cast<difference_type>(!key_cmp(k, key_extract(*lb)))){
++ub;
}
return std::pair<RanIt, RanIt>(lb, ub);
}
template<class InIt>
void priv_insert_equal_loop(InIt first, InIt last)
{
+17 -1
View File
@@ -1071,7 +1071,8 @@ class tree
void clear()
{ AllocHolder::clear(alloc_version()); }
// set operations:
// search operations. Const and non-const overloads even if no iterator is returned
// so splay implementations can to their rebalancing when searching in non-const versions
iterator find(const key_type& k)
{ return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); }
@@ -1108,6 +1109,21 @@ class tree
(const_iterator(ret.first), const_iterator(ret.second));
}
std::pair<iterator,iterator> lower_bound_range(const key_type& k)
{
std::pair<iiterator, iiterator> ret =
this->icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
}
std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
{
std::pair<iiterator, iiterator> ret =
this->non_const_icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
return std::pair<const_iterator,const_iterator>
(const_iterator(ret.first), const_iterator(ret.second));
}
void rebalance()
{ intrusive_tree_proxy_t::rebalance(this->icont()); }
+2 -2
View File
@@ -857,13 +857,13 @@ class flat_map
//!
//! <b>Complexity</b>: Logarithmic
std::pair<iterator,iterator> equal_range(const key_type& x)
{ return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
{ return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
//! <b>Effects</b>: Returns true if x and y are equal
//!
+2 -15
View File
@@ -604,30 +604,17 @@ class flat_set
#endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{
const_iterator lb = this->lower_bound(x), ub(lb);
if(lb != this->cend() && static_cast<difference_type>(!this->key_comp()(x, *lb))){
++ub;
}
return std::pair<const_iterator, const_iterator>(lb, ub);
}
{ return this->base_t::lower_bound_range(x); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<iterator,iterator> equal_range(const key_type& x)
{
iterator lb = this->lower_bound(x), ub(lb);
if(lb != this->end() && static_cast<difference_type>(!this->key_comp()(x, *lb))){
++ub;
}
return std::pair<iterator, iterator>(lb, ub);
}
{ return this->base_t::lower_bound_range(x); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+16
View File
@@ -540,6 +540,22 @@ class set
//! <b>Complexity</b>: Logarithmic
const_iterator upper_bound(const key_type& x) const;
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<iterator,iterator> equal_range(const key_type& x)
{ return this->base_t::lower_bound_range(x); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return this->base_t::lower_bound_range(x); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic