diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index e7e7693..a6d7990 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -1942,15 +1942,18 @@ the same options explained in the section [section:advanced_lookups Advanced lookups] -[*Boost.Intrusive] associative containers offer the same interface as STL associative -containers. However, STL and TR1 ordered and unordered simple associative containers -(`std::set`, `std::multiset`, `std::tr1::unordered_set` and `std::tr1::unordered_multiset`) -have some inefficiencies caused by the interface: the user can only operate with `value_type` -objects. When using these containers we must use `iterator find(const value_type &value)` -to find a value. The same happens in other functions -like `equal_range`, `lower_bound`, `upper_bound`, etc. +[*Boost.Intrusive] associative containers offer an interface similar to STL associative +containers. However, STL's ordered and unordered simple associative containers +(`std::set`, `std::multiset`, `std::unordered_set` and `std::unordered_multiset`) +have some inefficiencies caused by the interface in several search functions +(`equal_range`, `lower_bound`, `upper_bound`, ...): the user can only operate with +`value_type` objects or (starting from C++11), +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3657.htm heterogeneous comparison lookups] +which are not flexible enough as `key_compare` shall support the comparison between the provided +key and `value_type`, avoiding the use of user-defined comparison objects that can partition the +search in advanced ways. -However, sometimes the object to be searched is quite expensive to construct: +Imagine that the object to be searched is quite expensive to construct: [import ../example/doc_assoc_optimized_code.cpp] [doc_assoc_optimized_code_normal_find] @@ -1968,15 +1971,16 @@ equivalent one. Sometimes this interface limitation is severe, because we [*might not have enough information to construct the object] but we might [*have enough information to find the object]. In this case, a name is enough -to search `Expensive` in the container but constructing an `Expensive` -might require more information that the user might not have. +to search `Expensive` in the container but constructing an `Expensive` object +might requires more information that the user might not have. -To solve this, [classref boost::intrusive::set set]/[classref boost::intrusive::multiset multiset] +To solve this, [*Boost.Intrusive] associative containers offer alternative functions, which take any type comparable with the value and a -functor that should be compatible with the -ordering function of the associative container. +functor that should be `compatible` +(the associative container must be also partitioned in regards to the supplied comparison type) +with container's predicate function (`key_compare`). [classref boost::intrusive::unordered_set unordered_set]/[classref boost::intrusive::unordered_multiset unordered_multiset] -offers functions that take any key type and compatible hash and equality functions. Now, let's see the +offer similar functions that take any key type, a compatible hash (the hash of the key) and a equality function. Now, let's see optimized search function: [doc_assoc_optimized_code_optimized_find] @@ -3819,6 +3823,16 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std [section:release_notes Release Notes] +[section:release_notes_boost_1_60_00 Boost 1.60 Release] + +* [link intrusive.advanced_lookups_insertions Advanced lookup and insertions] in ordered associative containers + now support comparison functions that are not required to offer the same strict weak ordering as `key_compare`, + the container must be partitioned in regards to the passed comparison object. +* Fixed bugs: + * [@https://svn.boost.org/trac/boost/ticket/11701 Boost Trac #11701: ['Regression in boost::intrusive::set::equal_range]] + +[endsect] + [section:release_notes_boost_1_59_00 Boost 1.59 Release] * Implemented [link intrusive.map_multimap map and multimap-like interfaces]. diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index c3d8d99..5c51e59 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -328,7 +328,7 @@ class avl_set_impl //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare) template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair @@ -339,7 +339,7 @@ class avl_set_impl template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) const - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED diff --git a/include/boost/intrusive/bs_set.hpp b/include/boost/intrusive/bs_set.hpp index a46ca38..2f560f5 100644 --- a/include/boost/intrusive/bs_set.hpp +++ b/include/boost/intrusive/bs_set.hpp @@ -325,7 +325,7 @@ class bs_set_impl //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare) template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)const std::pair @@ -336,7 +336,7 @@ class bs_set_impl template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) const - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index a995244..0934d86 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -1385,6 +1385,10 @@ class bstree_impl size_type erase(const key_type &key) { return this->erase(key, this->key_comp()); } + //! Requires: key is a value such that `*this` is partitioned with respect to + //! comp(nk, key) and !c(key, nk), with c(nk, key) implying !c(key, nk), + //! with nk the key_type of a value_type inserted into `*this`. + //! //! Effects: Erases all the elements with the given key. //! according to the comparison functor "comp". //! @@ -1465,6 +1469,10 @@ class bstree_impl iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) { size_type n; return this->private_erase(b, e, n, disposer); } + //! Requires: key is a value such that `*this` is partitioned with respect to + //! comp(nk, key) and !c(key, nk), with c(nk, key) implying !c(key, nk) + //! and nk the key_type of a value_type inserted into `*this`. + //! //! Requires: Disposer::operator()(pointer) shouldn't throw. //! //! Effects: Erases all the elements with the given key. @@ -1537,6 +1545,10 @@ class bstree_impl size_type count(const key_type &key) const { return size_type(this->count(key, this->key_comp())); } + //! Requires: key is a value such that `*this` is partitioned with respect to + //! comp(nk, key) and !c(key, nk), with c(nk, key) implying !c(key, nk), + //! and nk the key_type of a value_type inserted into `*this`. + //! //! Effects: Returns the number of contained elements with the given key //! //! Complexity: Logarithmic to the number of elements contained plus lineal @@ -1586,21 +1598,11 @@ class bstree_impl //! Throws: If `key_compare` throws. const_iterator lower_bound(const key_type &key) const; - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `comp` throws. + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &) template iterator lower_bound(const KeyType &key, KeyTypeKeyCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `comp` throws. + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare) template const_iterator lower_bound(const KeyType &key, KeyTypeKeyCompare comp) const; @@ -1612,6 +1614,9 @@ class bstree_impl //! Throws: If `key_compare` throws. iterator upper_bound(const key_type &key); + //! Requires: key is a value such that `*this` is partitioned with respect to + //! !comp(key, nk), with nk the key_type of a value_type inserted into `*this`. + //! //! Effects: Returns an iterator to the first element whose //! key is greater than k according to comp or end() if that element //! does not exist. @@ -1622,21 +1627,10 @@ class bstree_impl template iterator upper_bound(const KeyType &key, KeyTypeKeyCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `key_compare` throws. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &) const_iterator upper_bound(const key_type &key) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `comp` throws. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare) template const_iterator upper_bound(const KeyType &key, KeyTypeKeyCompare comp) const; @@ -1648,6 +1642,10 @@ class bstree_impl //! Throws: If `key_compare` throws. iterator find(const key_type &key); + //! Requires: key is a value such that `*this` is partitioned with respect to + //! comp(nk, key) and !c(key, nk), with c(nk, key) implying !c(key, nk), + //! and nk the key_type of a value_type inserted into `*this`. + //! //! Effects: Finds an iterator to the first element whose key is //! k or end() if that element does not exist. //! @@ -1657,20 +1655,10 @@ class bstree_impl template iterator find(const KeyType &key, KeyTypeKeyCompare comp); - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `key_compare` throws. + //! @copydoc ::boost::intrusive::bstree::find(const key_type &) const_iterator find(const key_type &key) const; - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `comp` throws. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare) template const_iterator find(const KeyType &key, KeyTypeKeyCompare comp) const; @@ -1683,6 +1671,10 @@ class bstree_impl //! Throws: If `key_compare` throws. std::pair equal_range(const key_type &key); + //! Requires: key is a value such that `*this` is partitioned with respect to + //! comp(nk, key) and !c(key, nk), with c(nk, key) implying !c(key, nk), + //! with nk the key_type of a value_type inserted into `*this`. + //! //! Effects: Finds a range containing all elements whose key is k or //! an empty range that indicates the position where those elements would be //! if they there is no elements with key k. @@ -1693,29 +1685,21 @@ class bstree_impl template std::pair equal_range(const KeyType &key, KeyTypeKeyCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `key_compare` throws. - std::pair - equal_range(const key_type &key) const; + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &) + std::pair equal_range(const key_type &key) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `comp` throws. + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare) template std::pair equal_range(const KeyType &key, KeyTypeKeyCompare comp) const; - //! Requires: 'lower_key' must not be greater than 'upper_key'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. + //! Requires: + //! `upper_key` shall not precede `lower_key` according to key_compare. + //! [key_comp()(upper_key, lower_key) shall be false] + //! + //! If `lower_key` is equivalent to `upper_key` + //! [!key_comp()(upper_key, lower_key) && !key_comp()(lower_key, upper_key)] then + //! ('left_closed' || 'right_closed') must be false. //! //! Effects: Returns an a pair with the following criteria: //! @@ -1734,11 +1718,19 @@ class bstree_impl std::pair bounded_range (const key_type &lower_key, const key_type &upper_value, bool left_closed, bool right_closed); - //! Requires: KeyTypeKeyCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the container. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. + //! Requires: + //! `lower_key` is a value such that `*this` is partitioned with respect to + //! comp(nk, lower_key) if left_closed is true, with respect to !comp(lower_key, nk) otherwise. + //! + //! `upper_key` is a value such that `*this` is partitioned with respect to + //! !comp(upper_key, nk) if right_closed is true, with respect to comp(nk, upper_key) otherwise. + //! + //! `upper_key` shall not precede `lower_key` according to comp + //! [comp(upper_key, lower_key) shall be false] + //! + //! If `lower_key` is equivalent to `upper_key` + //! [!comp(upper_key, lower_key) && !comp(lower_key, upper_key)] then + //! ('left_closed' || 'right_closed') must be false. //! //! Effects: Returns an a pair with the following criteria: //! @@ -1757,47 +1749,12 @@ class bstree_impl template std::pair bounded_range (const KeyType &lower_key, const KeyType &upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - - //! Requires: 'lower_key' must not be greater than 'upper_key'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `key_compare` throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. - //! - //! Note: Experimental function, the interface might change in future releases. + + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! Requires: KeyTypeKeyCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the container. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If `comp` throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. - //! - //! Note: Experimental function, the interface might change in future releases. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) template std::pair bounded_range (const KeyType &lower_key, const KeyType &upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index ae6a7a0..f0072ea 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -328,7 +328,7 @@ class set_impl //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare) template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair @@ -339,7 +339,7 @@ class set_impl template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) const - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED diff --git a/include/boost/intrusive/sg_set.hpp b/include/boost/intrusive/sg_set.hpp index 560845e..e6d4e37 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -326,7 +326,7 @@ class sg_set_impl //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare) template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair @@ -337,7 +337,7 @@ class sg_set_impl template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) const - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index eea19d7..3d43215 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -333,7 +333,7 @@ class splay_set_impl //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare) template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair @@ -344,7 +344,7 @@ class splay_set_impl template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) const - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index 188c80f..60cf449 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -375,7 +375,7 @@ class treap_set_impl //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare) template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair @@ -386,7 +386,7 @@ class treap_set_impl template std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp) const - { return this->tree_type::lower_bound_range(key, comp); } + { return this->tree_type::equal_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED