From 71d216b90256936a9638f325af9bc69d720e75de Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Thu, 6 Oct 2016 10:30:07 +0900 Subject: Imported Upstream version 1.59.0 Change-Id: I2dde00f4eca71df3eea9d251dcaecde18a6c90a5 Signed-off-by: DongHun Kwak --- boost/intrusive/avl_set.hpp | 390 ++-- boost/intrusive/avltree.hpp | 232 +- boost/intrusive/bs_set.hpp | 390 ++-- boost/intrusive/bstree.hpp | 648 +++--- boost/intrusive/bstree_algorithms.hpp | 4 - boost/intrusive/detail/common_slist_algorithms.hpp | 2 +- boost/intrusive/detail/default_header_holder.hpp | 8 +- boost/intrusive/detail/ebo_functor_holder.hpp | 1 + boost/intrusive/detail/get_value_traits.hpp | 6 +- boost/intrusive/detail/hashtable_node.hpp | 69 +- .../intrusive/detail/is_stateful_value_traits.hpp | 2 +- boost/intrusive/detail/iterator.hpp | 8 + boost/intrusive/detail/key_nodeptr_comp.hpp | 28 +- boost/intrusive/detail/list_iterator.hpp | 2 +- boost/intrusive/detail/math.hpp | 8 +- boost/intrusive/detail/mpl.hpp | 320 +-- boost/intrusive/detail/node_cloner_disposer.hpp | 41 +- boost/intrusive/detail/reverse_iterator.hpp | 33 +- boost/intrusive/detail/slist_iterator.hpp | 2 +- boost/intrusive/detail/std_fwd.hpp | 6 +- boost/intrusive/detail/transform_iterator.hpp | 13 +- boost/intrusive/detail/tree_iterator.hpp | 6 +- boost/intrusive/detail/tree_value_compare.hpp | 78 + boost/intrusive/hashtable.hpp | 2320 +++++++++++--------- boost/intrusive/intrusive_fwd.hpp | 18 + boost/intrusive/list.hpp | 167 +- boost/intrusive/options.hpp | 11 +- boost/intrusive/rbtree.hpp | 236 +- boost/intrusive/rbtree_algorithms.hpp | 4 +- boost/intrusive/set.hpp | 390 ++-- boost/intrusive/sg_set.hpp | 390 ++-- boost/intrusive/sgtree.hpp | 287 ++- boost/intrusive/slist.hpp | 206 +- boost/intrusive/splay_set.hpp | 416 ++-- boost/intrusive/splaytree.hpp | 255 +-- boost/intrusive/treap.hpp | 395 ++-- boost/intrusive/treap_set.hpp | 398 ++-- boost/intrusive/unordered_set.hpp | 1917 ++++------------ 38 files changed, 4372 insertions(+), 5335 deletions(-) create mode 100644 boost/intrusive/detail/tree_value_compare.hpp (limited to 'boost/intrusive') diff --git a/boost/intrusive/avl_set.hpp b/boost/intrusive/avl_set.hpp index d06d441a19..c3d8d999ac 100644 --- a/boost/intrusive/avl_set.hpp +++ b/boost/intrusive/avl_set.hpp @@ -40,15 +40,15 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class avl_set_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public bstree_impl + : public bstree_impl #endif { /// @cond - typedef bstree_impl tree_type; + typedef bstree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_set_impl) typedef tree_type implementation_defined; @@ -56,6 +56,8 @@ class avl_set_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -80,16 +82,16 @@ class avl_set_impl public: - //! @copydoc ::boost::intrusive::avltree::avltree(const value_compare &,const value_traits &) - explicit avl_set_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::avltree::avltree(const key_compare &,const value_traits &) + explicit avl_set_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::avltree::avltree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::avltree::avltree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template avl_set_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(true, b, e, cmp, v_traits) {} @@ -171,11 +173,20 @@ class avl_set_impl //! @copydoc ::boost::intrusive::avltree::swap void swap(avl_set_impl& other); - //! @copydoc ::boost::intrusive::avltree::clone_from + //! @copydoc ::boost::intrusive::avltree::clone_from(const avltree&,Cloner,Disposer) template void clone_from(const avl_set_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::avltree::clone_from(avltree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(avl_set_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::avltree::insert_unique(reference) std::pair insert(reference value) @@ -185,18 +196,18 @@ class avl_set_impl iterator insert(const_iterator hint, reference value) { return tree_type::insert_unique(hint, value); } - //! @copydoc ::boost::intrusive::avltree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::avltree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(key, comp, commit_data); } - //! @copydoc ::boost::intrusive::avltree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::avltree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(hint, key, comp, commit_data); } //! @copydoc ::boost::intrusive::avltree::insert_unique(Iterator,Iterator) template @@ -223,12 +234,12 @@ class avl_set_impl //! @copydoc ::boost::intrusive::avltree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::avltree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::avltree::erase(const key_type &key) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::avltree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::avltree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,Disposer) template @@ -238,13 +249,13 @@ class avl_set_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::avltree::clear void clear(); @@ -255,100 +266,100 @@ class avl_set_impl #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::avltree::count(const_reference)const - size_type count(const_reference value) const - { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } + //! @copydoc ::boost::intrusive::avltree::count(const key_type &)const + size_type count(const key_type &key) const + { return static_cast(this->tree_type::find(key) != this->tree_type::cend()); } - //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const + //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::avltree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::avltree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::avltree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::avltree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::avltree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::avltree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::avltree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::avltree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) - std::pair equal_range(const_reference value) - { return this->tree_type::lower_bound_range(value); } + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &) + std::pair equal_range(const key_type &key) + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) + //! @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); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const - { return this->tree_type::lower_bound_range(value); } + equal_range(const key_type &key) const + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const { return this->tree_type::lower_bound_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::avltree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::avltree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::avltree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -402,7 +413,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_avl_set { @@ -410,7 +421,7 @@ struct make_avl_set typedef typename pack_options < avltree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -421,6 +432,7 @@ struct make_avl_set typedef avl_set_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -432,14 +444,14 @@ struct make_avl_set #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class avl_set : public make_avl_set::value)); - explicit avl_set( const value_compare &cmp = value_compare() + explicit avl_set( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template avl_set( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -483,6 +495,14 @@ class avl_set avl_set& operator=(BOOST_RV_REF(avl_set) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const avl_set &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(avl_set) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static avl_set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -512,15 +532,15 @@ class avl_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class avl_multiset_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public bstree_impl + : public bstree_impl #endif { /// @cond - typedef bstree_impl tree_type; + typedef bstree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_multiset_impl) typedef tree_type implementation_defined; @@ -528,6 +548,8 @@ class avl_multiset_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -551,16 +573,16 @@ class avl_multiset_impl static const bool constant_time_size = tree_type::constant_time_size; public: - //! @copydoc ::boost::intrusive::avltree::avltree(const value_compare &,const value_traits &) - explicit avl_multiset_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::avltree::avltree(const key_compare &,const value_traits &) + explicit avl_multiset_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::avltree::avltree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::avltree::avltree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template avl_multiset_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(false, b, e, cmp, v_traits) {} @@ -641,11 +663,20 @@ class avl_multiset_impl //! @copydoc ::boost::intrusive::avltree::swap void swap(avl_multiset_impl& other); - //! @copydoc ::boost::intrusive::avltree::clone_from + //! @copydoc ::boost::intrusive::avltree::clone_from(const avltree&,Cloner,Disposer) template void clone_from(const avl_multiset_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::avltree::clone_from(avltree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(avl_multiset_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::avltree::insert_equal(reference) iterator insert(reference value) @@ -676,12 +707,12 @@ class avl_multiset_impl //! @copydoc ::boost::intrusive::avltree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::avltree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::avltree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::avltree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::avltree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,Disposer) template @@ -691,13 +722,13 @@ class avl_multiset_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::avltree::clear void clear(); @@ -706,88 +737,88 @@ class avl_multiset_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::avltree::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::avltree::count(const key_type &)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::avltree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::avltree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::avltree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::avltree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::avltree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::avltree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::avltree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::avltree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::avltree::equal_range(const key_type &) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::avltree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::avltree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::avltree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &key upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::avltree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -841,7 +872,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_avl_multiset { @@ -849,7 +880,7 @@ struct make_avl_multiset typedef typename pack_options < avltree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -860,6 +891,7 @@ struct make_avl_multiset typedef avl_multiset_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -872,14 +904,14 @@ struct make_avl_multiset #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class avl_multiset : public make_avl_multiset::value)); - explicit avl_multiset( const value_compare &cmp = value_compare() + explicit avl_multiset( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template avl_multiset( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -923,6 +955,14 @@ class avl_multiset avl_multiset& operator=(BOOST_RV_REF(avl_multiset) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const avl_multiset &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(avl_multiset) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static avl_multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/avltree.hpp b/boost/intrusive/avltree.hpp index 1996d69c68..8462293d6f 100644 --- a/boost/intrusive/avltree.hpp +++ b/boost/intrusive/avltree.hpp @@ -48,19 +48,16 @@ struct is_default_hook_tag { static const bool value = true; }; struct avltree_defaults + : bstree_defaults { typedef default_avltree_hook_applier proto_value_traits; - static const bool constant_time_size = true; - typedef std::size_t size_type; - typedef void compare; - typedef void header_holder_type; }; /// @endcond //! The class template avltree is an intrusive AVL tree container, that //! is used to construct intrusive avl_set and avl_multiset containers. -//! The no-throw guarantee holds only, if the value_compare object +//! The no-throw guarantee holds only, if the key_compare object //! doesn't throw. //! //! The template parameter \c T is the type to be managed by the container. @@ -74,17 +71,17 @@ struct avltree_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class avltree_impl /// @cond - : public bstree_impl + : public bstree_impl /// @endcond { public: typedef ValueTraits value_traits; /// @cond - typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType + typedef bstree_impl< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType , ConstantTimeSize, AvlTreeAlgorithms , HeaderHolder> tree_type; typedef tree_type implementation_defined; @@ -94,6 +91,7 @@ class avltree_impl typedef typename implementation_defined::const_pointer const_pointer; typedef typename implementation_defined::value_type value_type; typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::reference reference; typedef typename implementation_defined::const_reference const_reference; typedef typename implementation_defined::difference_type difference_type; @@ -124,16 +122,16 @@ class avltree_impl typedef typename implementation_defined::insert_commit_data insert_commit_data; - //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) - explicit avltree_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &) + explicit avltree_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template avltree_impl( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(unique, b, e, cmp, v_traits) {} @@ -215,10 +213,23 @@ class avltree_impl //! @copydoc ::boost::intrusive::bstree::swap void swap(avltree_impl& other); - //! @copydoc ::boost::intrusive::bstree::clone_from + //! @copydoc ::boost::intrusive::bstree::clone_from(const bstree&,Cloner,Disposer) template void clone_from(const avltree_impl &src, Cloner cloner, Disposer disposer); + #else //BOOST_INTRUSIVE_DOXYGEN_INVOKED + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree::clone_from(bstree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(avltree_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) iterator insert_equal(reference value); @@ -235,16 +246,16 @@ class avltree_impl //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference) iterator insert_unique(const_iterator hint, reference value); - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_unique_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data); + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data); - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_unique_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data); + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data); //! @copydoc ::boost::intrusive::bstree::insert_unique_commit iterator insert_unique_commit(reference value, const insert_commit_data &commit_data); @@ -268,12 +279,12 @@ class avltree_impl //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::bstree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::bstree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) template @@ -283,13 +294,13 @@ class avltree_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::bstree::clear void clear(); @@ -298,88 +309,88 @@ class avltree_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::count(const key_type &ke)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &key) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::bstree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @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, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -404,33 +415,23 @@ class avltree_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED -}; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + friend bool operator< (const avltree_impl &x, const avltree_impl &y); -template -bool operator< (const avltree_impl &x, const avltree_impl &y); + friend bool operator==(const avltree_impl &x, const avltree_impl &y); -template -bool operator==(const avltree_impl &x, const avltree_impl &y); + friend bool operator!= (const avltree_impl &x, const avltree_impl &y); -template -bool operator!= (const avltree_impl &x, const avltree_impl &y); - -template -bool operator>(const avltree_impl &x, const avltree_impl &y); + friend bool operator>(const avltree_impl &x, const avltree_impl &y); -template -bool operator<=(const avltree_impl &x, const avltree_impl &y); + friend bool operator<=(const avltree_impl &x, const avltree_impl &y); -template -bool operator>=(const avltree_impl &x, const avltree_impl &y); + friend bool operator>=(const avltree_impl &x, const avltree_impl &y); -template -void swap(avltree_impl &x, avltree_impl &y); + friend void swap(avltree_impl &x, avltree_impl &y); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +}; -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c avltree that yields to the same type when the //! same options (either explicitly or implicitly) are used. @@ -439,7 +440,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_avltree { @@ -447,7 +448,7 @@ struct make_avltree typedef typename pack_options < avltree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -458,6 +459,7 @@ struct make_avltree typedef avltree_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -471,14 +473,14 @@ struct make_avltree #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class avltree : public make_avltree::value)); - explicit avltree( const value_compare &cmp = value_compare() + explicit avltree( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template avltree( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(unique, b, e, cmp, v_traits) {} @@ -524,6 +526,14 @@ class avltree avltree& operator=(BOOST_RV_REF(avltree) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const avltree &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(avltree) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static avltree &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/bs_set.hpp b/boost/intrusive/bs_set.hpp index f246ce606d..a46ca38a01 100644 --- a/boost/intrusive/bs_set.hpp +++ b/boost/intrusive/bs_set.hpp @@ -40,15 +40,15 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class bs_set_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public bstree_impl + : public bstree_impl #endif { /// @cond - typedef bstree_impl tree_type; + typedef bstree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_set_impl) typedef tree_type implementation_defined; @@ -56,6 +56,7 @@ class bs_set_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -79,16 +80,16 @@ class bs_set_impl static const bool constant_time_size = tree_type::constant_time_size; public: - //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) - explicit bs_set_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &) + explicit bs_set_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template bs_set_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(true, b, e, cmp, v_traits) {} @@ -169,11 +170,20 @@ class bs_set_impl //! @copydoc ::boost::intrusive::bstree::swap void swap(bs_set_impl& other); - //! @copydoc ::boost::intrusive::bstree::clone_from + //! @copydoc ::boost::intrusive::bstree::clone_from(const bstree&,Cloner,Disposer) template void clone_from(const bs_set_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree::clone_from(bstree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(bs_set_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::bstree::insert_unique(reference) std::pair insert(reference value) @@ -183,18 +193,18 @@ class bs_set_impl iterator insert(const_iterator hint, reference value) { return tree_type::insert_unique(hint, value); } - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(key, comp, commit_data); } - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(hint, key, comp, commit_data); } //! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator) template @@ -221,12 +231,12 @@ class bs_set_impl //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::bstree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::bstree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) template @@ -236,13 +246,13 @@ class bs_set_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::bstree::clear void clear(); @@ -253,100 +263,100 @@ class bs_set_impl #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - size_type count(const_reference value) const - { return static_cast(this->tree_type::find(value) == this->tree_type::cend()); } + //! @copydoc ::boost::intrusive::bstree::count(const key_type &)const + size_type count(const key_type &key) const + { return static_cast(this->tree_type::find(key) != this->tree_type::cend()); } - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const - { return static_cast(this->tree_type::find(key, comp) == this->tree_type::cend()); } + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &) + iterator lower_bound(const key_type &); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::bstree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) - std::pair equal_range(const_reference value) - { return this->tree_type::lower_bound_range(value); } + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &) + std::pair equal_range(const key_type &key) + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) + //! @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); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const - { return this->tree_type::lower_bound_range(value); } + equal_range(const key_type &key) const + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const { return this->tree_type::lower_bound_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type&,const key_type&,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type& lower_key, const key_type& upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @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, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type&,const key_type&,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type& lower_key, const key_type& upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -400,7 +410,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_bs_set { @@ -408,7 +418,7 @@ struct make_bs_set typedef typename pack_options < bstree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -419,6 +429,7 @@ struct make_bs_set typedef bs_set_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -430,14 +441,14 @@ struct make_bs_set #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class bs_set : public make_bs_set::value)); - explicit bs_set( const value_compare &cmp = value_compare() + explicit bs_set( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template bs_set( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -481,6 +492,14 @@ class bs_set bs_set& operator=(BOOST_RV_REF(bs_set) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const bs_set &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(bs_set) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static bs_set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -510,15 +529,15 @@ class bs_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class bs_multiset_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public bstree_impl + : public bstree_impl #endif { /// @cond - typedef bstree_impl tree_type; + typedef bstree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_multiset_impl) typedef tree_type implementation_defined; @@ -526,6 +545,7 @@ class bs_multiset_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -549,16 +569,16 @@ class bs_multiset_impl static const bool constant_time_size = tree_type::constant_time_size; public: - //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) - explicit bs_multiset_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &) + explicit bs_multiset_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template bs_multiset_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(false, b, e, cmp, v_traits) {} @@ -639,11 +659,20 @@ class bs_multiset_impl //! @copydoc ::boost::intrusive::bstree::swap void swap(bs_multiset_impl& other); - //! @copydoc ::boost::intrusive::bstree::clone_from + //! @copydoc ::boost::intrusive::bstree::clone_from(const bstree&,Cloner,Disposer) template void clone_from(const bs_multiset_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree::clone_from(bstree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(bs_multiset_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) iterator insert(reference value) @@ -674,12 +703,12 @@ class bs_multiset_impl //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::bstree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::bstree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) template @@ -689,13 +718,13 @@ class bs_multiset_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::bstree::clear void clear(); @@ -704,88 +733,88 @@ class bs_multiset_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::count(const key_type &)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::bstree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type & lower_key, const key_type & upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @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, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type & lower_key, const key_type & upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -839,7 +868,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_bs_multiset { @@ -847,7 +876,7 @@ struct make_bs_multiset typedef typename pack_options < bstree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -858,6 +887,7 @@ struct make_bs_multiset typedef bs_multiset_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -870,14 +900,14 @@ struct make_bs_multiset #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class bs_multiset : public make_bs_multiset::value)); - explicit bs_multiset( const value_compare &cmp = value_compare() + explicit bs_multiset( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template bs_multiset( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -921,6 +951,14 @@ class bs_multiset bs_multiset& operator=(BOOST_RV_REF(bs_multiset) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const bs_multiset &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(bs_multiset) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static bs_multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/bstree.hpp b/boost/intrusive/bstree.hpp index 39c9d3ed2a..7a67de6e12 100644 --- a/boost/intrusive/bstree.hpp +++ b/boost/intrusive/bstree.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,7 @@ struct bstree_defaults static const bool constant_time_size = true; typedef std::size_t size_type; typedef void compare; + typedef void key_of_value; static const bool floating_point = true; //For sgtree typedef void priority; //For treap typedef void header_holder_type; @@ -90,7 +92,6 @@ struct bstbase3 typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::pointer) pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::const_pointer) const_pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; - typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) const_reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::difference_type) difference_type; @@ -239,28 +240,62 @@ struct get_compare typedef ::std::less type; }; -template +template +struct get_key_of_value +{ + typedef KeyOfValue type; +}; + +template +struct get_key_of_value +{ + typedef ::boost::intrusive::detail::identity type; +}; + +template +struct bst_key_types +{ + typedef typename get_key_of_value + < VoidOrKeyOfValue, T>::type key_of_value; + typedef typename key_of_value::type key_type; + typedef typename get_compare< VoidOrKeyComp + , key_type + >::type key_compare; + typedef tree_value_compare + value_compare; +}; + +template struct bstbase2 //Put the (possibly empty) functor in the first position to get EBO in MSVC //Use public inheritance to avoid MSVC bugs with closures - : public detail::ebo_functor_holder::type> + : public detail::ebo_functor_holder + < typename bst_key_types + < typename ValueTraits::value_type + , VoidOrKeyOfValue + , VoidOrKeyComp + >::value_compare + > , public bstbase3 { typedef bstbase3 treeheader_t; + typedef bst_key_types< typename ValueTraits::value_type + , VoidOrKeyOfValue + , VoidOrKeyComp> key_types; typedef typename treeheader_t::value_traits value_traits; typedef typename treeheader_t::node_algorithms node_algorithms; - typedef typename get_compare - < VoidOrKeyComp, typename value_traits::value_type>::type value_compare; - typedef BOOST_INTRUSIVE_IMPDEF(value_compare) key_compare; + typedef typename ValueTraits::value_type value_type; + typedef typename key_types::key_type key_type; + typedef typename key_types::key_of_value key_of_value; + typedef typename key_types::key_compare key_compare; + typedef typename key_types::value_compare value_compare; typedef typename treeheader_t::iterator iterator; typedef typename treeheader_t::const_iterator const_iterator; typedef typename treeheader_t::node_ptr node_ptr; typedef typename treeheader_t::const_node_ptr const_node_ptr; - bstbase2(const value_compare &comp, const ValueTraits &vtraits) - : detail::ebo_functor_holder(comp), treeheader_t(vtraits) + bstbase2(const key_compare &comp, const ValueTraits &vtraits) + : detail::ebo_functor_holder(value_compare(comp)), treeheader_t(vtraits) {} const value_compare &comp() const @@ -271,8 +306,6 @@ struct bstbase2 typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::pointer) pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::const_pointer) const_pointer; - typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; - typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) const_reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::difference_type) difference_type; @@ -282,203 +315,181 @@ struct bstbase2 { return this->comp(); } key_compare key_comp() const - { return this->comp(); } + { return this->comp().key_comp(); } //lower_bound - iterator lower_bound(const_reference value) - { return this->lower_bound(value, this->comp()); } + iterator lower_bound(const key_type &key) + { return this->lower_bound(key, this->key_comp()); } - const_iterator lower_bound(const_reference value) const - { return this->lower_bound(value, this->comp()); } + const_iterator lower_bound(const key_type &key) const + { return this->lower_bound(key, this->key_comp()); } - template - iterator lower_bound(const KeyType &key, KeyValueCompare comp) + template + iterator lower_bound(const KeyType &key, KeyTypeKeyCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); return iterator(node_algorithms::lower_bound - (this->header_ptr(), key, key_node_comp), this->priv_value_traits_ptr()); + (this->header_ptr(), key, this->key_node_comp(comp)), this->priv_value_traits_ptr()); } - template - const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const + template + const_iterator lower_bound(const KeyType &key, KeyTypeKeyCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); return const_iterator(node_algorithms::lower_bound - (this->header_ptr(), key, key_node_comp), this->priv_value_traits_ptr()); + (this->header_ptr(), key, this->key_node_comp(comp)), this->priv_value_traits_ptr()); } //upper_bound - iterator upper_bound(const_reference value) - { return this->upper_bound(value, this->comp()); } + iterator upper_bound(const key_type &key) + { return this->upper_bound(key, this->key_comp()); } - template - iterator upper_bound(const KeyType &key, KeyValueCompare comp) + template + iterator upper_bound(const KeyType &key, KeyTypeKeyCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); return iterator(node_algorithms::upper_bound - (this->header_ptr(), key, key_node_comp), this->priv_value_traits_ptr()); + (this->header_ptr(), key, this->key_node_comp(comp)), this->priv_value_traits_ptr()); } - const_iterator upper_bound(const_reference value) const - { return this->upper_bound(value, this->comp()); } + const_iterator upper_bound(const key_type &key) const + { return this->upper_bound(key, this->key_comp()); } - template - const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const + template + const_iterator upper_bound(const KeyType &key, KeyTypeKeyCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); return const_iterator(node_algorithms::upper_bound - (this->header_ptr(), key, key_node_comp), this->priv_value_traits_ptr()); + (this->header_ptr(), key, this->key_node_comp(comp)), this->priv_value_traits_ptr()); + } + + template + detail::key_nodeptr_comp key_node_comp(KeyTypeKeyCompare comp) const + { + return detail::key_nodeptr_comp(comp, &this->get_value_traits()); } //find - iterator find(const_reference value) - { return this->find(value, this->comp()); } + iterator find(const key_type &key) + { return this->find(key, this->key_comp()); } - template - iterator find(const KeyType &key, KeyValueCompare comp) + template + iterator find(const KeyType &key, KeyTypeKeyCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); return iterator - (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->priv_value_traits_ptr()); + (node_algorithms::find(this->header_ptr(), key, this->key_node_comp(comp)), this->priv_value_traits_ptr()); } - const_iterator find(const_reference value) const - { return this->find(value, this->comp()); } + const_iterator find(const key_type &key) const + { return this->find(key, this->key_comp()); } - template - const_iterator find(const KeyType &key, KeyValueCompare comp) const + template + const_iterator find(const KeyType &key, KeyTypeKeyCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); return const_iterator - (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->priv_value_traits_ptr()); + (node_algorithms::find(this->header_ptr(), key, this->key_node_comp(comp)), this->priv_value_traits_ptr()); } //equal_range - std::pair equal_range(const_reference value) - { return this->equal_range(value, this->comp()); } + std::pair equal_range(const key_type &key) + { return this->equal_range(key, this->key_comp()); } - template - std::pair equal_range(const KeyType &key, KeyValueCompare comp) + template + std::pair equal_range(const KeyType &key, KeyTypeKeyCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); std::pair ret - (node_algorithms::equal_range(this->header_ptr(), key, key_node_comp)); + (node_algorithms::equal_range(this->header_ptr(), key, this->key_node_comp(comp))); return std::pair( iterator(ret.first, this->priv_value_traits_ptr()) , iterator(ret.second, this->priv_value_traits_ptr())); } std::pair - equal_range(const_reference value) const - { return this->equal_range(value, this->comp()); } + equal_range(const key_type &key) const + { return this->equal_range(key, this->key_comp()); } - template + template std::pair - equal_range(const KeyType &key, KeyValueCompare comp) const + equal_range(const KeyType &key, KeyTypeKeyCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); std::pair ret - (node_algorithms::equal_range(this->header_ptr(), key, key_node_comp)); + (node_algorithms::equal_range(this->header_ptr(), key, this->key_node_comp(comp))); return std::pair( const_iterator(ret.first, this->priv_value_traits_ptr()) , const_iterator(ret.second, this->priv_value_traits_ptr())); } //lower_bound_range - std::pair lower_bound_range(const_reference value) - { return this->lower_bound_range(value, this->comp()); } + std::pair lower_bound_range(const key_type &key) + { return this->lower_bound_range(key, this->key_comp()); } - template - std::pair lower_bound_range(const KeyType &key, KeyValueCompare comp) + template + std::pair lower_bound_range(const KeyType &key, KeyTypeKeyCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); std::pair ret - (node_algorithms::lower_bound_range(this->header_ptr(), key, key_node_comp)); + (node_algorithms::lower_bound_range(this->header_ptr(), key, this->key_node_comp(comp))); return std::pair( iterator(ret.first, this->priv_value_traits_ptr()) , iterator(ret.second, this->priv_value_traits_ptr())); } std::pair - lower_bound_range(const_reference value) const - { return this->lower_bound_range(value, this->comp()); } + lower_bound_range(const key_type &key) const + { return this->lower_bound_range(key, this->key_comp()); } - template + template std::pair - lower_bound_range(const KeyType &key, KeyValueCompare comp) const + lower_bound_range(const KeyType &key, KeyTypeKeyCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); std::pair ret - (node_algorithms::lower_bound_range(this->header_ptr(), key, key_node_comp)); + (node_algorithms::lower_bound_range(this->header_ptr(), key, this->key_node_comp(comp))); return std::pair( const_iterator(ret.first, this->priv_value_traits_ptr()) , const_iterator(ret.second, this->priv_value_traits_ptr())); } //bounded_range std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) - { return this->bounded_range(lower_value, upper_value, this->comp(), left_closed, right_closed); } + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) + { return this->bounded_range(lower_key, upper_key, this->key_comp(), left_closed, right_closed); } - template + template std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) + (const KeyType &lower_key, const KeyType &upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::bounded_range - (this->header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); + (this->header_ptr(), lower_key, upper_key, this->key_node_comp(comp), left_closed, right_closed)); return std::pair( iterator(ret.first, this->priv_value_traits_ptr()) , iterator(ret.second, this->priv_value_traits_ptr())); } std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return this->bounded_range(lower_value, upper_value, this->comp(), left_closed, right_closed); } + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const + { return this->bounded_range(lower_key, upper_key, this->key_comp(), left_closed, right_closed); } - template + template std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const + (const KeyType &lower_key, const KeyType &upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::bounded_range - (this->header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); + (this->header_ptr(), lower_key, upper_key, this->key_node_comp(comp), left_closed, right_closed)); return std::pair( const_iterator(ret.first, this->priv_value_traits_ptr()) , const_iterator(ret.second, this->priv_value_traits_ptr())); } //insert_unique_check - template + template std::pair insert_unique_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check - (this->header_ptr(), key, ocomp, commit_data)); + (this->header_ptr(), key, this->key_node_comp(comp), commit_data)); return std::pair(iterator(ret.first, this->priv_value_traits_ptr()), ret.second); } - template + template std::pair insert_unique_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check - (this->header_ptr(), hint.pointed_node(), key, ocomp, commit_data)); + (this->header_ptr(), hint.pointed_node(), key, this->key_node_comp(comp), commit_data)); return std::pair(iterator(ret.first, this->priv_value_traits_ptr()), ret.second); } }; @@ -486,19 +497,20 @@ struct bstbase2 //Due to MSVC's EBO implementation, to save space and maintain the ABI, we must put the non-empty size member //in the first position, but if size is not going to be stored then we'll use an specialization //that doesn't inherit from size_holder -template +template struct bstbase_hack : public detail::size_holder - , public bstbase2 < ValueTraits, VoidOrKeyComp, AlgoType, HeaderHolder> + , public bstbase2 < ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, AlgoType, HeaderHolder> { - typedef bstbase2< ValueTraits, VoidOrKeyComp, AlgoType, HeaderHolder> base_type; + typedef bstbase2< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, AlgoType, HeaderHolder> base_type; + typedef typename base_type::key_compare key_compare; typedef typename base_type::value_compare value_compare; typedef SizeType size_type; typedef typename base_type::node_traits node_traits; typedef typename get_algo ::type algo_type; - bstbase_hack(const value_compare & comp, const ValueTraits &vtraits) + bstbase_hack(const key_compare & comp, const ValueTraits &vtraits) : base_type(comp, vtraits) { this->sz_traits().set_size(size_type(0)); @@ -514,17 +526,18 @@ struct bstbase_hack }; //Specialization for ConstantTimeSize == false -template -struct bstbase_hack - : public bstbase2 < ValueTraits, VoidOrKeyComp, AlgoType, HeaderHolder> +template +struct bstbase_hack + : public bstbase2 < ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, AlgoType, HeaderHolder> { - typedef bstbase2< ValueTraits, VoidOrKeyComp, AlgoType, HeaderHolder> base_type; + typedef bstbase2< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, AlgoType, HeaderHolder> base_type; typedef typename base_type::value_compare value_compare; - bstbase_hack(const value_compare & comp, const ValueTraits &vtraits) + typedef typename base_type::key_compare key_compare; + bstbase_hack(const key_compare & comp, const ValueTraits &vtraits) : base_type(comp, vtraits) {} - typedef detail::size_holder size_traits; + typedef detail::size_holder size_traits; size_traits &sz_traits() { return s_size_traits; } @@ -535,18 +548,18 @@ struct bstbase_hack -detail::size_holder bstbase_hack::s_size_traits; +template +detail::size_holder bstbase_hack::s_size_traits; //This class will -template +template struct bstbase - : public bstbase_hack< ValueTraits, VoidOrKeyComp, ConstantTimeSize, SizeType, AlgoType, HeaderHolder> + : public bstbase_hack< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, ConstantTimeSize, SizeType, AlgoType, HeaderHolder> { - typedef bstbase_hack< ValueTraits, VoidOrKeyComp, ConstantTimeSize, SizeType, AlgoType, HeaderHolder> base_type; + typedef bstbase_hack< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, ConstantTimeSize, SizeType, AlgoType, HeaderHolder> base_type; typedef ValueTraits value_traits; typedef typename base_type::value_compare value_compare; - typedef value_compare key_compare; + typedef typename base_type::key_compare key_compare; typedef typename base_type::const_reference const_reference; typedef typename base_type::reference reference; typedef typename base_type::iterator iterator; @@ -556,7 +569,7 @@ struct bstbase ::type node_algorithms; typedef SizeType size_type; - bstbase(const value_compare & comp, const ValueTraits &vtraits) + bstbase(const key_compare & comp, const ValueTraits &vtraits) : base_type(comp, vtraits) {} @@ -578,7 +591,7 @@ struct bstbase /// @endcond //! The class template bstree is an unbalanced intrusive binary search tree -//! container. The no-throw guarantee holds only, if the value_compare object +//! container. The no-throw guarantee holds only, if the key_compare object //! doesn't throw. //! //! The complexity guarantees only hold if the tree is balanced, logarithmic @@ -595,14 +608,14 @@ struct bstbase #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class bstree_impl - : public bstbase + : public bstbase { public: /// @cond - typedef bstbase data_type; + typedef bstbase data_type; typedef tree_iterator iterator_type; typedef tree_iterator const_iterator_type; /// @endcond @@ -611,13 +624,14 @@ class bstree_impl typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::pointer) pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::const_pointer) const_pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; - typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; + typedef BOOST_INTRUSIVE_IMPDEF(typename data_type::key_type) key_type; + typedef BOOST_INTRUSIVE_IMPDEF(typename data_type::key_of_value) key_of_value; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) const_reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::difference_type) difference_type; typedef BOOST_INTRUSIVE_IMPDEF(SizeType) size_type; typedef BOOST_INTRUSIVE_IMPDEF(typename data_type::value_compare) value_compare; - typedef BOOST_INTRUSIVE_IMPDEF(value_compare) key_compare; + typedef BOOST_INTRUSIVE_IMPDEF(typename data_type::key_compare) key_compare; typedef BOOST_INTRUSIVE_IMPDEF(iterator_type) iterator; typedef BOOST_INTRUSIVE_IMPDEF(const_iterator_type) const_iterator; typedef BOOST_INTRUSIVE_IMPDEF(boost::intrusive::reverse_iterator) reverse_iterator; @@ -660,8 +674,8 @@ class bstree_impl //! //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor of the value_compare object throws. Basic guarantee. - explicit bstree_impl( const value_compare &cmp = value_compare() + //! or the copy constructor of the key_compare object throws. Basic guarantee. + explicit bstree_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : data_type(cmp, v_traits) {} @@ -677,10 +691,10 @@ class bstree_impl //! //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee. + //! or the copy constructor/operator() of the key_compare object throws. Basic guarantee. template bstree_impl( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : data_type(cmp, v_traits) { @@ -863,7 +877,7 @@ class bstree_impl //! //! Complexity: Constant. //! - //! Throws: If value_compare copy-constructor throws. + //! Throws: If key_compare copy-constructor throws. key_compare key_comp() const; //! Effects: Returns the value_compare object used by the container. @@ -960,7 +974,7 @@ class bstree_impl //! //! Effects: Erases all the elements from *this //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) + //! elements from src calling Cloner::operator()(reference) //! and inserts them on *this. Copies the predicate from the source container. //! //! If cloner throws, all cloned elements are unlinked and disposed @@ -973,7 +987,7 @@ class bstree_impl //! Note: This version can modify the source container, useful to implement //! move semantics. template - void clone_from(bstree_impl &src, Cloner cloner, Disposer disposer) + void clone_from(BOOST_RV_REF(bstree_impl) src, Cloner cloner, Disposer disposer) { this->clear_and_dispose(disposer); if(!src.empty()){ @@ -997,19 +1011,17 @@ class bstree_impl //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If the internal key_compare ordering function throws. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(this->comp(), &this->get_value_traits()); node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret(node_algorithms::insert_equal_upper_bound - (this->header_ptr(), to_insert, key_node_comp), this->priv_value_traits_ptr()); + (this->header_ptr(), to_insert, this->key_node_comp(this->key_comp())), this->priv_value_traits_ptr()); this->sz_traits().increment(); return ret; } @@ -1024,19 +1036,17 @@ class bstree_impl //! Complexity: Logarithmic in general, but it is amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If the internal key_compare ordering function throws. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(this->comp(), &this->get_value_traits()); node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret(node_algorithms::insert_equal - (this->header_ptr(), hint.pointed_node(), to_insert, key_node_comp), this->priv_value_traits_ptr()); + (this->header_ptr(), hint.pointed_node(), to_insert, this->key_node_comp(this->key_comp())), this->priv_value_traits_ptr()); this->sz_traits().increment(); return ret; } @@ -1078,10 +1088,13 @@ class bstree_impl std::pair insert_unique(reference value) { insert_commit_data commit_data; - std::pair ret = this->insert_unique_check(value, this->comp(), commit_data); - if(!ret.second) - return ret; - return std::pair (this->insert_unique_commit(value, commit_data), true); + std::pair ret = + (node_algorithms::insert_unique_check + (this->header_ptr(), key_of_value()(value), this->key_node_comp(this->key_comp()), commit_data)); + return std::pair + ( ret.second ? this->insert_unique_commit(value, commit_data) + : iterator(ret.first, this->priv_value_traits_ptr()) + , ret.second); } //! Requires: value must be an lvalue, and "hint" must be @@ -1101,10 +1114,11 @@ class bstree_impl iterator insert_unique(const_iterator hint, reference value) { insert_commit_data commit_data; - std::pair ret = this->insert_unique_check(hint, value, this->comp(), commit_data); - if(!ret.second) - return ret.first; - return this->insert_unique_commit(value, commit_data); + std::pair ret = + (node_algorithms::insert_unique_check + (this->header_ptr(), hint.pointed_node(), key_of_value()(value), this->key_node_comp(this->key_comp()), commit_data)); + return ret.second ? this->insert_unique_commit(value, commit_data) + : iterator(ret.first, this->priv_value_traits_ptr()); } //! Requires: Dereferencing iterator must yield an lvalue @@ -1136,9 +1150,9 @@ class bstree_impl #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. + //! Requires: comp must be a comparison function that induces + //! the same strict weak ordering as key_compare. The difference is that + //! comp compares an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the container, using //! a user provided key instead of the value itself. @@ -1151,7 +1165,7 @@ class bstree_impl //! //! Complexity: Average complexity is at most logarithmic. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If the comp ordering function throws. Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -1166,13 +1180,13 @@ class bstree_impl //! //! "commit_data" remains valid for a subsequent "insert_commit" only if no more //! objects are inserted or erased from the container. - template + template std::pair insert_unique_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data); + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data); - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. + //! Requires: comp must be a comparison function that induces + //! the same strict weak ordering as key_compare. The difference is that + //! comp compares an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the container, using //! a user provided key instead of the value itself, using "hint" @@ -1187,7 +1201,7 @@ class bstree_impl //! Complexity: Logarithmic in general, but it's amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If the comp ordering function throws. Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -1202,10 +1216,10 @@ class bstree_impl //! //! "commit_data" remains valid for a subsequent "insert_commit" only if no more //! objects are inserted or erased from the container. - template + template std::pair insert_unique_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data); + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data); #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED @@ -1351,8 +1365,8 @@ class bstree_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return this->erase(value, this->comp()); } + size_type erase(const key_type &key) + { return this->erase(key, this->key_comp()); } //! Effects: Erases all the elements with the given key. //! according to the comparison functor "comp". @@ -1365,12 +1379,10 @@ class bstree_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + template + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase(const KeyType& key, KeyTypeKeyCompare comp) { std::pair p = this->equal_range(key, comp); size_type n; @@ -1398,12 +1410,6 @@ class bstree_impl return ret; } - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif - //! Requires: Disposer::operator()(pointer) shouldn't throw. //! //! Effects: Erases all the elements with the given value. @@ -1418,9 +1424,9 @@ class bstree_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. template - size_type erase_and_dispose(const_reference value, Disposer disposer) + size_type erase_and_dispose(const key_type &key, Disposer disposer) { - std::pair p = this->equal_range(value); + std::pair p = this->equal_range(key); size_type n; this->private_erase(p.first, p.second, n, disposer); return n; @@ -1456,12 +1462,10 @@ class bstree_impl //! //! Note: Invalidates the iterators //! to the erased elements. - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + template + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer) { std::pair p = this->equal_range(key, comp); size_type n; @@ -1512,9 +1516,9 @@ class bstree_impl //! Complexity: Logarithmic to the number of elements contained plus lineal //! to number of objects with the given value. //! - //! Throws: If `value_compare` throws. - size_type count(const_reference value) const - { return size_type(this->count(value, this->comp())); } + //! Throws: If `key_compare` throws. + size_type count(const key_type &key) const + { return size_type(this->count(key, this->key_comp())); } //! Effects: Returns the number of contained elements with the given key //! @@ -1522,8 +1526,8 @@ class bstree_impl //! to number of objects with the given key. //! //! Throws: If `comp` throws. - template - size_type count(const KeyType &key, KeyValueCompare comp) const + template + size_type count(const KeyType &key, KeyTypeKeyCompare comp) const { std::pair ret = this->equal_range(key, comp); size_type n = 0; @@ -1535,11 +1539,11 @@ class bstree_impl //Add non-const overloads to theoretically const members //as some algorithms have different behavior when non-const versions are used (like splay trees). - size_type count(const_reference value) - { return size_type(this->count(value, this->comp())); } + size_type count(const key_type &key) + { return size_type(this->count(key, this->key_comp())); } - template - size_type count(const KeyType &key, KeyValueCompare comp) + template + size_type count(const KeyType &key, KeyTypeKeyCompare comp) { std::pair ret = this->equal_range(key, comp); size_type n = 0; @@ -1554,16 +1558,16 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If `value_compare` throws. - iterator lower_bound(const_reference value); + //! Throws: If `key_compare` throws. + iterator lower_bound(const key_type &key); //! 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 `value_compare` throws. - const_iterator lower_bound(const_reference value) const; + //! 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. @@ -1571,8 +1575,8 @@ class bstree_impl //! Complexity: Logarithmic. //! //! Throws: If `comp` throws. - template - iterator lower_bound(const KeyType &key, KeyValueCompare comp); + 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. @@ -1580,16 +1584,16 @@ class bstree_impl //! Complexity: Logarithmic. //! //! Throws: If `comp` throws. - template - const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const; + template + const_iterator lower_bound(const KeyType &key, KeyTypeKeyCompare comp) const; //! 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 `value_compare` throws. - iterator upper_bound(const_reference value); + //! Throws: If `key_compare` throws. + iterator upper_bound(const key_type &key); //! Effects: Returns an iterator to the first element whose //! key is greater than k according to comp or end() if that element @@ -1598,16 +1602,16 @@ class bstree_impl //! Complexity: Logarithmic. //! //! Throws: If `comp` throws. - template - iterator upper_bound(const KeyType &key, KeyValueCompare comp); + 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 `value_compare` throws. - const_iterator upper_bound(const_reference value) const; + //! Throws: If `key_compare` throws. + 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 @@ -1616,16 +1620,16 @@ class bstree_impl //! Complexity: Logarithmic. //! //! Throws: If `comp` throws. - template - const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const; + template + const_iterator upper_bound(const KeyType &key, KeyTypeKeyCompare comp) const; //! Effects: Finds an iterator to the first element whose key is //! k or end() if that element does not exist. //! //! Complexity: Logarithmic. //! - //! Throws: If `value_compare` throws. - iterator find(const_reference value); + //! Throws: If `key_compare` throws. + iterator find(const key_type &key); //! Effects: Finds an iterator to the first element whose key is //! k or end() if that element does not exist. @@ -1633,16 +1637,16 @@ class bstree_impl //! Complexity: Logarithmic. //! //! Throws: If `comp` throws. - template - iterator find(const KeyType &key, KeyValueCompare comp); + 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 `value_compare` throws. - const_iterator find(const_reference value) const; + //! Throws: If `key_compare` throws. + 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. @@ -1650,8 +1654,8 @@ class bstree_impl //! Complexity: Logarithmic. //! //! Throws: If `comp` throws. - template - const_iterator find(const KeyType &key, KeyValueCompare comp) const; + template + const_iterator find(const KeyType &key, KeyTypeKeyCompare comp) 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 @@ -1659,8 +1663,8 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If `value_compare` throws. - std::pair equal_range(const_reference value); + //! Throws: If `key_compare` throws. + std::pair equal_range(const key_type &key); //! Effects: Finds a range containing all elements whose key is k or //! an empty range that indicates the position where those elements would be @@ -1669,8 +1673,8 @@ class bstree_impl //! Complexity: Logarithmic. //! //! Throws: If `comp` throws. - template - std::pair equal_range(const KeyType &key, KeyValueCompare comp); + 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 @@ -1678,9 +1682,9 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If `value_compare` throws. + //! Throws: If `key_compare` throws. std::pair - equal_range(const_reference value) const; + 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 @@ -1689,12 +1693,12 @@ class bstree_impl //! Complexity: Logarithmic. //! //! Throws: If `comp` throws. - template + template std::pair - equal_range(const KeyType &key, KeyValueCompare comp) const; + equal_range(const KeyType &key, KeyTypeKeyCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. + //! 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: //! @@ -1704,16 +1708,16 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If `value_compare` throws. + //! 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. std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak + //! 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 @@ -1733,12 +1737,12 @@ class bstree_impl //! and lower_bound for lower_key and upper_key. //! //! Note: Experimental function, the interface might change in future releases. - template + template std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType &lower_key, const KeyType &upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. + //! 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: //! @@ -1748,16 +1752,16 @@ class bstree_impl //! //! Complexity: Logarithmic. //! - //! Throws: If `value_compare` throws. + //! 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. std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak + //! 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 @@ -1777,9 +1781,9 @@ class bstree_impl //! and lower_bound for lower_key and upper_key. //! //! Note: Experimental function, the interface might change in future releases. - template + template std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType &lower_key, const KeyType &upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! Requires: value must be an lvalue and shall be in a set of //! appropriate type. Otherwise the behavior is undefined. @@ -1936,8 +1940,8 @@ class bstree_impl template void check(ExtraChecker extra_checker) const { - typedef detail::key_nodeptr_comp nodeptr_comp_t; - nodeptr_comp_t nodeptr_comp(this->comp(), &this->get_value_traits()); + typedef detail::key_nodeptr_comp nodeptr_comp_t; + nodeptr_comp_t nodeptr_comp(this->key_comp(), &this->get_value_traits()); typedef typename get_node_checker::type node_checker_t; typename node_checker_t::return_type checker_return; node_algorithms::check(this->header_ptr(), node_checker_t(nodeptr_comp, extra_checker), checker_return); @@ -1956,6 +1960,32 @@ class bstree_impl check(detail::empty_node_checker()); } + friend bool operator==(const bstree_impl &x, const bstree_impl &y) + { + if(constant_time_size && x.size() != y.size()){ + return false; + } + return boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + friend bool operator!=(const bstree_impl &x, const bstree_impl &y) + { return !(x == y); } + + friend bool operator<(const bstree_impl &x, const bstree_impl &y) + { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + friend bool operator>(const bstree_impl &x, const bstree_impl &y) + { return y < x; } + + friend bool operator<=(const bstree_impl &x, const bstree_impl &y) + { return !(x > y); } + + friend bool operator>=(const bstree_impl &x, const bstree_impl &y) + { return !(x < y); } + + friend void swap(bstree_impl &x, bstree_impl &y) + { x.swap(y); } + /// @cond private: template @@ -1975,111 +2005,6 @@ class bstree_impl /// @endcond }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ - typedef bstree_impl tree_type; - - if(tree_type::constant_time_size && x.size() != y.size()){ - return false; - } - return boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return !(x == y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return y < x; } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return !(y < x); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return !(x < y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(bstree_impl &x, bstree_impl &y) -#else -( bstree_impl &x -, bstree_impl &y) -#endif -{ x.swap(y); } - //! Helper metafunction to define a \c bstree that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) @@ -2087,7 +2012,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_bstree { @@ -2095,7 +2020,7 @@ struct make_bstree typedef typename pack_options < bstree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -2106,6 +2031,7 @@ struct make_bstree typedef bstree_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -2120,14 +2046,14 @@ struct make_bstree #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class bstree : public make_bstree::value)); - bstree( const value_compare &cmp = value_compare() + bstree( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template bstree( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(unique, b, e, cmp, v_traits) {} @@ -2171,6 +2097,14 @@ class bstree bstree& operator=(BOOST_RV_REF(bstree) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const bstree &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(bstree) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static bstree &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/bstree_algorithms.hpp b/boost/intrusive/bstree_algorithms.hpp index f7e915e914..dcb7e5c4ff 100644 --- a/boost/intrusive/bstree_algorithms.hpp +++ b/boost/intrusive/bstree_algorithms.hpp @@ -37,10 +37,6 @@ namespace intrusive { template struct insert_commit_data_t { - insert_commit_data_t() - : link_left(false) - , node() - {} bool link_left; NodePtr node; }; diff --git a/boost/intrusive/detail/common_slist_algorithms.hpp b/boost/intrusive/detail/common_slist_algorithms.hpp index deaea7c97b..c6fa289a23 100644 --- a/boost/intrusive/detail/common_slist_algorithms.hpp +++ b/boost/intrusive/detail/common_slist_algorithms.hpp @@ -46,7 +46,7 @@ class common_slist_algorithms ; this_node != (p_next = NodeTraits::get_next(p)) ; p = p_next){ //Logic error: possible use of linear lists with - //operations only permitted with lists + //operations only permitted with circular lists BOOST_INTRUSIVE_INVARIANT_ASSERT(p); } return p; diff --git a/boost/intrusive/detail/default_header_holder.hpp b/boost/intrusive/detail/default_header_holder.hpp index d10109b8c9..5f9cd9a444 100644 --- a/boost/intrusive/detail/default_header_holder.hpp +++ b/boost/intrusive/detail/default_header_holder.hpp @@ -51,15 +51,15 @@ struct default_header_holder : public NodeTraits::node }; // type function producing the header node holder -template < typename Value_Traits, typename HeaderHolder > +template < typename ValueTraits, typename HeaderHolder > struct get_header_holder_type { typedef HeaderHolder type; }; -template < typename Value_Traits > -struct get_header_holder_type< Value_Traits, void > +template < typename ValueTraits > +struct get_header_holder_type< ValueTraits, void > { - typedef default_header_holder< typename Value_Traits::node_traits > type; + typedef default_header_holder< typename ValueTraits::node_traits > type; }; } //namespace detail diff --git a/boost/intrusive/detail/ebo_functor_holder.hpp b/boost/intrusive/detail/ebo_functor_holder.hpp index e8e73ff62a..27dd093b60 100644 --- a/boost/intrusive/detail/ebo_functor_holder.hpp +++ b/boost/intrusive/detail/ebo_functor_holder.hpp @@ -203,6 +203,7 @@ class ebo_functor_holder typedef ebo_functor_holder_impl::value> super; public: + typedef T functor_type; ebo_functor_holder(){} explicit ebo_functor_holder(const T& t) : super(t) diff --git a/boost/intrusive/detail/get_value_traits.hpp b/boost/intrusive/detail/get_value_traits.hpp index 686e059583..222f8078a6 100644 --- a/boost/intrusive/detail/get_value_traits.hpp +++ b/boost/intrusive/detail/get_value_traits.hpp @@ -107,9 +107,9 @@ BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_base_hook, hooktags::is_ba template struct internal_member_value_traits { - template static one test(...); - template static two test(typename U::member_value_traits* = 0); - static const bool value = sizeof(test(0)) == sizeof(two); + template static yes_type test(...); + template static no_type test(typename U::member_value_traits* = 0); + static const bool value = sizeof(test(0)) == sizeof(no_type); }; template::value> diff --git a/boost/intrusive/detail/hashtable_node.hpp b/boost/intrusive/detail/hashtable_node.hpp index 923a3e1d38..352be28cbe 100644 --- a/boost/intrusive/detail/hashtable_node.hpp +++ b/boost/intrusive/detail/hashtable_node.hpp @@ -113,9 +113,9 @@ struct bucket_traits_impl template struct hash_reduced_slist_node_traits { - template static detail::one test(...); - template static detail::two test(typename U::reduced_slist_node_traits* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); + template static detail::no_type test(...); + template static detail::yes_type test(typename U::reduced_slist_node_traits*); + static const bool value = sizeof(test(0)) == sizeof(detail::yes_type); }; template @@ -154,52 +154,48 @@ struct get_slist_impl template class hashtable_iterator { - typedef boost::intrusive::iterator - < std::forward_iterator_tag - , typename BucketValueTraits::value_traits::value_type - , typename pointer_traits::difference_type - , typename detail::add_const_if_c - ::type * - , typename detail::add_const_if_c - ::type & - > iterator_traits; - - typedef typename BucketValueTraits::value_traits value_traits; - typedef typename BucketValueTraits::bucket_traits bucket_traits; - typedef typename value_traits::node_traits node_traits; + typedef typename BucketValueTraits::value_traits value_traits; + typedef typename BucketValueTraits::bucket_traits bucket_traits; + + typedef iiterator< value_traits, IsConst + , std::forward_iterator_tag> types_t; + public: + typedef typename types_t::iterator_traits::difference_type difference_type; + typedef typename types_t::iterator_traits::value_type value_type; + typedef typename types_t::iterator_traits::pointer pointer; + typedef typename types_t::iterator_traits::reference reference; + typedef typename types_t::iterator_traits::iterator_category iterator_category; + + private: + typedef typename value_traits::node_traits node_traits; + typedef typename node_traits::node_ptr node_ptr; typedef typename detail::get_slist_impl - ::type - >::type slist_impl; - typedef typename slist_impl::iterator siterator; - typedef typename slist_impl::const_iterator const_siterator; - typedef detail::bucket_impl bucket_type; + < typename detail::reduced_slist_node_traits + ::type >::type slist_impl; + typedef typename slist_impl::iterator siterator; + typedef typename slist_impl::const_iterator const_siterator; + typedef detail::bucket_impl bucket_type; typedef typename pointer_traits - ::template rebind_pointer - < const BucketValueTraits >::type const_bucketvaltraits_ptr; - typedef typename slist_impl::size_type size_type; - + ::template rebind_pointer + < const BucketValueTraits >::type const_bucketvaltraits_ptr; + typedef typename slist_impl::size_type size_type; - static typename node_traits::node_ptr downcast_bucket(typename bucket_type::node_ptr p) + static node_ptr downcast_bucket(typename bucket_type::node_ptr p) { - return pointer_traits:: + return pointer_traits:: pointer_to(static_cast(*p)); } public: - typedef typename iterator_traits::difference_type difference_type; - typedef typename iterator_traits::value_type value_type; - typedef typename iterator_traits::pointer pointer; - typedef typename iterator_traits::reference reference; - typedef typename iterator_traits::iterator_category iterator_category; hashtable_iterator () : slist_it_() //Value initialization to achieve "null iterators" (N3644) {} explicit hashtable_iterator(siterator ptr, const BucketValueTraits *cont) - : slist_it_ (ptr), traitsptr_ (cont ? pointer_traits::pointer_to(*cont) : const_bucketvaltraits_ptr() ) + : slist_it_ (ptr) + , traitsptr_ (cont ? pointer_traits::pointer_to(*cont) : const_bucketvaltraits_ptr() ) {} hashtable_iterator(const hashtable_iterator &other) @@ -212,7 +208,6 @@ class hashtable_iterator hashtable_iterator unconst() const { return hashtable_iterator(this->slist_it(), this->get_bucket_value_traits()); } - public: hashtable_iterator& operator++() { this->increment(); return *this; } @@ -234,8 +229,8 @@ class hashtable_iterator pointer operator->() const { - return boost::intrusive::detail::to_raw_pointer(this->priv_value_traits().to_value_ptr - (downcast_bucket(slist_it_.pointed_node()))); + return this->priv_value_traits().to_value_ptr + (downcast_bucket(slist_it_.pointed_node())); } const const_bucketvaltraits_ptr &get_bucket_value_traits() const diff --git a/boost/intrusive/detail/is_stateful_value_traits.hpp b/boost/intrusive/detail/is_stateful_value_traits.hpp index 680b043aa8..e43f6d340a 100644 --- a/boost/intrusive/detail/is_stateful_value_traits.hpp +++ b/boost/intrusive/detail/is_stateful_value_traits.hpp @@ -32,7 +32,7 @@ namespace detail { template struct is_stateful_value_traits { - static const bool value = !detail::is_empty_class::value; + static const bool value = !detail::is_empty::value; }; }}} diff --git a/boost/intrusive/detail/iterator.hpp b/boost/intrusive/detail/iterator.hpp index fb6fb81976..9f0fe606f4 100644 --- a/boost/intrusive/detail/iterator.hpp +++ b/boost/intrusive/detail/iterator.hpp @@ -141,6 +141,14 @@ typename iterator_enable_if_tag_difference_type return off; } +template +typename iterator_traits::pointer iterator_arrow_result(const I &i) +{ return i.operator->(); } + +template +T * iterator_arrow_result(T *p) +{ return p; } + } //namespace intrusive } //namespace boost diff --git a/boost/intrusive/detail/key_nodeptr_comp.hpp b/boost/intrusive/detail/key_nodeptr_comp.hpp index 8c456634e5..df2b895db9 100644 --- a/boost/intrusive/detail/key_nodeptr_comp.hpp +++ b/boost/intrusive/detail/key_nodeptr_comp.hpp @@ -28,18 +28,27 @@ namespace boost { namespace intrusive { namespace detail { -template +template < class KeyTypeKeyCompare + , class ValueTraits + , class KeyOfValue = void + > struct key_nodeptr_comp //Use public inheritance to avoid MSVC bugs with closures - : public ebo_functor_holder + : public ebo_functor_holder { typedef ValueTraits value_traits; typedef typename value_traits::value_type value_type; typedef typename value_traits::node_ptr node_ptr; typedef typename value_traits::const_node_ptr const_node_ptr; - typedef ebo_functor_holder base_t; - - key_nodeptr_comp(KeyValueCompare kcomp, const ValueTraits *traits) + typedef ebo_functor_holder base_t; + typedef typename detail::if_c + < detail::is_same::value + , detail::identity + , KeyOfValue + >::type key_of_value; + typedef typename key_of_value::type key_type; + + key_nodeptr_comp(KeyTypeKeyCompare kcomp, const ValueTraits *traits) : base_t(kcomp), traits_(traits) {} @@ -51,12 +60,13 @@ struct key_nodeptr_comp //key_forward template - const value_type & key_forward - (const T &node, typename enable_if_c::value>::type * = 0) const - { return *traits_->to_value_ptr(node); } + typename enable_if, const key_type &>::type + key_forward(const T &node) const + { return key_of_value()(*traits_->to_value_ptr(node)); } template - const T & key_forward(const T &key, typename enable_if_c::value>::type* = 0) const + typename disable_if, const T &>::type + const key_forward(const T &key) const { return key; } //operator() 1 arg diff --git a/boost/intrusive/detail/list_iterator.hpp b/boost/intrusive/detail/list_iterator.hpp index 77c9fa6097..6af4841c3e 100644 --- a/boost/intrusive/detail/list_iterator.hpp +++ b/boost/intrusive/detail/list_iterator.hpp @@ -34,7 +34,7 @@ namespace intrusive { template class list_iterator { - protected: + private: typedef iiterator types_t; diff --git a/boost/intrusive/detail/math.hpp b/boost/intrusive/detail/math.hpp index 03000fceeb..dfebe2ab42 100644 --- a/boost/intrusive/detail/math.hpp +++ b/boost/intrusive/detail/math.hpp @@ -127,7 +127,7 @@ namespace detail { { return (n >> 1) + ((n & 1u) & (n != 1)); } template - inline std::size_t floor_log2 (std::size_t x, integer) + inline std::size_t floor_log2 (std::size_t x, integral_constant) { const std::size_t Bits = N; const bool Size_t_Bits_Power_2= !(Bits & (Bits-1)); @@ -156,7 +156,7 @@ namespace detail { //http://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers //Thanks to Desmond Hume - inline std::size_t floor_log2 (std::size_t v, integer) + inline std::size_t floor_log2 (std::size_t v, integral_constant) { static const int MultiplyDeBruijnBitPosition[32] = { @@ -173,7 +173,7 @@ namespace detail { return MultiplyDeBruijnBitPosition[(std::size_t)(v * 0x07C4ACDDU) >> 27]; } - inline std::size_t floor_log2 (std::size_t v, integer) + inline std::size_t floor_log2 (std::size_t v, integral_constant) { static const std::size_t MultiplyDeBruijnBitPosition[64] = { 63, 0, 58, 1, 59, 47, 53, 2, @@ -198,7 +198,7 @@ namespace detail { inline std::size_t floor_log2 (std::size_t x) { const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT; - return floor_log2(x, integer()); + return floor_log2(x, integral_constant()); } #endif diff --git a/boost/intrusive/detail/mpl.hpp b/boost/intrusive/detail/mpl.hpp index 39d2c58bd3..8d227a16fd 100644 --- a/boost/intrusive/detail/mpl.hpp +++ b/boost/intrusive/detail/mpl.hpp @@ -23,260 +23,48 @@ #endif #include +#include #include namespace boost { namespace intrusive { namespace detail { - -template -struct is_same -{ - static const bool value = false; -}; - -template -struct is_same -{ - static const bool value = true; -}; - -template -struct add_const -{ typedef const T type; }; - -template -struct remove_const -{ typedef T type; }; - -template -struct remove_const -{ typedef T type; }; - -template -struct remove_cv -{ typedef T type; }; - -template -struct remove_cv -{ typedef T type; }; - -template -struct remove_cv -{ typedef T type; }; - -template -struct remove_cv -{ typedef T type; }; - -template -struct remove_reference -{ - typedef T type; -}; - -template -struct remove_reference -{ - typedef T type; -}; - -template -struct remove_pointer -{ - typedef T type; -}; - -template -struct remove_pointer -{ - typedef T type; -}; - -template -struct add_pointer -{ - typedef T *type; -}; - -typedef char one; -struct two {one _[2];}; - -template< bool C_ > -struct bool_ -{ - static const bool value = C_; -}; - -template< class Integer, Integer Value > -struct integer -{ - static const Integer value = Value; -}; - -typedef bool_ true_; -typedef bool_ false_; - -typedef true_ true_type; -typedef false_ false_type; - -typedef char yes_type; -struct no_type -{ - char padding[8]; -}; - -template -struct enable_if_c { - typedef T type; -}; - -template -struct enable_if_c {}; - -template -struct enable_if : public enable_if_c{}; - -template -struct apply -{ - typedef typename F::template apply::type type; -}; - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) - -template -struct is_convertible -{ - static const bool value = __is_convertible_to(T, U); -}; - -#else - -template -class is_convertible -{ - typedef char true_t; - class false_t { char dummy[2]; }; - //use any_conversion as first parameter since in MSVC - //overaligned types can't go through ellipsis - static false_t dispatch(...); - static true_t dispatch(U); - static typename remove_reference::type &trigger(); - public: - static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); -}; - -#endif - -template< - bool C - , typename T1 - , typename T2 - > -struct if_c -{ - typedef T1 type; -}; - -template< - typename T1 - , typename T2 - > -struct if_c -{ - typedef T2 type; -}; - -template< - typename C - , typename T1 - , typename T2 - > -struct if_ -{ - typedef typename if_c<0 != C::value, T1, T2>::type type; -}; - -template< - bool C - , typename F1 - , typename F2 - > -struct eval_if_c - : if_c::type -{}; - -template< - typename C - , typename T1 - , typename T2 - > -struct eval_if - : if_::type -{}; - -// identity is an extension: it is not part of the standard. -template -struct identity -{ - typedef T type; -}; - -template -struct add_const_if_c -{ - typedef typename if_c - < Add - , typename add_const::type - , T - >::type type; -}; - - -//boost::alignment_of yields to 10K lines of preprocessed code, so we -//need an alternative -template struct alignment_of; - -template -struct alignment_of_hack -{ - char c; - T t; - alignment_of_hack(); -}; - -template -struct alignment_logic -{ - static const std::size_t value = A < S ? A : S; -}; - -template< typename T > -struct alignment_of -{ - static const std::size_t value = alignment_logic - < sizeof(alignment_of_hack) - sizeof(T) - , sizeof(T) - >::value; -}; - -template -class is_empty_class -{ - template - struct empty_helper_t1 : public T - { - empty_helper_t1(); - int i[256]; - }; - - struct empty_helper_t2 - { int i[256]; }; - - public: - static const bool value = sizeof(empty_helper_t1) == sizeof(empty_helper_t2); -}; + +using boost::move_detail::is_same; +using boost::move_detail::add_const; +using boost::move_detail::remove_const; +using boost::move_detail::remove_cv; +using boost::move_detail::remove_reference; +using boost::move_detail::add_reference; +using boost::move_detail::remove_pointer; +using boost::move_detail::add_pointer; +using boost::move_detail::true_type; +using boost::move_detail::false_type; +using boost::move_detail::enable_if_c; +using boost::move_detail::enable_if; +using boost::move_detail::disable_if_c; +using boost::move_detail::disable_if; +using boost::move_detail::is_convertible; +using boost::move_detail::if_c; +using boost::move_detail::if_; +using boost::move_detail::is_const; +using boost::move_detail::identity; +using boost::move_detail::alignment_of; +using boost::move_detail::is_empty; +using boost::move_detail::addressof; +using boost::move_detail::integral_constant; +using boost::move_detail::enable_if_convertible; +using boost::move_detail::disable_if_convertible; +using boost::move_detail::bool_; +using boost::move_detail::true_; +using boost::move_detail::false_; +using boost::move_detail::yes_type; +using boost::move_detail::no_type; +using boost::move_detail::apply; +using boost::move_detail::eval_if_c; +using boost::move_detail::eval_if; +using boost::move_detail::unvoid_ref; +using boost::move_detail::add_const_if_c; template struct ls_zeros @@ -296,10 +84,6 @@ struct ls_zeros<1> static const std::size_t value = 0; }; -template struct unvoid_ref { typedef T &type; }; -template <> struct unvoid_ref { struct type_impl { }; typedef type_impl & type; }; -template <> struct unvoid_ref { struct type_impl { }; typedef type_impl & type; }; - // Infrastructure for providing a default type for T::TNAME if absent. #define BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(TNAME) \ template \ @@ -360,8 +144,8 @@ template \ struct TRAITS_PREFIX##_bool\ {\ template\ - struct two_or_three {one _[2 + Add];};\ - template static one test(...);\ + struct two_or_three {yes_type _[2 + Add];};\ + template static yes_type test(...);\ template static two_or_three test (int);\ static const std::size_t value = sizeof(test(0));\ };\ @@ -369,7 +153,7 @@ struct TRAITS_PREFIX##_bool\ template \ struct TRAITS_PREFIX##_bool_is_true\ {\ - static const bool value = TRAITS_PREFIX##_bool::value > sizeof(one)*2;\ + static const bool value = TRAITS_PREFIX##_bool::value > sizeof(yes_type)*2;\ };\ // @@ -380,10 +164,10 @@ struct TRAITS_PREFIX##_bool_is_true\ private: \ template struct helper;\ template \ - static ::boost::intrusive::detail::yes_type check(helper<&T::FUNC_NAME>*); \ - template static ::boost::intrusive::detail::no_type check(...); \ + static ::boost::intrusive::detail::yes_type test(helper<&T::FUNC_NAME>*); \ + template static ::boost::intrusive::detail::no_type test(...); \ public: \ - static const bool value = sizeof(check(0)) == sizeof(::boost::intrusive::detail::yes_type); \ + static const bool value = sizeof(test(0)) == sizeof(::boost::intrusive::detail::yes_type); \ }; \ // @@ -398,9 +182,9 @@ struct TRAITS_NAME \ struct Base : public Type, public BaseMixin { Base(); }; \ template class Helper{}; \ template \ - static ::boost::intrusive::detail::no_type check(U*, Helper* = 0); \ - static ::boost::intrusive::detail::yes_type check(...); \ - static const bool value = sizeof(::boost::intrusive::detail::yes_type) == sizeof(check((Base*)(0))); \ + static ::boost::intrusive::detail::no_type test(U*, Helper* = 0); \ + static ::boost::intrusive::detail::yes_type test(...); \ + static const bool value = sizeof(::boost::intrusive::detail::yes_type) == sizeof(test((Base*)(0))); \ };\ // @@ -413,18 +197,6 @@ struct TRAITS_NAME \ {};\ // - -template -inline T* addressof(T& obj) -{ - return static_cast - (static_cast - (const_cast - (&reinterpret_cast(obj)) - ) - ); -} - } //namespace detail } //namespace intrusive } //namespace boost diff --git a/boost/intrusive/detail/node_cloner_disposer.hpp b/boost/intrusive/detail/node_cloner_disposer.hpp index 65af3e37b8..3fe2954347 100644 --- a/boost/intrusive/detail/node_cloner_disposer.hpp +++ b/boost/intrusive/detail/node_cloner_disposer.hpp @@ -36,21 +36,22 @@ struct node_cloner //Use public inheritance to avoid MSVC bugs with closures : public ebo_functor_holder { - typedef ValueTraits value_traits; - typedef typename value_traits::node_traits node_traits; - typedef typename node_traits::node_ptr node_ptr; - typedef ebo_functor_holder base_t; + typedef ValueTraits value_traits; + typedef typename value_traits::node_traits node_traits; + typedef typename node_traits::node_ptr node_ptr; + typedef ebo_functor_holder base_t; typedef typename get_algo< AlgoType - , node_traits>::type node_algorithms; + , node_traits>::type node_algorithms; static const bool safemode_or_autounlink = is_safe_autounlink::value; - typedef typename value_traits::value_type value_type; - typedef typename value_traits::pointer pointer; - typedef typename node_traits::node node; - typedef typename value_traits::const_node_ptr const_node_ptr; - typedef typename value_traits::reference reference; - typedef typename value_traits::const_reference const_reference; - + typedef typename value_traits::value_type value_type; + typedef typename value_traits::pointer pointer; + typedef typename value_traits::const_pointer const_pointer; + typedef typename node_traits::node node; + typedef typename value_traits::const_node_ptr const_node_ptr; + typedef typename pointer_traits::reference reference; + typedef typename pointer_traits + ::reference const_reference; typedef typename if_c::type reference_type; node_cloner(F f, const ValueTraits *traits) @@ -63,21 +64,7 @@ struct node_cloner reference_type v = *traits_->to_value_ptr(p); node_ptr n = traits_->to_node_ptr(*base_t::get()(v)); //Cloned node must be in default mode if the linking mode requires it - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); - return n; - } - - // hashtables use this method, which is proxy-reference unfriendly - node_ptr operator()(const node &to_clone) - { - reference_type v = - *traits_->to_value_ptr - (pointer_traits::pointer_to(to_clone)); - node_ptr n = traits_->to_node_ptr(*base_t::get()(v)); - //Cloned node must be in default mode if the linking mode requires it - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(n)); return n; } diff --git a/boost/intrusive/detail/reverse_iterator.hpp b/boost/intrusive/detail/reverse_iterator.hpp index 6a6fee5ac2..552e8f4d71 100644 --- a/boost/intrusive/detail/reverse_iterator.hpp +++ b/boost/intrusive/detail/reverse_iterator.hpp @@ -23,6 +23,7 @@ #include #include +#include namespace boost { namespace intrusive { @@ -49,10 +50,17 @@ class reverse_iterator {} template - reverse_iterator(const reverse_iterator& r) + reverse_iterator( const reverse_iterator& r + , typename boost::intrusive::detail::enable_if_convertible::type* =0 + ) : m_current(r.base()) {} + template + typename boost::intrusive::detail::enable_if_convertible::type + operator=( const reverse_iterator& r) + { m_current = r.base(); return *this; } + It base() const { return m_current; } @@ -60,10 +68,10 @@ class reverse_iterator { It temp(m_current); --temp; return *temp; } pointer operator->() const - { It temp(m_current); --temp; return temp.operator->(); } + { It temp(m_current); --temp; return iterator_arrow_result(temp); } reference operator[](difference_type off) const - { return this->m_current[-off-1]; } + { return this->m_current[-off - 1]; } reverse_iterator& operator++() { --m_current; return *this; } @@ -109,22 +117,17 @@ class reverse_iterator reverse_iterator& operator+=(difference_type off) { m_current -= off; return *this; } - friend reverse_iterator operator+(const reverse_iterator & l, difference_type off) - { - reverse_iterator tmp(l.m_current); - tmp.m_current -= off; - return tmp; - } + friend reverse_iterator operator+(reverse_iterator l, difference_type off) + { l.m_current -= off; return l; } + + friend reverse_iterator operator+(difference_type off, reverse_iterator r) + { return (r += off); } reverse_iterator& operator-=(difference_type off) { m_current += off; return *this; } - friend reverse_iterator operator-(const reverse_iterator & l, difference_type off) - { - reverse_iterator tmp(l.m_current); - tmp.m_current += off; - return tmp; - } + friend reverse_iterator operator-(reverse_iterator l, difference_type off) + { l.m_current += off; return l; } friend difference_type operator-(const reverse_iterator& l, const reverse_iterator& r) { return r.m_current - l.m_current; } diff --git a/boost/intrusive/detail/slist_iterator.hpp b/boost/intrusive/detail/slist_iterator.hpp index 80a6fef924..1699064ec1 100644 --- a/boost/intrusive/detail/slist_iterator.hpp +++ b/boost/intrusive/detail/slist_iterator.hpp @@ -36,7 +36,7 @@ namespace intrusive { template class slist_iterator { - protected: + private: typedef iiterator types_t; diff --git a/boost/intrusive/detail/std_fwd.hpp b/boost/intrusive/detail/std_fwd.hpp index 0492c1dc3d..4b5cedbae3 100644 --- a/boost/intrusive/detail/std_fwd.hpp +++ b/boost/intrusive/detail/std_fwd.hpp @@ -23,10 +23,12 @@ // Standard predeclarations ////////////////////////////////////////////////////////////////////////////// -#if defined(__clang__) && defined(_LIBCPP_VERSION) +#if defined(_LIBCPP_VERSION) #define BOOST_INTRUSIVE_CLANG_INLINE_STD_NS #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wc++11-extensions" + #if defined(__clang__) + #pragma GCC diagnostic ignored "-Wc++11-extensions" + #endif #define BOOST_INTRUSIVE_STD_NS_BEG _LIBCPP_BEGIN_NAMESPACE_STD #define BOOST_INTRUSIVE_STD_NS_END _LIBCPP_END_NAMESPACE_STD #elif defined(BOOST_GNU_STDLIB) && defined(_GLIBCXX_BEGIN_NAMESPACE_VERSION) //GCC >= 4.6 diff --git a/boost/intrusive/detail/transform_iterator.hpp b/boost/intrusive/detail/transform_iterator.hpp index 89ec973967..5e3b1a7652 100644 --- a/boost/intrusive/detail/transform_iterator.hpp +++ b/boost/intrusive/detail/transform_iterator.hpp @@ -23,6 +23,7 @@ #include #include +#include namespace boost { namespace intrusive { @@ -58,14 +59,14 @@ struct operator_arrow_proxy template class transform_iterator - : public boost::intrusive::iterator - < typename Iterator::iterator_category - , typename detail::remove_reference::type - , typename Iterator::difference_type - , operator_arrow_proxy - , typename UnaryFunction::result_type> { public: + typedef typename Iterator::iterator_category iterator_category; + typedef typename detail::remove_reference::type value_type; + typedef typename Iterator::difference_type difference_type; + typedef operator_arrow_proxy pointer; + typedef typename UnaryFunction::result_type reference; + explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction()) : members_(it, f) {} diff --git a/boost/intrusive/detail/tree_iterator.hpp b/boost/intrusive/detail/tree_iterator.hpp index 525761f3d6..c2e980d27a 100644 --- a/boost/intrusive/detail/tree_iterator.hpp +++ b/boost/intrusive/detail/tree_iterator.hpp @@ -40,13 +40,11 @@ namespace intrusive { template class tree_iterator { - protected: + private: typedef iiterator< ValueTraits, IsConst , std::bidirectional_iterator_tag> types_t; - - typedef ValueTraits value_traits; + typedef typename types_t::value_traits value_traits; typedef typename types_t::node_traits node_traits; - typedef typename types_t::node node; typedef typename types_t::node_ptr node_ptr; typedef typename types_t::const_value_traits_ptr const_value_traits_ptr; diff --git a/boost/intrusive/detail/tree_value_compare.hpp b/boost/intrusive/detail/tree_value_compare.hpp new file mode 100644 index 0000000000..a05741edee --- /dev/null +++ b/boost/intrusive/detail/tree_value_compare.hpp @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_DETAIL_TREE_VALUE_COMPARE_HPP +#define BOOST_INTRUSIVE_DETAIL_TREE_VALUE_COMPARE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +namespace boost{ +namespace intrusive{ + +template +struct tree_value_compare + : public boost::intrusive::detail::ebo_functor_holder +{ + typedef boost::intrusive::detail::ebo_functor_holder base_t; + typedef T value_type; + typedef KeyCompare key_compare; + typedef KeyOfValue key_of_value; + typedef Key key_type; + + explicit tree_value_compare(const key_compare &kcomp) + : base_t(kcomp) + {} + + tree_value_compare() + : base_t() + {} + + const key_compare &key_comp() const + { return static_cast(*this); } + + key_compare &key_comp() + { return static_cast(*this); } + + template + struct is_key + : boost::intrusive::detail::is_same + {}; + + template + typename boost::intrusive::detail::enable_if, const key_type &>::type + key_forward(const U &key) const + { return key; } + + template + typename boost::intrusive::detail::disable_if, const key_type &>::type + key_forward(const U &key) const + { return KeyOfValue()(key); } + + template + bool operator()(const KeyType &key1, const KeyType2 &key2) const + { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); } + + template + bool operator()(const KeyType &key1, const KeyType2 &key2) + { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); } +}; + +} //namespace intrusive{ +} //namespace boost{ + +#endif //#ifdef BOOST_INTRUSIVE_DETAIL_TREE_VALUE_COMPARE_HPP diff --git a/boost/intrusive/hashtable.hpp b/boost/intrusive/hashtable.hpp index 1d4f3d3f0c..125330ff6e 100644 --- a/boost/intrusive/hashtable.hpp +++ b/boost/intrusive/hashtable.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2013 +// (C) Copyright Ion Gaztanaga 2006-2015 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -26,6 +26,7 @@ #include #include #include +#include //Implementation utilities #include @@ -55,6 +56,62 @@ namespace intrusive { /// @cond +template +InputIt priv_algo_find(InputIt first, InputIt last, const T& value) +{ + for (; first != last; ++first) { + if (*first == value) { + return first; + } + } + return last; +} + +template +typename boost::intrusive::iterator_traits::difference_type + priv_algo_count(InputIt first, InputIt last, const T& value) +{ + typename boost::intrusive::iterator_traits::difference_type ret = 0; + for (; first != last; ++first) { + if (*first == value) { + ret++; + } + } + return ret; +} + +template +bool priv_algo_is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) +{ + typedef typename + boost::intrusive::iterator_traits::difference_type + distance_type; + //Efficiently compare identical prefixes: O(N) if sequences + //have the same elements in the same order. + for ( ; first1 != last1; ++first1, ++first2){ + if (! (*first1 == *first2)) + break; + } + if (first1 == last1){ + return true; + } + + //Establish last2 assuming equal ranges by iterating over the + //rest of the list. + ForwardIterator2 last2 = first2; + boost::intrusive::iterator_advance(last2, boost::intrusive::iterator_distance(first1, last1)); + for(ForwardIterator1 scan = first1; scan != last1; ++scan){ + if (scan != (priv_algo_find)(first1, scan, *scan)){ + continue; //We've seen this one before. + } + distance_type matches = (priv_algo_count)(first2, last2, *scan); + if (0 == matches || (priv_algo_count)(scan, last1, *scan != matches)){ + return false; + } + } + return true; +} + template struct prime_list_holder { @@ -169,35 +226,23 @@ struct unordered_bucket_ptr_impl }; template -struct store_hash_bool +struct store_hash_is_true { template - struct two_or_three {one _[2 + Add];}; - template static one test(...); + struct two_or_three {yes_type _[2 + Add];}; + template static yes_type test(...); template static two_or_three test (int); - static const std::size_t value = sizeof(test(0)); -}; - -template -struct store_hash_is_true -{ - static const bool value = store_hash_bool::value > sizeof(one)*2; + static const bool value = sizeof(test(0)) > sizeof(yes_type)*2; }; template -struct optimize_multikey_bool +struct optimize_multikey_is_true { template - struct two_or_three {one _[2 + Add];}; - template static one test(...); + struct two_or_three {yes_type _[2 + Add];}; + template static yes_type test(...); template static two_or_three test (int); - static const std::size_t value = sizeof(test(0)); -}; - -template -struct optimize_multikey_is_true -{ - static const bool value = optimize_multikey_bool::value > sizeof(one)*2; + static const bool value = sizeof(test(0)) > sizeof(yes_type)*2; }; struct insert_commit_data_impl @@ -216,6 +261,23 @@ inline typename pointer_traits::template rebind_pointer::typ template struct group_functions { + // A group is reverse-linked + // + // A is "first in group" + // C is "last in group" + // __________________ + // | _____ _____ | + // | | | | | | <- Group links + // ^ V ^ V ^ V + // _ _ _ _ + // A|_| B|_| C|_| D|_| + // + // ^ | ^ | ^ | ^ V <- Bucket links + // _ _____| |_____| |______| |____| | + // |B| | + // ^________________________________| + // + typedef NodeTraits node_traits; typedef unordered_group_adapter group_traits; typedef typename node_traits::node_ptr node_ptr; @@ -225,6 +287,7 @@ struct group_functions typedef typename reduced_node_traits::node_ptr slist_node_ptr; typedef typename reduced_node_traits::node slist_node; typedef circular_slist_algorithms group_algorithms; + typedef circular_slist_algorithms node_algorithms; static slist_node_ptr get_bucket_before_begin (const slist_node_ptr &bucket_beg, const slist_node_ptr &bucket_end, const node_ptr &p) @@ -260,53 +323,20 @@ struct group_functions static node_ptr get_prev_to_first_in_group(const slist_node_ptr &bucket_node, const node_ptr &first_in_group) { - //Just iterate using group links and obtain the node - //before "first_in_group)" - node_ptr prev_node = detail::dcast_bucket_ptr(bucket_node); - node_ptr nxt(node_traits::get_next(prev_node)); - while(nxt != first_in_group){ - prev_node = group_traits::get_next(nxt); - nxt = node_traits::get_next(prev_node); - } - return prev_node; - } - - static node_ptr get_first_in_group_of_last_in_group(const node_ptr &last_in_group) - { - //Just iterate using group links and obtain the node - //before "last_in_group" - node_ptr possible_first = group_traits::get_next(last_in_group); - node_ptr possible_first_prev = group_traits::get_next(possible_first); - // The deleted node is at the end of the group, so the - // node in the group pointing to it is at the beginning - // of the group. Find that to change its pointer. - while(possible_first_prev != last_in_group){ - possible_first = possible_first_prev; - possible_first_prev = group_traits::get_next(possible_first); + node_ptr nb = detail::dcast_bucket_ptr(bucket_node); + node_ptr n; + while((n = node_traits::get_next(nb)) != first_in_group){ + nb = group_traits::get_next(n); //go to last in group } - return possible_first; + return nb; } static void erase_from_group(const slist_node_ptr &end_ptr, const node_ptr &to_erase_ptr, detail::true_) { - node_ptr nxt_ptr(node_traits::get_next(to_erase_ptr)); - node_ptr prev_in_group_ptr(group_traits::get_next(to_erase_ptr)); - bool last_in_group = (end_ptr == nxt_ptr) || - (group_traits::get_next(nxt_ptr) != to_erase_ptr); - bool is_first_in_group = node_traits::get_next(prev_in_group_ptr) != to_erase_ptr; - - if(is_first_in_group && last_in_group){ - group_algorithms::init(to_erase_ptr); - } - else if(is_first_in_group){ - group_algorithms::unlink_after(nxt_ptr); - } - else if(last_in_group){ - node_ptr first_in_group = - get_first_in_group_of_last_in_group(to_erase_ptr); - group_algorithms::unlink_after(first_in_group); - } - else{ + node_ptr const nxt_ptr(node_traits::get_next(to_erase_ptr)); + //Check if the next node is in the group (not end node) and reverse linked to + //'to_erase_ptr'. Erase if that's the case. + if(nxt_ptr != end_ptr && to_erase_ptr == group_traits::get_next(nxt_ptr)){ group_algorithms::unlink_after(nxt_ptr); } } @@ -317,81 +347,42 @@ struct group_functions static node_ptr get_last_in_group(const node_ptr &first_in_group, detail::true_) { return group_traits::get_next(first_in_group); } - static node_ptr get_last_in_group(const node_ptr &n, detail::false_) + static node_ptr get_last_in_group(node_ptr n, detail::false_) { return n; } - static void init_group(const node_ptr &n, true_) - { group_algorithms::init(n); } - - static void init_group(const node_ptr &, false_) - {} - - static void insert_in_group(const node_ptr &first_in_group, const node_ptr &n, true_) + static node_ptr get_first_in_group(node_ptr n, detail::true_) { - if(first_in_group){ - if(group_algorithms::unique(first_in_group)) - group_algorithms::link_after(first_in_group, n); - else{ - group_algorithms::link_after(node_traits::get_next(first_in_group), n); - } - } - else{ - group_algorithms::init_header(n); + node_ptr ng; + while(n == node_traits::get_next((ng = group_traits::get_next(n)))){ + n = ng; } + return n; } - static slist_node_ptr get_previous_and_next_in_group - ( const slist_node_ptr &i, node_ptr &nxt_in_group - //If first_end_ptr == last_end_ptr, then first_end_ptr is the bucket of i - //Otherwise first_end_ptr is the first bucket and last_end_ptr the last one. - , const slist_node_ptr &first_end_ptr, const slist_node_ptr &last_end_ptr) - { - slist_node_ptr prev; - node_ptr elem(detail::dcast_bucket_ptr(i)); - - //It's the last in group if the next_node is a bucket - slist_node_ptr nxt(node_traits::get_next(elem)); - bool last_in_group = (first_end_ptr <= nxt && nxt <= last_end_ptr) || - (group_traits::get_next(detail::dcast_bucket_ptr(nxt)) != elem); - //It's the first in group if group_previous's next_node is not - //itself, as group list does not link bucket - node_ptr prev_in_group(group_traits::get_next(elem)); - bool first_in_group = node_traits::get_next(prev_in_group) != elem; - - if(first_in_group){ - node_ptr start_pos; - if(last_in_group){ - start_pos = elem; - nxt_in_group = node_ptr(); - } - else{ - start_pos = prev_in_group; - nxt_in_group = node_traits::get_next(elem); - } - slist_node_ptr bucket_node; - if(first_end_ptr != last_end_ptr){ - bucket_node = group_functions::get_bucket_before_begin - (first_end_ptr, last_end_ptr, start_pos); - } - else{ - bucket_node = first_end_ptr; - } - prev = group_functions::get_prev_to_first_in_group(bucket_node, elem); - } - else{ - if(last_in_group){ - nxt_in_group = group_functions::get_first_in_group_of_last_in_group(elem); - } - else{ - nxt_in_group = node_traits::get_next(elem); - } - prev = group_traits::get_next(elem); - } - return prev; + static node_ptr next_group_if_first_in_group(node_ptr ptr) + { + return node_traits::get_next(group_traits::get_next(ptr)); } + static node_ptr get_first_in_group(const node_ptr &n, detail::false_) + { return n; } + + static void insert_in_group(const node_ptr &first_in_group, const node_ptr &n, true_) + { group_algorithms::link_after(first_in_group, n); } + static void insert_in_group(const node_ptr&, const node_ptr&, false_) {} + + static node_ptr split_group(node_ptr const new_first_in_group) + { + node_ptr const first((get_first_in_group)(new_first_in_group, detail::true_())); + if(first != new_first_in_group){ + node_ptr const last = group_traits::get_next(first); + group_traits::set_next(first, group_traits::get_next(new_first_in_group)); + group_traits::set_next(new_first_in_group, last); + } + return first; + } }; template @@ -453,8 +444,7 @@ inline std::size_t hash_to_bucket_split(std::size_t hash_value, std::size_t buck { std::size_t bucket_number = detail::hash_to_bucket(hash_value, bucket_cnt, detail::bool_()); if(Incremental) - if(bucket_number >= split) - bucket_number -= bucket_cnt/2; + bucket_number -= static_cast(bucket_number >= split)*(bucket_cnt/2); return bucket_number; } @@ -513,6 +503,7 @@ struct hashtable_defaults { typedef default_hashtable_hook_applier proto_value_traits; typedef std::size_t size_type; + typedef void key_of_value; typedef void equal; typedef void hash; typedef default_bucket_traits bucket_traits; @@ -576,17 +567,11 @@ struct node_cast_adaptor } }; -static const std::size_t hashtable_data_bool_flags_mask = - ( hash_bool_flags::cache_begin_pos - | hash_bool_flags::constant_time_size_pos - | hash_bool_flags::incremental_pos - ); - //bucket_plus_vtraits stores ValueTraits + BucketTraits //this data is needed by iterators to obtain the //value from the iterator and detect the bucket template -struct bucket_plus_vtraits : public ValueTraits +struct bucket_plus_vtraits { typedef BucketTraits bucket_traits; typedef ValueTraits value_traits; @@ -607,6 +592,11 @@ struct bucket_plus_vtraits : public ValueTraits typedef typename node_traits::node_ptr node_ptr; typedef typename node_traits::node node; typedef typename value_traits::value_type value_type; + typedef typename value_traits::pointer pointer; + typedef typename value_traits::const_pointer const_pointer; + typedef typename pointer_traits::reference reference; + typedef typename pointer_traits + ::reference const_reference; typedef circular_slist_algorithms group_algorithms; typedef typename pointer_traits :: @@ -618,16 +608,14 @@ struct bucket_plus_vtraits : public ValueTraits ::type const_bucket_value_traits_ptr; typedef typename detail::unordered_bucket_ptr_impl ::type bucket_ptr; - typedef detail::bool_::value> optimize_multikey_t; template bucket_plus_vtraits(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits) - : ValueTraits(val_traits), bucket_traits_(::boost::forward(b_traits)) + : data(val_traits, ::boost::forward(b_traits)) {} bucket_plus_vtraits & operator =(const bucket_plus_vtraits &x) - { bucket_traits_ = x.bucket_traits_; return *this; } + { data.bucket_traits_ = x.data.bucket_traits_; return *this; } const_value_traits_ptr priv_value_traits_ptr() const { return pointer_traits::pointer_to(this->priv_value_traits()); } @@ -646,18 +634,18 @@ struct bucket_plus_vtraits : public ValueTraits //value traits // const value_traits &priv_value_traits() const - { return *this; } + { return this->data; } value_traits &priv_value_traits() - { return *this; } + { return this->data; } //bucket_traits // const bucket_traits &priv_bucket_traits() const - { return this->bucket_traits_; } + { return this->data.bucket_traits_; } bucket_traits &priv_bucket_traits() - { return this->bucket_traits_; } + { return this->data.bucket_traits_; } //bucket operations bucket_ptr priv_bucket_pointer() const @@ -674,6 +662,119 @@ struct bucket_plus_vtraits : public ValueTraits siterator priv_invalid_local_it() const { return this->priv_bucket_traits().bucket_begin()->before_begin(); } + template + static size_type priv_erase_from_single_bucket(bucket_type &b, siterator sbefore_first, siterator slast, NodeDisposer node_disposer, detail::true_) //optimize multikey + { + size_type n = 0; + siterator const sfirst(++siterator(sbefore_first)); + if(sfirst != slast){ + node_ptr const nf = detail::dcast_bucket_ptr(sfirst.pointed_node()); + node_ptr const nl = detail::dcast_bucket_ptr(slast.pointed_node()); + node_ptr const ne = detail::dcast_bucket_ptr(b.end().pointed_node()); + + if(group_functions_t::next_group_if_first_in_group(nf) != nf) { + // The node is at the beginning of a group. + if(nl != ne){ + group_functions_t::split_group(nl); + } + } + else { + node_ptr const group1 = group_functions_t::split_group(nf); + if(nl != ne) { + node_ptr const group2 = group_functions_t::split_group(ne); + if(nf == group2) { //Both first and last in the same group + //so join group1 and group2 + node_ptr const end1 = group_traits::get_next(group1); + node_ptr const end2 = group_traits::get_next(group2); + group_traits::set_next(group1, end2); + group_traits::set_next(group2, end1); + } + } + } + + siterator it(++siterator(sbefore_first)); + while(it != slast){ + node_disposer((it++).pointed_node()); + ++n; + } + b.erase_after(sbefore_first, slast); + } + return n; + } + + template + static size_type priv_erase_from_single_bucket(bucket_type &b, siterator sbefore_first, siterator slast, NodeDisposer node_disposer, detail::false_) //optimize multikey + { + size_type n = 0; + siterator it(++siterator(sbefore_first)); + while(it != slast){ + node_disposer((it++).pointed_node()); + ++n; + } + b.erase_after(sbefore_first, slast); + return n; + } + + template + static void priv_erase_node(bucket_type &b, siterator i, NodeDisposer node_disposer, detail::true_) //optimize multikey + { + node_ptr const ne(detail::dcast_bucket_ptr(b.end().pointed_node())); + node_ptr n(detail::dcast_bucket_ptr(i.pointed_node())); + node_ptr pos = node_traits::get_next(group_traits::get_next(n)); + node_ptr bn; + node_ptr nn(node_traits::get_next(n)); + + if(pos != n) { + //Node is the first of the group + bn = group_functions_t::get_prev_to_first_in_group(ne, n); + + //Unlink the rest of the group if it's not the last node of its group + if(nn != ne && group_traits::get_next(nn) == n){ + group_algorithms::unlink_after(nn); + } + } + else if(nn != ne && group_traits::get_next(nn) == n){ + //Node is not the end of the group + bn = group_traits::get_next(n); + group_algorithms::unlink_after(nn); + } + else{ + //Node is the end of the group + bn = group_traits::get_next(n); + node_ptr const x(group_algorithms::get_previous_node(n)); + group_algorithms::unlink_after(x); + } + b.erase_after_and_dispose(bucket_type::s_iterator_to(*bn), node_disposer); + } + + template + static void priv_erase_node(bucket_type &b, siterator i, NodeDisposer node_disposer, detail::false_) //optimize multikey + { b.erase_after_and_dispose(b.previous(i), node_disposer); } + + template + size_type priv_erase_node_range( siterator const &before_first_it, size_type const first_bucket + , siterator const &last_it, size_type const last_bucket + , NodeDisposer node_disposer, detail::bool_ optimize_multikey_tag) + { + size_type num_erased(0); + siterator last_step_before_it; + if(first_bucket != last_bucket){ + bucket_type *b = (&this->priv_bucket_pointer()[0]); + num_erased += this->priv_erase_from_single_bucket + (b[first_bucket], before_first_it, b[first_bucket].end(), node_disposer, optimize_multikey_tag); + for(size_type i = 0, n = (last_bucket - first_bucket - 1); i != n; ++i){ + num_erased += this->priv_erase_whole_bucket(b[first_bucket+i+1], node_disposer); + } + last_step_before_it = b[last_bucket].before_begin(); + } + else{ + last_step_before_it = before_first_it; + } + num_erased += this->priv_erase_from_single_bucket + (this->priv_bucket_pointer()[last_bucket], last_step_before_it, last_it, node_disposer, optimize_multikey_tag); + return num_erased; + } + static siterator priv_get_last(bucket_type &b, detail::true_) //optimize multikey { //First find the last node of p's group. @@ -690,14 +791,30 @@ struct bucket_plus_vtraits : public ValueTraits return bucket_type::s_iterator_to(*last_node_group); } + template + size_type priv_erase_whole_bucket(bucket_type &b, NodeDisposer node_disposer) + { + size_type num_erased = 0; + siterator b_begin(b.before_begin()); + siterator nxt(b_begin); + ++nxt; + siterator const end_sit(b.end()); + while(nxt != end_sit){ + //No need to init group links as we'll delete all bucket nodes + nxt = bucket_type::s_erase_after_and_dispose(b_begin, node_disposer); + ++num_erased; + } + return num_erased; + } + static siterator priv_get_last(bucket_type &b, detail::false_) //NOT optimize multikey { return b.previous(b.end()); } static siterator priv_get_previous(bucket_type &b, siterator i, detail::true_) //optimize multikey { - node_ptr elem(detail::dcast_bucket_ptr(i.pointed_node())); - node_ptr prev_in_group(group_traits::get_next(elem)); - bool first_in_group = node_traits::get_next(prev_in_group) != elem; + node_ptr const elem(detail::dcast_bucket_ptr(i.pointed_node())); + node_ptr const prev_in_group(group_traits::get_next(elem)); + bool const first_in_group = node_traits::get_next(prev_in_group) != elem; typename bucket_type::node &n = first_in_group ? *group_functions_t::get_prev_to_first_in_group(b.end().pointed_node(), elem) : *group_traits::get_next(elem) @@ -708,19 +825,6 @@ struct bucket_plus_vtraits : public ValueTraits static siterator priv_get_previous(bucket_type &b, siterator i, detail::false_) //NOT optimize multikey { return b.previous(i); } - static void priv_clear_group_nodes(bucket_type &b, detail::true_) //optimize multikey - { - siterator it(b.begin()), itend(b.end()); - while(it != itend){ - node_ptr to_erase(detail::dcast_bucket_ptr(it.pointed_node())); - ++it; - group_algorithms::init(to_erase); - } - } - - static void priv_clear_group_nodes(bucket_type &, detail::false_) //NOT optimize multikey - {} - std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::true_) //optimize multikey { const bucket_ptr f(this->priv_bucket_pointer()), l(f + this->priv_bucket_count() - 1); @@ -757,19 +861,19 @@ struct bucket_plus_vtraits : public ValueTraits static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) //store_hash { return node_traits::get_hash(detail::dcast_bucket_ptr(n)); } - static std::size_t priv_stored_hash(slist_node_ptr, detail::false_) //NO store_hash (This should never be called) - { BOOST_INTRUSIVE_INVARIANT_ASSERT(0); return 0; } + static std::size_t priv_stored_hash(slist_node_ptr, detail::false_) //NO store_hash + { return std::size_t(-1); } - node &priv_value_to_node(value_type &v) + node &priv_value_to_node(reference v) { return *this->priv_value_traits().to_node_ptr(v); } - const node &priv_value_to_node(const value_type &v) const + const node &priv_value_to_node(const_reference v) const { return *this->priv_value_traits().to_node_ptr(v); } - value_type &priv_value_from_slist_node(slist_node_ptr n) + reference priv_value_from_slist_node(slist_node_ptr n) { return *this->priv_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } - const value_type &priv_value_from_slist_node(slist_node_ptr n) const + const_reference priv_value_from_slist_node(slist_node_ptr n) const { return *this->priv_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } void priv_clear_buckets(const bucket_ptr buckets_ptr, const size_type bucket_cnt) @@ -777,7 +881,6 @@ struct bucket_plus_vtraits : public ValueTraits bucket_ptr buckets_it = buckets_ptr; for(size_type bucket_i = 0; bucket_i != bucket_cnt; ++buckets_it, ++bucket_i){ if(safemode_or_autounlink){ - bucket_plus_vtraits::priv_clear_group_nodes(*buckets_it, optimize_multikey_t()); buckets_it->clear_and_dispose(detail::init_disposer()); } else{ @@ -786,10 +889,51 @@ struct bucket_plus_vtraits : public ValueTraits } } - bucket_traits bucket_traits_; + std::size_t priv_stored_or_compute_hash(const value_type &v, detail::true_) const //For store_hash == true + { return node_traits::get_hash(this->priv_value_traits().to_node_ptr(v)); } + + typedef hashtable_iterator iterator; + typedef hashtable_iterator const_iterator; + + iterator end() + { return iterator(this->priv_invalid_local_it(), 0); } + + const_iterator end() const + { return this->cend(); } + + const_iterator cend() const + { return const_iterator(this->priv_invalid_local_it(), 0); } + + static size_type suggested_upper_bucket_count(size_type n) + { + const std::size_t *primes = &prime_list_holder<0>::prime_list[0]; + const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size; + std::size_t const* bound = std::lower_bound(primes, primes_end, n); + bound -= (bound == primes_end); + return size_type(*bound); + } + + static size_type suggested_lower_bucket_count(size_type n) + { + const std::size_t *primes = &prime_list_holder<0>::prime_list[0]; + const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size; + size_type const* bound = std::upper_bound(primes, primes_end, n); + bound -= (bound != primes); + return size_type(*bound); + } + + //Public functions: + struct data_type : public ValueTraits + { + template + data_type(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits) + : ValueTraits(val_traits), bucket_traits_(::boost::forward(b_traits)) + {} + bucket_traits bucket_traits_; + } data; }; -template +template struct get_hash { typedef Hash type; @@ -801,76 +945,124 @@ struct get_hash typedef ::boost::hash type; }; +template +struct get_equal_to +{ + typedef EqualTo type; +}; + +template +struct get_equal_to +{ + typedef std::equal_to type; +}; + +template +struct get_hash_key_of_value +{ + typedef KeyOfValue type; +}; + +template +struct get_hash_key_of_value +{ + typedef ::boost::intrusive::detail::identity type; +}; + +template +struct hash_key_types_base +{ + typedef typename get_hash_key_of_value + < VoidOrKeyOfValue, T>::type key_of_value; + typedef typename key_of_value::type key_type; +}; + +template +struct hash_key_hash + : get_hash + < VoidOrKeyHash + , typename hash_key_types_base::key_type + > +{}; + +template +struct hash_key_equal + : get_equal_to + < VoidOrKeyEqual + , typename hash_key_types_base::key_type + > + +{}; + //bucket_hash_t //Stores bucket_plus_vtraits plust the hash function -template +template struct bucket_hash_t //Use public inheritance to avoid MSVC bugs with closures : public detail::ebo_functor_holder - ::value_traits::value_type - >::type - > + ::value_traits::value_type + , VoidOrKeyOfValue + , VoidOrKeyHash + >::type + > + , bucket_plus_vtraits //4 { typedef typename bucket_plus_vtraits::value_traits value_traits; typedef typename value_traits::value_type value_type; typedef typename value_traits::node_traits node_traits; - typedef typename get_hash< VoidOrKeyHash, value_type>::type hasher; + typedef hash_key_hash + < value_type, VoidOrKeyOfValue, VoidOrKeyHash> hash_key_hash_t; + typedef typename hash_key_hash_t::type hasher; + typedef typename hash_key_types_base::key_of_value key_of_value; + typedef BucketTraits bucket_traits; typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef detail::ebo_functor_holder base_t; template bucket_hash_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h) - : detail::ebo_functor_holder(h), internal(val_traits, ::boost::forward(b_traits)) + : detail::ebo_functor_holder(h), bucket_plus_vtraits_t(val_traits, ::boost::forward(b_traits)) {} const hasher &priv_hasher() const - { return this->detail::ebo_functor_holder::get(); } + { return this->base_t::get(); } hasher &priv_hasher() - { return this->detail::ebo_functor_holder::get(); } + { return this->base_t::get(); } - std::size_t priv_stored_or_compute_hash(const value_type &v, detail::true_) const //For store_hash == true - { return node_traits::get_hash(this->internal.priv_value_traits().to_node_ptr(v)); } + using bucket_plus_vtraits_t::priv_stored_or_compute_hash; //For store_hash == true std::size_t priv_stored_or_compute_hash(const value_type &v, detail::false_) const //For store_hash == false - { return this->priv_hasher()(v); } - - bucket_plus_vtraits_t internal; //4 -}; - - -template -struct get_equal_to -{ - typedef EqualTo type; + { return this->priv_hasher()(key_of_value()(v)); } }; -template -struct get_equal_to +template +struct hashtable_equal_holder { - typedef ::std::equal_to type; + typedef detail::ebo_functor_holder + < typename hash_key_equal < typename bucket_plus_vtraits::value_traits::value_type + , VoidOrKeyOfValue + , VoidOrKeyEqual + >::type + > type; }; //bucket_hash_equal_t //Stores bucket_hash_t and the equality function when the first //non-empty bucket shall not be cached. -template +template struct bucket_hash_equal_t //Use public inheritance to avoid MSVC bugs with closures - : public detail::ebo_functor_holder //equal - ::value_traits::value_type - >::type - > + : public bucket_hash_t //3 + , public hashtable_equal_holder::type //equal { - typedef bucket_hash_t bucket_hash_type; + typedef typename hashtable_equal_holder + ::type equal_holder_t; + typedef bucket_hash_t bucket_hash_type; typedef bucket_plus_vtraits bucket_plus_vtraits_t; - typedef typename bucket_plus_vtraits_t::value_traits value_traits; - typedef typename get_equal_to< VoidOrKeyEqual - , typename value_traits::value_type - >::type value_equal; + typedef ValueTraits value_traits; + typedef typename equal_holder_t::functor_type key_equal; typedef typename bucket_hash_type::hasher hasher; typedef BucketTraits bucket_traits; typedef typename bucket_plus_vtraits_t::slist_impl slist_impl; @@ -880,13 +1072,13 @@ struct bucket_hash_equal_t typedef typename detail::unordered_bucket_ptr_impl::type bucket_ptr; template - bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) - : detail::ebo_functor_holder(e) - , internal(val_traits, ::boost::forward(b_traits), h) + bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const key_equal &e) + : bucket_hash_type(val_traits, ::boost::forward(b_traits), h) + , equal_holder_t(e) {} bucket_ptr priv_get_cache() - { return this->internal.internal.priv_bucket_pointer(); } + { return this->bucket_hash_type::priv_bucket_pointer(); } void priv_set_cache(const bucket_ptr &) {} @@ -903,14 +1095,14 @@ struct bucket_hash_equal_t siterator priv_begin() const { size_type n = 0; - size_type bucket_cnt = this->internal.internal.priv_bucket_count(); + size_type bucket_cnt = this->bucket_hash_type::priv_bucket_count(); for (n = 0; n < bucket_cnt; ++n){ - bucket_type &b = this->internal.internal.priv_bucket_pointer()[n]; + bucket_type &b = this->bucket_hash_type::priv_bucket_pointer()[n]; if(!b.empty()){ return b.begin(); } } - return this->internal.internal.priv_invalid_local_it(); + return this->bucket_hash_type::priv_invalid_local_it(); } void priv_insertion_update_cache(size_type) @@ -922,43 +1114,38 @@ struct bucket_hash_equal_t void priv_erasure_update_cache() {} - const value_equal &priv_equal() const - { return this->detail::ebo_functor_holder::get(); } - - value_equal &priv_equal() - { return this->detail::ebo_functor_holder::get(); } + const key_equal &priv_equal() const + { return this->equal_holder_t::get(); } - bucket_hash_t internal; //3 + key_equal &priv_equal() + { return this->equal_holder_t::get(); } }; //bucket_hash_equal_t //Stores bucket_hash_t and the equality function when the first //non-empty bucket shall be cached. -template //cache_begin == true version -struct bucket_hash_equal_t +template //cache_begin == true version +struct bucket_hash_equal_t //Use public inheritance to avoid MSVC bugs with closures - : public detail::ebo_functor_holder //equal - ::value_traits::value_type - >::type - > + : bucket_hash_t //2 + , hashtable_equal_holder::type { - typedef bucket_plus_vtraits bucket_plus_vtraits_t; - typedef bucket_hash_t bucket_hash_type; - typedef typename bucket_plus_vtraits - ::value_traits value_traits; - typedef typename get_equal_to - < VoidOrKeyEqual - , typename value_traits::value_type>::type value_equal; + typedef typename hashtable_equal_holder + ::type equal_holder_t; + + typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef ValueTraits value_traits; + typedef typename equal_holder_t::functor_type key_equal; + typedef bucket_hash_t bucket_hash_type; typedef typename bucket_hash_type::hasher hasher; typedef BucketTraits bucket_traits; typedef typename bucket_plus_vtraits_t::slist_impl::size_type size_type; typedef typename bucket_plus_vtraits_t::slist_impl::iterator siterator; template - bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) - : detail::ebo_functor_holder(e) - , internal(val_traits, ::boost::forward(b_traits), h) + bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const key_equal &e) + : bucket_hash_type(val_traits, ::boost::forward(b_traits), h) + , equal_holder_t(e) {} typedef typename detail::unordered_bucket_ptr_impl @@ -974,10 +1161,10 @@ struct bucket_hash_equal_tcached_begin_ - this->internal.internal.priv_bucket_pointer(); } + { return this->cached_begin_ - this->bucket_hash_type::priv_bucket_pointer(); } void priv_initialize_cache() - { this->cached_begin_ = this->internal.internal.priv_invalid_bucket(); } + { this->cached_begin_ = this->bucket_hash_type::priv_invalid_bucket(); } void priv_swap_cache(bucket_hash_equal_t &other) { @@ -986,8 +1173,8 @@ struct bucket_hash_equal_tcached_begin_ == this->internal.internal.priv_invalid_bucket()){ - return this->internal.internal.priv_invalid_local_it(); + if(this->cached_begin_ == this->bucket_hash_type::priv_invalid_bucket()){ + return this->bucket_hash_type::priv_invalid_local_it(); } else{ return this->cached_begin_->begin(); @@ -996,34 +1183,34 @@ struct bucket_hash_equal_tinternal.internal.priv_bucket_pointer() + insertion_bucket; + bucket_ptr p = this->bucket_hash_type::priv_bucket_pointer() + insertion_bucket; if(p < this->cached_begin_){ this->cached_begin_ = p; } } - const value_equal &priv_equal() const - { return this->detail::ebo_functor_holder::get(); } + const key_equal &priv_equal() const + { return this->equal_holder_t::get(); } - value_equal &priv_equal() - { return this->detail::ebo_functor_holder::get(); } + key_equal &priv_equal() + { return this->equal_holder_t::get(); } void priv_erasure_update_cache_range(size_type first_bucket_num, size_type last_bucket_num) { //If the last bucket is the end, the cache must be updated //to the last position if all if(this->priv_get_cache_bucket_num() == first_bucket_num && - this->internal.internal.priv_bucket_pointer()[first_bucket_num].empty() ){ - this->priv_set_cache(this->internal.internal.priv_bucket_pointer() + last_bucket_num); + this->bucket_hash_type::priv_bucket_pointer()[first_bucket_num].empty() ){ + this->priv_set_cache(this->bucket_hash_type::priv_bucket_pointer() + last_bucket_num); this->priv_erasure_update_cache(); } } void priv_erasure_update_cache() { - if(this->cached_begin_ != this->internal.internal.priv_invalid_bucket()){ - size_type current_n = this->priv_get_cache() - this->internal.internal.priv_bucket_pointer(); - for( const size_type num_buckets = this->internal.internal.priv_bucket_count() + if(this->cached_begin_ != this->bucket_hash_type::priv_invalid_bucket()){ + size_type current_n = this->priv_get_cache() - this->bucket_hash_type::priv_bucket_pointer(); + for( const size_type num_buckets = this->bucket_hash_type::priv_bucket_count() ; current_n < num_buckets ; ++current_n, ++this->priv_get_cache()){ if(!this->priv_get_cache()->empty()){ @@ -1035,103 +1222,291 @@ struct bucket_hash_equal_t internal; //2 }; +//This wrapper around size_traits is used +//to maintain minimal container size with compilers like MSVC +//that have problems with EBO and multiple empty base classes +template +struct hashtable_size_traits_wrapper + : public DeriveFrom +{ + template + hashtable_size_traits_wrapper( BOOST_FWD_REF(Base) base, BOOST_FWD_REF(Arg0) arg0 + , BOOST_FWD_REF(Arg1) arg1, BOOST_FWD_REF(Arg2) arg2) + : DeriveFrom(::boost::forward(base) + , ::boost::forward(arg0) + , ::boost::forward(arg1) + , ::boost::forward(arg2)) + {} + typedef detail::size_holder < true, SizeType> size_traits;//size_traits + + size_traits size_traits_; + + const size_traits &priv_size_traits() const + { return size_traits_; } + + size_traits &priv_size_traits() + { return size_traits_; } +}; + +template +struct hashtable_size_traits_wrapper + : public DeriveFrom +{ + template + hashtable_size_traits_wrapper( BOOST_FWD_REF(Base) base, BOOST_FWD_REF(Arg0) arg0 + , BOOST_FWD_REF(Arg1) arg1, BOOST_FWD_REF(Arg2) arg2) + : DeriveFrom(::boost::forward(base) + , ::boost::forward(arg0) + , ::boost::forward(arg1) + , ::boost::forward(arg2)) + {} + + typedef detail::size_holder< false, SizeType> size_traits; + + const size_traits &priv_size_traits() const + { return size_traits_; } + + size_traits &priv_size_traits() + { return size_traits_; } + + static size_traits size_traits_; +}; + +template +detail::size_holder< false, SizeType > hashtable_size_traits_wrapper::size_traits_; + //hashdata_internal //Stores bucket_hash_equal_t and split_traits -template +template struct hashdata_internal - : public detail::size_holder< 0 != (BoolFlags & hash_bool_flags::incremental_pos), SizeType, int> //split_traits + : public hashtable_size_traits_wrapper + < bucket_hash_equal_t + < ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual + , BucketTraits + , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos) + > //2 + , SizeType + , (BoolFlags & hash_bool_flags::incremental_pos) != 0 + > { - typedef bucket_hash_equal_t - < VoidOrKeyHash, VoidOrKeyEqual - , ValueTraits, BucketTraits - , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos) + typedef hashtable_size_traits_wrapper + < bucket_hash_equal_t + < ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual + , BucketTraits + , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos) + > //2 + , SizeType + , (BoolFlags & hash_bool_flags::incremental_pos) != 0 > internal_type; - typedef typename internal_type::value_equal value_equal; + typedef typename internal_type::key_equal key_equal; typedef typename internal_type::hasher hasher; typedef bucket_plus_vtraits bucket_plus_vtraits_t; typedef typename bucket_plus_vtraits_t::size_type size_type; + typedef typename internal_type::size_traits split_traits; typedef typename bucket_plus_vtraits_t::bucket_ptr bucket_ptr; - typedef detail::size_holder - <0 != (BoolFlags & hash_bool_flags::incremental_pos) - , SizeType, int> split_traits; - typedef typename bucket_plus_vtraits_t:: - value_traits::node_traits node_traits; - typedef detail::bool_::value> optimize_multikey_t; + typedef typename bucket_plus_vtraits_t::const_value_traits_ptr const_value_traits_ptr; + typedef typename bucket_plus_vtraits_t::siterator siterator; + typedef typename bucket_plus_vtraits_t::bucket_traits bucket_traits; + typedef typename bucket_plus_vtraits_t::value_traits value_traits; + typedef typename bucket_plus_vtraits_t::bucket_type bucket_type; + typedef typename value_traits::value_type value_type; + typedef typename value_traits::pointer pointer; + typedef typename value_traits::const_pointer const_pointer; + typedef typename pointer_traits::reference reference; + typedef typename pointer_traits + ::reference const_reference; + typedef typename value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef detail::node_functions node_functions_t; + typedef typename detail::get_slist_impl + ::type + >::type slist_impl; + typedef typename slist_impl::node_algorithms node_algorithms; + typedef typename slist_impl::node_ptr slist_node_ptr; + + typedef hash_key_types_base + < typename ValueTraits::value_type + , VoidOrKeyOfValue + > hash_types_base; + typedef typename hash_types_base::key_of_value key_of_value; + + static const bool store_hash = detail::store_hash_is_true::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + + typedef detail::bool_ store_hash_t; + + typedef detail::transform_iterator + < typename slist_impl::iterator + , downcast_node_to_value_t + < value_traits + , false> > local_iterator; + + typedef detail::transform_iterator + < typename slist_impl::iterator + , downcast_node_to_value_t + < value_traits + , true> > const_local_iterator; + // template hashdata_internal( const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits - , const hasher & h, const value_equal &e) - : internal(val_traits, ::boost::forward(b_traits), h, e) + , const hasher & h, const key_equal &e) + : internal_type(val_traits, ::boost::forward(b_traits), h, e) {} split_traits &priv_split_traits() - { return *this; } + { return this->priv_size_traits(); } const split_traits &priv_split_traits() const - { return *this; } + { return this->priv_size_traits(); } ~hashdata_internal() { this->priv_clear_buckets(); } void priv_clear_buckets() { - this->internal.internal.internal.priv_clear_buckets - ( this->internal.priv_get_cache() - , this->internal.internal.internal.priv_bucket_count() - - (this->internal.priv_get_cache() - - this->internal.internal.internal.priv_bucket_pointer())); + this->internal_type::priv_clear_buckets + ( this->priv_get_cache() + , this->internal_type::priv_bucket_count() + - (this->priv_get_cache() + - this->internal_type::priv_bucket_pointer())); } void priv_clear_buckets_and_cache() { this->priv_clear_buckets(); - this->internal.priv_initialize_cache(); + this->priv_initialize_cache(); } void priv_initialize_buckets_and_cache() { - this->internal.internal.internal.priv_clear_buckets - ( this->internal.internal.internal.priv_bucket_pointer() - , this->internal.internal.internal.priv_bucket_count()); - this->internal.priv_initialize_cache(); + this->internal_type::priv_clear_buckets + ( this->internal_type::priv_bucket_pointer() + , this->internal_type::priv_bucket_count()); + this->priv_initialize_cache(); } - internal_type internal; //2 -}; + typedef hashtable_iterator iterator; + typedef hashtable_iterator const_iterator; -//hashtable_data_t -//Stores hashdata_internal and size_traits -template -struct hashtable_data_t - : public detail::size_holder - < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos), SizeType> //size_traits -{ - typedef detail::size_holder - < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos) - , SizeType> size_traits; - typedef hashdata_internal - < SizeType - , BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) - , VoidOrKeyHash, VoidOrKeyEqual - , ValueTraits, BucketTraits> internal_type; - typedef ValueTraits value_traits; - typedef typename internal_type::value_equal value_equal; - typedef typename internal_type::hasher hasher; - typedef BucketTraits bucket_traits; - typedef bucket_plus_vtraits - bucket_plus_vtraits_t; + static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_ true_value) + { return bucket_plus_vtraits::priv_stored_hash(n, true_value); } - template - hashtable_data_t( BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h - , const value_equal &e, const value_traits &val_traits) - : internal(val_traits, ::boost::forward(b_traits), h, e) - {} + static std::size_t priv_stored_hash(slist_node_ptr n, detail::false_ false_value) + { return bucket_plus_vtraits::priv_stored_hash(n, false_value); } + + //public functions + SizeType split_count() const + { + return this->priv_split_traits().get_size(); + } + + iterator iterator_to(reference value) + { + return iterator(bucket_type::s_iterator_to + (this->priv_value_to_node(value)), &this->get_bucket_value_traits()); + } + + const_iterator iterator_to(const_reference value) const + { + siterator const sit = bucket_type::s_iterator_to + ( *pointer_traits::const_cast_from + (pointer_traits::pointer_to(this->priv_value_to_node(value))) + ); + return const_iterator(sit, &this->get_bucket_value_traits()); + } + + static local_iterator s_local_iterator_to(reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + siterator sit = bucket_type::s_iterator_to(*value_traits::to_node_ptr(value)); + return local_iterator(sit, const_value_traits_ptr()); + } + + static const_local_iterator s_local_iterator_to(const_reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + siterator const sit = bucket_type::s_iterator_to + ( *pointer_traits::const_cast_from + (value_traits::to_node_ptr(value)) + ); + return const_local_iterator(sit, const_value_traits_ptr()); + } + + local_iterator local_iterator_to(reference value) + { + siterator sit = bucket_type::s_iterator_to(this->priv_value_to_node(value)); + return local_iterator(sit, this->priv_value_traits_ptr()); + } + + const_local_iterator local_iterator_to(const_reference value) const + { + siterator sit = bucket_type::s_iterator_to + ( *pointer_traits::const_cast_from + (pointer_traits::pointer_to(this->priv_value_to_node(value))) + ); + return const_local_iterator(sit, this->priv_value_traits_ptr()); + } + + size_type bucket_count() const + { return this->priv_bucket_count(); } + + size_type bucket_size(size_type n) const + { return this->priv_bucket_pointer()[n].size(); } + + bucket_ptr bucket_pointer() const + { return this->priv_bucket_pointer(); } + + local_iterator begin(size_type n) + { return local_iterator(this->priv_bucket_pointer()[n].begin(), this->priv_value_traits_ptr()); } + + const_local_iterator begin(size_type n) const + { return this->cbegin(n); } + + const_local_iterator cbegin(size_type n) const + { + return const_local_iterator + ( pointer_traits::const_cast_from(this->priv_bucket_pointer())[n].begin() + , this->priv_value_traits_ptr()); + } + + using internal_type::end; + using internal_type::cend; + local_iterator end(size_type n) + { return local_iterator(this->priv_bucket_pointer()[n].end(), this->priv_value_traits_ptr()); } + + const_local_iterator end(size_type n) const + { return this->cend(n); } + + const_local_iterator cend(size_type n) const + { + return const_local_iterator + ( pointer_traits::const_cast_from(this->priv_bucket_pointer())[n].end() + , this->priv_value_traits_ptr()); + } + + //Public functions for hashtable_impl + + iterator begin() + { return iterator(this->priv_begin(), &this->get_bucket_value_traits()); } + + const_iterator begin() const + { return this->cbegin(); } - internal_type internal; //1 + const_iterator cbegin() const + { return const_iterator(this->priv_begin(), &this->get_bucket_value_traits()); } + + hasher hash_function() const + { return this->priv_hasher(); } + + key_equal key_eq() const + { return this->priv_equal(); } }; /// @endcond @@ -1175,61 +1550,82 @@ struct hashtable_data_t #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class hashtable_impl - : private hashtable_data_t - < SizeType - , BoolFlags & hashtable_data_bool_flags_mask - , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> + : private hashtable_size_traits_wrapper + < hashdata_internal + < ValueTraits + , VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual + , BucketTraits, SizeType + , BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) //1 + > + , SizeType + , (BoolFlags & hash_bool_flags::constant_time_size_pos) != 0 + > { - typedef hashtable_data_t - < SizeType - , BoolFlags & hashtable_data_bool_flags_mask - , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> data_type; - + typedef hashtable_size_traits_wrapper + < hashdata_internal + < ValueTraits + , VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual + , BucketTraits, SizeType + , BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) //1 + > + , SizeType + , (BoolFlags & hash_bool_flags::constant_time_size_pos) != 0 + > internal_type; + typedef typename internal_type::size_traits size_traits; + typedef hash_key_types_base + < typename ValueTraits::value_type + , VoidOrKeyOfValue + > hash_types_base; public: typedef ValueTraits value_traits; /// @cond typedef BucketTraits bucket_traits; - typedef typename detail::get_slist_impl - ::type - >::type slist_impl; + typedef typename internal_type::slist_impl slist_impl; typedef bucket_plus_vtraits bucket_plus_vtraits_t; typedef typename bucket_plus_vtraits_t::const_value_traits_ptr const_value_traits_ptr; + using internal_type::begin; + using internal_type::cbegin; + using internal_type::end; + using internal_type::cend; + using internal_type::hash_function; + using internal_type::key_eq; + using internal_type::bucket_size; + using internal_type::bucket_count; + using internal_type::local_iterator_to; + using internal_type::s_local_iterator_to; + using internal_type::iterator_to; + using internal_type::bucket_pointer; + using internal_type::suggested_upper_bucket_count; + using internal_type::suggested_lower_bucket_count; + using internal_type::split_count; /// @endcond typedef typename value_traits::pointer pointer; typedef typename value_traits::const_pointer const_pointer; typedef typename value_traits::value_type value_type; + typedef typename hash_types_base::key_type key_type; + typedef typename hash_types_base::key_of_value key_of_value; typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; typedef SizeType size_type; - typedef value_type key_type; - typedef typename data_type::value_equal key_equal; - typedef typename data_type::value_equal value_equal; - typedef typename data_type::hasher hasher; + typedef typename internal_type::key_equal key_equal; + typedef typename internal_type::hasher hasher; typedef detail::bucket_impl bucket_type; - typedef typename pointer_traits - ::template rebind_pointer - < bucket_type >::type bucket_ptr; - typedef typename pointer_traits - ::template rebind_pointer - < const bucket_type >::type const_bucket_ptr; - typedef typename pointer_traits - ::reference bucket_reference; - typedef typename pointer_traits - ::reference const_bucket_reference; + typedef typename internal_type::bucket_ptr bucket_ptr; typedef typename slist_impl::iterator siterator; typedef typename slist_impl::const_iterator const_siterator; - typedef hashtable_iterator iterator; - typedef hashtable_iterator const_iterator; + typedef typename internal_type::iterator iterator; + typedef typename internal_type::const_iterator const_iterator; + typedef typename internal_type::local_iterator local_iterator; + typedef typename internal_type::const_local_iterator const_local_iterator; typedef typename value_traits::node_traits node_traits; typedef typename node_traits::node node; typedef typename pointer_traits @@ -1244,8 +1640,8 @@ class hashtable_impl ::reference const_node_reference; typedef typename slist_impl::node_algorithms node_algorithms; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; - static const bool store_hash = detail::store_hash_is_true::value; + static const bool stateful_value_traits = internal_type::stateful_value_traits; + static const bool store_hash = internal_type::store_hash; static const bool unique_keys = 0 != (BoolFlags & hash_bool_flags::unique_keys_pos); static const bool constant_time_size = 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos); @@ -1258,6 +1654,7 @@ class hashtable_impl = detail::optimize_multikey_is_true::value && !unique_keys; /// @cond + static const bool is_multikey = !unique_keys; private: //Configuration error: compare_hash<> can't be specified without store_hash<> @@ -1272,12 +1669,11 @@ class hashtable_impl //optimize_multikey is not true typedef unordered_group_adapter group_traits; typedef circular_slist_algorithms group_algorithms; - typedef detail::bool_ store_hash_t; + typedef typename internal_type::store_hash_t store_hash_t; typedef detail::bool_ optimize_multikey_t; typedef detail::bool_ cache_begin_t; typedef detail::bool_ power_2_buckets_t; - typedef detail::size_holder size_traits; - typedef detail::size_holder split_traits; + typedef typename internal_type::split_traits split_traits; typedef detail::group_functions group_functions_t; typedef detail::node_functions node_functions_t; @@ -1285,7 +1681,7 @@ class hashtable_impl //noncopyable, movable BOOST_MOVABLE_BUT_NOT_COPYABLE(hashtable_impl) - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = internal_type::safemode_or_autounlink; //Constant-time size is incompatible with auto-unlink hooks! BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink))); @@ -1293,14 +1689,19 @@ class hashtable_impl BOOST_STATIC_ASSERT(!(cache_begin && ((int)value_traits::link_mode == (int)auto_unlink))); template - node_cast_adaptor< detail::node_disposer - , slist_node_ptr, node_ptr > + struct typeof_node_disposer + { + typedef node_cast_adaptor + < detail::node_disposer< Disposer, value_traits, CircularSListAlgorithms> + , slist_node_ptr, node_ptr > type; + }; + + template + typename typeof_node_disposer::type make_node_disposer(const Disposer &disposer) const { - return node_cast_adaptor - < detail::node_disposer - , slist_node_ptr, node_ptr > - (disposer, &this->priv_value_traits()); + typedef typename typeof_node_disposer::type return_t; + return return_t(disposer, &this->priv_value_traits()); } /// @endcond @@ -1308,17 +1709,6 @@ class hashtable_impl public: typedef detail::insert_commit_data_impl insert_commit_data; - typedef detail::transform_iterator - < typename slist_impl::iterator - , downcast_node_to_value_t - < value_traits - , false> > local_iterator; - - typedef detail::transform_iterator - < typename slist_impl::iterator - , downcast_node_to_value_t - < value_traits - , true> > const_local_iterator; public: @@ -1339,9 +1729,42 @@ class hashtable_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : data_type(b_traits, hash_func, equal_func, v_traits) + : internal_type(v_traits, b_traits, hash_func, equal_func) { - this->data_type::internal.priv_initialize_buckets_and_cache(); + this->priv_initialize_buckets_and_cache(); + this->priv_size_traits().set_size(size_type(0)); + size_type bucket_sz = this->priv_bucket_count(); + BOOST_INTRUSIVE_INVARIANT_ASSERT(bucket_sz != 0); + //Check power of two bucket array if the option is activated + BOOST_INTRUSIVE_INVARIANT_ASSERT + (!power_2_buckets || (0 == (bucket_sz & (bucket_sz-1)))); + this->priv_split_traits().set_size(bucket_sz>>1); + } + + //! Requires: buckets must not be being used by any other resource + //! and dereferencing iterator must yield an lvalue of type value_type. + //! + //! Effects: Constructs an empty container and inserts elements from + //! [b, e). + //! + //! Complexity: If N is distance(b, e): Average case is O(N) + //! (with a good hash function and with buckets_len >= N),worst case O(N^2). + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor or invocation of hasher or key_equal throws. + //! + //! Notes: buckets array must be disposed only after + //! *this is disposed. + template + hashtable_impl ( bool unique, Iterator b, Iterator e + , const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : internal_type(v_traits, b_traits, hash_func, equal_func) + { + this->priv_initialize_buckets_and_cache(); this->priv_size_traits().set_size(size_type(0)); size_type bucket_sz = this->priv_bucket_count(); BOOST_INTRUSIVE_INVARIANT_ASSERT(bucket_sz != 0); @@ -1349,16 +1772,21 @@ class hashtable_impl BOOST_INTRUSIVE_INVARIANT_ASSERT (!power_2_buckets || (0 == (bucket_sz & (bucket_sz-1)))); this->priv_split_traits().set_size(bucket_sz>>1); + //Now insert + if(unique) + this->insert_unique(b, e); + else + this->insert_equal(b, e); } //! Effects: to-do //! hashtable_impl(BOOST_RV_REF(hashtable_impl) x) - : data_type( ::boost::move(x.priv_bucket_traits()) - , ::boost::move(x.priv_hasher()) - , ::boost::move(x.priv_equal()) - , ::boost::move(x.priv_value_traits()) - ) + : internal_type( ::boost::move(x.priv_value_traits()) + , ::boost::move(x.priv_bucket_traits()) + , ::boost::move(x.priv_hasher()) + , ::boost::move(x.priv_equal()) + ) { this->priv_swap_cache(x); x.priv_initialize_cache(); @@ -1387,7 +1815,6 @@ class hashtable_impl //! //! Throws: Nothing. ~hashtable_impl(); - #endif //! Effects: Returns an iterator pointing to the beginning of the unordered_set. //! @@ -1395,8 +1822,7 @@ class hashtable_impl //! Worst case (empty unordered_set): O(this->bucket_count()) //! //! Throws: Nothing. - iterator begin() - { return iterator(this->priv_begin(), &this->get_bucket_value_traits()); } + iterator begin(); //! Effects: Returns a const_iterator pointing to the beginning //! of the unordered_set. @@ -1405,8 +1831,7 @@ class hashtable_impl //! Worst case (empty unordered_set): O(this->bucket_count()) //! //! Throws: Nothing. - const_iterator begin() const - { return this->cbegin(); } + const_iterator begin() const; //! Effects: Returns a const_iterator pointing to the beginning //! of the unordered_set. @@ -1415,48 +1840,44 @@ class hashtable_impl //! Worst case (empty unordered_set): O(this->bucket_count()) //! //! Throws: Nothing. - const_iterator cbegin() const - { return const_iterator(this->priv_begin(), &this->get_bucket_value_traits()); } + const_iterator cbegin() const; //! Effects: Returns an iterator pointing to the end of the unordered_set. //! //! Complexity: Constant. //! //! Throws: Nothing. - iterator end() - { return iterator(this->priv_invalid_local_it(), 0); } + iterator end(); //! Effects: Returns a const_iterator pointing to the end of the unordered_set. //! //! Complexity: Constant. //! //! Throws: Nothing. - const_iterator end() const - { return this->cend(); } + const_iterator end() const; //! Effects: Returns a const_iterator pointing to the end of the unordered_set. //! //! Complexity: Constant. //! //! Throws: Nothing. - const_iterator cend() const - { return const_iterator(this->priv_invalid_local_it(), 0); } + const_iterator cend() const; //! Effects: Returns the hasher object used by the unordered_set. //! //! Complexity: Constant. //! //! Throws: If hasher copy-constructor throws. - hasher hash_function() const - { return this->priv_hasher(); } + hasher hash_function() const; //! Effects: Returns the key_equal object used by the unordered_set. //! //! Complexity: Constant. //! //! Throws: If key_equal copy-constructor throws. - key_equal key_eq() const - { return this->priv_equal(); } + key_equal key_eq() const; + + #endif //! Effects: Returns true if the container is empty. //! @@ -1525,16 +1946,8 @@ class hashtable_impl ::boost::adl_move_swap(this->priv_bucket_traits(), other.priv_bucket_traits()); ::boost::adl_move_swap(this->priv_value_traits(), other.priv_value_traits()); this->priv_swap_cache(other); - if(constant_time_size){ - size_type backup = this->priv_size_traits().get_size(); - this->priv_size_traits().set_size(other.priv_size_traits().get_size()); - other.priv_size_traits().set_size(backup); - } - if(incremental){ - size_type backup = this->priv_split_traits().get_size(); - this->priv_split_traits().set_size(other.priv_split_traits().get_size()); - other.priv_split_traits().set_size(backup); - } + ::boost::adl_move_swap(this->priv_size_traits(), other.priv_size_traits()); + ::boost::adl_move_swap(this->priv_split_traits(), other.priv_split_traits()); } //! Requires: Disposer::operator()(pointer) shouldn't throw @@ -1558,87 +1971,30 @@ class hashtable_impl //! throws. Basic guarantee. template void clone_from(const hashtable_impl &src, Cloner cloner, Disposer disposer) - { - this->clear_and_dispose(disposer); - if(!constant_time_size || !src.empty()){ - const size_type src_bucket_count = src.bucket_count(); - const size_type dst_bucket_count = this->bucket_count(); - //Check power of two bucket array if the option is activated - BOOST_INTRUSIVE_INVARIANT_ASSERT - (!power_2_buckets || (0 == (src_bucket_count & (src_bucket_count-1)))); - BOOST_INTRUSIVE_INVARIANT_ASSERT - (!power_2_buckets || (0 == (dst_bucket_count & (dst_bucket_count-1)))); + { this->priv_clone_from(src, cloner, disposer); } - //If src bucket count is bigger or equal, structural copy is possible - if(!incremental && (src_bucket_count >= dst_bucket_count)){ - //First clone the first ones - const bucket_ptr src_buckets = src.priv_bucket_pointer(); - const bucket_ptr dst_buckets = this->priv_bucket_pointer(); - size_type constructed; - - typedef node_cast_adaptor< detail::node_disposer - , slist_node_ptr, node_ptr > NodeDisposer; - typedef node_cast_adaptor< detail::node_cloner - , slist_node_ptr, node_ptr > NodeCloner; - NodeDisposer node_disp(disposer, &this->priv_value_traits()); - - detail::exception_array_disposer - rollback(dst_buckets[0], node_disp, constructed); - for( constructed = 0 - ; constructed < dst_bucket_count - ; ++constructed){ - dst_buckets[constructed].clone_from - ( src_buckets[constructed] - , NodeCloner(cloner, &this->priv_value_traits()), node_disp); - } - if(src_bucket_count != dst_bucket_count){ - //Now insert the remaining ones using the modulo trick - for(//"constructed" comes from the previous loop - ; constructed < src_bucket_count - ; ++constructed){ - bucket_type &dst_b = - dst_buckets[detail::hash_to_bucket_split(constructed, dst_bucket_count, dst_bucket_count)]; - bucket_type &src_b = src_buckets[constructed]; - for( siterator b(src_b.begin()), e(src_b.end()) - ; b != e - ; ++b){ - dst_b.push_front(*(NodeCloner(cloner, &this->priv_value_traits())(*b.pointed_node()))); - } - } - } - this->priv_hasher() = src.priv_hasher(); - this->priv_equal() = src.priv_equal(); - rollback.release(); - this->priv_size_traits().set_size(src.priv_size_traits().get_size()); - this->priv_split_traits().set_size(dst_bucket_count); - this->priv_insertion_update_cache(0u); - this->priv_erasure_update_cache(); - } - else if(store_hash){ - //Unlike previous cloning algorithm, this can throw - //if cloner, hasher or comparison functor throw - const_iterator b(src.cbegin()), e(src.cend()); - detail::exception_disposer - rollback(*this, disposer); - for(; b != e; ++b){ - std::size_t hash_value = this->priv_stored_or_compute_hash(*b, store_hash_t());; - this->priv_insert_equal_with_hash(*cloner(*b), hash_value); - } - rollback.release(); - } - else{ - //Unlike previous cloning algorithm, this can throw - //if cloner, hasher or comparison functor throw - const_iterator b(src.cbegin()), e(src.cend()); - detail::exception_disposer - rollback(*this, disposer); - for(; b != e; ++b){ - this->insert_equal(*cloner(*b)); - } - rollback.release(); - } - } - } + //! Requires: Disposer::operator()(pointer) shouldn't throw + //! Cloner should yield to nodes that compare equal and produce the same + //! hash than the original node. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(reference) + //! and inserts them on *this. The hash function and the equality + //! predicate are copied from the source. + //! + //! If store_hash option is true, this method does not use the hash function. + //! + //! If any operation throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner or hasher throw or hash or equality predicate copying + //! throws. Basic guarantee. + template + void clone_from(BOOST_RV_REF(hashtable_impl) src, Cloner cloner, Disposer disposer) + { this->priv_clone_from(static_cast(src), cloner, disposer); } //! Requires: value must be an lvalue //! @@ -1657,9 +2013,10 @@ class hashtable_impl size_type bucket_num; std::size_t hash_value; siterator prev; - siterator it = this->priv_find - (value, this->priv_hasher(), this->priv_equal(), bucket_num, hash_value, prev); - return this->priv_insert_equal_find(value, bucket_num, hash_value, it); + siterator const it = this->priv_find + (key_of_value()(value), this->priv_hasher(), this->priv_equal(), bucket_num, hash_value, prev); + bool const next_is_in_group = optimize_multikey && it != this->priv_invalid_local_it(); + return this->priv_insert_equal_after_find(value, bucket_num, hash_value, prev, next_is_in_group); } //! Requires: Dereferencing iterator must yield an lvalue @@ -1701,11 +2058,11 @@ class hashtable_impl { insert_commit_data commit_data; std::pair ret = this->insert_unique_check - (value, this->priv_hasher(), this->priv_equal(), commit_data); - if(!ret.second) - return ret; - return std::pair - (this->insert_unique_commit(value, commit_data), true); + (key_of_value()(value), this->priv_hasher(), this->priv_equal(), commit_data); + if(ret.second){ + ret.first = this->insert_unique_commit(value, commit_data); + } + return ret; } //! Requires: Dereferencing iterator must yield an lvalue @@ -1762,22 +2119,19 @@ class hashtable_impl //! objects are inserted or erased from the unordered_set. //! //! After a successful rehashing insert_commit_data remains valid. - template + template std::pair insert_unique_check ( const KeyType &key , KeyHasher hash_func - , KeyValueEqual equal_func + , KeyEqual equal_func , insert_commit_data &commit_data) { size_type bucket_num; siterator prev; - siterator prev_pos = - this->priv_find(key, hash_func, equal_func, bucket_num, commit_data.hash, prev); - bool success = prev_pos == this->priv_invalid_local_it(); - if(success){ - prev_pos = prev; - } - return std::pair(iterator(prev_pos, &this->get_bucket_value_traits()),success); + siterator const pos = this->priv_find(key, hash_func, equal_func, bucket_num, commit_data.hash, prev); + return std::pair + ( iterator(pos, &this->get_bucket_value_traits()) + , pos == this->priv_invalid_local_it()); } //! Requires: value must be an lvalue of type value_type. commit_data @@ -1804,12 +2158,11 @@ class hashtable_impl size_type bucket_num = this->priv_hash_to_bucket(commit_data.hash); bucket_type &b = this->priv_bucket_pointer()[bucket_num]; this->priv_size_traits().increment(); - node_ptr n = pointer_traits::pointer_to(this->priv_value_to_node(value)); + node_ptr const n = pointer_traits::pointer_to(this->priv_value_to_node(value)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(n)); node_functions_t::store_hash(n, commit_data.hash, store_hash_t()); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); this->priv_insertion_update_cache(bucket_num); - group_functions_t::insert_in_group(node_ptr(), n, optimize_multikey_t()); + group_functions_t::insert_in_group(n, n, optimize_multikey_t()); return iterator(b.insert_after(b.before_begin(), *n), &this->get_bucket_value_traits()); } @@ -1848,8 +2201,8 @@ class hashtable_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return this->erase(value, this->priv_hasher(), this->priv_equal()); } + size_type erase(const key_type &key) + { return this->erase(key, this->priv_hasher(), this->priv_equal()); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -1871,8 +2224,8 @@ class hashtable_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - template - size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) + template + size_type erase(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) { return this->erase_and_dispose(key, hash_func, equal_func, detail::null_disposer()); } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -1887,15 +2240,16 @@ class hashtable_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator i, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { - this->priv_erase(i, disposer, optimize_multikey_t()); + BOOST_INTRUSIVE_DOC1ST(void + , typename detail::disable_if_convertible::type) + erase_and_dispose(const_iterator i, Disposer disposer) + { + //Get the bucket number and local iterator for both iterators + siterator const first_local_it(i.slist_it()); + size_type const first_bucket_num = this->priv_get_bucket_num(first_local_it); + this->priv_erase_node(this->priv_bucket_pointer()[first_bucket_num], first_local_it, make_node_disposer(disposer), optimize_multikey_t()); this->priv_size_traits().decrement(); - this->priv_erasure_update_cache(); + this->priv_erasure_update_cache_range(first_bucket_num, first_bucket_num); } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -1934,7 +2288,10 @@ class hashtable_impl last_local_it = e.slist_it(); last_bucket_num = this->priv_get_bucket_num(last_local_it); } - this->priv_erase_range(before_first_local_it, first_bucket_num, last_local_it, last_bucket_num, disposer); + size_type const num_erased = this->priv_erase_node_range + ( before_first_local_it, first_bucket_num, last_local_it, last_bucket_num + , make_node_disposer(disposer), optimize_multikey_t()); + this->priv_size_traits().set_size(this->priv_size_traits().get_size()-num_erased); this->priv_erasure_update_cache_range(first_bucket_num, last_bucket_num); } } @@ -1955,8 +2312,8 @@ class hashtable_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return this->erase_and_dispose(value, this->priv_hasher(), this->priv_equal(), disposer); } + size_type erase_and_dispose(const key_type &key, Disposer disposer) + { return this->erase_and_dispose(key, this->priv_hasher(), this->priv_equal(), disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -1973,45 +2330,37 @@ class hashtable_impl //! //! Note: Invalidates the iterators //! to the erased elements. - template + template size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func - ,KeyValueEqual equal_func, Disposer disposer) + ,KeyEqual equal_func, Disposer disposer) { size_type bucket_num; std::size_t h; siterator prev; siterator it = this->priv_find(key, hash_func, equal_func, bucket_num, h, prev); - bool success = it != this->priv_invalid_local_it(); + bool const success = it != this->priv_invalid_local_it(); + size_type cnt(0); - if(!success){ - return 0; - } - else if(optimize_multikey){ - siterator last = bucket_type::s_iterator_to - (*node_traits::get_next(group_functions_t::get_last_in_group - (detail::dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t()))); - this->priv_erase_range_impl(bucket_num, prev, last, disposer, cnt); - } - else{ - //If found erase all equal values - bucket_type &b = this->priv_bucket_pointer()[bucket_num]; - for(siterator end_sit = b.end(); it != end_sit; ++cnt, ++it){ - slist_node_ptr n(it.pointed_node()); - const value_type &v = this->priv_value_from_slist_node(n); - if(compare_hash){ - std::size_t vh = this->priv_stored_or_compute_hash(v, store_hash_t()); - if(h != vh || !equal_func(key, v)){ - break; - } - } - else if(!equal_func(key, v)){ - break; - } - this->priv_size_traits().decrement(); + if(success){ + if(optimize_multikey){ + cnt = this->priv_erase_from_single_bucket + (this->priv_bucket_pointer()[bucket_num], prev, ++(priv_last_in_group)(it), make_node_disposer(disposer), optimize_multikey_t()); + } + else{ + bucket_type &b = this->priv_bucket_pointer()[bucket_num]; + siterator const end_sit = b.end(); + do{ + ++cnt; + ++it; + }while(it != end_sit && + this->priv_is_value_equal_to_key + (this->priv_value_from_slist_node(it.pointed_node()), h, key, equal_func)); + bucket_type::s_erase_after_and_dispose(prev, it, make_node_disposer(disposer)); } - b.erase_after_and_dispose(prev, it, make_node_disposer(disposer)); + this->priv_size_traits().set_size(this->priv_size_traits().get_size()-cnt); + this->priv_erasure_update_cache(); } - this->priv_erasure_update_cache(); + return cnt; } @@ -2026,7 +2375,7 @@ class hashtable_impl //! to the erased elements. No destructors are called. void clear() { - this->data_type::internal.priv_clear_buckets_and_cache(); + this->priv_clear_buckets_and_cache(); this->priv_size_traits().set_size(size_type(0)); } @@ -2047,8 +2396,9 @@ class hashtable_impl if(!constant_time_size || !this->empty()){ size_type num_buckets = this->bucket_count(); bucket_ptr b = this->priv_bucket_pointer(); + typename typeof_node_disposer::type d(disposer, &this->priv_value_traits()); for(; num_buckets--; ++b){ - b->clear_and_dispose(make_node_disposer(disposer)); + b->clear_and_dispose(d); } this->priv_size_traits().set_size(size_type(0)); } @@ -2060,8 +2410,8 @@ class hashtable_impl //! Complexity: Average case O(1), worst case O(this->size()). //! //! Throws: If the internal hasher or the equality functor throws. - size_type count(const_reference value) const - { return this->count(value, this->priv_hasher(), this->priv_equal()); } + size_type count(const key_type &key) const + { return this->count(key, this->priv_hasher(), this->priv_equal()); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -2076,11 +2426,12 @@ class hashtable_impl //! Complexity: Average case O(1), worst case O(this->size()). //! //! Throws: If hash_func or equal throw. - template - size_type count(const KeyType &key, const KeyHasher &hash_func, const KeyValueEqual &equal_func) const + template + size_type count(const KeyType &key, KeyHasher hash_func, KeyEqual equal_func) const { - size_type bucket_n1, bucket_n2, cnt; - this->priv_equal_range(key, hash_func, equal_func, bucket_n1, bucket_n2, cnt); + size_type cnt; + size_type n_bucket; + this->priv_local_equal_range(key, hash_func, equal_func, n_bucket, cnt); return cnt; } @@ -2090,8 +2441,8 @@ class hashtable_impl //! Complexity: Average case O(1), worst case O(this->size()). //! //! Throws: If the internal hasher or the equality functor throws. - iterator find(const_reference value) - { return this->find(value, this->priv_hasher(), this->priv_equal()); } + iterator find(const key_type &key) + { return this->find(key, this->priv_hasher(), this->priv_equal()); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -2112,14 +2463,14 @@ class hashtable_impl //! Note: This function is used when constructing a value_type //! is expensive and the value_type can be compared with a cheaper //! key type. Usually this key is part of the value_type. - template - iterator find(const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func) + template + iterator find(const KeyType &key, KeyHasher hash_func, KeyEqual equal_func) { size_type bucket_n; std::size_t hash; siterator prev; - siterator local_it = this->priv_find(key, hash_func, equal_func, bucket_n, hash, prev); - return iterator(local_it, &this->get_bucket_value_traits()); + return iterator( this->priv_find(key, hash_func, equal_func, bucket_n, hash, prev) + , &this->get_bucket_value_traits()); } //! Effects: Finds a const_iterator to the first element whose key is @@ -2128,8 +2479,8 @@ class hashtable_impl //! Complexity: Average case O(1), worst case O(this->size()). //! //! Throws: If the internal hasher or the equality functor throws. - const_iterator find(const_reference value) const - { return this->find(value, this->priv_hasher(), this->priv_equal()); } + const_iterator find(const key_type &key) const + { return this->find(key, this->priv_hasher(), this->priv_equal()); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -2150,15 +2501,15 @@ class hashtable_impl //! Note: This function is used when constructing a value_type //! is expensive and the value_type can be compared with a cheaper //! key type. Usually this key is part of the value_type. - template + template const_iterator find - (const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func) const + (const KeyType &key, KeyHasher hash_func, KeyEqual equal_func) const { size_type bucket_n; std::size_t hash_value; siterator prev; - siterator sit = this->priv_find(key, hash_func, equal_func, bucket_n, hash_value, prev); - return const_iterator(sit, &this->get_bucket_value_traits()); + return const_iterator( this->priv_find(key, hash_func, equal_func, bucket_n, hash_value, prev) + , &this->get_bucket_value_traits()); } //! Effects: Returns a range containing all elements with values equivalent @@ -2168,8 +2519,8 @@ class hashtable_impl //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). //! //! Throws: If the internal hasher or the equality functor throws. - std::pair equal_range(const_reference value) - { return this->equal_range(value, this->priv_hasher(), this->priv_equal()); } + std::pair equal_range(const key_type &key) + { return this->equal_range(key, this->priv_hasher(), this->priv_equal()); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -2191,15 +2542,15 @@ class hashtable_impl //! Note: This function is used when constructing a value_type //! is expensive and the value_type can be compared with a cheaper //! key type. Usually this key is part of the value_type. - template + template std::pair equal_range - (const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func) + (const KeyType &key, KeyHasher hash_func, KeyEqual equal_func) { - size_type bucket_n1, bucket_n2, cnt; - std::pair ret = this->priv_equal_range - (key, hash_func, equal_func, bucket_n1, bucket_n2, cnt); + std::pair ret = + this->priv_equal_range(key, hash_func, equal_func); return std::pair - (iterator(ret.first, &this->get_bucket_value_traits()), iterator(ret.second, &this->get_bucket_value_traits())); + ( iterator(ret.first, &this->get_bucket_value_traits()) + , iterator(ret.second, &this->get_bucket_value_traits())); } //! Effects: Returns a range containing all elements with values equivalent @@ -2210,8 +2561,8 @@ class hashtable_impl //! //! Throws: If the internal hasher or the equality functor throws. std::pair - equal_range(const_reference value) const - { return this->equal_range(value, this->priv_hasher(), this->priv_equal()); } + equal_range(const key_type &key) const + { return this->equal_range(key, this->priv_hasher(), this->priv_equal()); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -2233,18 +2584,19 @@ class hashtable_impl //! Note: This function is used when constructing a value_type //! is expensive and the value_type can be compared with a cheaper //! key type. Usually this key is part of the value_type. - template + template std::pair equal_range - (const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func) const + (const KeyType &key, KeyHasher hash_func, KeyEqual equal_func) const { - size_type bucket_n1, bucket_n2, cnt; std::pair ret = - this->priv_equal_range(key, hash_func, equal_func, bucket_n1, bucket_n2, cnt); + this->priv_equal_range(key, hash_func, equal_func); return std::pair ( const_iterator(ret.first, &this->get_bucket_value_traits()) , const_iterator(ret.second, &this->get_bucket_value_traits())); } + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. //! @@ -2254,11 +2606,7 @@ class hashtable_impl //! Complexity: Constant. //! //! Throws: If the internal hash function throws. - iterator iterator_to(reference value) - { - return iterator(bucket_type::s_iterator_to - (this->priv_value_to_node(value)), &this->get_bucket_value_traits()); - } + iterator iterator_to(reference value); //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -2269,13 +2617,7 @@ class hashtable_impl //! Complexity: Constant. //! //! Throws: If the internal hash function throws. - const_iterator iterator_to(const_reference value) const - { - node_reference r = *pointer_traits::const_cast_from - (pointer_traits::pointer_to(this->priv_value_to_node(value))); - siterator sit = bucket_type::s_iterator_to(r); - return const_iterator(sit, &this->get_bucket_value_traits()); - } + const_iterator iterator_to(const_reference value) const; //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -2289,12 +2631,7 @@ class hashtable_impl //! //! Note: This static function is available only if the value traits //! is stateless. - static local_iterator s_local_iterator_to(reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - siterator sit = bucket_type::s_iterator_to(*value_traits::to_node_ptr(value)); - return local_iterator(sit, const_value_traits_ptr()); - } + static local_iterator s_local_iterator_to(reference value); //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -2308,14 +2645,7 @@ class hashtable_impl //! //! Note: This static function is available only if the value traits //! is stateless. - static const_local_iterator s_local_iterator_to(const_reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - node_reference r = *pointer_traits::const_cast_from - (value_traits::to_node_ptr(value)); - siterator sit = bucket_type::s_iterator_to(r); - return const_local_iterator(sit, const_value_traits_ptr()); - } + static const_local_iterator s_local_iterator_to(const_reference value); //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -2326,11 +2656,7 @@ class hashtable_impl //! Complexity: Constant. //! //! Throws: Nothing. - local_iterator local_iterator_to(reference value) - { - siterator sit = bucket_type::s_iterator_to(this->priv_value_to_node(value)); - return local_iterator(sit, this->priv_value_traits_ptr()); - } + local_iterator local_iterator_to(reference value); //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -2341,13 +2667,7 @@ class hashtable_impl //! Complexity: Constant. //! //! Throws: Nothing. - const_local_iterator local_iterator_to(const_reference value) const - { - node_reference r = *pointer_traits::const_cast_from - (pointer_traits::pointer_to(this->priv_value_to_node(value))); - siterator sit = bucket_type::s_iterator_to(r); - return const_local_iterator(sit, this->priv_value_traits_ptr()); - } + const_local_iterator local_iterator_to(const_reference value) const; //! Effects: Returns the number of buckets passed in the constructor //! or the last rehash function. @@ -2355,8 +2675,7 @@ class hashtable_impl //! Complexity: Constant. //! //! Throws: Nothing. - size_type bucket_count() const - { return this->priv_bucket_count(); } + size_type bucket_count() const; //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2365,8 +2684,8 @@ class hashtable_impl //! Complexity: Constant. //! //! Throws: Nothing. - size_type bucket_size(size_type n) const - { return this->priv_bucket_pointer()[n].size(); } + size_type bucket_size(size_type n) const; + #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: Returns the index of the bucket in which elements //! with keys equivalent to k would be found, if any such element existed. @@ -2392,17 +2711,17 @@ class hashtable_impl //! //! Note: the return value is in the range [0, this->bucket_count()). template - size_type bucket(const KeyType& k, const KeyHasher &hash_func) const + size_type bucket(const KeyType& k, KeyHasher hash_func) const { return this->priv_hash_to_bucket(hash_func(k)); } + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: Returns the bucket array pointer passed in the constructor //! or the last rehash function. //! //! Complexity: Constant. //! //! Throws: Nothing. - bucket_ptr bucket_pointer() const - { return this->priv_bucket_pointer(); } + bucket_ptr bucket_pointer() const; //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2415,8 +2734,7 @@ class hashtable_impl //! //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. - local_iterator begin(size_type n) - { return local_iterator(this->priv_bucket_pointer()[n].begin(), this->priv_value_traits_ptr()); } + local_iterator begin(size_type n); //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2429,8 +2747,7 @@ class hashtable_impl //! //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. - const_local_iterator begin(size_type n) const - { return this->cbegin(n); } + const_local_iterator begin(size_type n) const; //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2443,11 +2760,7 @@ class hashtable_impl //! //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. - const_local_iterator cbegin(size_type n) const - { - bucket_reference br = pointer_traits::const_cast_from(this->priv_bucket_pointer())[n]; - return const_local_iterator(br.begin(), this->priv_value_traits_ptr()); - } + const_local_iterator cbegin(size_type n) const; //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2460,8 +2773,7 @@ class hashtable_impl //! //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. - local_iterator end(size_type n) - { return local_iterator(this->priv_bucket_pointer()[n].end(), this->priv_value_traits_ptr()); } + local_iterator end(size_type n); //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2474,8 +2786,7 @@ class hashtable_impl //! //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. - const_local_iterator end(size_type n) const - { return this->cend(n); } + const_local_iterator end(size_type n) const; //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2488,11 +2799,8 @@ class hashtable_impl //! //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. - const_local_iterator cend(size_type n) const - { - bucket_reference br = pointer_traits::const_cast_from(this->priv_bucket_pointer())[n]; - return const_local_iterator ( br.end(), this->priv_value_traits_ptr()); - } + const_local_iterator cend(size_type n) const; + #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Requires: new_bucket_traits can hold a pointer to a new bucket array //! or the same as the old bucket array with a different length. new_size is the length of the @@ -2520,36 +2828,33 @@ class hashtable_impl //Check power of two bucket array if the option is activated BOOST_INTRUSIVE_INVARIANT_ASSERT - (!power_2_buckets || (0 == (new_bucket_count & (new_bucket_count-1u)))); + (!power_2_buckets || (0 == (new_bucket_count & (new_bucket_count-1u)))); size_type n = this->priv_get_cache_bucket_num(); const bool same_buffer = old_buckets == new_buckets; //If the new bucket length is a common factor //of the old one we can avoid hash calculations. - const bool fast_shrink = (!incremental) && (old_bucket_count > new_bucket_count) && - (power_2_buckets ||(old_bucket_count % new_bucket_count) == 0); + const bool fast_shrink = (!incremental) && (old_bucket_count >= new_bucket_count) && + (power_2_buckets || (old_bucket_count % new_bucket_count) == 0); //If we are shrinking the same bucket array and it's //is a fast shrink, just rehash the last nodes size_type new_first_bucket_num = new_bucket_count; if(same_buffer && fast_shrink && (n < new_bucket_count)){ + new_first_bucket_num = n; n = new_bucket_count; - new_first_bucket_num = this->priv_get_cache_bucket_num(); } //Anti-exception stuff: they destroy the elements if something goes wrong. //If the source and destination buckets are the same, the second rollback function //is harmless, because all elements have been already unlinked and destroyed typedef detail::init_disposer NodeDisposer; + typedef detail::exception_array_disposer ArrayDisposer; NodeDisposer node_disp; - bucket_type & newbuck = new_buckets[0]; - bucket_type & oldbuck = old_buckets[0]; - detail::exception_array_disposer - rollback1(newbuck, node_disp, new_bucket_count); - detail::exception_array_disposer - rollback2(oldbuck, node_disp, old_bucket_count); + ArrayDisposer rollback1(new_buckets[0], node_disp, new_bucket_count); + ArrayDisposer rollback2(old_buckets[0], node_disp, old_bucket_count); //Put size in a safe value for rollback exception - size_type size_backup = this->priv_size_traits().get_size(); + size_type const size_backup = this->priv_size_traits().get_size(); this->priv_size_traits().set_size(0); //Put cache to safe position this->priv_initialize_cache(); @@ -2558,20 +2863,17 @@ class hashtable_impl //Iterate through nodes for(; n < old_bucket_count; ++n){ bucket_type &old_bucket = old_buckets[n]; - if(!fast_shrink){ - siterator before_i(old_bucket.before_begin()); - siterator end_sit(old_bucket.end()); - siterator i(old_bucket.begin()); - for(;i != end_sit; ++i){ + for( siterator before_i(old_bucket.before_begin()), i(old_bucket.begin()), end_sit(old_bucket.end()) + ; i != end_sit + ; i = before_i, ++i){ const value_type &v = this->priv_value_from_slist_node(i.pointed_node()); const std::size_t hash_value = this->priv_stored_or_compute_hash(v, store_hash_t()); - const size_type new_n = detail::hash_to_bucket_split(hash_value, new_bucket_count, new_bucket_count); + const size_type new_n = detail::hash_to_bucket_split + (hash_value, new_bucket_count, new_bucket_count); if(cache_begin && new_n < new_first_bucket_num) new_first_bucket_num = new_n; - siterator last = bucket_type::s_iterator_to - (*group_functions_t::get_last_in_group - (detail::dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t())); + siterator const last = (priv_last_in_group)(i); if(same_buffer && new_n == n){ before_i = last; } @@ -2579,7 +2881,6 @@ class hashtable_impl bucket_type &new_b = new_buckets[new_n]; new_b.splice_after(new_b.before_begin(), old_bucket, before_i, last); } - i = before_i; } } else{ @@ -2587,12 +2888,10 @@ class hashtable_impl if(cache_begin && new_n < new_first_bucket_num) new_first_bucket_num = new_n; bucket_type &new_b = new_buckets[new_n]; - if(!old_bucket.empty()){ - new_b.splice_after( new_b.before_begin() - , old_bucket - , old_bucket.before_begin() - , hashtable_impl::priv_get_last(old_bucket)); - } + new_b.splice_after( new_b.before_begin() + , old_bucket + , old_bucket.before_begin() + , bucket_plus_vtraits_t::priv_get_last(old_bucket, optimize_multikey_t())); } } @@ -2621,56 +2920,47 @@ class hashtable_impl const size_type split_idx = this->priv_split_traits().get_size(); const size_type bucket_cnt = this->priv_bucket_count(); const bucket_ptr buck_ptr = this->priv_bucket_pointer(); + bool ret = false; if(grow){ //Test if the split variable can be changed - if(split_idx >= bucket_cnt) - return false; - - const size_type bucket_to_rehash = split_idx - bucket_cnt/2; - bucket_type &old_bucket = buck_ptr[bucket_to_rehash]; - siterator before_i(old_bucket.before_begin()); - const siterator end_sit(old_bucket.end()); - siterator i(old_bucket.begin()); - this->priv_split_traits().increment(); - - //Anti-exception stuff: if an exception is thrown while - //moving elements from old_bucket to the target bucket, all moved - //elements are moved back to the original one. - detail::incremental_rehash_rollback rollback - ( buck_ptr[split_idx], old_bucket, this->priv_split_traits()); - for(;i != end_sit; ++i){ - const value_type &v = this->priv_value_from_slist_node(i.pointed_node()); - const std::size_t hash_value = this->priv_stored_or_compute_hash(v, store_hash_t()); - const size_type new_n = this->priv_hash_to_bucket(hash_value); - siterator last = bucket_type::s_iterator_to - (*group_functions_t::get_last_in_group - (detail::dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t())); - if(new_n == bucket_to_rehash){ - before_i = last; - } - else{ - bucket_type &new_b = buck_ptr[new_n]; - new_b.splice_after(new_b.before_begin(), old_bucket, before_i, last); + if((ret = split_idx < bucket_cnt)){ + const size_type bucket_to_rehash = split_idx - bucket_cnt/2; + bucket_type &old_bucket = buck_ptr[bucket_to_rehash]; + this->priv_split_traits().increment(); + + //Anti-exception stuff: if an exception is thrown while + //moving elements from old_bucket to the target bucket, all moved + //elements are moved back to the original one. + detail::incremental_rehash_rollback rollback + ( buck_ptr[split_idx], old_bucket, this->priv_split_traits()); + for( siterator before_i(old_bucket.before_begin()), i(old_bucket.begin()), end_sit(old_bucket.end()) + ; i != end_sit; i = before_i, ++i){ + const value_type &v = this->priv_value_from_slist_node(i.pointed_node()); + const std::size_t hash_value = this->priv_stored_or_compute_hash(v, store_hash_t()); + const size_type new_n = this->priv_hash_to_bucket(hash_value); + siterator const last = (priv_last_in_group)(i); + if(new_n == bucket_to_rehash){ + before_i = last; + } + else{ + bucket_type &new_b = buck_ptr[new_n]; + new_b.splice_after(new_b.before_begin(), old_bucket, before_i, last); + } } - i = before_i; + rollback.release(); + this->priv_erasure_update_cache(); } - rollback.release(); - this->priv_erasure_update_cache(); - return true; } - else{ - //Test if the split variable can be changed - if(split_idx <= bucket_cnt/2) - return false; + else if((ret = split_idx > bucket_cnt/2)){ //!grow const size_type target_bucket_num = split_idx - 1 - bucket_cnt/2; bucket_type &target_bucket = buck_ptr[target_bucket_num]; bucket_type &source_bucket = buck_ptr[split_idx-1]; target_bucket.splice_after(target_bucket.cbefore_begin(), source_bucket); this->priv_split_traits().decrement(); this->priv_insertion_update_cache(target_bucket_num); - return true; } + return ret; } //! Effects: If new_bucket_traits.bucket_count() is not @@ -2690,24 +2980,22 @@ class hashtable_impl { //This function is only available for containers with incremental hashing BOOST_STATIC_ASSERT(( incremental && power_2_buckets )); - size_type new_bucket_traits_size = new_bucket_traits.bucket_count(); - size_type cur_bucket_traits = this->priv_bucket_count(); - if(new_bucket_traits_size/2 != cur_bucket_traits && new_bucket_traits_size != cur_bucket_traits/2){ - return false; - } - + size_type const new_bucket_traits_size = new_bucket_traits.bucket_count(); + size_type const cur_bucket_traits = this->priv_bucket_count(); const size_type split_idx = this->split_count(); + //Test new bucket size is consistent with internal bucket size and split count if(new_bucket_traits_size/2 == cur_bucket_traits){ - //Test if the split variable can be changed if(!(split_idx >= cur_bucket_traits)) return false; } - else{ - //Test if the split variable can be changed - if(!(split_idx <= cur_bucket_traits/2)) + else if(new_bucket_traits_size == cur_bucket_traits/2){ + if(!(split_idx <= new_bucket_traits_size)) return false; } + else{ + return false; + } const size_type ini_n = this->priv_get_cache_bucket_num(); const bucket_ptr old_buckets = this->priv_bucket_pointer(); @@ -2725,19 +3013,16 @@ class hashtable_impl return true; } - //! Requires: + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + + //! Requires: incremental<> option must be set //! - //! Effects: + //! Effects: returns the current split count //! - //! Complexity: + //! Complexity: Constant //! - //! Throws: - size_type split_count() const - { - //This function is only available if incremental hashing is activated - BOOST_STATIC_ASSERT(( incremental && power_2_buckets )); - return this->priv_split_traits().get_size(); - } + //! Throws: Nothing + size_type split_count() const; //! Effects: Returns the nearest new bucket count optimized for //! the container that is bigger or equal than n. This suggestion can be @@ -2748,14 +3033,7 @@ class hashtable_impl //! Complexity: Amortized constant time. //! //! Throws: Nothing. - static size_type suggested_upper_bucket_count(size_type n) - { - const std::size_t *primes = &prime_list_holder<0>::prime_list[0]; - const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size; - std::size_t const* bound = std::lower_bound(primes, primes_end, n); - bound -= (bound == primes_end); - return size_type(*bound); - } + static size_type suggested_upper_bucket_count(size_type n); //! Effects: Returns the nearest new bucket count optimized for //! the container that is smaller or equal than n. This suggestion can be @@ -2766,403 +3044,306 @@ class hashtable_impl //! Complexity: Amortized constant time. //! //! Throws: Nothing. - static size_type suggested_lower_bucket_count(size_type n) - { - const std::size_t *primes = &prime_list_holder<0>::prime_list[0]; - const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size; - size_type const* bound = std::upper_bound(primes, primes_end, n); - bound -= (bound != primes); - return size_type(*bound); - } - /// @cond - void check() const {} - private: - size_traits &priv_size_traits() - { return static_cast(static_cast(*this)); } - - const size_traits &priv_size_traits() const - { return static_cast(static_cast(*this)); } - - bucket_ptr priv_bucket_pointer() const - { return this->data_type::internal.internal.internal.internal.priv_bucket_pointer(); } - - SizeType priv_bucket_count() const - { return this->data_type::internal.internal.internal.internal.priv_bucket_count(); } - - const bucket_plus_vtraits &get_bucket_value_traits() const - { return this->data_type::internal.internal.internal.internal.get_bucket_value_traits(); } - - bucket_plus_vtraits &get_bucket_value_traits() - { return this->data_type::internal.internal.internal.internal.get_bucket_value_traits(); } - - bucket_traits &priv_bucket_traits() - { return this->data_type::internal.internal.internal.internal.priv_bucket_traits(); } - - const bucket_traits &priv_bucket_traits() const - { return this->data_type::internal.internal.internal.internal.priv_bucket_traits(); } - - value_traits &priv_value_traits() - { return this->data_type::internal.internal.internal.internal.priv_value_traits(); } + static size_type suggested_lower_bucket_count(size_type n); + #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - const value_traits &priv_value_traits() const - { return this->data_type::internal.internal.internal.internal.priv_value_traits(); } - - const_value_traits_ptr priv_value_traits_ptr() const - { return this->data_type::internal.internal.internal.internal.priv_value_traits_ptr(); } - - siterator priv_invalid_local_it() const - { return this->data_type::internal.internal.internal.internal.priv_invalid_local_it(); } - - split_traits &priv_split_traits() - { return this->data_type::internal.priv_split_traits(); } - - const split_traits &priv_split_traits() const - { return this->data_type::internal.priv_split_traits(); } - - bucket_ptr priv_get_cache() - { return this->data_type::internal.internal.priv_get_cache(); } - - void priv_initialize_cache() - { return this->data_type::internal.internal.priv_initialize_cache(); } - - siterator priv_begin() const - { return this->data_type::internal.internal.priv_begin(); } - - const value_equal &priv_equal() const - { return this->data_type::internal.internal.priv_equal(); } - - value_equal &priv_equal() - { return this->data_type::internal.internal.priv_equal(); } - - const hasher &priv_hasher() const - { return this->data_type::internal.internal.internal.priv_hasher(); } - hasher &priv_hasher() - { return this->data_type::internal.internal.internal.priv_hasher(); } - - void priv_swap_cache(hashtable_impl &h) - { this->data_type::internal.internal.priv_swap_cache(h.data_type::internal.internal); } - - node &priv_value_to_node(value_type &v) - { return this->data_type::internal.internal.internal.internal.priv_value_to_node(v); } - - const node &priv_value_to_node(const value_type &v) const - { return this->data_type::internal.internal.internal.internal.priv_value_to_node(v); } - - SizeType priv_get_cache_bucket_num() - { return this->data_type::internal.internal.priv_get_cache_bucket_num(); } - - void priv_insertion_update_cache(SizeType n) - { return this->data_type::internal.internal.priv_insertion_update_cache(n); } - - template - std::size_t priv_stored_or_compute_hash(const value_type &v, detail::bool_ b) const - { return this->data_type::internal.internal.internal.priv_stored_or_compute_hash(v, b); } - - value_type &priv_value_from_slist_node(slist_node_ptr n) - { return this->data_type::internal.internal.internal.internal.priv_value_from_slist_node(n); } + friend bool operator==(const hashtable_impl &x, const hashtable_impl &y) + { + //Taken from N3068 + if(constant_time_size && x.size() != y.size()){ + return false; + } + for (const_iterator ix = x.cbegin(), ex = x.cend(); ix != ex; ++ix){ + std::pair eqx(x.equal_range(key_of_value()(*ix))), + eqy(y.equal_range(key_of_value()(*ix))); + if (boost::intrusive::iterator_distance(eqx.first, eqx.second) != + boost::intrusive::iterator_distance(eqy.first, eqy.second) || + !(priv_algo_is_permutation)(eqx.first, eqx.second, eqy.first) ){ + return false; + } + ix = eqx.second; + } + return true; + } - const value_type &priv_value_from_slist_node(slist_node_ptr n) const - { return this->data_type::internal.internal.internal.internal.priv_value_from_slist_node(n); } + friend bool operator!=(const hashtable_impl &x, const hashtable_impl &y) + { return !(x == y); } - void priv_erasure_update_cache_range(SizeType first_bucket_num, SizeType last_bucket_num) - { return this->data_type::internal.internal.priv_erasure_update_cache_range(first_bucket_num, last_bucket_num); } + friend bool operator<(const hashtable_impl &x, const hashtable_impl &y) + { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } - void priv_erasure_update_cache() - { return this->data_type::internal.internal.priv_erasure_update_cache(); } + friend bool operator>(const hashtable_impl &x, const hashtable_impl &y) + { return y < x; } - static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_ true_value) - { return bucket_plus_vtraits::priv_stored_hash(n, true_value); } + friend bool operator<=(const hashtable_impl &x, const hashtable_impl &y) + { return !(y < x); } - static std::size_t priv_stored_hash(slist_node_ptr n, detail::false_ false_value) - { return bucket_plus_vtraits::priv_stored_hash(n, false_value); } + friend bool operator>=(const hashtable_impl &x, const hashtable_impl &y) + { return !(x < y); } - std::size_t priv_hash_to_bucket(std::size_t hash_value) const - { - return detail::hash_to_bucket_split - (hash_value, this->priv_bucket_traits().bucket_count(), this->priv_split_traits().get_size()); - } + /// @cond + void check() const {} + private: - template - void priv_erase_range_impl - (size_type bucket_num, siterator before_first_it, siterator end_sit, Disposer disposer, size_type &num_erased) + template + void priv_clone_from(MaybeConstHashtableImpl &src, Cloner cloner, Disposer disposer) { - const bucket_ptr buckets = this->priv_bucket_pointer(); - bucket_type &b = buckets[bucket_num]; - - if(before_first_it == b.before_begin() && end_sit == b.end()){ - this->priv_erase_range_impl(bucket_num, 1, disposer, num_erased); - } - else{ - num_erased = 0; - siterator to_erase(before_first_it); - ++to_erase; - slist_node_ptr end_ptr = end_sit.pointed_node(); - while(to_erase != end_sit){ - group_functions_t::erase_from_group(end_ptr, detail::dcast_bucket_ptr(to_erase.pointed_node()), optimize_multikey_t()); - to_erase = b.erase_after_and_dispose(before_first_it, make_node_disposer(disposer)); - ++num_erased; + this->clear_and_dispose(disposer); + if(!constant_time_size || !src.empty()){ + const size_type src_bucket_count = src.bucket_count(); + const size_type dst_bucket_count = this->bucket_count(); + //Check power of two bucket array if the option is activated + BOOST_INTRUSIVE_INVARIANT_ASSERT + (!power_2_buckets || (0 == (src_bucket_count & (src_bucket_count-1)))); + BOOST_INTRUSIVE_INVARIANT_ASSERT + (!power_2_buckets || (0 == (dst_bucket_count & (dst_bucket_count-1)))); + //If src bucket count is bigger or equal, structural copy is possible + const bool structural_copy = (!incremental) && (src_bucket_count >= dst_bucket_count) && + (power_2_buckets || (src_bucket_count % dst_bucket_count) == 0); + if(structural_copy){ + this->priv_structural_clone_from(src, cloner, disposer); + } + else{ + //Unlike previous cloning algorithm, this can throw + //if cloner, hasher or comparison functor throw + typedef typename detail::if_c< detail::is_const::value + , typename MaybeConstHashtableImpl::const_iterator + , typename MaybeConstHashtableImpl::iterator + >::type clone_iterator; + clone_iterator b(src.begin()), e(src.end()); + detail::exception_disposer rollback(*this, disposer); + for(; b != e; ++b){ + //No need to check for duplicates and insert it in the first position + //as this is an unordered container. So use minimal insertion code + std::size_t const hash_to_store = this->priv_stored_or_compute_hash(*b, store_hash_t());; + size_type const bucket_number = this->priv_hash_to_bucket(hash_to_store); + typedef typename detail::if_c + ::value, const_reference, reference>::type reference_type; + reference_type r = *b; + this->priv_clone_front_in_bucket(bucket_number, r, hash_to_store, cloner); + } + rollback.release(); } - this->priv_size_traits().set_size(this->priv_size_traits().get_size()-num_erased); } } - template - void priv_erase_range_impl - (size_type first_bucket_num, size_type num_buckets, Disposer disposer, size_type &num_erased) - { - //Now fully clear the intermediate buckets - const bucket_ptr buckets = this->priv_bucket_pointer(); - num_erased = 0; - for(size_type i = first_bucket_num; i < (num_buckets + first_bucket_num); ++i){ - bucket_type &b = buckets[i]; - siterator b_begin(b.before_begin()); - siterator nxt(b_begin); - ++nxt; - siterator end_sit(b.end()); - while(nxt != end_sit){ - group_functions_t::init_group(detail::dcast_bucket_ptr(nxt.pointed_node()), optimize_multikey_t()); - nxt = b.erase_after_and_dispose - (b_begin, make_node_disposer(disposer)); - this->priv_size_traits().decrement(); - ++num_erased; + template + void priv_clone_front_in_bucket( size_type const bucket_number + , typename detail::identity::type src_ref + , std::size_t const hash_to_store, Cloner cloner) + { + //No need to check for duplicates and insert it in the first position + //as this is an unordered container. So use minimal insertion code + //std::size_t const hash_value = this->priv_stored_or_compute_hash(src_ref, store_hash_t());; + //size_type const bucket_number = this->priv_hash_to_bucket(hash_value); + bucket_type &cur_bucket = this->priv_bucket_pointer()[bucket_number]; + siterator const prev(cur_bucket.before_begin()); + //Just check if the cloned node is equal to the first inserted value in the new bucket + //as equal src values were contiguous and they should be already inserted in the + //destination bucket. + bool const next_is_in_group = optimize_multikey && !cur_bucket.empty() && + this->priv_equal()( key_of_value()(src_ref) + , key_of_value()(this->priv_value_from_slist_node((++siterator(prev)).pointed_node()))); + this->priv_insert_equal_after_find(*cloner(src_ref), bucket_number, hash_to_store, prev, next_is_in_group); + } + + template + void priv_structural_clone_from(MaybeConstHashtableImpl &src, Cloner cloner, Disposer disposer) + { + //First clone the first ones + const size_type src_bucket_count = src.bucket_count(); + const size_type dst_bucket_count = this->bucket_count(); + const bucket_ptr src_buckets = src.priv_bucket_pointer(); + const bucket_ptr dst_buckets = this->priv_bucket_pointer(); + size_type constructed = 0; + typedef node_cast_adaptor< detail::node_disposer + , slist_node_ptr, node_ptr > NodeDisposer; + NodeDisposer node_disp(disposer, &this->priv_value_traits()); + + detail::exception_array_disposer + rollback(dst_buckets[0], node_disp, constructed); + //Now insert the remaining ones using the modulo trick + for( //"constructed" already initialized + ; constructed < src_bucket_count + ; ++constructed){ + //Since incremental hashing can't be structurally copied, avoid hash_to_bucket_split + const std::size_t new_n = detail::hash_to_bucket(constructed, dst_bucket_count, detail::bool_()); + bucket_type &src_b = src_buckets[constructed]; + for( siterator b(src_b.begin()), e(src_b.end()); b != e; ++b){ + slist_node_ptr const n(b.pointed_node()); + typedef typename detail::if_c + ::value, const_reference, reference>::type reference_type; + reference_type r = this->priv_value_from_slist_node(n); + this->priv_clone_front_in_bucket + (new_n, r, this->priv_stored_hash(n, store_hash_t()), cloner); } } + this->priv_hasher() = src.priv_hasher(); + this->priv_equal() = src.priv_equal(); + rollback.release(); + this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + this->priv_split_traits().set_size(dst_bucket_count); + this->priv_insertion_update_cache(0u); + this->priv_erasure_update_cache(); } - template - void priv_erase_range( siterator before_first_it, size_type first_bucket - , siterator last_it, size_type last_bucket - , Disposer disposer) + std::size_t priv_hash_to_bucket(std::size_t hash_value) const { - size_type num_erased; - if (first_bucket == last_bucket){ - this->priv_erase_range_impl(first_bucket, before_first_it, last_it, disposer, num_erased); - } - else { - bucket_type *b = (&this->priv_bucket_pointer()[0]); - this->priv_erase_range_impl(first_bucket, before_first_it, b[first_bucket].end(), disposer, num_erased); - if(size_type n = (last_bucket - first_bucket - 1)) - this->priv_erase_range_impl(first_bucket + 1, n, disposer, num_erased); - this->priv_erase_range_impl(last_bucket, b[last_bucket].before_begin(), last_it, disposer, num_erased); - } + return detail::hash_to_bucket_split + (hash_value, this->priv_bucket_traits().bucket_count(), this->priv_split_traits().get_size()); } - std::size_t priv_get_bucket_num(siterator it) - { return this->priv_get_bucket_num_hash_dispatch(it, store_hash_t()); } - - std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::true_) //store_hash + iterator priv_insert_equal_after_find(reference value, size_type bucket_num, std::size_t hash_value, siterator prev, bool const next_is_in_group) { - return this->priv_hash_to_bucket - (this->priv_stored_hash(it.pointed_node(), store_hash_t())); + //Now store hash if needed + node_ptr n = pointer_traits::pointer_to(this->priv_value_to_node(value)); + node_functions_t::store_hash(n, hash_value, store_hash_t()); + //Checks for some modes + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(n)); + //Shortcut to optimize_multikey cases + group_functions_t::insert_in_group + ( next_is_in_group ? detail::dcast_bucket_ptr((++siterator(prev)).pointed_node()) : n + , n, optimize_multikey_t()); + //Update cache and increment size if needed + this->priv_insertion_update_cache(bucket_num); + this->priv_size_traits().increment(); + //Insert the element in the bucket after it + return iterator(bucket_type::s_insert_after(prev, *n), &this->get_bucket_value_traits()); } - std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_) //NO store_hash - { return this->data_type::internal.internal.internal.internal.priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); } - - static siterator priv_get_previous(bucket_type &b, siterator i) - { return bucket_plus_vtraits_t::priv_get_previous(b, i, optimize_multikey_t()); } - - static siterator priv_get_last(bucket_type &b) - { return bucket_plus_vtraits_t::priv_get_last(b, optimize_multikey_t()); } - - template - void priv_erase(const_iterator i, Disposer disposer, detail::true_) - { - slist_node_ptr elem(i.slist_it().pointed_node()); - slist_node_ptr f_bucket_end, l_bucket_end; - if(store_hash){ - f_bucket_end = l_bucket_end = - (this->priv_bucket_pointer() - [this->priv_hash_to_bucket - (this->priv_stored_hash(elem, store_hash_t())) - ]).before_begin().pointed_node(); - } - else{ - f_bucket_end = this->priv_bucket_pointer()->cend().pointed_node(); - l_bucket_end = f_bucket_end + this->priv_bucket_count() - 1; - } - node_ptr nxt_in_group; - siterator prev = bucket_type::s_iterator_to - (*group_functions_t::get_previous_and_next_in_group - ( elem, nxt_in_group, f_bucket_end, l_bucket_end) - ); - bucket_type::s_erase_after_and_dispose(prev, make_node_disposer(disposer)); - if(nxt_in_group) - group_algorithms::unlink_after(nxt_in_group); - if(safemode_or_autounlink) - group_algorithms::init(detail::dcast_bucket_ptr(elem)); + template + siterator priv_find //In case it is not found previt is bucket.before_begin() + ( const KeyType &key, KeyHasher hash_func + , KeyEqual equal_func, size_type &bucket_number, std::size_t &h, siterator &previt) const + { + h = hash_func(key); + return this->priv_find_with_hash(key, equal_func, bucket_number, h, previt); } - template - void priv_erase(const_iterator i, Disposer disposer, detail::false_) + template + bool priv_is_value_equal_to_key(const value_type &v, const std::size_t h, const KeyType &key, KeyEqual equal_func) const { - siterator to_erase(i.slist_it()); - bucket_type &b = this->priv_bucket_pointer()[this->priv_get_bucket_num(to_erase)]; - siterator prev(this->priv_get_previous(b, to_erase)); - b.erase_after_and_dispose(prev, make_node_disposer(disposer)); + (void)h; + return (!compare_hash || this->priv_stored_or_compute_hash(v, store_hash_t()) == h) && equal_func(key, key_of_value()(v)); } - template - siterator priv_find - ( const KeyType &key, KeyHasher hash_func - , KeyValueEqual equal_func, size_type &bucket_number, std::size_t &h, siterator &previt) const + //return previous iterator to the next equal range group in case + static siterator priv_last_in_group(const siterator &it_first_in_group) { - h = hash_func(key); - return this->priv_find_with_hash(key, equal_func, bucket_number, h, previt); + return bucket_type::s_iterator_to + (*group_functions_t::get_last_in_group + (detail::dcast_bucket_ptr(it_first_in_group.pointed_node()), optimize_multikey_t())); } - template - siterator priv_find_with_hash - ( const KeyType &key, KeyValueEqual equal_func, size_type &bucket_number, const std::size_t h, siterator &previt) const + template + siterator priv_find_with_hash //In case it is not found previt is bucket.before_begin() + ( const KeyType &key, KeyEqual equal_func, size_type &bucket_number, const std::size_t h, siterator &previt) const { bucket_number = this->priv_hash_to_bucket(h); bucket_type &b = this->priv_bucket_pointer()[bucket_number]; previt = b.before_begin(); - if(constant_time_size && this->empty()){ - return this->priv_invalid_local_it(); - } - siterator it = previt; - ++it; - - while(it != b.end()){ - const value_type &v = this->priv_value_from_slist_node(it.pointed_node()); - if(compare_hash){ - std::size_t vh = this->priv_stored_or_compute_hash(v, store_hash_t()); - if(h == vh && equal_func(key, v)){ - return it; - } - } - else if(equal_func(key, v)){ + siterator const endit = b.end(); + + while(++it != endit){ + if(this->priv_is_value_equal_to_key(this->priv_value_from_slist_node(it.pointed_node()), h, key, equal_func)){ return it; } - if(optimize_multikey){ - previt = bucket_type::s_iterator_to - (*group_functions_t::get_last_in_group - (detail::dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t())); - it = previt; - } - else{ - previt = it; - } - ++it; + previt = it = (priv_last_in_group)(it); } previt = b.before_begin(); return this->priv_invalid_local_it(); } - iterator priv_insert_equal_with_hash(reference value, std::size_t hash_value) - { - size_type bucket_num; - siterator prev; - siterator it = this->priv_find_with_hash - (value, this->priv_equal(), bucket_num, hash_value, prev); - return this->priv_insert_equal_find(value, bucket_num, hash_value, it); - } - - iterator priv_insert_equal_find(reference value, size_type bucket_num, std::size_t hash_value, siterator it) - { - bucket_type &b = this->priv_bucket_pointer()[bucket_num]; - bool found_equal = it != this->priv_invalid_local_it(); - if(!found_equal){ - it = b.before_begin(); - } - //Now store hash if needed - node_ptr n = pointer_traits::pointer_to(this->priv_value_to_node(value)); - node_functions_t::store_hash(n, hash_value, store_hash_t()); - //Checks for some modes - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); - //Shortcut for optimize_multikey cases - if(optimize_multikey){ - node_ptr first_in_group = found_equal ? - detail::dcast_bucket_ptr(it.pointed_node()) : node_ptr(); - group_functions_t::insert_in_group(first_in_group, n, optimize_multikey_t()); - } - //Update cache and increment size if needed - this->priv_insertion_update_cache(bucket_num); - this->priv_size_traits().increment(); - //Insert the element in the bucket after it - return iterator(b.insert_after(it, *n), &this->get_bucket_value_traits()); - } - - template - std::pair priv_equal_range + template + std::pair priv_local_equal_range ( const KeyType &key , KeyHasher hash_func - , KeyValueEqual equal_func - , size_type &bucket_number_first - , size_type &bucket_number_second + , KeyEqual equal_func + , size_type &found_bucket , size_type &cnt) const { - std::size_t h; cnt = 0; - siterator prev; //Let's see if the element is present + + siterator prev; + size_type n_bucket; + std::size_t h; std::pair to_return - ( this->priv_find(key, hash_func, equal_func, bucket_number_first, h, prev) + ( this->priv_find(key, hash_func, equal_func, n_bucket, h, prev) , this->priv_invalid_local_it()); - if(to_return.first == to_return.second){ - bucket_number_second = bucket_number_first; - return to_return; - } - { + + if(to_return.first != to_return.second){ + found_bucket = n_bucket; //If it's present, find the first that it's not equal in //the same bucket - bucket_type &b = this->priv_bucket_pointer()[bucket_number_first]; + bucket_type &b = this->priv_bucket_pointer()[n_bucket]; siterator it = to_return.first; + ++cnt; //At least one is found if(optimize_multikey){ - to_return.second = bucket_type::s_iterator_to - (*node_traits::get_next(group_functions_t::get_last_in_group - (detail::dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t()))); - - cnt = 0; - for(; it != to_return.second; ++it){ ++cnt; } - if(to_return.second != b.end()){ - bucket_number_second = bucket_number_first; - return to_return; - } + to_return.second = ++(priv_last_in_group)(it); + cnt += boost::intrusive::iterator_distance(++it, to_return.second); } else{ - ++cnt; - ++it; - while(it != b.end()){ - const value_type &v = this->priv_value_from_slist_node(it.pointed_node()); - if(compare_hash){ - std::size_t hv = this->priv_stored_or_compute_hash(v, store_hash_t()); - if(hv != h || !equal_func(key, v)){ - to_return.second = it; - bucket_number_second = bucket_number_first; - return to_return; - } - } - else if(!equal_func(key, v)){ - to_return.second = it; - bucket_number_second = bucket_number_first; - return to_return; - } - ++it; + siterator const bend = b.end(); + while(++it != bend && + this->priv_is_value_equal_to_key(this->priv_value_from_slist_node(it.pointed_node()), h, key, equal_func)){ ++cnt; } + to_return.second = it; } } + return to_return; + } - //If we reached the end, find the first, non-empty bucket - for(bucket_number_second = bucket_number_first+1 - ; bucket_number_second != this->priv_bucket_count() - ; ++bucket_number_second){ - bucket_type &b = this->priv_bucket_pointer()[bucket_number_second]; - if(!b.empty()){ - to_return.second = b.begin(); - return to_return; + template + std::pair priv_equal_range + ( const KeyType &key + , KeyHasher hash_func + , KeyEqual equal_func) const + { + size_type n_bucket; + size_type cnt; + + //Let's see if the element is present + std::pair to_return + (this->priv_local_equal_range(key, hash_func, equal_func, n_bucket, cnt)); + //If not, find the next element as ".second" if ".second" local iterator + //is not pointing to an element. + bucket_ptr const bp = this->priv_bucket_pointer(); + if(to_return.first != to_return.second && + to_return.second == bp[n_bucket].end()){ + to_return.second = this->priv_invalid_local_it(); + ++n_bucket; + for( const size_type max_bucket = this->priv_bucket_count() + ; n_bucket != max_bucket + ; ++n_bucket){ + bucket_type &b = bp[n_bucket]; + if(!b.empty()){ + to_return.second = b.begin(); + break; + } } } - - //Otherwise, return the end node - to_return.second = this->priv_invalid_local_it(); return to_return; } + + std::size_t priv_get_bucket_num(siterator it) + { return this->priv_get_bucket_num_hash_dispatch(it, store_hash_t()); } + + std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::true_) //store_hash + { + return this->priv_hash_to_bucket + (this->priv_stored_hash(it.pointed_node(), store_hash_t())); + } + + std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_) //NO store_hash + { return this->priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); } + + static siterator priv_get_previous(bucket_type &b, siterator i) + { return bucket_plus_vtraits_t::priv_get_previous(b, i, optimize_multikey_t()); } + /// @endcond }; @@ -3232,16 +3413,17 @@ struct make_hashtable typedef hashtable_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::hash , typename packed_options::equal - , typename packed_options::size_type , bucket_traits + , typename packed_options::size_type , (std::size_t(false)*hash_bool_flags::unique_keys_pos) - | (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos) - | (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos) - | (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos) - | (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos) - | (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos) + |(std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos) + |(std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos) + |(std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos) + |(std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos) + |(std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos) > implementation_defined; /// @endcond @@ -3299,6 +3481,14 @@ class hashtable hashtable& operator=(BOOST_RV_REF(hashtable) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + + template + void clone_from(const hashtable &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(hashtable) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } }; #endif diff --git a/boost/intrusive/intrusive_fwd.hpp b/boost/intrusive/intrusive_fwd.hpp index 88cb537c6b..b6b14c0698 100644 --- a/boost/intrusive/intrusive_fwd.hpp +++ b/boost/intrusive/intrusive_fwd.hpp @@ -184,6 +184,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -198,6 +199,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -212,6 +214,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -251,6 +254,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -265,6 +269,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -279,6 +284,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -294,6 +300,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -308,6 +315,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -322,6 +330,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -362,6 +371,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -376,6 +386,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -390,6 +401,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -405,6 +417,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -419,6 +432,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -433,6 +447,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -447,6 +462,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -461,6 +477,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template @@ -475,6 +492,7 @@ template , class O3 = void , class O4 = void , class O5 = void + , class O6 = void > #else template diff --git a/boost/intrusive/list.hpp b/boost/intrusive/list.hpp index 906b002907..cc6d73bb43 100644 --- a/boost/intrusive/list.hpp +++ b/boost/intrusive/list.hpp @@ -248,8 +248,7 @@ class list_impl void push_back(reference value) { node_ptr to_insert = priv_value_traits().to_node_ptr(value); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(to_insert)); node_algorithms::link_before(this->get_root_node(), to_insert); this->priv_size_traits().increment(); } @@ -267,8 +266,7 @@ class list_impl void push_front(reference value) { node_ptr to_insert = priv_value_traits().to_node_ptr(value); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(to_insert)); node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert); this->priv_size_traits().increment(); } @@ -770,6 +768,33 @@ class list_impl rollback.release(); } + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! Cloner should yield to nodes equivalent to the original nodes. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(reference) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. Basic guarantee. + template + void clone_from(BOOST_RV_REF(list_impl) src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + detail::exception_disposer + rollback(*this, disposer); + iterator b(src.begin()), e(src.end()); + for(; b != e; ++b){ + this->push_back(*cloner(*b)); + } + rollback.release(); + } + //! Requires: value must be an lvalue and p must be a valid iterator of *this. //! //! Effects: Inserts the value before the position pointed by p. @@ -784,8 +809,7 @@ class list_impl iterator insert(const_iterator p, reference value) { node_ptr to_insert = this->priv_value_traits().to_node_ptr(value); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(to_insert)); node_algorithms::link_before(p.pointed_node(), to_insert); this->priv_size_traits().increment(); return iterator(to_insert, this->priv_value_traits_ptr()); @@ -1320,6 +1344,32 @@ class list_impl BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_size_traits().get_size() == node_count); } + friend bool operator==(const list_impl &x, const list_impl &y) + { + if(constant_time_size && x.size() != y.size()){ + return false; + } + return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + friend bool operator!=(const list_impl &x, const list_impl &y) + { return !(x == y); } + + friend bool operator<(const list_impl &x, const list_impl &y) + { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + friend bool operator>(const list_impl &x, const list_impl &y) + { return y < x; } + + friend bool operator<=(const list_impl &x, const list_impl &y) + { return !(y < x); } + + friend bool operator>=(const list_impl &x, const list_impl &y) + { return !(x < y); } + + friend void swap(list_impl &x, list_impl &y) + { x.swap(y); } + /// @cond private: @@ -1338,103 +1388,6 @@ class list_impl /// @endcond }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ - typedef list_impl list_type; - const bool C = list_type::constant_time_size; - if(C && x.size() != y.size()){ - return false; - } - return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return !(x == y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return y < x; } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return !(y < x); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return !(x < y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(list_impl &x, list_impl &y) -#else -(list_impl &x, list_impl &y) -#endif -{ x.swap(y); } //! Helper metafunction to define a \c list that yields to the same type when the //! same options (either explicitly or implicitly) are used. @@ -1518,6 +1471,14 @@ class list list& operator=(BOOST_RV_REF(list) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const list &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(list) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static list &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/options.hpp b/boost/intrusive/options.hpp index ec6e9674d9..fdcb5cb3c5 100644 --- a/boost/intrusive/options.hpp +++ b/boost/intrusive/options.hpp @@ -61,6 +61,15 @@ BOOST_INTRUSIVE_OPTION_TYPE(size_type, SizeType, SizeType, size_type) //!comparison functor for the value type BOOST_INTRUSIVE_OPTION_TYPE(compare, Compare, Compare, compare) +//!This option setter specifies the a function object +//!that specifies the type of the key of an associative +//!container and an operator to obtain it from a value type. +//! +//!This function object must the define a `key_type` and +//!a member with signature `const key_type & operator()(const value_type &) const` +//!that will return the key from a value_type of an associative container +BOOST_INTRUSIVE_OPTION_TYPE(key_of_value, KeyOfValue, KeyOfValue, key_of_value) + //!This option setter for scapegoat containers specifies if //!the intrusive scapegoat container should use a non-variable //!alpha value that does not need floating-point operations. @@ -199,7 +208,7 @@ BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_multikey, bool, Enabled, optimize_multi //!This allows using masks instead of the default modulo operation to determine //!the bucket number from the hash value, leading to better performance. //!In debug mode, if power of two buckets mode is activated, the bucket length -//!will be checked to through assertions to assure the bucket length is power of two. +//!will be checked with assertions. BOOST_INTRUSIVE_OPTION_CONSTANT(power_2_buckets, bool, Enabled, power_2_buckets) //!This option setter specifies if the container will cache a pointer to the first diff --git a/boost/intrusive/rbtree.hpp b/boost/intrusive/rbtree.hpp index 4ef50b4c4f..f3afd017c8 100644 --- a/boost/intrusive/rbtree.hpp +++ b/boost/intrusive/rbtree.hpp @@ -48,19 +48,16 @@ struct is_default_hook_tag { static const bool value = true; }; struct rbtree_defaults + : bstree_defaults { typedef default_rbtree_hook_applier proto_value_traits; - static const bool constant_time_size = true; - typedef std::size_t size_type; - typedef void compare; - typedef void header_holder_type; }; /// @endcond //! The class template rbtree is an intrusive red-black tree container, that //! is used to construct intrusive set and multiset containers. The no-throw -//! guarantee holds only, if the value_compare object +//! guarantee holds only, if the key_compare object //! doesn't throw. //! //! The template parameter \c T is the type to be managed by the container. @@ -74,17 +71,17 @@ struct rbtree_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class rbtree_impl /// @cond - : public bstree_impl + : public bstree_impl /// @endcond { public: typedef ValueTraits value_traits; /// @cond - typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType + typedef bstree_impl< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType , ConstantTimeSize, RbTreeAlgorithms , HeaderHolder> tree_type; typedef tree_type implementation_defined; @@ -94,6 +91,7 @@ class rbtree_impl typedef typename implementation_defined::const_pointer const_pointer; typedef typename implementation_defined::value_type value_type; typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::reference reference; typedef typename implementation_defined::const_reference const_reference; typedef typename implementation_defined::difference_type difference_type; @@ -123,16 +121,16 @@ class rbtree_impl typedef typename implementation_defined::insert_commit_data insert_commit_data; - //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) - explicit rbtree_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &) + explicit rbtree_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template rbtree_impl( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(unique, b, e, cmp, v_traits) {} @@ -213,13 +211,26 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::swap void swap(rbtree_impl& other); - //! @copydoc ::boost::intrusive::bstree::clone_from(const bstree &src, cloner, Disposer) + //! @copydoc ::boost::intrusive::bstree::clone_from(const bstree&,Cloner,Disposer) template void clone_from(const rbtree_impl &src, Cloner cloner, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::clone_from(bstree &src, cloner, Disposer) + #else //BOOST_INTRUSIVE_DOXYGEN_INVOKED + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree::clone_from(bstree&&,Cloner,Disposer) template - void clone_from(rbtree_impl &src, Cloner cloner, Disposer disposer); + void clone_from(BOOST_RV_REF(rbtree_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree::clone_from(bstree&&,Cloner,Disposer) + template + void clone_from(rbtree_impl &&src, Cloner cloner, Disposer disposer); //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) iterator insert_equal(reference value); @@ -237,16 +248,16 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference) iterator insert_unique(const_iterator hint, reference value); - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_unique_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data); + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data); - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_unique_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data); + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data); //! @copydoc ::boost::intrusive::bstree::insert_unique_commit iterator insert_unique_commit(reference value, const insert_commit_data &commit_data); @@ -270,12 +281,12 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::bstree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::bstree::erase(const key_type &key) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) template @@ -285,13 +296,13 @@ class rbtree_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::bstree::clear void clear(); @@ -300,88 +311,88 @@ class rbtree_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::count(const key_type &)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::bstree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @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, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -406,33 +417,23 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED -}; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + friend bool operator< (const rbtree_impl &x, const rbtree_impl &y); -template -bool operator< (const rbtree_impl &x, const rbtree_impl &y); + friend bool operator==(const rbtree_impl &x, const rbtree_impl &y); -template -bool operator==(const rbtree_impl &x, const rbtree_impl &y); + friend bool operator!= (const rbtree_impl &x, const rbtree_impl &y); -template -bool operator!= (const rbtree_impl &x, const rbtree_impl &y); - -template -bool operator>(const rbtree_impl &x, const rbtree_impl &y); + friend bool operator>(const rbtree_impl &x, const rbtree_impl &y); -template -bool operator<=(const rbtree_impl &x, const rbtree_impl &y); + friend bool operator<=(const rbtree_impl &x, const rbtree_impl &y); -template -bool operator>=(const rbtree_impl &x, const rbtree_impl &y); + friend bool operator>=(const rbtree_impl &x, const rbtree_impl &y); -template -void swap(rbtree_impl &x, rbtree_impl &y); + friend void swap(rbtree_impl &x, rbtree_impl &y); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +}; -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c rbtree that yields to the same type when the //! same options (either explicitly or implicitly) are used. @@ -441,7 +442,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_rbtree { @@ -449,7 +450,7 @@ struct make_rbtree typedef typename pack_options < rbtree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -460,6 +461,7 @@ struct make_rbtree typedef rbtree_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -473,14 +475,14 @@ struct make_rbtree #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class rbtree : public make_rbtree::value)); - explicit rbtree( const value_compare &cmp = value_compare() + explicit rbtree( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template rbtree( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(unique, b, e, cmp, v_traits) {} @@ -526,6 +528,14 @@ class rbtree rbtree& operator=(BOOST_RV_REF(rbtree) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const rbtree &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(rbtree) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static rbtree &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/rbtree_algorithms.hpp b/boost/intrusive/rbtree_algorithms.hpp index ad9c7658e3..00d9fe3b18 100644 --- a/boost/intrusive/rbtree_algorithms.hpp +++ b/boost/intrusive/rbtree_algorithms.hpp @@ -92,8 +92,8 @@ struct rbtree_node_checker if (node_traits::get_color(p) == node_traits::red()){ //Red nodes have black children - const node_ptr p_left(node_traits::get_left(p)); - const node_ptr p_right(node_traits::get_right(p)); + const node_ptr p_left(node_traits::get_left(p)); (void)p_left; + const node_ptr p_right(node_traits::get_right(p)); (void)p_right; BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_left || node_traits::get_color(p_left) == node_traits::black()); BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_right || node_traits::get_color(p_right) == node_traits::black()); //Red node can't be root diff --git a/boost/intrusive/set.hpp b/boost/intrusive/set.hpp index 1048429005..ae6a7a0812 100644 --- a/boost/intrusive/set.hpp +++ b/boost/intrusive/set.hpp @@ -42,15 +42,15 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class set_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public bstree_impl + : public bstree_impl #endif { /// @cond - typedef bstree_impl tree_type; + typedef bstree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(set_impl) typedef tree_type implementation_defined; @@ -58,6 +58,8 @@ class set_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -81,16 +83,16 @@ class set_impl static const bool constant_time_size = tree_type::constant_time_size; public: - //! @copydoc ::boost::intrusive::rbtree::rbtree(const value_compare &,const value_traits &) - explicit set_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::rbtree::rbtree(const key_compare &,const value_traits &) + explicit set_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::rbtree::rbtree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::rbtree::rbtree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template set_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(true, b, e, cmp, v_traits) {} @@ -171,11 +173,20 @@ class set_impl //! @copydoc ::boost::intrusive::rbtree::swap void swap(set_impl& other); - //! @copydoc ::boost::intrusive::rbtree::clone_from + //! @copydoc ::boost::intrusive::rbtree::clone_from(const rbtree&,Cloner,Disposer) template void clone_from(const set_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::rbtree::clone_from(rbtree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(set_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::rbtree::insert_unique(reference) std::pair insert(reference value) @@ -185,18 +196,18 @@ class set_impl iterator insert(const_iterator hint, reference value) { return tree_type::insert_unique(hint, value); } - //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(key, comp, commit_data); } - //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(hint, key, comp, commit_data); } //! @copydoc ::boost::intrusive::rbtree::insert_unique(Iterator,Iterator) template @@ -223,12 +234,12 @@ class set_impl //! @copydoc ::boost::intrusive::rbtree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::rbtree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::rbtree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::rbtree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::rbtree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_iterator,Disposer) template @@ -238,13 +249,13 @@ class set_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::rbtree::clear void clear(); @@ -255,100 +266,100 @@ class set_impl #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::rbtree::count(const_reference)const - size_type count(const_reference value) const - { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } + //! @copydoc ::boost::intrusive::rbtree::count(const key_type &)const + size_type count(const key_type &key) const + { return static_cast(this->tree_type::find(key) != this->tree_type::cend()); } - //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const + //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::rbtree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::rbtree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::rbtree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::rbtree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::rbtree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::rbtree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) - std::pair equal_range(const_reference value) - { return this->tree_type::lower_bound_range(value); } + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &) + std::pair equal_range(const key_type &key) + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) + //! @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); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const - { return this->tree_type::lower_bound_range(value); } + equal_range(const key_type &key) const + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const { return this->tree_type::lower_bound_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::rbtree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::rbtree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::rbtree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -402,7 +413,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_set { @@ -410,7 +421,7 @@ struct make_set typedef typename pack_options < rbtree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -421,6 +432,7 @@ struct make_set typedef set_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -432,14 +444,14 @@ struct make_set #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class set : public make_set::value)); - explicit set( const value_compare &cmp = value_compare() + explicit set( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template set( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -483,6 +495,14 @@ class set set& operator=(BOOST_RV_REF(set) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const set &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(set) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -512,15 +532,15 @@ class set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class multiset_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public bstree_impl + : public bstree_impl #endif { /// @cond - typedef bstree_impl tree_type; + typedef bstree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(multiset_impl) typedef tree_type implementation_defined; @@ -528,6 +548,8 @@ class multiset_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -551,16 +573,16 @@ class multiset_impl static const bool constant_time_size = tree_type::constant_time_size; public: - //! @copydoc ::boost::intrusive::rbtree::rbtree(const value_compare &,const value_traits &) - explicit multiset_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::rbtree::rbtree(const key_compare &,const value_traits &) + explicit multiset_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::rbtree::rbtree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::rbtree::rbtree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template multiset_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(false, b, e, cmp, v_traits) {} @@ -641,11 +663,20 @@ class multiset_impl //! @copydoc ::boost::intrusive::rbtree::swap void swap(multiset_impl& other); - //! @copydoc ::boost::intrusive::rbtree::clone_from + //! @copydoc ::boost::intrusive::rbtree::clone_from(const rbtree&,Cloner,Disposer) template void clone_from(const multiset_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::rbtree::clone_from(rbtree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(multiset_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::rbtree::insert_equal(reference) iterator insert(reference value) @@ -676,12 +707,12 @@ class multiset_impl //! @copydoc ::boost::intrusive::rbtree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::rbtree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::rbtree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::rbtree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::rbtree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_iterator,Disposer) template @@ -691,13 +722,13 @@ class multiset_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::rbtree::clear void clear(); @@ -706,88 +737,88 @@ class multiset_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::rbtree::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::rbtree::count(const key_type &)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::rbtree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::rbtree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::rbtree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::rbtree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::rbtree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::rbtree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::rbtree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::rbtree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::rbtree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -841,7 +872,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_multiset { @@ -849,7 +880,7 @@ struct make_multiset typedef typename pack_options < rbtree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -860,6 +891,7 @@ struct make_multiset typedef multiset_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -872,14 +904,14 @@ struct make_multiset #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class multiset : public make_multiset::value)); - multiset( const value_compare &cmp = value_compare() + multiset( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template multiset( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -923,6 +955,14 @@ class multiset multiset& operator=(BOOST_RV_REF(multiset) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const multiset &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(multiset) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/sg_set.hpp b/boost/intrusive/sg_set.hpp index 7e250cb6a0..560845e7a2 100644 --- a/boost/intrusive/sg_set.hpp +++ b/boost/intrusive/sg_set.hpp @@ -40,15 +40,15 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class sg_set_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public sgtree_impl + : public sgtree_impl #endif { /// @cond - typedef sgtree_impl tree_type; + typedef sgtree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(sg_set_impl) typedef tree_type implementation_defined; @@ -56,6 +56,8 @@ class sg_set_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -79,16 +81,16 @@ class sg_set_impl static const bool constant_time_size = tree_type::constant_time_size; public: - //! @copydoc ::boost::intrusive::sgtree::sgtree(const value_compare &,const value_traits &) - explicit sg_set_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::sgtree::sgtree(const key_compare &,const value_traits &) + explicit sg_set_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::sgtree::sgtree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::sgtree::sgtree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template sg_set_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(true, b, e, cmp, v_traits) {} @@ -169,11 +171,20 @@ class sg_set_impl //! @copydoc ::boost::intrusive::sgtree::swap void swap(sg_set_impl& other); - //! @copydoc ::boost::intrusive::sgtree::clone_from + //! @copydoc ::boost::intrusive::sgtree::clone_from(const sgtree&,Cloner,Disposer) template void clone_from(const sg_set_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::sgtree::clone_from(sgtree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(sg_set_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::sgtree::insert_unique(reference) std::pair insert(reference value) @@ -183,18 +194,18 @@ class sg_set_impl iterator insert(const_iterator hint, reference value) { return tree_type::insert_unique(hint, value); } - //! @copydoc ::boost::intrusive::sgtree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::sgtree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(key, comp, commit_data); } - //! @copydoc ::boost::intrusive::sgtree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::sgtree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(hint, key, comp, commit_data); } //! @copydoc ::boost::intrusive::sgtree::insert_unique(Iterator,Iterator) template @@ -221,12 +232,12 @@ class sg_set_impl //! @copydoc ::boost::intrusive::sgtree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::sgtree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::sgtree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::sgtree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::sgtree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_iterator,Disposer) template @@ -236,13 +247,13 @@ class sg_set_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::sgtree::clear void clear(); @@ -253,100 +264,100 @@ class sg_set_impl #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::sgtree::count(const_reference)const - size_type count(const_reference value) const - { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } + //! @copydoc ::boost::intrusive::sgtree::count(const key_type &)const + size_type count(const key_type &key) const + { return static_cast(this->tree_type::find(key) != this->tree_type::cend()); } - //! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const + //! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::sgtree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::sgtree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::sgtree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::sgtree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::sgtree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::sgtree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) - std::pair equal_range(const_reference value) - { return this->tree_type::lower_bound_range(value); } + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &) + std::pair equal_range(const key_type &key) + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) + //! @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); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const - { return this->tree_type::lower_bound_range(value); } + equal_range(const key_type &key) const + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const { return this->tree_type::lower_bound_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::sgtree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::sgtree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::sgtree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -413,7 +424,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_sg_set { @@ -421,7 +432,7 @@ struct make_sg_set typedef typename pack_options < sgtree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -432,6 +443,7 @@ struct make_sg_set typedef sg_set_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::floating_point @@ -443,14 +455,14 @@ struct make_sg_set #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class sg_set : public make_sg_set::value)); - explicit sg_set( const value_compare &cmp = value_compare() + explicit sg_set( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template sg_set( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -494,6 +506,14 @@ class sg_set sg_set& operator=(BOOST_RV_REF(sg_set) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const sg_set &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(sg_set) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static sg_set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -523,15 +543,15 @@ class sg_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class sg_multiset_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public sgtree_impl + : public sgtree_impl #endif { /// @cond - typedef sgtree_impl tree_type; + typedef sgtree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(sg_multiset_impl) typedef tree_type implementation_defined; @@ -539,6 +559,8 @@ class sg_multiset_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -562,16 +584,16 @@ class sg_multiset_impl static const bool constant_time_size = tree_type::constant_time_size; public: - //! @copydoc ::boost::intrusive::sgtree::sgtree(const value_compare &,const value_traits &) - explicit sg_multiset_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::sgtree::sgtree(const key_compare &,const value_traits &) + explicit sg_multiset_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::sgtree::sgtree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::sgtree::sgtree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template sg_multiset_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(false, b, e, cmp, v_traits) {} @@ -652,11 +674,20 @@ class sg_multiset_impl //! @copydoc ::boost::intrusive::sgtree::swap void swap(sg_multiset_impl& other); - //! @copydoc ::boost::intrusive::sgtree::clone_from + //! @copydoc ::boost::intrusive::sgtree::clone_from(const sgtree&,Cloner,Disposer) template void clone_from(const sg_multiset_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::sgtree::clone_from(sgtree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(sg_multiset_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::sgtree::insert_equal(reference) iterator insert(reference value) @@ -687,12 +718,12 @@ class sg_multiset_impl //! @copydoc ::boost::intrusive::sgtree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::sgtree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::sgtree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::sgtree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::sgtree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_iterator,Disposer) template @@ -702,13 +733,13 @@ class sg_multiset_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::sgtree::clear void clear(); @@ -717,88 +748,88 @@ class sg_multiset_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::sgtree::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::sgtree::count(const key_type &)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::sgtree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::sgtree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::sgtree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::sgtree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::sgtree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::sgtree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::sgtree::equal_range(const key_type &) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::sgtree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::sgtree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::sgtree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::sgtree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -865,7 +896,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_sg_multiset { @@ -873,7 +904,7 @@ struct make_sg_multiset typedef typename pack_options < sgtree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -884,6 +915,7 @@ struct make_sg_multiset typedef sg_multiset_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::floating_point @@ -896,14 +928,14 @@ struct make_sg_multiset #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class sg_multiset : public make_sg_multiset::value)); - sg_multiset( const value_compare &cmp = value_compare() + sg_multiset( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template sg_multiset( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -947,6 +979,14 @@ class sg_multiset sg_multiset& operator=(BOOST_RV_REF(sg_multiset) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const sg_multiset &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(sg_multiset) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static sg_multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/sgtree.hpp b/boost/intrusive/sgtree.hpp index feeaf3bcbf..dc84c80462 100644 --- a/boost/intrusive/sgtree.hpp +++ b/boost/intrusive/sgtree.hpp @@ -195,13 +195,9 @@ struct alpha_holder } //namespace detail{ struct sgtree_defaults + : bstree_defaults { - typedef default_bstree_hook_applier proto_value_traits; - static const bool constant_time_size = true; - typedef std::size_t size_type; - typedef void compare; static const bool floating_point = true; - typedef void header_holder_type; }; /// @endcond @@ -222,18 +218,18 @@ struct sgtree_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class sgtree_impl /// @cond - : public bstree_impl + : public bstree_impl , public detail::alpha_holder /// @endcond { public: typedef ValueTraits value_traits; /// @cond - typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType + typedef bstree_impl< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType , true, SgTreeAlgorithms, HeaderHolder> tree_type; typedef tree_type implementation_defined; @@ -243,6 +239,7 @@ class sgtree_impl typedef typename implementation_defined::const_pointer const_pointer; typedef typename implementation_defined::value_type value_type; typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::reference reference; typedef typename implementation_defined::const_reference const_reference; typedef typename implementation_defined::difference_type difference_type; @@ -284,16 +281,16 @@ class sgtree_impl typedef BOOST_INTRUSIVE_IMPDEF(typename node_algorithms::insert_commit_data) insert_commit_data; - //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) - explicit sgtree_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &) + explicit sgtree_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template sgtree_impl( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) { @@ -408,26 +405,33 @@ class sgtree_impl ::boost::adl_move_swap(this->get_alpha_traits(), other.get_alpha_traits()); } - //! @copydoc ::boost::intrusive::bstree::clone_from + //! @copydoc ::boost::intrusive::bstree::clone_from(const bstree&,Cloner,Disposer) //! Additional notes: it also copies the alpha factor from the source container. template void clone_from(const sgtree_impl &src, Cloner cloner, Disposer disposer) { - this->tree_type::clone_from(src, cloner, disposer); + tree_type::clone_from(src, cloner, disposer); this->get_alpha_traits() = src.get_alpha_traits(); } + //! @copydoc ::boost::intrusive::bstree::clone_from(bstree&&,Cloner,Disposer) + //! Additional notes: it also copies the alpha factor from the source container. + template + void clone_from(BOOST_RV_REF(sgtree_impl) src, Cloner cloner, Disposer disposer) + { + tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); + this->get_alpha_traits() = ::boost::move(src.get_alpha_traits()); + } + //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_value_traits()); node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; node_ptr p = node_algorithms::insert_equal_upper_bound - (this->tree_type::header_ptr(), to_insert, key_node_comp + (this->tree_type::header_ptr(), to_insert, this->key_node_comp(this->key_comp()) , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; @@ -437,14 +441,12 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference) iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_value_traits()); node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; node_ptr p = node_algorithms::insert_equal - (this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp + ( this->tree_type::header_ptr(), hint.pointed_node(), to_insert, this->key_node_comp(this->key_comp()) , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; @@ -464,46 +466,44 @@ class sgtree_impl std::pair insert_unique(reference value) { insert_commit_data commit_data; - std::pair ret = insert_unique_check(value, this->value_comp(), commit_data); + std::pair ret = this->insert_unique_check + (key_of_value()(value), this->key_comp(), commit_data); if(!ret.second) return ret; - return std::pair (insert_unique_commit(value, commit_data), true); + return std::pair (this->insert_unique_commit(value, commit_data), true); } //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference) iterator insert_unique(const_iterator hint, reference value) { insert_commit_data commit_data; - std::pair ret = insert_unique_check(hint, value, this->value_comp(), commit_data); + std::pair ret = this->insert_unique_check + (hint, key_of_value()(value), this->key_comp(), commit_data); if(!ret.second) return ret.first; - return insert_unique_commit(value, commit_data); + return this->insert_unique_commit(value, commit_data); } - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_unique_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - comp(key_value_comp, &this->get_value_traits()); std::pair ret = - (node_algorithms::insert_unique_check - (this->tree_type::header_ptr(), key, comp, commit_data)); + node_algorithms::insert_unique_check + (this->tree_type::header_ptr(), key, this->key_node_comp(comp), commit_data); return std::pair(iterator(ret.first, this->priv_value_traits_ptr()), ret.second); } - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_unique_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - comp(key_value_comp, &this->get_value_traits()); std::pair ret = - (node_algorithms::insert_unique_check - (this->tree_type::header_ptr(), hint.pointed_node(), key, comp, commit_data)); + node_algorithms::insert_unique_check + (this->tree_type::header_ptr(), hint.pointed_node(), key, this->key_node_comp(comp), commit_data); return std::pair(iterator(ret.first, this->priv_value_traits_ptr()), ret.second); } @@ -604,17 +604,15 @@ class sgtree_impl iterator erase(const_iterator b, const_iterator e) { size_type n; return private_erase(b, e, n); } - //! @copydoc ::boost::intrusive::bstree::erase(const_reference) - size_type erase(const_reference value) - { return this->erase(value, this->value_comp()); } - - //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + //! @copydoc ::boost::intrusive::bstree::erase(const key_type &) + size_type erase(const key_type &key) + { return this->erase(key, this->key_comp()); } + + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyTypeKeyCompare) + template + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase(const KeyType& key, KeyTypeKeyCompare comp) { std::pair p = this->equal_range(key, comp); size_type n; @@ -643,23 +641,21 @@ class sgtree_impl iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) { size_type n; return private_erase(b, e, n, disposer); } - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer) + size_type erase_and_dispose(const key_type &key, Disposer disposer) { - std::pair p = this->equal_range(value); + std::pair p = this->equal_range(key); size_type n; private_erase(p.first, p.second, n, disposer); return n; } - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer) { std::pair p = this->equal_range(key, comp); size_type n; @@ -683,88 +679,88 @@ class sgtree_impl } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::count(const key_type &)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::bstree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @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, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -796,6 +792,20 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::rebalance_subtree iterator rebalance_subtree(iterator root); + friend bool operator< (const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator==(const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator!= (const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator>(const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator<=(const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator>=(const sgtree_impl &x, const sgtree_impl &y); + + friend void swap(sgtree_impl &x, sgtree_impl &y); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Returns: The balance factor (alpha) used in this tree @@ -850,30 +860,6 @@ class sgtree_impl /// @endcond }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - -template -bool operator< (const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator==(const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator!= (const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator>(const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator<=(const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator>=(const sgtree_impl &x, const sgtree_impl &y); - -template -void swap(sgtree_impl &x, sgtree_impl &y); - -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c sgtree that yields to the same type when the //! same options (either explicitly or implicitly) are used. @@ -882,7 +868,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_sgtree { @@ -890,7 +876,7 @@ struct make_sgtree typedef typename pack_options < sgtree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -901,6 +887,7 @@ struct make_sgtree typedef sgtree_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::floating_point @@ -914,14 +901,14 @@ struct make_sgtree #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class sgtree : public make_sgtree::value)); - explicit sgtree( const value_compare &cmp = value_compare() + explicit sgtree( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template sgtree( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(unique, b, e, cmp, v_traits) {} @@ -967,6 +954,14 @@ class sgtree sgtree& operator=(BOOST_RV_REF(sgtree) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const sgtree &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(sgtree) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static sgtree &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/slist.hpp b/boost/intrusive/slist.hpp index 757508149b..dd3a05f2f8 100644 --- a/boost/intrusive/slist.hpp +++ b/boost/intrusive/slist.hpp @@ -416,8 +416,7 @@ class slist_impl void push_front(reference value) { node_ptr to_insert = priv_value_traits().to_node_ptr(value); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(to_insert)); if(cache_last){ if(this->empty()){ this->set_last_node(to_insert); @@ -442,8 +441,7 @@ class slist_impl { BOOST_STATIC_ASSERT((cache_last)); node_ptr n = priv_value_traits().to_node_ptr(value); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(n)); node_algorithms::link_after(this->get_last_node(), n); if(cache_last){ this->set_last_node(n); @@ -768,6 +766,34 @@ class slist_impl rollback.release(); } + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! Cloner should yield to nodes equivalent to the original nodes. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(reference) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(BOOST_RV_REF(slist_impl) src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + detail::exception_disposer + rollback(*this, disposer); + iterator prev(this->cbefore_begin()); + iterator b(src.begin()), e(src.end()); + for(; b != e; ++b){ + prev = this->insert_after(prev, *cloner(*b)); + } + rollback.release(); + } + //! Requires: value must be an lvalue and prev_p must point to an element //! contained by the list or to end(). //! @@ -784,8 +810,7 @@ class slist_impl iterator insert_after(const_iterator prev_p, reference value) { node_ptr n = priv_value_traits().to_node_ptr(value); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(n)); node_ptr prev_n(prev_p.pointed_node()); node_algorithms::link_after(prev_n, n); if(cache_last && (this->get_last_node() == prev_n)){ @@ -815,8 +840,7 @@ class slist_impl node_ptr prev_n(prev_p.pointed_node()); for (; f != l; ++f, ++count){ const node_ptr n = priv_value_traits().to_node_ptr(*f); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(n)); node_algorithms::link_after(prev_n, n); prev_n = n; } @@ -1028,6 +1052,15 @@ class slist_impl /// @cond + static iterator s_insert_after(const_iterator const prev_p, reference value) + { + BOOST_STATIC_ASSERT(((!cache_last)&&(!constant_time_size)&&(!stateful_value_traits))); + node_ptr const n = value_traits::to_node_ptr(value); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(n)); + node_algorithms::link_after(prev_p.pointed_node(), n); + return iterator (n, const_value_traits_ptr()); + } + template static iterator s_erase_after_and_dispose(const_iterator prev, Disposer disposer) { @@ -1044,6 +1077,23 @@ class slist_impl return it.unconst(); } + template + static iterator s_erase_after_and_dispose(const_iterator before_f, const_iterator l, Disposer disposer) + { + BOOST_STATIC_ASSERT(((!cache_last)&&(!constant_time_size)&&(!stateful_value_traits))); + node_ptr bfp(before_f.pointed_node()), lp(l.pointed_node()); + node_ptr fp(node_traits::get_next(bfp)); + node_algorithms::unlink_after(bfp, lp); + while(fp != lp){ + node_ptr to_erase(fp); + fp = node_traits::get_next(fp); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(value_traits::to_value_ptr(to_erase)); + } + return l.unconst(); + } + static iterator s_erase_after(const_iterator prev) { return s_erase_after_and_dispose(prev, detail::null_disposer()); } @@ -1905,6 +1955,33 @@ class slist_impl BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_size_traits().get_size() == node_count); } + + friend bool operator==(const slist_impl &x, const slist_impl &y) + { + if(constant_time_size && x.size() != y.size()){ + return false; + } + return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + friend bool operator!=(const slist_impl &x, const slist_impl &y) + { return !(x == y); } + + friend bool operator<(const slist_impl &x, const slist_impl &y) + { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + friend bool operator>(const slist_impl &x, const slist_impl &y) + { return y < x; } + + friend bool operator<=(const slist_impl &x, const slist_impl &y) + { return !(y < x); } + + friend bool operator>=(const slist_impl &x, const slist_impl &y) + { return !(x < y); } + + friend void swap(slist_impl &x, slist_impl &y) + { x.swap(y); } + private: void priv_splice_after(const node_ptr & prev_pos_n, slist_impl &x, const node_ptr & before_f_n, const node_ptr & before_l_n) { @@ -2044,111 +2121,6 @@ class slist_impl } }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ - typedef slist_impl slist_type; - const bool C = slist_type::constant_time_size; - if(C && x.size() != y.size()){ - return false; - } - return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return !(x == y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return y < x; } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return !(y < x); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return !(x < y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(slist_impl &x, slist_impl &y) -#else -( slist_impl &x -, slist_impl &y) -#endif -{ x.swap(y); } - //! Helper metafunction to define a \c slist that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) @@ -2241,6 +2213,14 @@ class slist slist& operator=(BOOST_RV_REF(slist) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const slist &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(slist) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static slist &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/splay_set.hpp b/boost/intrusive/splay_set.hpp index 80887dffdc..eea19d7999 100644 --- a/boost/intrusive/splay_set.hpp +++ b/boost/intrusive/splay_set.hpp @@ -40,15 +40,15 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class splay_set_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public splaytree_impl + : public splaytree_impl #endif { /// @cond - typedef splaytree_impl tree_type; + typedef splaytree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(splay_set_impl) typedef tree_type implementation_defined; @@ -56,6 +56,8 @@ class splay_set_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -79,16 +81,16 @@ class splay_set_impl static const bool constant_time_size = tree_type::constant_time_size; public: - //! @copydoc ::boost::intrusive::splaytree::splaytree(const value_compare &,const value_traits &) - explicit splay_set_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::splaytree::splaytree(const key_compare &,const value_traits &) + explicit splay_set_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::splaytree::splaytree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::splaytree::splaytree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template splay_set_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(true, b, e, cmp, v_traits) {} @@ -169,11 +171,20 @@ class splay_set_impl //! @copydoc ::boost::intrusive::splaytree::swap void swap(splay_set_impl& other); - //! @copydoc ::boost::intrusive::splaytree::clone_from + //! @copydoc ::boost::intrusive::splaytree::clone_from(const splaytree&,Cloner,Disposer) template void clone_from(const splay_set_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::splaytree::clone_from(splaytree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(splay_set_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::splaytree::insert_unique(reference) std::pair insert(reference value) @@ -183,18 +194,18 @@ class splay_set_impl iterator insert(const_iterator hint, reference value) { return tree_type::insert_unique(hint, value); } - //! @copydoc ::boost::intrusive::splaytree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::splaytree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(key, comp, commit_data); } - //! @copydoc ::boost::intrusive::splaytree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::splaytree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(hint, key, comp, commit_data); } //! @copydoc ::boost::intrusive::splaytree::insert_unique(Iterator,Iterator) template @@ -221,12 +232,12 @@ class splay_set_impl //! @copydoc ::boost::intrusive::splaytree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::splaytree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::splaytree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_iterator,Disposer) template @@ -236,13 +247,13 @@ class splay_set_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::splaytree::clear void clear(); @@ -253,107 +264,107 @@ class splay_set_impl #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const - size_type count(const_reference value) const - { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } + //! @copydoc ::boost::intrusive::splaytree::count(const key_type &)const + size_type count(const key_type &key) const + { return static_cast(this->tree_type::find(key) != this->tree_type::cend()); } - //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const + //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::splaytree::count(const key_type &)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::splaytree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) - std::pair equal_range(const_reference value) - { return this->tree_type::lower_bound_range(value); } + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &) + std::pair equal_range(const key_type &key) + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) + //! @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); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const - { return this->tree_type::lower_bound_range(value); } + equal_range(const key_type &key) const + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const { return this->tree_type::lower_bound_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const key_type&,const key_type&,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const key_type&,const key_type&,bool,bool)const std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -382,12 +393,12 @@ class splay_set_impl //! @copydoc ::boost::intrusive::splaytree::splay_up(iterator) void splay_up(iterator i); - //! @copydoc ::boost::intrusive::splaytree::splay_down(const KeyType&,KeyValueCompare) - template - iterator splay_down(const KeyType &key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::splay_down(const KeyType&,KeyTypeKeyCompare) + template + iterator splay_down(const KeyType &key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::splay_down(const_reference) - iterator splay_down(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::splay_down(const key_type &key) + iterator splay_down(const key_type &key); //! @copydoc ::boost::intrusive::splaytree::rebalance void rebalance(); @@ -423,7 +434,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_splay_set { @@ -431,7 +442,7 @@ struct make_splay_set typedef typename pack_options < splaytree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -442,6 +453,7 @@ struct make_splay_set typedef splay_set_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -453,14 +465,14 @@ struct make_splay_set #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class splay_set : public make_splay_set::value)); - explicit splay_set( const value_compare &cmp = value_compare() + explicit splay_set( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template splay_set( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -504,6 +516,14 @@ class splay_set splay_set& operator=(BOOST_RV_REF(splay_set) x) { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } + template + void clone_from(const splay_set &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(splay_set) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static splay_set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -533,15 +553,15 @@ class splay_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class splay_multiset_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public splaytree_impl + : public splaytree_impl #endif { /// @cond - typedef splaytree_impl tree_type; + typedef splaytree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(splay_multiset_impl) typedef tree_type implementation_defined; @@ -549,6 +569,8 @@ class splay_multiset_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; @@ -572,16 +594,16 @@ class splay_multiset_impl static const bool constant_time_size = tree_type::constant_time_size; public: - //! @copydoc ::boost::intrusive::splaytree::splaytree(const value_compare &,const value_traits &) - explicit splay_multiset_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::splaytree::splaytree(const key_compare &,const value_traits &) + explicit splay_multiset_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::splaytree::splaytree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::splaytree::splaytree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template splay_multiset_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(false, b, e, cmp, v_traits) {} @@ -662,11 +684,20 @@ class splay_multiset_impl //! @copydoc ::boost::intrusive::splaytree::swap void swap(splay_multiset_impl& other); - //! @copydoc ::boost::intrusive::splaytree::clone_from + //! @copydoc ::boost::intrusive::splaytree::clone_from(const splaytree&,Cloner,Disposer) template void clone_from(const splay_multiset_impl &src, Cloner cloner, Disposer disposer); - #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + #else + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::splaytree::clone_from(splaytree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(splay_multiset_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } //! @copydoc ::boost::intrusive::splaytree::insert_equal(reference) iterator insert(reference value) @@ -697,12 +728,12 @@ class splay_multiset_impl //! @copydoc ::boost::intrusive::splaytree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::splaytree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::erase(const key_type&) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::splaytree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_iterator,Disposer) template @@ -712,13 +743,13 @@ class splay_multiset_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const key_type&, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::splaytree::clear void clear(); @@ -727,88 +758,88 @@ class splay_multiset_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::splaytree::count(const_reference) - size_type count(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::count(const key_type&) + size_type count(const key_type&); - //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const key_type&) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const key_type&)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const key_type&) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const key_type&)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::find(const key_type&) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::splaytree::find(const key_type&)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::equal_range(const key_type&) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::splaytree::equal_range(const key_type&)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const key_type&, const key_type&,bool,bool) std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const key_type&, const key_type&,bool,bool)const std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -837,12 +868,12 @@ class splay_multiset_impl //! @copydoc ::boost::intrusive::splaytree::splay_up(iterator) void splay_up(iterator i); - //! @copydoc ::boost::intrusive::splaytree::splay_down(const KeyType&,KeyValueCompare) - template - iterator splay_down(const KeyType &key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::splaytree::splay_down(const KeyType&,KeyTypeKeyCompare) + template + iterator splay_down(const KeyType &key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::splaytree::splay_down(const_reference) - iterator splay_down(const_reference value); + //! @copydoc ::boost::intrusive::splaytree::splay_down(const key_type &key) + iterator splay_down(const key_type &key); //! @copydoc ::boost::intrusive::splaytree::rebalance void rebalance(); @@ -878,7 +909,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_splay_multiset { @@ -886,7 +917,7 @@ struct make_splay_multiset typedef typename pack_options < splaytree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -897,6 +928,7 @@ struct make_splay_multiset typedef splay_multiset_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -909,14 +941,14 @@ struct make_splay_multiset #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class splay_multiset : public make_splay_multiset::value)); - explicit splay_multiset( const value_compare &cmp = value_compare() + explicit splay_multiset( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template splay_multiset( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, v_traits) {} @@ -960,6 +992,14 @@ class splay_multiset splay_multiset& operator=(BOOST_RV_REF(splay_multiset) x) { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } + template + void clone_from(const splay_multiset &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(splay_multiset) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static splay_multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/splaytree.hpp b/boost/intrusive/splaytree.hpp index e3866aa912..27d75df70f 100644 --- a/boost/intrusive/splaytree.hpp +++ b/boost/intrusive/splaytree.hpp @@ -40,19 +40,14 @@ namespace intrusive { /// @cond struct splaytree_defaults -{ - typedef default_bstree_hook_applier proto_value_traits; - static const bool constant_time_size = true; - typedef std::size_t size_type; - typedef void compare; - typedef void header_holder_type; -}; + : bstree_defaults +{}; /// @endcond //! The class template splaytree is an intrusive splay tree container that //! is used to construct intrusive splay_set and splay_multiset containers. The no-throw -//! guarantee holds only, if the value_compare object +//! guarantee holds only, if the key_compare object //! doesn't throw. //! //! The template parameter \c T is the type to be managed by the container. @@ -66,17 +61,17 @@ struct splaytree_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class splaytree_impl /// @cond - : public bstree_impl + : public bstree_impl /// @endcond { public: typedef ValueTraits value_traits; /// @cond - typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType + typedef bstree_impl< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType , ConstantTimeSize, SplayTreeAlgorithms , HeaderHolder> tree_type; typedef tree_type implementation_defined; @@ -86,6 +81,7 @@ class splaytree_impl typedef typename implementation_defined::const_pointer const_pointer; typedef typename implementation_defined::value_type value_type; typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::reference reference; typedef typename implementation_defined::const_reference const_reference; typedef typename implementation_defined::difference_type difference_type; @@ -115,16 +111,16 @@ class splaytree_impl typedef typename implementation_defined::insert_commit_data insert_commit_data; - //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) - explicit splaytree_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &) + explicit splaytree_impl( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) {} - //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const key_compare &,const value_traits &) template splaytree_impl( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits) { @@ -210,10 +206,24 @@ class splaytree_impl //! @copydoc ::boost::intrusive::bstree::swap void swap(splaytree_impl& other); - //! @copydoc ::boost::intrusive::bstree::clone_from + //! @copydoc ::boost::intrusive::bstree::clone_from(const bstree&,Cloner,Disposer) + //! Additional notes: it also copies the alpha factor from the source container. template void clone_from(const splaytree_impl &src, Cloner cloner, Disposer disposer); + #else //BOOST_INTRUSIVE_DOXYGEN_INVOKED + + using tree_type::clone_from; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree::clone_from(bstree&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(splaytree_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) iterator insert_equal(reference value); @@ -230,16 +240,16 @@ class splaytree_impl //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference) iterator insert_unique(const_iterator hint, reference value); - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_unique_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data); + (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data); - //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&) + template std::pair insert_unique_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data); + ,KeyTypeKeyCompare comp, insert_commit_data &commit_data); //! @copydoc ::boost::intrusive::bstree::insert_unique_commit iterator insert_unique_commit(reference value, const insert_commit_data &commit_data); @@ -263,12 +273,12 @@ class splaytree_impl //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::bstree::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::bstree::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) template @@ -278,13 +288,13 @@ class splaytree_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::bstree::clear void clear(); @@ -293,120 +303,120 @@ class splaytree_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const + //! @copydoc ::boost::intrusive::bstree::count(const key_type &)const //! Additional note: non-const function, splaying is performed. - size_type count(const_reference value); + size_type count(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyTypeKeyCompare)const //! Additional note: non-const function, splaying is performed. - template - size_type count(const KeyType &key, KeyValueCompare comp); + template + size_type count(const KeyType &key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const + //! @copydoc ::boost::intrusive::bstree::count(const key_type &)const //! Additional note: const function, no splaying is performed - size_type count(const_reference value) const; + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyTypeKeyCompare)const //! Additional note: const function, no splaying is performed - template - size_type count(const KeyType &key, KeyValueCompare comp) const; + template + size_type count(const KeyType &key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &) //! Additional note: non-const function, splaying is performed. - iterator lower_bound(const_reference value); + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &)const //! Additional note: const function, no splaying is performed - const_iterator lower_bound(const_reference value) const; + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" - template - iterator lower_bound(const KeyType &key, KeyValueCompare comp); + template + iterator lower_bound(const KeyType &key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare)const //! Additional note: const function, no splaying is performed - template - const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const; + template + const_iterator lower_bound(const KeyType &key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" - iterator upper_bound(const_reference value); + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &)const //! Additional note: const function, no splaying is performed - const_iterator upper_bound(const_reference value) const; + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" - template - iterator upper_bound(const KeyType &key, KeyValueCompare comp); + template + iterator upper_bound(const KeyType &key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare)const //! Additional note: const function, no splaying is performed - template - const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const; + template + const_iterator upper_bound(const KeyType &key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) + //! @copydoc ::boost::intrusive::bstree::find(const key_type &) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" - iterator find(const_reference value); + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const + //! @copydoc ::boost::intrusive::bstree::find(const key_type &)const //! Additional note: const function, no splaying is performed - const_iterator find(const_reference value) const; + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" - template - iterator find(const KeyType &key, KeyValueCompare comp); + template + iterator find(const KeyType &key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare)const //! Additional note: const function, no splaying is performed - template - const_iterator find(const KeyType &key, KeyValueCompare comp) const; + template + const_iterator find(const KeyType &key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" - std::pair equal_range(const_reference value); + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)const //! Additional note: const function, no splaying is performed - std::pair equal_range(const_reference value) const; + std::pair equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" - template - std::pair equal_range(const KeyType &key, KeyValueCompare comp); + template + std::pair equal_range(const KeyType &key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare)const //! Additional note: const function, no splaying is performed - template - std::pair equal_range(const KeyType &key, KeyValueCompare comp) const; + template + std::pair equal_range(const KeyType &key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @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, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -455,8 +465,8 @@ class splaytree_impl //! Returns: An iterator to the new root of the tree, end() if the tree is empty. //! //! Throws: If the comparison functor throws. - template - iterator splay_down(const KeyType &key, KeyValueCompare comp) + template + iterator splay_down(const KeyType &key, KeyTypeKeyCompare comp) { detail::key_nodeptr_comp key_node_comp(comp, &this->get_value_traits()); @@ -473,8 +483,8 @@ class splaytree_impl //! Returns: An iterator to the new root of the tree, end() if the tree is empty. //! //! Throws: If the predicate throws. - iterator splay_down(const_reference value) - { return this->splay_down(value, this->value_comp()); } + iterator splay_down(const key_type &key) + { return this->splay_down(key, this->key_comp()); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree::rebalance @@ -482,33 +492,23 @@ class splaytree_impl //! @copydoc ::boost::intrusive::bstree::rebalance_subtree iterator rebalance_subtree(iterator root); - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED -}; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + friend bool operator< (const splaytree_impl &x, const splaytree_impl &y); -template -bool operator< (const splaytree_impl &x, const splaytree_impl &y); + friend bool operator==(const splaytree_impl &x, const splaytree_impl &y); -template -bool operator==(const splaytree_impl &x, const splaytree_impl &y); + friend bool operator!= (const splaytree_impl &x, const splaytree_impl &y); -template -bool operator!= (const splaytree_impl &x, const splaytree_impl &y); + friend bool operator>(const splaytree_impl &x, const splaytree_impl &y); -template -bool operator>(const splaytree_impl &x, const splaytree_impl &y); + friend bool operator<=(const splaytree_impl &x, const splaytree_impl &y); -template -bool operator<=(const splaytree_impl &x, const splaytree_impl &y); + friend bool operator>=(const splaytree_impl &x, const splaytree_impl &y); -template -bool operator>=(const splaytree_impl &x, const splaytree_impl &y); - -template -void swap(splaytree_impl &x, splaytree_impl &y); + friend void swap(splaytree_impl &x, splaytree_impl &y); -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +}; //! Helper metafunction to define a \c splaytree that yields to the same type when the //! same options (either explicitly or implicitly) are used. @@ -517,7 +517,7 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_splaytree { @@ -525,7 +525,7 @@ struct make_splaytree typedef typename pack_options < splaytree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -536,6 +536,7 @@ struct make_splaytree typedef splaytree_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::size_type , packed_options::constant_time_size @@ -549,14 +550,14 @@ struct make_splaytree #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class splaytree : public make_splaytree::value)); - explicit splaytree( const value_compare &cmp = value_compare() + explicit splaytree( const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template splaytree( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const value_traits &v_traits = value_traits()) : Base(unique, b, e, cmp, v_traits) {} @@ -602,6 +603,14 @@ class splaytree splaytree& operator=(BOOST_RV_REF(splaytree) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const splaytree &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(splaytree) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static splaytree &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/treap.hpp b/boost/intrusive/treap.hpp index bf374696fb..52785dafb0 100644 --- a/boost/intrusive/treap.hpp +++ b/boost/intrusive/treap.hpp @@ -47,20 +47,16 @@ namespace intrusive { /// @cond struct treap_defaults + : bstree_defaults { - typedef default_bstree_hook_applier proto_value_traits; - static const bool constant_time_size = true; - typedef std::size_t size_type; - typedef void compare; typedef void priority; - typedef void header_holder_type; }; /// @endcond //! The class template treap is an intrusive treap container that //! is used to construct intrusive set and multiset containers. The no-throw -//! guarantee holds only, if the value_compare object and priority_compare object +//! guarantee holds only, if the key_compare object and priority_compare object //! don't throw. //! //! The template parameter \c T is the type to be managed by the container. @@ -74,24 +70,24 @@ struct treap_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class treap_impl /// @cond - : public bstree_impl + : public bstree_impl //Use public inheritance to avoid MSVC bugs with closures , public detail::ebo_functor_holder < typename get_prio < VoidOrPrioComp , typename bstree_impl - ::value_type>::type + ::value_type>::type > /// @endcond { public: typedef ValueTraits value_traits; /// @cond - typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType + typedef bstree_impl< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType , ConstantTimeSize, BsTreeAlgorithms , HeaderHolder> tree_type; typedef tree_type implementation_defined; @@ -108,6 +104,7 @@ class treap_impl typedef typename implementation_defined::const_pointer const_pointer; typedef typename implementation_defined::value_type value_type; typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::reference reference; typedef typename implementation_defined::const_reference const_reference; typedef typename implementation_defined::difference_type difference_type; @@ -129,6 +126,15 @@ class treap_impl static const bool stateful_value_traits = implementation_defined::stateful_value_traits; static const bool safemode_or_autounlink = is_safe_autounlink::value; + typedef detail::key_nodeptr_comp value_node_prio_comp_t; + + template + detail::key_nodeptr_comp key_node_prio_comp(KeyPrioComp keypriocomp) const + { return detail::key_nodeptr_comp(keypriocomp, &this->get_value_traits()); } + + value_node_prio_comp_t value_node_prio_comp() const + { return this->key_node_prio_comp(this->priv_pcomp()); } + /// @cond private: @@ -153,7 +159,7 @@ class treap_impl //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) //! or the copy constructor of the value_compare/priority_compare objects throw. Basic guarantee. - explicit treap_impl( const value_compare &cmp = value_compare() + explicit treap_impl( const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits), prio_base(pcmp) @@ -170,11 +176,11 @@ class treap_impl //! //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare/priority_compare objects + //! or the copy constructor/operator() of the key_compare/priority_compare objects //! throw. Basic guarantee. template treap_impl( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, v_traits), prio_base(pcmp) @@ -356,6 +362,27 @@ class treap_impl this->priv_pcomp() = src.priv_pcomp(); } + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! Cloner should yield to nodes equivalent to the original nodes. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(reference) + //! and inserts them on *this. Copies the predicate from the source container. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + template + void clone_from(BOOST_RV_REF(treap_impl) src, Cloner cloner, Disposer disposer) + { + tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); + this->priv_pcomp() = ::boost::move(src.priv_pcomp()); + } + //! Requires: value must be an lvalue //! //! Effects: Inserts value into the container before the upper bound. @@ -363,21 +390,21 @@ class treap_impl //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare or priority_compare functions throw. Strong guarantee. + //! Throws: If the internal key_compare or priority_compare functions throw. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_value_traits()); - detail::key_nodeptr_comp - key_node_pcomp(this->priv_pcomp(), &this->get_value_traits()); node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - iterator ret(node_algorithms::insert_equal_upper_bound - (this->tree_type::header_ptr(), to_insert, key_node_comp, key_node_pcomp), this->priv_value_traits_ptr()); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(to_insert)); + iterator ret + ( node_algorithms::insert_equal_upper_bound + ( this->tree_type::header_ptr() + , to_insert + , this->key_node_comp(this->key_comp()) + , this->value_node_prio_comp()) + , this->priv_value_traits_ptr()); this->tree_type::sz_traits().increment(); return ret; } @@ -392,21 +419,22 @@ class treap_impl //! Complexity: Logarithmic in general, but it is amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare or priority_compare functions throw. Strong guarantee. + //! Throws: If the internal key_compare or priority_compare functions throw. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_value_traits()); - detail::key_nodeptr_comp - key_node_pcomp(this->priv_pcomp(), &this->get_value_traits()); node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - iterator ret (node_algorithms::insert_equal - (this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp, key_node_pcomp), this->priv_value_traits_ptr()); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(to_insert)); + iterator ret + (node_algorithms::insert_equal + ( this->tree_type::header_ptr() + , hint.pointed_node() + , to_insert + , this->key_node_comp(this->key_comp()) + , this->value_node_prio_comp()) + , this->priv_value_traits_ptr()); this->tree_type::sz_traits().increment(); return ret; } @@ -419,9 +447,9 @@ class treap_impl //! //! Complexity: Insert range is in general O(N * log(N)), where N is the //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). + //! by key_comp(). //! - //! Throws: If the internal value_compare or priority_compare functions throw. + //! Throws: If the internal key_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -442,7 +470,7 @@ class treap_impl //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare or priority_compare functions throw. + //! Throws: If the internal key_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -450,10 +478,11 @@ class treap_impl std::pair insert_unique(reference value) { insert_commit_data commit_data; - std::pair ret = insert_unique_check(value, this->value_comp(), this->priv_pcomp(), commit_data); + std::pair ret = this->insert_unique_check + (value, this->comp(), this->priv_pcomp(), commit_data); if(!ret.second) return ret; - return std::pair (insert_unique_commit(value, commit_data), true); + return std::pair (this->insert_unique_commit(value, commit_data), true); } //! Requires: value must be an lvalue, and "hint" must be @@ -466,7 +495,7 @@ class treap_impl //! constant time (two comparisons in the worst case) //! if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare or priority_compare functions throw. + //! Throws: If the internal key_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -474,10 +503,11 @@ class treap_impl iterator insert_unique(const_iterator hint, reference value) { insert_commit_data commit_data; - std::pair ret = insert_unique_check(hint, value, this->value_comp(), this->priv_pcomp(), commit_data); + std::pair ret = this->insert_unique_check + (hint, value, this->comp(), this->priv_pcomp(), commit_data); if(!ret.second) return ret.first; - return insert_unique_commit(value, commit_data); + return this->insert_unique_commit(value, commit_data); } //! Requires: Dereferencing iterator must yield an lvalue @@ -487,9 +517,9 @@ class treap_impl //! //! Complexity: Insert range is in general O(N * log(N)), where N is the //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). + //! by key_comp(). //! - //! Throws: If the internal value_compare or priority_compare functions throw. + //! Throws: If the internal key_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -508,11 +538,11 @@ class treap_impl } } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. + //! Requires: comp must be a comparison function that induces + //! the same strict weak ordering as key_compare. //! key_value_pcomp must be a comparison function that induces //! the same strict weak ordering as priority_compare. The difference is that - //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. + //! key_value_pcomp and comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the container, using //! a user provided key instead of the value itself. @@ -525,7 +555,7 @@ class treap_impl //! //! Complexity: Average complexity is at most logarithmic. //! - //! Throws: If the key_value_comp or key_value_pcomp + //! Throws: If the comp or key_value_pcomp //! ordering functions throw. Strong guarantee. //! //! Notes: This function is used to improve performance when constructing @@ -541,26 +571,23 @@ class treap_impl //! //! "commit_data" remains valid for a subsequent "insert_commit" only if no more //! objects are inserted or erased from the container. - template + template std::pair insert_unique_check - ( const KeyType &key, KeyValueCompare key_value_comp + ( const KeyType &key, KeyTypeKeyCompare comp , KeyValuePrioCompare key_value_pcomp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_value_traits()); - detail::key_nodeptr_comp - pcomp(key_value_pcomp, &this->get_value_traits()); - std::pair ret = + std::pair const ret = (node_algorithms::insert_unique_check - (this->tree_type::header_ptr(), key, ocomp, pcomp, commit_data)); + ( this->tree_type::header_ptr(), key + , this->key_node_comp(comp), this->key_node_prio_comp(key_value_pcomp), commit_data)); return std::pair(iterator(ret.first, this->priv_value_traits_ptr()), ret.second); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. + //! Requires: comp must be a comparison function that induces + //! the same strict weak ordering as key_compare. //! key_value_pcomp must be a comparison function that induces //! the same strict weak ordering as priority_compare. The difference is that - //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. + //! key_value_pcomp and comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the container, using //! a user provided key instead of the value itself, using "hint" @@ -575,7 +602,7 @@ class treap_impl //! Complexity: Logarithmic in general, but it's amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the key_value_comp or key_value_pcomp + //! Throws: If the comp or key_value_pcomp //! ordering functions throw. Strong guarantee. //! //! Notes: This function is used to improve performance when constructing @@ -591,20 +618,17 @@ class treap_impl //! //! "commit_data" remains valid for a subsequent "insert_commit" only if no more //! objects are inserted or erased from the container. - template + template std::pair insert_unique_check ( const_iterator hint, const KeyType &key - , KeyValueCompare key_value_comp + , KeyTypeKeyCompare comp , KeyValuePrioCompare key_value_pcomp , insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_value_traits()); - detail::key_nodeptr_comp - pcomp(key_value_pcomp, &this->get_value_traits()); - std::pair ret = + std::pair const ret = (node_algorithms::insert_unique_check - (this->tree_type::header_ptr(), hint.pointed_node(), key, ocomp, pcomp, commit_data)); + ( this->tree_type::header_ptr(), hint.pointed_node(), key + , this->key_node_comp(comp), this->key_node_prio_comp(key_value_pcomp), commit_data)); return std::pair(iterator(ret.first, this->priv_value_traits_ptr()), ret.second); } @@ -628,8 +652,7 @@ class treap_impl iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) { node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(to_insert)); node_algorithms::insert_unique_commit(this->tree_type::header_ptr(), to_insert, commit_data); this->tree_type::sz_traits().increment(); return iterator(to_insert, this->priv_value_traits_ptr()); @@ -652,12 +675,11 @@ class treap_impl iterator insert_before(const_iterator pos, reference value) { node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - detail::key_nodeptr_comp - pcomp(this->priv_pcomp(), &this->get_value_traits()); - iterator ret (node_algorithms::insert_before - (this->tree_type::header_ptr(), pos.pointed_node(), to_insert, pcomp), this->priv_value_traits_ptr()); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(to_insert)); + iterator ret + ( node_algorithms::insert_before + ( this->tree_type::header_ptr(), pos.pointed_node(), to_insert, this->value_node_prio_comp()) + , this->priv_value_traits_ptr()); this->tree_type::sz_traits().increment(); return ret; } @@ -679,11 +701,8 @@ class treap_impl void push_back(reference value) { node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - detail::key_nodeptr_comp - pcomp(this->priv_pcomp(), &this->get_value_traits()); - node_algorithms::push_back(this->tree_type::header_ptr(), to_insert, pcomp); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(to_insert)); + node_algorithms::push_back(this->tree_type::header_ptr(), to_insert, this->value_node_prio_comp()); this->tree_type::sz_traits().increment(); } @@ -704,11 +723,8 @@ class treap_impl void push_front(reference value) { node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - detail::key_nodeptr_comp - pcomp(this->priv_pcomp(), &this->get_value_traits()); - node_algorithms::push_front(this->tree_type::header_ptr(), to_insert, pcomp); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(to_insert)); + node_algorithms::push_front(this->tree_type::header_ptr(), to_insert, this->value_node_prio_comp()); this->tree_type::sz_traits().increment(); } @@ -725,11 +741,8 @@ class treap_impl const_iterator ret(i); ++ret; node_ptr to_erase(i.pointed_node()); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); - detail::key_nodeptr_comp - key_node_pcomp(this->priv_pcomp(), &this->get_value_traits()); - node_algorithms::erase(this->tree_type::header_ptr(), to_erase, key_node_pcomp); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || !node_algorithms::unique(to_erase)); + node_algorithms::erase(this->tree_type::header_ptr(), to_erase, this->value_node_prio_comp()); this->tree_type::sz_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); @@ -758,8 +771,8 @@ class treap_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return this->erase(value, this->value_comp()); } + size_type erase(const key_type &key) + { return this->erase(key, this->key_comp()); } //! Effects: Erases all the elements with the given key. //! according to the comparison functor "comp". @@ -773,12 +786,10 @@ class treap_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + template + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase(const KeyType& key, KeyTypeKeyCompare comp) { std::pair p = this->equal_range(key, comp); size_type n; @@ -843,9 +854,9 @@ class treap_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. template - size_type erase_and_dispose(const_reference value, Disposer disposer) + size_type erase_and_dispose(const key_type &key, Disposer disposer) { - std::pair p = this->equal_range(value); + std::pair p = this->equal_range(key); size_type n; private_erase(p.first, p.second, n, disposer); return n; @@ -866,12 +877,10 @@ class treap_impl //! //! Note: Invalidates the iterators //! to the erased elements. - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + template + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer) { std::pair p = this->equal_range(key, comp); size_type n; @@ -913,9 +922,8 @@ class treap_impl template void check(ExtraChecker extra_checker) const { - typedef detail::key_nodeptr_comp nodeptr_prio_comp_t; - nodeptr_prio_comp_t nodeptr_prio_comp(priv_pcomp(), &this->get_value_traits()); - tree_type::check(detail::treap_node_extra_checker(nodeptr_prio_comp, extra_checker)); + tree_type::check(detail::treap_node_extra_checker + (this->value_node_prio_comp(), extra_checker)); } //! @copydoc ::boost::intrusive::bstree::check()const @@ -923,88 +931,88 @@ class treap_impl { check(detail::empty_node_checker()); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::count(const key_type &)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::bstree::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::bstree::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @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, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -1030,6 +1038,20 @@ class treap_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); + friend bool operator< (const treap_impl &x, const treap_impl &y); + + friend bool operator==(const treap_impl &x, const treap_impl &y); + + friend bool operator!= (const treap_impl &x, const treap_impl &y); + + friend bool operator>(const treap_impl &x, const treap_impl &y); + + friend bool operator<=(const treap_impl &x, const treap_impl &y); + + friend bool operator>=(const treap_impl &x, const treap_impl &y); + + friend void swap(treap_impl &x, treap_impl &y); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED /// @cond @@ -1051,30 +1073,6 @@ class treap_impl /// @endcond }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - -template -bool operator< (const treap_impl &x, const treap_impl &y); - -template -bool operator==(const treap_impl &x, const treap_impl &y); - -template -bool operator!= (const treap_impl &x, const treap_impl &y); - -template -bool operator>(const treap_impl &x, const treap_impl &y); - -template -bool operator<=(const treap_impl &x, const treap_impl &y); - -template -bool operator>=(const treap_impl &x, const treap_impl &y); - -template -void swap(treap_impl &x, treap_impl &y); - -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c treap that yields to the same type when the //! same options (either explicitly or implicitly) are used. @@ -1083,14 +1081,14 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_treap { typedef typename pack_options < treap_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -1101,6 +1099,7 @@ struct make_treap typedef treap_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::priority , typename packed_options::size_type @@ -1114,14 +1113,14 @@ struct make_treap #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class treap : public make_treap::value)); - explicit treap( const value_compare &cmp = value_compare() + explicit treap( const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, pcmp, v_traits) @@ -1157,7 +1156,7 @@ class treap template treap( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : Base(unique, b, e, cmp, pcmp, v_traits) @@ -1170,6 +1169,14 @@ class treap treap& operator=(BOOST_RV_REF(treap) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const treap &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(treap) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static treap &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/treap_set.hpp b/boost/intrusive/treap_set.hpp index a88df58e44..188c80fdce 100644 --- a/boost/intrusive/treap_set.hpp +++ b/boost/intrusive/treap_set.hpp @@ -40,16 +40,16 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class treap_set_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public treap_impl + : public treap_impl #endif { /// @cond public: - typedef treap_impl tree_type; + typedef treap_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(treap_set_impl) typedef tree_type implementation_defined; @@ -58,6 +58,8 @@ class treap_set_impl public: typedef typename implementation_defined::value_type value_type; typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; typedef typename implementation_defined::reference reference; @@ -65,8 +67,8 @@ class treap_set_impl typedef typename implementation_defined::difference_type difference_type; typedef typename implementation_defined::size_type size_type; typedef typename implementation_defined::value_compare value_compare; - typedef typename implementation_defined::priority_compare priority_compare; typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::priority_compare priority_compare; typedef typename implementation_defined::iterator iterator; typedef typename implementation_defined::const_iterator const_iterator; typedef typename implementation_defined::reverse_iterator reverse_iterator; @@ -87,8 +89,8 @@ class treap_set_impl //! //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor of the value_compare object throws. - explicit treap_set_impl( const value_compare &cmp = value_compare() + //! or the copy constructor of the key_compare object throws. + explicit treap_set_impl( const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, pcmp, v_traits) @@ -105,10 +107,10 @@ class treap_set_impl //! //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! or the copy constructor/operator() of the key_compare object throws. template treap_set_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : tree_type(true, b, e, cmp, pcmp, v_traits) @@ -192,10 +194,23 @@ class treap_set_impl //! @copydoc ::boost::intrusive::treap::swap void swap(treap_set_impl& other); - //! @copydoc ::boost::intrusive::treap::clone_from + //! @copydoc ::boost::intrusive::treap::clone_from(const treap&,Cloner,Disposer) template void clone_from(const treap_set_impl &src, Cloner cloner, Disposer disposer); + #else + + using tree_type::clone_from; + + #endif + + //! @copydoc ::boost::intrusive::treap::clone_from(treap&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(treap_set_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } + + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::treap::top() iterator top(); @@ -226,20 +241,20 @@ class treap_set_impl iterator insert(const_iterator hint, reference value) { return tree_type::insert_unique(hint, value); } - //! @copydoc ::boost::intrusive::treap::insert_unique_check(const KeyType&,KeyValueCompare,KeyValuePrioCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::treap::insert_unique_check(const KeyType&,KeyTypeKeyCompare,KeyValuePrioCompare,insert_commit_data&) + template std::pair insert_check - ( const KeyType &key, KeyValueCompare key_value_comp, KeyValuePrioCompare key_value_pcomp + ( const KeyType &key, KeyTypeKeyCompare comp, KeyValuePrioCompare key_value_pcomp , insert_commit_data &commit_data) - { return tree_type::insert_unique_check(key, key_value_comp, key_value_pcomp, commit_data); } + { return tree_type::insert_unique_check(key, comp, key_value_pcomp, commit_data); } - //! @copydoc ::boost::intrusive::treap::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,KeyValuePrioCompare,insert_commit_data&) - template + //! @copydoc ::boost::intrusive::treap::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,KeyValuePrioCompare,insert_commit_data&) + template std::pair insert_check ( const_iterator hint, const KeyType &key - , KeyValueCompare key_value_comp, KeyValuePrioCompare key_value_pcomp + , KeyTypeKeyCompare comp, KeyValuePrioCompare key_value_pcomp , insert_commit_data &commit_data) - { return tree_type::insert_unique_check(hint, key, key_value_comp, key_value_pcomp, commit_data); } + { return tree_type::insert_unique_check(hint, key, comp, key_value_pcomp, commit_data); } //! @copydoc ::boost::intrusive::treap::insert_unique(Iterator,Iterator) template @@ -266,12 +281,12 @@ class treap_set_impl //! @copydoc ::boost::intrusive::treap::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::treap::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::treap::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::treap::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::treap::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_iterator,Disposer) template @@ -281,13 +296,13 @@ class treap_set_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::treap::clear void clear(); @@ -298,100 +313,100 @@ class treap_set_impl #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::treap::count(const_reference)const - size_type count(const_reference value) const - { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } + //! @copydoc ::boost::intrusive::treap::count(const key_type &)const + size_type count(const key_type &key) const + { return static_cast(this->tree_type::find(key) != this->tree_type::cend()); } - //! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const + //! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::treap::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::treap::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::treap::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::treap::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::treap::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::treap::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::treap::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::treap::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::treap::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::treap::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) - std::pair equal_range(const_reference value) - { return this->tree_type::lower_bound_range(value); } + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &) + std::pair equal_range(const key_type &key) + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) + //! @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); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const - { return this->tree_type::lower_bound_range(value); } + equal_range(const key_type &key) const + { return this->tree_type::lower_bound_range(key); } - //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const { return this->tree_type::lower_bound_range(key, comp); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::treap::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::treap::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::treap::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::treap::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::treap::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -428,14 +443,14 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_treap_set { typedef typename pack_options < treap_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -446,6 +461,7 @@ struct make_treap_set typedef treap_set_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::priority , typename packed_options::size_type @@ -459,14 +475,14 @@ struct make_treap_set #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class treap_set : public make_treap_set::value)); - explicit treap_set( const value_compare &cmp = value_compare() + explicit treap_set( const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, pcmp, v_traits) @@ -500,7 +516,7 @@ class treap_set template treap_set( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, pcmp, v_traits) @@ -513,6 +529,14 @@ class treap_set treap_set& operator=(BOOST_RV_REF(treap_set) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const treap_set &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(treap_set) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static treap_set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -542,15 +566,15 @@ class treap_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class treap_multiset_impl #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - : public treap_impl + : public treap_impl #endif { /// @cond - typedef treap_impl tree_type; + typedef treap_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(treap_multiset_impl) typedef tree_type implementation_defined; @@ -559,6 +583,8 @@ class treap_multiset_impl public: typedef typename implementation_defined::value_type value_type; typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; typedef typename implementation_defined::reference reference; @@ -566,8 +592,8 @@ class treap_multiset_impl typedef typename implementation_defined::difference_type difference_type; typedef typename implementation_defined::size_type size_type; typedef typename implementation_defined::value_compare value_compare; - typedef typename implementation_defined::priority_compare priority_compare; typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::priority_compare priority_compare; typedef typename implementation_defined::iterator iterator; typedef typename implementation_defined::const_iterator const_iterator; typedef typename implementation_defined::reverse_iterator reverse_iterator; @@ -588,8 +614,8 @@ class treap_multiset_impl //! //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor of the value_compare object throws. - explicit treap_multiset_impl( const value_compare &cmp = value_compare() + //! or the copy constructor of the key_compare object throws. + explicit treap_multiset_impl( const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : tree_type(cmp, pcmp, v_traits) @@ -606,10 +632,10 @@ class treap_multiset_impl //! //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! or the copy constructor/operator() of the key_compare object throws. template treap_multiset_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : tree_type(false, b, e, cmp, pcmp, v_traits) @@ -693,10 +719,23 @@ class treap_multiset_impl //! @copydoc ::boost::intrusive::treap::swap void swap(treap_multiset_impl& other); - //! @copydoc ::boost::intrusive::treap::clone_from + //! @copydoc ::boost::intrusive::treap::clone_from(const treap&,Cloner,Disposer) template void clone_from(const treap_multiset_impl &src, Cloner cloner, Disposer disposer); + #else + + using tree_type::clone_from; + + #endif + + //! @copydoc ::boost::intrusive::treap::clone_from(treap&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(treap_multiset_impl) src, Cloner cloner, Disposer disposer) + { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer); } + + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::treap::top() iterator top(); @@ -748,12 +787,12 @@ class treap_multiset_impl //! @copydoc ::boost::intrusive::treap::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e); - //! @copydoc ::boost::intrusive::treap::erase(const_reference) - size_type erase(const_reference value); + //! @copydoc ::boost::intrusive::treap::erase(const key_type &) + size_type erase(const key_type &key); - //! @copydoc ::boost::intrusive::treap::erase(const KeyType&,KeyValueCompare) - template - size_type erase(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::treap::erase(const KeyType&,KeyTypeKeyCompare) + template + size_type erase(const KeyType& key, KeyTypeKeyCompare comp); //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_iterator,Disposer) template @@ -763,13 +802,13 @@ class treap_multiset_impl template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_reference, Disposer) + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const key_type &, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer); + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) - template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer); //! @copydoc ::boost::intrusive::treap::clear void clear(); @@ -778,88 +817,88 @@ class treap_multiset_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::treap::count(const_reference)const - size_type count(const_reference value) const; + //! @copydoc ::boost::intrusive::treap::count(const key_type &)const + size_type count(const key_type &key) const; - //! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyTypeKeyCompare)const + template + size_type count(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference) - iterator lower_bound(const_reference value); + //! @copydoc ::boost::intrusive::treap::lower_bound(const key_type &) + iterator lower_bound(const key_type &key); - //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyValueCompare) - template - iterator lower_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference)const - const_iterator lower_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::treap::lower_bound(const key_type &)const + const_iterator lower_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::treap::upper_bound(const_reference) - iterator upper_bound(const_reference value); + //! @copydoc ::boost::intrusive::treap::upper_bound(const key_type &) + iterator upper_bound(const key_type &key); - //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyValueCompare) - template - iterator upper_bound(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyTypeKeyCompare) + template + iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::treap::upper_bound(const_reference)const - const_iterator upper_bound(const_reference value) const; + //! @copydoc ::boost::intrusive::treap::upper_bound(const key_type &)const + const_iterator upper_bound(const key_type &key) const; - //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::treap::find(const_reference) - iterator find(const_reference value); + //! @copydoc ::boost::intrusive::treap::find(const key_type &) + iterator find(const key_type &key); - //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyValueCompare) - template - iterator find(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyTypeKeyCompare) + template + iterator find(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::treap::find(const_reference)const - const_iterator find(const_reference value) const; + //! @copydoc ::boost::intrusive::treap::find(const key_type &)const + const_iterator find(const key_type &key) const; - //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyValueCompare)const - template - const_iterator find(const KeyType& key, KeyValueCompare comp) const; + //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyTypeKeyCompare)const + template + const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::treap::equal_range(const_reference) - std::pair equal_range(const_reference value); + //! @copydoc ::boost::intrusive::treap::equal_range(const key_type &) + std::pair equal_range(const key_type &key); - //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyTypeKeyCompare) + template + std::pair equal_range(const KeyType& key, KeyTypeKeyCompare comp); - //! @copydoc ::boost::intrusive::treap::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::treap::equal_range(const key_type &)const std::pair - equal_range(const_reference value) const; + equal_range(const key_type &key) const; - //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare)const - template + //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyTypeKeyCompare)const + template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyTypeKeyCompare comp) const; - //! @copydoc ::boost::intrusive::treap::bounded_range(const_reference,const_reference,bool,bool) + //! @copydoc ::boost::intrusive::treap::bounded_range(const key_type &,const key_type &,bool,bool) std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) - template + //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool) + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed); - //! @copydoc ::boost::intrusive::treap::bounded_range(const_reference,const_reference,bool,bool)const + //! @copydoc ::boost::intrusive::treap::bounded_range(const key_type &,const key_type &,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template + //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const + template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const; //! @copydoc ::boost::intrusive::treap::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -896,14 +935,14 @@ template #else template + , class O5 = void, class O6 = void> #endif struct make_treap_multiset { typedef typename pack_options < treap_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5 + O1, O2, O3, O4, O5, O6 #else Options... #endif @@ -914,6 +953,7 @@ struct make_treap_multiset typedef treap_multiset_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::compare , typename packed_options::priority , typename packed_options::size_type @@ -927,14 +967,14 @@ struct make_treap_multiset #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template +template #else template #endif class treap_multiset : public make_treap_multiset::value)); - explicit treap_multiset( const value_compare &cmp = value_compare() + explicit treap_multiset( const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : Base(cmp, pcmp, v_traits) @@ -968,7 +1008,7 @@ class treap_multiset template treap_multiset( Iterator b, Iterator e - , const value_compare &cmp = value_compare() + , const key_compare &cmp = key_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, pcmp, v_traits) @@ -981,6 +1021,14 @@ class treap_multiset treap_multiset& operator=(BOOST_RV_REF(treap_multiset) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + template + void clone_from(const treap_multiset &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(treap_multiset) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } + static treap_multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/boost/intrusive/unordered_set.hpp b/boost/intrusive/unordered_set.hpp index 4b0c91e741..5148f02f8c 100644 --- a/boost/intrusive/unordered_set.hpp +++ b/boost/intrusive/unordered_set.hpp @@ -64,14 +64,24 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class unordered_set_impl - : public hashtable_impl + : public hashtable_impl { /// @cond private: - typedef hashtable_impl table_type; + typedef hashtable_impl table_type; + + template + static std::pair priv_equal_range(MaybeConstThis &c, const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) + { + Iterator const it = c.find(key, hash_func, equal_func); + std::pair ret(it, it); + if(it != c.end()) + ++ret.second; + return ret; + } //! This class is //! movable @@ -82,6 +92,8 @@ class unordered_set_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_of_value key_of_value; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::bucket_traits bucket_traits; typedef typename implementation_defined::pointer pointer; @@ -90,7 +102,6 @@ class unordered_set_impl typedef typename implementation_defined::const_reference const_reference; typedef typename implementation_defined::difference_type difference_type; typedef typename implementation_defined::size_type size_type; - typedef typename implementation_defined::key_type key_type; typedef typename implementation_defined::key_equal key_equal; typedef typename implementation_defined::hasher hasher; typedef typename implementation_defined::bucket_type bucket_type; @@ -108,19 +119,7 @@ class unordered_set_impl public: - //! Requires: buckets must not be being used by any other resource. - //! - //! Effects: Constructs an empty unordered_set_impl, storing a reference - //! to the bucket array and copies of the hasher and equal functors. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor or invocation of Hash or Equal throws. - //! - //! Notes: buckets array must be disposed only after - //! *this is disposed. + //! @copydoc ::boost::intrusive::hashtable::hashtable(const bucket_traits &,const hasher &,const key_equal &,const value_traits &) explicit unordered_set_impl( const bucket_traits &b_traits , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() @@ -128,21 +127,7 @@ class unordered_set_impl : table_type(b_traits, hash_func, equal_func, v_traits) {} - //! Requires: buckets must not be being used by any other resource - //! and Dereferencing iterator must yield an lvalue of type value_type. - //! - //! Effects: Constructs an empty unordered_set and inserts elements from - //! [b, e). - //! - //! Complexity: If N is distance(b, e): Average case is O(N) - //! (with a good hash function and with buckets_len >= N),worst case O(N2). - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor or invocation of hasher or key_equal throws. - //! - //! Notes: buckets array must be disposed only after - //! *this is disposed. + //! @copydoc ::boost::intrusive::hashtable::hashtable(bool,Iterator,Iterator,const bucket_traits &,const hasher &,const key_equal &,const value_traits &) template unordered_set_impl( Iterator b , Iterator e @@ -150,859 +135,272 @@ class unordered_set_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : table_type(b_traits, hash_func, equal_func, v_traits) - { table_type::insert_unique(b, e); } + : table_type(true, b, e, b_traits, hash_func, equal_func, v_traits) + {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::hashtable::hashtable(hashtable&&) unordered_set_impl(BOOST_RV_REF(unordered_set_impl) x) : table_type(BOOST_MOVE_BASE(table_type, x)) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::hashtable::operator=(hashtable&&) unordered_set_impl& operator=(BOOST_RV_REF(unordered_set_impl) x) { return static_cast(table_type::operator=(BOOST_MOVE_BASE(table_type, x))); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Effects: Detaches all elements from this. The objects in the unordered_set - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements in the unordered_set, if - //! it's a safe-mode or auto-unlink value. Otherwise constant. - //! - //! Throws: Nothing. - ~unordered_set_impl() - {} + //! @copydoc ::boost::intrusive::hashtable::~hashtable() + ~unordered_set_impl(); - //! Effects: Returns an iterator pointing to the beginning of the unordered_set. - //! - //! Complexity: Constant time if `cache_begin<>` is true. Amortized - //! constant time with worst case (empty unordered_set) O(this->bucket_count()) - //! - //! Throws: Nothing. - iterator begin() - { return table_type::begin(); } + //! @copydoc ::boost::intrusive::hashtable::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning - //! of the unordered_set. - //! - //! Complexity: Constant time if `cache_begin<>` is true. Amortized - //! constant time with worst case (empty unordered_set) O(this->bucket_count()) - //! - //! Throws: Nothing. - const_iterator begin() const - { return table_type::begin(); } + //! @copydoc ::boost::intrusive::hashtable::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning - //! of the unordered_set. - //! - //! Complexity: Constant time if `cache_begin<>` is true. Amortized - //! constant time with worst case (empty unordered_set) O(this->bucket_count()) - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return table_type::cbegin(); } + //! @copydoc ::boost::intrusive::hashtable::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the unordered_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return table_type::end(); } + //! @copydoc ::boost::intrusive::hashtable::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the unordered_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return table_type::end(); } + //! @copydoc ::boost::intrusive::hashtable::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the unordered_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return table_type::cend(); } + //! @copydoc ::boost::intrusive::hashtable::cend()const + const_iterator cend() const; - //! Effects: Returns the hasher object used by the unordered_set. - //! - //! Complexity: Constant. - //! - //! Throws: If hasher copy-constructor throws. - hasher hash_function() const - { return table_type::hash_function(); } + //! @copydoc ::boost::intrusive::hashtable::hash_function()const + hasher hash_function() const; - //! Effects: Returns the key_equal object used by the unordered_set. - //! - //! Complexity: Constant. - //! - //! Throws: If key_equal copy-constructor throws. - key_equal key_eq() const - { return table_type::key_eq(); } + //! @copydoc ::boost::intrusive::hashtable::key_eq()const + key_equal key_eq() const; - //! Effects: Returns true if the container is empty. - //! - //! Complexity: if constant-time size and cache_last options are disabled, - //! average constant time (worst case, with empty() == true: O(this->bucket_count()). - //! Otherwise constant. - //! - //! Throws: Nothing. - bool empty() const - { return table_type::empty(); } + //! @copydoc ::boost::intrusive::hashtable::empty()const + bool empty() const; - //! Effects: Returns the number of elements stored in the unordered_set. - //! - //! Complexity: Linear to elements contained in *this if - //! constant-time size option is disabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return table_type::size(); } + //! @copydoc ::boost::intrusive::hashtable::size()const + size_type size() const; - //! Requires: the hasher and the equality function unqualified swap - //! call should not throw. - //! - //! Effects: Swaps the contents of two unordered_sets. - //! Swaps also the contained bucket array and equality and hasher functors. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison or hash functors - //! found using ADL throw. Basic guarantee. - void swap(unordered_set_impl& other) - { table_type::swap(other.table_); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes that compare equal and produce the same - //! hash than the original node. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. The hash function and the equality - //! predicate are copied from the source. - //! - //! If store_hash option is true, this method does not use the hash function. - //! - //! If any operation throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner or hasher throw or hash or equality predicate copying - //! throws. Basic guarantee. + //! @copydoc ::boost::intrusive::hashtable::hashtable + void swap(unordered_set_impl& other); + + //! @copydoc ::boost::intrusive::hashtable::clone_from(const hashtable&,Cloner,Disposer) template - void clone_from(const unordered_set_impl &src, Cloner cloner, Disposer disposer) - { table_type::clone_from(src.table_, cloner, disposer); } + void clone_from(const unordered_set_impl &src, Cloner cloner, Disposer disposer); + + #else + + using table_type::clone_from; #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: value must be an lvalue - //! - //! Effects: Tries to inserts value into the unordered_set. - //! - //! Returns: If the value - //! is not already present inserts it and returns a pair containing the - //! iterator to the new value and true. If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::hashtable::clone_from(hashtable&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(unordered_set_impl) src, Cloner cloner, Disposer disposer) + { table_type::clone_from(BOOST_MOVE_BASE(table_type, src), cloner, disposer); } + + //! @copydoc ::boost::intrusive::hashtable::insert_unique(reference) std::pair insert(reference value) { return table_type::insert_unique(value); } - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Equivalent to this->insert(t) for each element in [b, e). - //! - //! Complexity: Average case O(N), where N is distance(b, e). - //! Worst case O(N*this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::hashtable::insert_unique(Iterator,Iterator) template void insert(Iterator b, Iterator e) { table_type::insert_unique(b, e); } - //! Requires: "hasher" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hasher" hashes the given key instead of the value_type. - //! - //! "key_value_equal" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "key_value_equal" compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the unordered_set, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If hasher or key_value_equal throw. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the hash or the equality is much cheaper to - //! construct than the value_type and this function offers the possibility to - //! use that the part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the unordered_set. - //! - //! After a successful rehashing insert_commit_data remains valid. - template + //! @copydoc ::boost::intrusive::hashtable::insert_unique_check(const KeyType&,KeyHasher,KeyEqual,insert_commit_data&) + template std::pair insert_check - (const KeyType &key, KeyHasher hasher, KeyValueEqual key_value_equal, insert_commit_data &commit_data) + (const KeyType &key, KeyHasher hasher, KeyEqual key_value_equal, insert_commit_data &commit_data) { return table_type::insert_unique_check(key, hasher, key_value_equal, commit_data); } - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the unordered_set between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the unordered_set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. - //! - //! After a successful rehashing insert_commit_data remains valid. + //! @copydoc ::boost::intrusive::hashtable::insert_unique_commit iterator insert_commit(reference value, const insert_commit_data &commit_data) { return table_type::insert_unique_commit(value, commit_data); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Effects: Erases the element pointed to by i. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased element. No destructors are called. - void erase(const_iterator i) - { table_type::erase(i); } + //! @copydoc ::boost::intrusive::hashtable::erase(const_iterator) + void erase(const_iterator i); - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average case O(distance(b, e)), - //! worst case O(this->size()). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void erase(const_iterator b, const_iterator e) - { table_type::erase(b, e); } + //! @copydoc ::boost::intrusive::hashtable::erase(const_iterator,const_iterator) + void erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Average case O(this->count(value)). - //! Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return table_type::erase(value); } - - //! Requires: "hasher" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hasher" hashes the given key instead of the value_type. - //! - //! "key_value_equal" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "key_value_equal" compares an arbitrary key with the contained values. - //! - //! Effects: Erases all the elements that have the same hash and - //! compare equal with the given key. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Average case O(this->count(value)). - //! Worst case O(this->size()). - //! - //! Throws: If hash_func or equal_func throw. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_type::erase(key, hash_func, equal_func); } + //! @copydoc ::boost::intrusive::hashtable::erase(const key_type &) + size_type erase(const key_type &key); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by i. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::hashtable::erase(const KeyType&,KeyHasher,KeyEqual) + template + size_type erase(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func); + + //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const_iterator,Disposer) template - void erase_and_dispose(const_iterator i, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { table_type::erase_and_dispose(i, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average case O(distance(b, e)), - //! worst case O(this->size()). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + BOOST_INTRUSIVE_DOC1ST(void + , typename detail::disable_if_convertible::type) + erase_and_dispose(const_iterator i, Disposer disposer); + + //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const_iterator,const_iterator,Disposer) template - void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { table_type::erase_and_dispose(b, e, disposer); } + void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Average case O(this->count(value)). - //! Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const key_type &,Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return table_type::erase_and_dispose(value, disposer); } + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "equal_func". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Average case O(this->count(value)). - //! Worst case O(this->size()). - //! - //! Throws: If hash_func or equal_func throw. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. - template - size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func, Disposer disposer) - { return table_type::erase_and_dispose(key, hash_func, equal_func, disposer); } + //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const KeyType&,KeyHasher,KeyEqual,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func, Disposer disposer); - //! Effects: Erases all of the elements. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return table_type::clear(); } + //! @copydoc ::boost::intrusive::hashtable::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all of the elements. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::hashtable::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return table_type::clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given value - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - size_type count(const_reference value) const - { return table_type::find(value) != end(); } + //! @copydoc ::boost::intrusive::hashtable::count(const key_type &)const + size_type count(const key_type &key) const; - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "equal_func" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "equal_func" compares an arbitrary key with the contained values. - //! - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If hash_func or equal_func throw. - template - size_type count(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_type::find(key, hash_func, equal_func) != end(); } + //! @copydoc ::boost::intrusive::hashtable::count(const KeyType&,KeyHasher,KeyEqual)const + template + size_type count(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const; - //! Effects: Finds an iterator to the first element is equal to - //! "value" or end() if that element does not exist. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - iterator find(const_reference value) - { return table_type::find(value); } + //! @copydoc ::boost::intrusive::hashtable::find(const key_type &) + iterator find(const key_type &key); - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "equal_func" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "equal_func" compares an arbitrary key with the contained values. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the given hasher and equality functor or end() if - //! that element does not exist. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If hash_func or equal_func throw. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. - template - iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_type::find(key, hash_func, equal_func); } - - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" or end() if that element does not exist. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - const_iterator find(const_reference value) const - { return table_type::find(value); } + //! @copydoc ::boost::intrusive::hashtable::find(const KeyType &,KeyHasher,KeyEqual) + template + iterator find(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func); - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "equal_func" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "equal_func" compares an arbitrary key with the contained values. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the given hasher and equality functor or end() if - //! that element does not exist. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If hash_func or equal_func throw. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. - template - const_iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_type::find(key, hash_func, equal_func); } - - //! Effects: Returns a range containing all elements with values equivalent - //! to value. Returns std::make_pair(this->end(), this->end()) if no such - //! elements exist. - //! - //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - std::pair equal_range(const_reference value) - { return table_type::equal_range(value); } + //! @copydoc ::boost::intrusive::hashtable::count(const key_type &)const + const_iterator find(const key_type &key) const; - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "equal_func" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "equal_func" compares an arbitrary key with the contained values. - //! - //! Effects: Returns a range containing all elements with equivalent - //! keys. Returns std::make_pair(this->end(), this->end()) if no such - //! elements exist. - //! - //! Complexity: Average case O(this->count(key, hash_func, hash_func)). - //! Worst case O(this->size()). - //! - //! Throws: If hash_func or the equal_func throw. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. - template - std::pair equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_type::equal_range(key, hash_func, equal_func); } - - //! Effects: Returns a range containing all elements with values equivalent - //! to value. Returns std::make_pair(this->end(), this->end()) if no such - //! elements exist. - //! - //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. + //! @copydoc ::boost::intrusive::hashtable::find(const KeyType &,KeyHasher,KeyEqual)const + template + const_iterator find(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const; + #endif + + //! @copydoc ::boost::intrusive::hashtable::equal_range(const key_type&) + std::pair equal_range(const key_type &key) + { return this->equal_range(key, this->hash_function(), this->key_eq()); } + + //! @copydoc ::boost::intrusive::hashtable::equal_range(const KeyType &,KeyHasher,KeyEqual) + template + std::pair equal_range(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) + { return this->priv_equal_range(*this, key, hash_func, equal_func); } + + //! @copydoc ::boost::intrusive::hashtable::equal_range(const key_type&)const std::pair - equal_range(const_reference value) const - { return table_type::equal_range(value); } + equal_range(const key_type &key) const + { return this->equal_range(key, this->hash_function(), this->key_eq()); } - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "equal_func" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "equal_func" compares an arbitrary key with the contained values. - //! - //! Effects: Returns a range containing all elements with equivalent - //! keys. Returns std::make_pair(this->end(), this->end()) if no such - //! elements exist. - //! - //! Complexity: Average case O(this->count(key, hash_func, equal_func)). - //! Worst case O(this->size()). - //! - //! Throws: If the hash_func or equal_func throw. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. - template + //! @copydoc ::boost::intrusive::hashtable::equal_range(const KeyType &,KeyHasher,KeyEqual)const + template std::pair - equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_type::equal_range(key, hash_func, equal_func); } + equal_range(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const + { return this->priv_equal_range(*this, key, hash_func, equal_func); } - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator belonging to the unordered_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: If the internal hash function throws. - iterator iterator_to(reference value) - { return table_type::iterator_to(value); } + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::hashtable::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator belonging to the - //! unordered_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: If the internal hash function throws. - const_iterator iterator_to(const_reference value) const - { return table_type::iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid local_iterator belonging to the unordered_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static local_iterator s_local_iterator_to(reference value) - { return table_type::s_local_iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::s_local_iterator_to(reference) + static local_iterator s_local_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_local_iterator belonging to - //! the unordered_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_local_iterator s_local_iterator_to(const_reference value) - { return table_type::s_local_iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::s_local_iterator_to(const_reference) + static const_local_iterator s_local_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid local_iterator belonging to the unordered_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - local_iterator local_iterator_to(reference value) - { return table_type::local_iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::local_iterator_to(reference) + local_iterator local_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_local_iterator belonging to - //! the unordered_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_local_iterator local_iterator_to(const_reference value) const - { return table_type::local_iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::local_iterator_to(const_reference) + const_local_iterator local_iterator_to(const_reference value) const; - //! Effects: Returns the number of buckets passed in the constructor - //! or the last rehash function. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - size_type bucket_count() const - { return table_type::bucket_count(); } + //! @copydoc ::boost::intrusive::hashtable::bucket_count + size_type bucket_count() const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns the number of elements in the nth bucket. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - size_type bucket_size(size_type n) const - { return table_type::bucket_size(n); } + //! @copydoc ::boost::intrusive::hashtable::bucket_size + size_type bucket_size(size_type n) const; - //! Effects: Returns the index of the bucket in which elements - //! with keys equivalent to k would be found, if any such element existed. - //! - //! Complexity: Constant. - //! - //! Throws: If the hash functor throws. - //! - //! Note: the return value is in the range [0, this->bucket_count()). - size_type bucket(const value_type& k) const - { return table_type::bucket(k); } + //! @copydoc ::boost::intrusive::hashtable::bucket(const key_type&)const + size_type bucket(const key_type& k) const; - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! Effects: Returns the index of the bucket in which elements - //! with keys equivalent to k would be found, if any such element existed. - //! - //! Complexity: Constant. - //! - //! Throws: If hash_func throws. - //! - //! Note: the return value is in the range [0, this->bucket_count()). + //! @copydoc ::boost::intrusive::hashtable::bucket(const KeyType&,KeyHasher)const template - size_type bucket(const KeyType& k, KeyHasher hash_func) const - { return table_type::bucket(k, hash_func); } + size_type bucket(const KeyType& k, KeyHasher hash_func) const; - //! Effects: Returns the bucket array pointer passed in the constructor - //! or the last rehash function. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bucket_ptr bucket_pointer() const - { return table_type::bucket_pointer(); } + //! @copydoc ::boost::intrusive::hashtable::bucket_pointer + bucket_ptr bucket_pointer() const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a local_iterator pointing to the beginning - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - local_iterator begin(size_type n) - { return table_type::begin(n); } + //! @copydoc ::boost::intrusive::hashtable::begin(size_type) + local_iterator begin(size_type n); - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a const_local_iterator pointing to the beginning - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - const_local_iterator begin(size_type n) const - { return table_type::begin(n); } + //! @copydoc ::boost::intrusive::hashtable::begin(size_type)const + const_local_iterator begin(size_type n) const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a const_local_iterator pointing to the beginning - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - const_local_iterator cbegin(size_type n) const - { return table_type::cbegin(n); } + //! @copydoc ::boost::intrusive::hashtable::cbegin(size_type)const + const_local_iterator cbegin(size_type n) const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a local_iterator pointing to the end - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - local_iterator end(size_type n) - { return table_type::end(n); } + //! @copydoc ::boost::intrusive::hashtable::end(size_type) + local_iterator end(size_type n); - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a const_local_iterator pointing to the end - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - const_local_iterator end(size_type n) const - { return table_type::end(n); } + //! @copydoc ::boost::intrusive::hashtable::end(size_type)const + const_local_iterator end(size_type n) const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a const_local_iterator pointing to the end - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - const_local_iterator cend(size_type n) const - { return table_type::cend(n); } - - //! Requires: new_buckets must be a pointer to a new bucket array - //! or the same as the old bucket array. new_size is the length of the - //! the array pointed by new_buckets. If new_buckets == this->bucket_pointer() - //! n can be bigger or smaller than this->bucket_count(). - //! - //! Effects: Updates the internal reference with the new bucket erases - //! the values from the old bucket and inserts then in the new one. - //! - //! If store_hash option is true, this method does not use the hash function. - //! - //! Complexity: Average case linear in this->size(), worst case quadratic. - //! - //! Throws: If the hasher functor throws. Basic guarantee. - void rehash(const bucket_traits &new_bucket_traits) - { table_type::rehash(new_bucket_traits); } + //! @copydoc ::boost::intrusive::hashtable::cend(size_type)const + const_local_iterator cend(size_type n) const; - //! Requires: - //! - //! Effects: - //! - //! Complexity: - //! - //! Throws: - //! - //! Note: this method is only available if incremental option is activated. - bool incremental_rehash(bool grow = true) - { return table_type::incremental_rehash(grow); } + //! @copydoc ::boost::intrusive::hashtable::rehash(const bucket_traits &) + void rehash(const bucket_traits &new_bucket_traits); - //! Note: this method is only available if incremental option is activated. - bool incremental_rehash(const bucket_traits &new_bucket_traits) - { return table_type::incremental_rehash(new_bucket_traits); } + //! @copydoc ::boost::intrusive::hashtable::incremental_rehash(bool) + bool incremental_rehash(bool grow = true); - //! Requires: - //! - //! Effects: - //! - //! Complexity: - //! - //! Throws: - size_type split_count() const - { return table_type::split_count(); } - - //! Effects: Returns the nearest new bucket count optimized for - //! the container that is bigger than n. This suggestion can be used - //! to create bucket arrays with a size that will usually improve - //! container's performance. If such value does not exist, the - //! higher possible value is returned. - //! - //! Complexity: Amortized constant time. - //! - //! Throws: Nothing. - static size_type suggested_upper_bucket_count(size_type n) - { return table_type::suggested_upper_bucket_count(n); } - - //! Effects: Returns the nearest new bucket count optimized for - //! the container that is smaller than n. This suggestion can be used - //! to create bucket arrays with a size that will usually improve - //! container's performance. If such value does not exist, the - //! lower possible value is returned. - //! - //! Complexity: Amortized constant time. - //! - //! Throws: Nothing. - static size_type suggested_lower_bucket_count(size_type n) - { return table_type::suggested_lower_bucket_count(n); } + //! @copydoc ::boost::intrusive::hashtable::incremental_rehash(const bucket_traits &) + bool incremental_rehash(const bucket_traits &new_bucket_traits); + + //! @copydoc ::boost::intrusive::hashtable::split_count + size_type split_count() const; + + //! @copydoc ::boost::intrusive::hashtable::suggested_upper_bucket_count + static size_type suggested_upper_bucket_count(size_type n); + + //! @copydoc ::boost::intrusive::hashtable::suggested_lower_bucket_count + static size_type suggested_lower_bucket_count(size_type n); #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + friend bool operator==(const unordered_set_impl &x, const unordered_set_impl &y) + { + if(table_type::constant_time_size && x.size() != y.size()){ + return false; + } + //Find each element of x in y + for (const_iterator ix = x.cbegin(), ex = x.cend(), ey = y.cend(); ix != ex; ++ix){ + const_iterator iy = y.find(key_of_value()(*ix)); + if (iy == ey || !(*ix == *iy)) + return false; + } + return true; + } + + friend bool operator!=(const unordered_set_impl &x, const unordered_set_impl &y) + { return !(x == y); } + + friend bool operator<(const unordered_set_impl &x, const unordered_set_impl &y) + { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + friend bool operator>(const unordered_set_impl &x, const unordered_set_impl &y) + { return y < x; } + + friend bool operator<=(const unordered_set_impl &x, const unordered_set_impl &y) + { return !(y < x); } + + friend bool operator>=(const unordered_set_impl &x, const unordered_set_impl &y) + { return !(x < y); } }; //! Helper metafunction to define an \c unordered_set that yields to the same type when the @@ -1037,6 +435,7 @@ struct make_unordered_set typedef unordered_set_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::hash , typename packed_options::equal , typename packed_options::size_type @@ -1115,6 +514,14 @@ class unordered_set unordered_set& operator=(BOOST_RV_REF(unordered_set) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + + template + void clone_from(const unordered_set &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(unordered_set) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } }; #endif @@ -1158,14 +565,14 @@ class unordered_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class unordered_multiset_impl - : public hashtable_impl + : public hashtable_impl { /// @cond private: - typedef hashtable_impl table_type; + typedef hashtable_impl table_type; /// @endcond //Movable @@ -1175,6 +582,7 @@ class unordered_multiset_impl public: typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; typedef typename implementation_defined::value_traits value_traits; typedef typename implementation_defined::bucket_traits bucket_traits; typedef typename implementation_defined::pointer pointer; @@ -1183,7 +591,6 @@ class unordered_multiset_impl typedef typename implementation_defined::const_reference const_reference; typedef typename implementation_defined::difference_type difference_type; typedef typename implementation_defined::size_type size_type; - typedef typename implementation_defined::key_type key_type; typedef typename implementation_defined::key_equal key_equal; typedef typename implementation_defined::hasher hasher; typedef typename implementation_defined::bucket_type bucket_type; @@ -1201,19 +608,7 @@ class unordered_multiset_impl public: - //! Requires: buckets must not be being used by any other resource. - //! - //! Effects: Constructs an empty unordered_multiset, storing a reference - //! to the bucket array and copies of the hasher and equal functors. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor or invocation of Hash or Equal throws. - //! - //! Notes: buckets array must be disposed only after - //! *this is disposed. + //! @copydoc ::boost::intrusive::hashtable::hashtable(const bucket_traits &,const hasher &,const key_equal &,const value_traits &) explicit unordered_multiset_impl ( const bucket_traits &b_traits , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() @@ -1221,21 +616,7 @@ class unordered_multiset_impl : table_type(b_traits, hash_func, equal_func, v_traits) {} - //! Requires: buckets must not be being used by any other resource - //! and Dereferencing iterator must yield an lvalue of type value_type. - //! - //! Effects: Constructs an empty unordered_multiset and inserts elements from - //! [b, e). - //! - //! Complexity: If N is distance(b, e): Average case is O(N) - //! (with a good hash function and with buckets_len >= N),worst case O(N2). - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor or invocation of hasher or key_equal throws. - //! - //! Notes: buckets array must be disposed only after - //! *this is disposed. + //! @copydoc ::boost::intrusive::hashtable::hashtable(bool,Iterator,Iterator,const bucket_traits &,const hasher &,const key_equal &,const value_traits &) template unordered_multiset_impl ( Iterator b , Iterator e @@ -1243,8 +624,8 @@ class unordered_multiset_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : table_type(b_traits, hash_func, equal_func, v_traits) - { table_type::insert_equal(b, e); } + : table_type(false, b, e, b_traits, hash_func, equal_func, v_traits) + {} //! Effects: to-do //! @@ -1259,785 +640,212 @@ class unordered_multiset_impl #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Effects: Detaches all elements from this. The objects in the unordered_multiset - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements in the unordered_multiset, if - //! it's a safe-mode or auto-unlink value. Otherwise constant. - //! - //! Throws: Nothing. - ~unordered_multiset_impl() - {} + //! @copydoc ::boost::intrusive::hashtable::~hashtable() + ~unordered_multiset_impl(); - //! Effects: Returns an iterator pointing to the beginning of the unordered_multiset. - //! - //! Complexity: Constant time if `cache_begin<>` is true. Amortized - //! constant time with worst case (empty unordered_set) O(this->bucket_count()) - //! - //! Throws: Nothing. - iterator begin() - { return table_type::begin(); } + //! @copydoc ::boost::intrusive::hashtable::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning - //! of the unordered_multiset. - //! - //! Complexity: Constant time if `cache_begin<>` is true. Amortized - //! constant time with worst case (empty unordered_set) O(this->bucket_count()) - //! - //! Throws: Nothing. - const_iterator begin() const - { return table_type::begin(); } + //! @copydoc ::boost::intrusive::hashtable::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning - //! of the unordered_multiset. - //! - //! Complexity: Constant time if `cache_begin<>` is true. Amortized - //! constant time with worst case (empty unordered_set) O(this->bucket_count()) - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return table_type::cbegin(); } + //! @copydoc ::boost::intrusive::hashtable::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the unordered_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return table_type::end(); } + //! @copydoc ::boost::intrusive::hashtable::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the unordered_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return table_type::end(); } + //! @copydoc ::boost::intrusive::hashtable::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the unordered_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return table_type::cend(); } + //! @copydoc ::boost::intrusive::hashtable::cend()const + const_iterator cend() const; - //! Effects: Returns the hasher object used by the unordered_set. - //! - //! Complexity: Constant. - //! - //! Throws: If hasher copy-constructor throws. - hasher hash_function() const - { return table_type::hash_function(); } + //! @copydoc ::boost::intrusive::hashtable::hash_function()const + hasher hash_function() const; - //! Effects: Returns the key_equal object used by the unordered_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If key_equal copy-constructor throws. - key_equal key_eq() const - { return table_type::key_eq(); } + //! @copydoc ::boost::intrusive::hashtable::key_eq()const + key_equal key_eq() const; - //! Effects: Returns true if the container is empty. - //! - //! Complexity: if constant-time size and cache_last options are disabled, - //! average constant time (worst case, with empty() == true: O(this->bucket_count()). - //! Otherwise constant. - //! - //! Throws: Nothing. - bool empty() const - { return table_type::empty(); } + //! @copydoc ::boost::intrusive::hashtable::empty()const + bool empty() const; - //! Effects: Returns the number of elements stored in the unordered_multiset. - //! - //! Complexity: Linear to elements contained in *this if - //! constant-time size option is disabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return table_type::size(); } + //! @copydoc ::boost::intrusive::hashtable::size()const + size_type size() const; - //! Requires: the hasher and the equality function unqualified swap - //! call should not throw. - //! - //! Effects: Swaps the contents of two unordered_multisets. - //! Swaps also the contained bucket array and equality and hasher functors. - //! - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison or hash functors - //! found using ADL throw. Basic guarantee. - void swap(unordered_multiset_impl& other) - { table_type::swap(other.table_); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes that compare equal and produce the same - //! hash than the original node. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. The hash function and the equality - //! predicate are copied from the source. - //! - //! If store_hash option is true, this method does not use the hash function. - //! - //! If any operation throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner or hasher throw or hash or equality predicate copying - //! throws. Basic guarantee. + //! @copydoc ::boost::intrusive::hashtable::hashtable + void swap(unordered_multiset_impl& other); + + //! @copydoc ::boost::intrusive::hashtable::clone_from(const hashtable&,Cloner,Disposer) template - void clone_from(const unordered_multiset_impl &src, Cloner cloner, Disposer disposer) - { table_type::clone_from(src.table_, cloner, disposer); } + void clone_from(const unordered_multiset_impl &src, Cloner cloner, Disposer disposer); + + #else + + using table_type::clone_from; #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the unordered_multiset. - //! - //! Returns: An iterator to the new inserted value. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::hashtable::clone_from(hashtable&&,Cloner,Disposer) + template + void clone_from(BOOST_RV_REF(unordered_multiset_impl) src, Cloner cloner, Disposer disposer) + { table_type::clone_from(BOOST_MOVE_BASE(table_type, src), cloner, disposer); } + + //! @copydoc ::boost::intrusive::hashtable::insert_equal(reference) iterator insert(reference value) { return table_type::insert_equal(value); } - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Equivalent to this->insert(t) for each element in [b, e). - //! - //! Complexity: Average case is O(N), where N is the - //! size of the range. - //! - //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::hashtable::insert_equal(Iterator,Iterator) template void insert(Iterator b, Iterator e) { table_type::insert_equal(b, e); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Effects: Erases the element pointed to by i. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased element. No destructors are called. - void erase(const_iterator i) - { table_type::erase(i); } + //! @copydoc ::boost::intrusive::hashtable::erase(const_iterator) + void erase(const_iterator i); - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average case O(distance(b, e)), - //! worst case O(this->size()). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void erase(const_iterator b, const_iterator e) - { table_type::erase(b, e); } + //! @copydoc ::boost::intrusive::hashtable::erase(const_iterator,const_iterator) + void erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Average case O(this->count(value)). - //! Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return table_type::erase(value); } - - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "key_value_equal" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "key_value_equal" compares an arbitrary key with the contained values. - //! - //! Effects: Erases all the elements that have the same hash and - //! compare equal with the given key. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Average case O(this->count(value)). - //! Worst case O(this->size()). - //! - //! Throws: If the hash_func or the equal_func functors throws. - //! Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_type::erase(key, hash_func, equal_func); } + //! @copydoc ::boost::intrusive::hashtable::erase(const key_type &) + size_type erase(const key_type &key); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by i. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. - template - void erase_and_dispose(const_iterator i, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { table_type::erase_and_dispose(i, disposer); } - - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::hashtable::erase(const KeyType&,KeyHasher,KeyEqual) + template + size_type erase(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func); + + //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const_iterator,Disposer) template - void erase_and_dispose(const_iterator i, Disposer disposer) - { this->erase_and_dispose(const_iterator(i), disposer); } - #endif + BOOST_INTRUSIVE_DOC1ST(void + , typename detail::disable_if_convertible::type) + erase_and_dispose(const_iterator i, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average case O(distance(b, e)), - //! worst case O(this->size()). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const_iterator,const_iterator,Disposer) template - void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { table_type::erase_and_dispose(b, e, disposer); } + void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Average case O(this->count(value)). - //! Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const key_type &,Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return table_type::erase_and_dispose(value, disposer); } + size_type erase_and_dispose(const key_type &key, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "equal_func". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Average case O(this->count(value)). - //! Worst case O(this->size()). - //! - //! Throws: If hash_func or equal_func throw. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. - template - size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func, Disposer disposer) - { return table_type::erase_and_dispose(key, hash_func, equal_func, disposer); } + //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const KeyType&,KeyHasher,KeyEqual,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return table_type::clear(); } + //! @copydoc ::boost::intrusive::hashtable::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::hashtable::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return table_type::clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - size_type count(const_reference value) const - { return table_type::count(value); } + //! @copydoc ::boost::intrusive::hashtable::count(const key_type &)const + size_type count(const key_type &key) const; - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "key_value_equal" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "key_value_equal" compares an arbitrary key with the contained values. - //! - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - template - size_type count(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_type::count(key, hash_func, equal_func); } + //! @copydoc ::boost::intrusive::hashtable::count(const KeyType&,KeyHasher,KeyEqual)const + template + size_type count(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - iterator find(const_reference value) - { return table_type::find(value); } + //! @copydoc ::boost::intrusive::hashtable::find(const key_type &) + iterator find(const key_type &key); - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "key_value_equal" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "key_value_equal" compares an arbitrary key with the contained values. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the given hasher and equality functor or end() if - //! that element does not exist. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. - template - iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_type::find(key, hash_func, equal_func); } - - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" or end() if that element does not exist. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - const_iterator find(const_reference value) const - { return table_type::find(value); } + //! @copydoc ::boost::intrusive::hashtable::find(const KeyType &,KeyHasher,KeyEqual) + template + iterator find(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func); - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "key_value_equal" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "key_value_equal" compares an arbitrary key with the contained values. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the given hasher and equality functor or end() if - //! that element does not exist. - //! - //! Complexity: Average case O(1), worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. - template - const_iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_type::find(key, hash_func, equal_func); } - - //! Effects: Returns a range containing all elements with values equivalent - //! to value. Returns std::make_pair(this->end(), this->end()) if no such - //! elements exist. - //! - //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - std::pair equal_range(const_reference value) - { return table_type::equal_range(value); } + //! @copydoc ::boost::intrusive::hashtable::count(const key_type &)const + const_iterator find(const key_type &key) const; - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "key_value_equal" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "key_value_equal" compares an arbitrary key with the contained values. - //! - //! Effects: Returns a range containing all elements with equivalent - //! keys. Returns std::make_pair(this->end(), this->end()) if no such - //! elements exist. - //! - //! Complexity: Average case O(this->count(key, hash_func, equal_func)). - //! Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. - template - std::pair equal_range - (const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_type::equal_range(key, hash_func, equal_func); } - - //! Effects: Returns a range containing all elements with values equivalent - //! to value. Returns std::make_pair(this->end(), this->end()) if no such - //! elements exist. - //! - //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. + //! @copydoc ::boost::intrusive::hashtable::find(const KeyType &,KeyHasher,KeyEqual)const + template + const_iterator find(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const; + + //! @copydoc ::boost::intrusive::hashtable::equal_range(const key_type&) + std::pair equal_range(const key_type &key); + + //! @copydoc ::boost::intrusive::hashtable::equal_range(const KeyType &,KeyHasher,KeyEqual) + template + std::pair equal_range(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func); + + //! @copydoc ::boost::intrusive::hashtable::equal_range(const key_type&)const std::pair - equal_range(const_reference value) const - { return table_type::equal_range(value); } + equal_range(const key_type &key) const; - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! "key_value_equal" must be a equality function that induces - //! the same equality as key_equal. The difference is that - //! "key_value_equal" compares an arbitrary key with the contained values. - //! - //! Effects: Returns a range containing all elements with equivalent - //! keys. Returns std::make_pair(this->end(), this->end()) if no such - //! elements exist. - //! - //! Complexity: Average case O(this->count(key, hash_func, equal_func)). - //! Worst case O(this->size()). - //! - //! Throws: If the internal hasher or the equality functor throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. - template + //! @copydoc ::boost::intrusive::hashtable::equal_range(const KeyType &,KeyHasher,KeyEqual)const + template std::pair - equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_type::equal_range(key, hash_func, equal_func); } + equal_range(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const; - //! Requires: value must be an lvalue and shall be in a unordered_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator belonging to the unordered_multiset - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: If the hash function throws. - iterator iterator_to(reference value) - { return table_type::iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a unordered_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator belonging to the - //! unordered_multiset that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: If the hash function throws. - const_iterator iterator_to(const_reference value) const - { return table_type::iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid local_iterator belonging to the unordered_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static local_iterator s_local_iterator_to(reference value) - { return table_type::s_local_iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::s_local_iterator_to(reference) + static local_iterator s_local_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_local_iterator belonging to - //! the unordered_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_local_iterator s_local_iterator_to(const_reference value) - { return table_type::s_local_iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::s_local_iterator_to(const_reference) + static const_local_iterator s_local_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid local_iterator belonging to the unordered_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - local_iterator local_iterator_to(reference value) - { return table_type::local_iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::local_iterator_to(reference) + local_iterator local_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a unordered_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_local_iterator belonging to - //! the unordered_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_local_iterator local_iterator_to(const_reference value) const - { return table_type::local_iterator_to(value); } + //! @copydoc ::boost::intrusive::hashtable::local_iterator_to(const_reference) + const_local_iterator local_iterator_to(const_reference value) const; - //! Effects: Returns the number of buckets passed in the constructor - //! or the last rehash function. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - size_type bucket_count() const - { return table_type::bucket_count(); } + //! @copydoc ::boost::intrusive::hashtable::bucket_count + size_type bucket_count() const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns the number of elements in the nth bucket. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - size_type bucket_size(size_type n) const - { return table_type::bucket_size(n); } + //! @copydoc ::boost::intrusive::hashtable::bucket_size + size_type bucket_size(size_type n) const; - //! Effects: Returns the index of the bucket in which elements - //! with keys equivalent to k would be found, if any such element existed. - //! - //! Complexity: Constant. - //! - //! Throws: If the hash functor throws. - //! - //! Note: the return value is in the range [0, this->bucket_count()). - size_type bucket(const value_type& k) const - { return table_type::bucket(k); } + //! @copydoc ::boost::intrusive::hashtable::bucket(const key_type&)const + size_type bucket(const key_type& k) const; - //! Requires: "hash_func" must be a hash function that induces - //! the same hash values as the stored hasher. The difference is that - //! "hash_func" hashes the given key instead of the value_type. - //! - //! Effects: Returns the index of the bucket in which elements - //! with keys equivalent to k would be found, if any such element existed. - //! - //! Complexity: Constant. - //! - //! Throws: If the hash functor throws. - //! - //! Note: the return value is in the range [0, this->bucket_count()). + //! @copydoc ::boost::intrusive::hashtable::bucket(const KeyType&,KeyHasher)const template - size_type bucket(const KeyType& k, const KeyHasher &hash_func) const - { return table_type::bucket(k, hash_func); } + size_type bucket(const KeyType& k, KeyHasher hash_func) const; - //! Effects: Returns the bucket array pointer passed in the constructor - //! or the last rehash function. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bucket_ptr bucket_pointer() const - { return table_type::bucket_pointer(); } + //! @copydoc ::boost::intrusive::hashtable::bucket_pointer + bucket_ptr bucket_pointer() const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a local_iterator pointing to the beginning - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - local_iterator begin(size_type n) - { return table_type::begin(n); } + //! @copydoc ::boost::intrusive::hashtable::begin(size_type) + local_iterator begin(size_type n); - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a const_local_iterator pointing to the beginning - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - const_local_iterator begin(size_type n) const - { return table_type::begin(n); } + //! @copydoc ::boost::intrusive::hashtable::begin(size_type)const + const_local_iterator begin(size_type n) const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a const_local_iterator pointing to the beginning - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - const_local_iterator cbegin(size_type n) const - { return table_type::cbegin(n); } + //! @copydoc ::boost::intrusive::hashtable::cbegin(size_type)const + const_local_iterator cbegin(size_type n) const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a local_iterator pointing to the end - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - local_iterator end(size_type n) - { return table_type::end(n); } + //! @copydoc ::boost::intrusive::hashtable::end(size_type) + local_iterator end(size_type n); - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a const_local_iterator pointing to the end - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - const_local_iterator end(size_type n) const - { return table_type::end(n); } + //! @copydoc ::boost::intrusive::hashtable::end(size_type)const + const_local_iterator end(size_type n) const; - //! Requires: n is in the range [0, this->bucket_count()). - //! - //! Effects: Returns a const_local_iterator pointing to the end - //! of the sequence stored in the bucket n. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: [this->begin(n), this->end(n)) is a valid range - //! containing all of the elements in the nth bucket. - const_local_iterator cend(size_type n) const - { return table_type::cend(n); } - - //! Requires: new_buckets must be a pointer to a new bucket array - //! or the same as the old bucket array. new_size is the length of the - //! the array pointed by new_buckets. If new_buckets == this->bucket_pointer() - //! n can be bigger or smaller than this->bucket_count(). - //! - //! Effects: Updates the internal reference with the new bucket erases - //! the values from the old bucket and inserts then in the new one. - //! - //! If store_hash option is true, this method does not use the hash function. - //! - //! Complexity: Average case linear in this->size(), worst case quadratic. - //! - //! Throws: If the hasher functor throws. - void rehash(const bucket_traits &new_bucket_traits) - { table_type::rehash(new_bucket_traits); } + //! @copydoc ::boost::intrusive::hashtable::cend(size_type)const + const_local_iterator cend(size_type n) const; - //! Requires: - //! - //! Effects: - //! - //! Complexity: - //! - //! Throws: - //! - //! Note: this method is only available if incremental option is activated. - bool incremental_rehash(bool grow = true) - { return table_type::incremental_rehash(grow); } + //! @copydoc ::boost::intrusive::hashtable::rehash(const bucket_traits &) + void rehash(const bucket_traits &new_bucket_traits); - //! Note: this method is only available if incremental option is activated. - bool incremental_rehash(const bucket_traits &new_bucket_traits) - { return table_type::incremental_rehash(new_bucket_traits); } + //! @copydoc ::boost::intrusive::hashtable::incremental_rehash(bool) + bool incremental_rehash(bool grow = true); - //! Requires: - //! - //! Effects: - //! - //! Complexity: - //! - //! Throws: - size_type split_count() const - { return table_type::split_count(); } - - //! Effects: Returns the nearest new bucket count optimized for - //! the container that is bigger than n. This suggestion can be used - //! to create bucket arrays with a size that will usually improve - //! container's performance. If such value does not exist, the - //! higher possible value is returned. - //! - //! Complexity: Amortized constant time. - //! - //! Throws: Nothing. - static size_type suggested_upper_bucket_count(size_type n) - { return table_type::suggested_upper_bucket_count(n); } - - //! Effects: Returns the nearest new bucket count optimized for - //! the container that is smaller than n. This suggestion can be used - //! to create bucket arrays with a size that will usually improve - //! container's performance. If such value does not exist, the - //! lower possible value is returned. - //! - //! Complexity: Amortized constant time. - //! - //! Throws: Nothing. - static size_type suggested_lower_bucket_count(size_type n) - { return table_type::suggested_lower_bucket_count(n); } + //! @copydoc ::boost::intrusive::hashtable::incremental_rehash(const bucket_traits &) + bool incremental_rehash(const bucket_traits &new_bucket_traits); + + //! @copydoc ::boost::intrusive::hashtable::split_count + size_type split_count() const; + + //! @copydoc ::boost::intrusive::hashtable::suggested_upper_bucket_count + static size_type suggested_upper_bucket_count(size_type n); + + //! @copydoc ::boost::intrusive::hashtable::suggested_lower_bucket_count + static size_type suggested_lower_bucket_count(size_type n); #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; @@ -2074,6 +882,7 @@ struct make_unordered_multiset typedef unordered_multiset_impl < value_traits + , typename packed_options::key_of_value , typename packed_options::hash , typename packed_options::equal , typename packed_options::size_type @@ -2151,6 +960,14 @@ class unordered_multiset unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x) { return static_cast(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); } + + template + void clone_from(const unordered_multiset &src, Cloner cloner, Disposer disposer) + { Base::clone_from(src, cloner, disposer); } + + template + void clone_from(BOOST_RV_REF(unordered_multiset) src, Cloner cloner, Disposer disposer) + { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); } }; #endif -- cgit v1.2.3