mirror of
https://github.com/boostorg/container.git
synced 2025-08-02 14:04:26 +02:00
Fix "count" with heterogeneous lookups in flat_map and flat_set
This commit is contained in:
@@ -1333,6 +1333,7 @@ use [*Boost.Container]? There are several reasons for that:
|
|||||||
* [@https://github.com/boostorg/container/issues/117 GitHub #117: ['"flat_map/map::insert_or_assign with hint has wrong return types"]].
|
* [@https://github.com/boostorg/container/issues/117 GitHub #117: ['"flat_map/map::insert_or_assign with hint has wrong return types"]].
|
||||||
* [@https://github.com/boostorg/container/issues/118 GitHub #118: ['"Non-unique inplace_set_difference used in in flat_tree_merge_unique and iterator invalidation in insert_unique"]].
|
* [@https://github.com/boostorg/container/issues/118 GitHub #118: ['"Non-unique inplace_set_difference used in in flat_tree_merge_unique and iterator invalidation in insert_unique"]].
|
||||||
* [@https://github.com/boostorg/container/issues/122 GitHub #122: ['"Fix has_trivial_destructor_after_move"]].
|
* [@https://github.com/boostorg/container/issues/122 GitHub #122: ['"Fix has_trivial_destructor_after_move"]].
|
||||||
|
* [@https://github.com/boostorg/container/issues/123 GitHub #123: ['"With heterogeneous lookup, `equal_range` can result in a range with length greater than 1"]].
|
||||||
|
|
||||||
* [classref boost::container::deque deque] can now have options, using [classref boost::container::deque_options deque_options].
|
* [classref boost::container::deque deque] can now have options, using [classref boost::container::deque_options deque_options].
|
||||||
The block size/bytes can be be specified.
|
The block size/bytes can be be specified.
|
||||||
|
@@ -1605,7 +1605,7 @@ class flat_tree
|
|||||||
const Compare &key_cmp = this->m_data.get_comp();
|
const Compare &key_cmp = this->m_data.get_comp();
|
||||||
KeyOfValue key_extract;
|
KeyOfValue key_extract;
|
||||||
RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
|
RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
|
||||||
if(lb != last && static_cast<difference_type>(!key_cmp(k, key_extract(*lb)))){
|
if(lb != last && !key_cmp(k, key_extract(*lb))){
|
||||||
++ub;
|
++ub;
|
||||||
}
|
}
|
||||||
return std::pair<RanIt, RanIt>(lb, ub);
|
return std::pair<RanIt, RanIt>(lb, ub);
|
||||||
|
@@ -1343,7 +1343,9 @@ class flat_map
|
|||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: log(size())+count(k)
|
//! <b>Complexity</b>: log(size())+count(k)
|
||||||
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
|
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
|
||||||
{ return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
|
//Don't use find() != end optimization here as transparent comparators with key K might
|
||||||
|
//return a different range than key_type (which can only return a single element range)
|
||||||
|
{ return m_flat_tree.count(x); }
|
||||||
|
|
||||||
//! <b>Requires</b>: This overload is available only if
|
//! <b>Requires</b>: This overload is available only if
|
||||||
//! key_compare::is_transparent exists.
|
//! key_compare::is_transparent exists.
|
||||||
@@ -1465,6 +1467,8 @@ class flat_map
|
|||||||
//! <b>Complexity</b>: Logarithmic.
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
template<class K>
|
template<class K>
|
||||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const K& x)
|
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const K& x)
|
||||||
|
//Don't use lower_bound_range optimization here as transparent comparators with key K might
|
||||||
|
//return a different range than key_type (which can only return a single element range)
|
||||||
{ return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
|
{ return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
|
||||||
|
|
||||||
//! <b>Requires</b>: This overload is available only if
|
//! <b>Requires</b>: This overload is available only if
|
||||||
@@ -1475,6 +1479,8 @@ class flat_map
|
|||||||
//! <b>Complexity</b>: Logarithmic.
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
template<class K>
|
template<class K>
|
||||||
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const K& x) const
|
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const K& x) const
|
||||||
|
//Don't use lower_bound_range optimization here as transparent comparators with key K might
|
||||||
|
//return a different range than key_type (which can only return a single element range)
|
||||||
{ return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
|
{ return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
|
||||||
|
|
||||||
//! <b>Effects</b>: Extracts the internal sequence container.
|
//! <b>Effects</b>: Extracts the internal sequence container.
|
||||||
|
@@ -925,7 +925,9 @@ class flat_set
|
|||||||
//! <b>Complexity</b>: log(size())+count(k)
|
//! <b>Complexity</b>: log(size())+count(k)
|
||||||
template<typename K>
|
template<typename K>
|
||||||
BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
|
BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
|
||||||
{ return static_cast<size_type>(this->tree_t::find(x) != this->tree_t::cend()); }
|
//Don't use find() != end optimization here as transparent comparators with key K might
|
||||||
|
//return a different range than key_type (which can only return a single element range)
|
||||||
|
{ return this->tree_t::count(x); }
|
||||||
|
|
||||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||||
|
|
||||||
@@ -1031,6 +1033,8 @@ class flat_set
|
|||||||
//! <b>Complexity</b>: Logarithmic
|
//! <b>Complexity</b>: Logarithmic
|
||||||
template<typename K>
|
template<typename K>
|
||||||
std::pair<iterator,iterator> equal_range(const K& x)
|
std::pair<iterator,iterator> equal_range(const K& x)
|
||||||
|
//Don't use lower_bound_range optimization here as transparent comparators with key K might
|
||||||
|
//return a different range than key_type (which can only return a single element range)
|
||||||
{ return this->tree_t::equal_range(x); }
|
{ return this->tree_t::equal_range(x); }
|
||||||
|
|
||||||
//! <b>Requires</b>: This overload is available only if
|
//! <b>Requires</b>: This overload is available only if
|
||||||
@@ -1041,6 +1045,8 @@ class flat_set
|
|||||||
//! <b>Complexity</b>: Logarithmic
|
//! <b>Complexity</b>: Logarithmic
|
||||||
template<typename K>
|
template<typename K>
|
||||||
std::pair<const_iterator,const_iterator> equal_range(const K& x) const
|
std::pair<const_iterator,const_iterator> equal_range(const K& x) const
|
||||||
|
//Don't use lower_bound_range optimization here as transparent comparators with key K might
|
||||||
|
//return a different range than key_type (which can only return a single element range)
|
||||||
{ return this->tree_t::equal_range(x); }
|
{ return this->tree_t::equal_range(x); }
|
||||||
|
|
||||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||||
|
@@ -589,7 +589,12 @@ bool test_heterogeneous_lookup_by_partial_key()
|
|||||||
|
|
||||||
std::pair<map_t::iterator, map_t::iterator> const first_0_range = map1.equal_range(0);
|
std::pair<map_t::iterator, map_t::iterator> const first_0_range = map1.equal_range(0);
|
||||||
|
|
||||||
return 2 == first_0_range.second - first_0_range.first;
|
if(2 != (first_0_range.second - first_0_range.first))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(2 != map1.count(0))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}}} //namespace boost::container::test
|
}}} //namespace boost::container::test
|
||||||
|
@@ -604,8 +604,12 @@ bool test_heterogeneous_lookup_by_partial_key()
|
|||||||
set1.insert(std::pair<int, int>(0, 2));
|
set1.insert(std::pair<int, int>(0, 2));
|
||||||
|
|
||||||
std::pair<set_t::iterator, set_t::iterator> const first_0_range = set1.equal_range(0);
|
std::pair<set_t::iterator, set_t::iterator> const first_0_range = set1.equal_range(0);
|
||||||
|
if(2 != (first_0_range.second - first_0_range.first))
|
||||||
|
return false;
|
||||||
|
|
||||||
return 2 == first_0_range.second - first_0_range.first;
|
if(2 != set1.count(0))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
Reference in New Issue
Block a user