From 2dd87072b79b0aa41b38e07e757a50670e4e5c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 13 Oct 2008 19:36:50 +0000 Subject: [PATCH] Changes and fixes for Boost 1.37 [SVN r49322] --- include/boost/intrusive/any_hook.hpp | 46 +- include/boost/intrusive/avl_set.hpp | 114 ++- include/boost/intrusive/avl_set_hook.hpp | 42 +- include/boost/intrusive/avltree.hpp | 98 +- .../boost/intrusive/avltree_algorithms.hpp | 16 +- include/boost/intrusive/bs_set_hook.hpp | 62 +- .../intrusive/circular_slist_algorithms.hpp | 4 +- .../detail/any_node_and_algorithms.hpp | 23 +- include/boost/intrusive/detail/assert.hpp | 18 +- include/boost/intrusive/detail/list_node.hpp | 3 + include/boost/intrusive/detail/mpl.hpp | 188 ++-- include/boost/intrusive/detail/slist_node.hpp | 3 + .../intrusive/detail/tree_algorithms.hpp | 4 +- include/boost/intrusive/detail/workaround.hpp | 30 + include/boost/intrusive/hashtable.hpp | 890 ++++++++++++------ include/boost/intrusive/intrusive_fwd.hpp | 152 ++- .../intrusive/linear_slist_algorithms.hpp | 4 +- include/boost/intrusive/list.hpp | 146 +-- include/boost/intrusive/list_hook.hpp | 44 +- include/boost/intrusive/options.hpp | 214 ++++- include/boost/intrusive/pointer_plus_bits.hpp | 7 +- include/boost/intrusive/rbtree.hpp | 106 ++- include/boost/intrusive/set.hpp | 116 ++- include/boost/intrusive/set_hook.hpp | 44 +- include/boost/intrusive/sg_set.hpp | 116 ++- include/boost/intrusive/sgtree.hpp | 96 +- include/boost/intrusive/sgtree_algorithms.hpp | 2 +- include/boost/intrusive/slist.hpp | 212 +++-- include/boost/intrusive/slist_hook.hpp | 44 +- include/boost/intrusive/splay_set.hpp | 115 ++- include/boost/intrusive/splay_set_hook.hpp | 44 +- include/boost/intrusive/splaytree.hpp | 109 ++- .../boost/intrusive/splaytree_algorithms.hpp | 2 +- include/boost/intrusive/unordered_set.hpp | 154 ++- .../boost/intrusive/unordered_set_hook.hpp | 44 +- 35 files changed, 2283 insertions(+), 1029 deletions(-) create mode 100644 include/boost/intrusive/detail/workaround.hpp diff --git a/include/boost/intrusive/any_hook.hpp b/include/boost/intrusive/any_hook.hpp index 148d41d..4690cef 100644 --- a/include/boost/intrusive/any_hook.hpp +++ b/include/boost/intrusive/any_hook.hpp @@ -34,7 +34,7 @@ struct get_any_node_algo //! Helper metafunction to define a \c \c any_base_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -43,8 +43,14 @@ struct make_any_base_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; - + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type packed_options; + typedef detail::generic_hook < get_any_node_algo , typename packed_options::tag @@ -70,15 +76,21 @@ struct make_any_base_hook //! //! \c void_pointer<> is the pointer type that will be used internally in the hook //! and the the container configured to use this hook. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class any_base_hook - : public make_any_base_hook::type + : public make_any_base_hook + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) public: //! Effects: If link_mode is or \c safe_link //! initializes the node to an unlinked state. @@ -127,7 +139,7 @@ class any_base_hook //! Helper metafunction to define a \c \c any_member_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -136,7 +148,13 @@ struct make_any_member_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_any_node_algo @@ -158,15 +176,21 @@ struct make_any_member_hook //! //! \c void_pointer<> is the pointer type that will be used internally in the hook //! and the the container configured to use this hook. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class any_member_hook - : public make_any_member_hook::type + : public make_any_member_hook + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) public: //! Effects: If link_mode is or \c safe_link //! initializes the node to an unlinked state. diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index 8429f13..a550232 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -31,7 +31,7 @@ namespace intrusive { //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -323,18 +323,19 @@ class avl_set_impl { tree_.swap(other.tree_); } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const avl_set_impl &src, Cloner cloner, Disposer disposer) { tree_.clone_from(src.tree_, cloner, disposer); } @@ -996,65 +997,65 @@ class avl_set_impl /// @endcond }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avl_set_impl &x, const avl_set_impl &y) #else (const avl_set_impl &x, const avl_set_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avl_set_impl &x, const avl_set_impl &y) #else (const avl_set_impl &x, const avl_set_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avl_set_impl &x, const avl_set_impl &y) #else (const avl_set_impl &x, const avl_set_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avl_set_impl &x, const avl_set_impl &y) #else (const avl_set_impl &x, const avl_set_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (avl_set_impl &x, avl_set_impl &y) #else (avl_set_impl &x, avl_set_impl &y) @@ -1063,7 +1064,7 @@ inline void swap //! Helper metafunction to define a \c avl_set that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_avltree_opt + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class avl_set - : public make_avl_set::type + : public make_avl_set + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type { typedef typename make_avl_set - ::type Base; + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type Base; public: typedef typename Base::value_compare value_compare; @@ -1134,7 +1157,7 @@ class avl_set //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -1422,18 +1445,19 @@ class avl_multiset_impl { tree_.swap(other.tree_); } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. Basic guarantee. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const avl_multiset_impl &src, Cloner cloner, Disposer disposer) { tree_.clone_from(src.tree_, cloner, disposer); } @@ -2002,65 +2026,65 @@ class avl_multiset_impl /// @endcond }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avl_multiset_impl &x, const avl_multiset_impl &y) #else (const avl_multiset_impl &x, const avl_multiset_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avl_multiset_impl &x, const avl_multiset_impl &y) #else (const avl_multiset_impl &x, const avl_multiset_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avl_multiset_impl &x, const avl_multiset_impl &y) #else (const avl_multiset_impl &x, const avl_multiset_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avl_multiset_impl &x, const avl_multiset_impl &y) #else (const avl_multiset_impl &x, const avl_multiset_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (avl_multiset_impl &x, avl_multiset_impl &y) #else (avl_multiset_impl &x, avl_multiset_impl &y) @@ -2069,7 +2093,7 @@ inline void swap //! Helper metafunction to define a \c avl_multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_avltree_opt + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class avl_multiset - : public make_avl_multiset::type + : public make_avl_multiset::type { typedef typename make_avl_multiset - ::type Base; + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type Base; public: typedef typename Base::value_compare value_compare; diff --git a/include/boost/intrusive/avl_set_hook.hpp b/include/boost/intrusive/avl_set_hook.hpp index 93a9a85..76fa739 100644 --- a/include/boost/intrusive/avl_set_hook.hpp +++ b/include/boost/intrusive/avl_set_hook.hpp @@ -34,7 +34,7 @@ struct get_avl_set_node_algo //! Helper metafunction to define a \c avl_set_base_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -43,7 +43,12 @@ struct make_avl_set_base_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3, O4>::type packed_options; + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type packed_options; typedef detail::generic_hook < get_avl_set_node_algo will tell the hook to optimize the hook for size instead //! of speed. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class avl_set_base_hook - : public make_avl_set_base_hook::type + : public make_avl_set_base_hook + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -153,7 +164,7 @@ class avl_set_base_hook //! Helper metafunction to define a \c avl_set_member_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -162,7 +173,12 @@ struct make_avl_set_member_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3, O4>::type packed_options; + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type packed_options; typedef detail::generic_hook < get_avl_set_node_algo will tell the hook to optimize the hook for size instead //! of speed. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class avl_set_member_hook - : public make_avl_set_member_hook::type + : public make_avl_set_member_hook + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index afd6bd4..46038a8 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -36,20 +36,6 @@ namespace intrusive { /// @cond -template -struct internal_default_avl_set_hook -{ - template static detail::one test(...); - template static detail::two test(typename U::default_avl_set_hook* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); -}; - -template -struct get_default_avl_set_hook -{ - typedef typename T::default_avl_set_hook type; -}; - template struct avl_setopt { @@ -63,13 +49,7 @@ template struct avl_set_defaults : pack_options < none - , base_hook - < typename detail::eval_if_c - < internal_default_avl_set_hook::value - , get_default_avl_set_hook - , detail::identity - >::type - > + , base_hook , constant_time_size , size_type , compare > @@ -91,7 +71,7 @@ struct avl_set_defaults //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -1055,29 +1035,34 @@ class avltree_impl } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const avltree_impl &src, Cloner cloner, Disposer disposer) { this->clear_and_dispose(disposer); if(!src.empty()){ + detail::exception_disposer + rollback(*this, disposer); node_algorithms::clone (const_node_ptr(&src.priv_header()) ,node_ptr(&this->priv_header()) ,detail::node_cloner(cloner, this) ,detail::node_disposer(disposer, this)); this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + this->priv_comp() = src.priv_comp(); + rollback.release(); } } @@ -1260,26 +1245,26 @@ class avltree_impl { return priv_container_from_end_iterator(it.end_iterator_from_it()); } }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator< -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avltree_impl &x, const avltree_impl &y) #else (const avltree_impl &x, const avltree_impl &y) #endif { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif bool operator== -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avltree_impl &x, const avltree_impl &y) #else (const avltree_impl &x, const avltree_impl &y) @@ -1311,65 +1296,65 @@ bool operator== } } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avltree_impl &x, const avltree_impl &y) #else (const avltree_impl &x, const avltree_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avltree_impl &x, const avltree_impl &y) #else (const avltree_impl &x, const avltree_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avltree_impl &x, const avltree_impl &y) #else (const avltree_impl &x, const avltree_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const avltree_impl &x, const avltree_impl &y) #else (const avltree_impl &x, const avltree_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (avltree_impl &x, avltree_impl &y) #else (avltree_impl &x, avltree_impl &y) @@ -1377,15 +1362,24 @@ inline void swap { x.swap(y); } /// @cond + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif struct make_avltree_opt { typedef typename pack_options - < avl_set_defaults, O1, O2, O3, O4>::type packed_options; + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + < avl_set_defaults, O1, O2, O3, O4> + #else + < avl_set_defaults, Options...> + #endif + ::type packed_options; + typedef typename detail::get_value_traits ::type value_traits; @@ -1400,7 +1394,7 @@ struct make_avltree_opt //! Helper metafunction to define a \c avltree that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + #else + < typename make_avltree_opt::type + #endif > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class avltree + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) : public make_avltree::type + #else + : public make_avltree::type + #endif { typedef typename make_avltree - ::type Base; + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type Base; public: typedef typename Base::value_compare value_compare; diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index dc4eed4..307dbc8 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -682,10 +682,10 @@ class avltree_algorithms // x is right child // a is left child node_ptr a = NodeTraits::get_left(x_parent); - assert(a); + BOOST_INTRUSIVE_INVARIANT_ASSERT(a); if (NodeTraits::get_balance(a) == NodeTraits::positive()) { // a MUST have a right child - assert(NodeTraits::get_right(a)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(a)); rotate_left_right(x_parent, root); x = NodeTraits::get_parent(x_parent); @@ -714,10 +714,10 @@ class avltree_algorithms // x is left child // a is right child node_ptr a = NodeTraits::get_right(x_parent); - assert(a); + BOOST_INTRUSIVE_INVARIANT_ASSERT(a); if (NodeTraits::get_balance(a) == NodeTraits::negative()) { // a MUST have then a left child - assert(NodeTraits::get_left(a)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(a)); rotate_right_left(x_parent, root); x = NodeTraits::get_parent(x_parent); @@ -735,7 +735,7 @@ class avltree_algorithms } } else{ - assert(false); // never reached + BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached } } NodeTraits::set_parent(header, root); @@ -784,7 +784,7 @@ class avltree_algorithms break; } else{ - assert(false); // never reached + BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached } } NodeTraits::set_parent(header, root); @@ -842,7 +842,7 @@ class avltree_algorithms NodeTraits::set_balance(b, NodeTraits::negative()); } else{ - assert(false); // never reached + BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached } NodeTraits::set_balance(c, NodeTraits::zero()); } @@ -899,7 +899,7 @@ class avltree_algorithms NodeTraits::set_balance(b, NodeTraits::zero()); } else{ - assert(false); + BOOST_INTRUSIVE_INVARIANT_ASSERT(false); } NodeTraits::set_balance(c, NodeTraits::zero()); } diff --git a/include/boost/intrusive/bs_set_hook.hpp b/include/boost/intrusive/bs_set_hook.hpp index bf55042..d4726b0 100644 --- a/include/boost/intrusive/bs_set_hook.hpp +++ b/include/boost/intrusive/bs_set_hook.hpp @@ -34,7 +34,7 @@ struct get_bs_set_node_algo //! Helper metafunction to define a \c bs_set_base_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -43,7 +43,12 @@ struct make_bs_set_base_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + < hook_defaults, O1, O2, O3> + #else + < hook_defaults, Options...> + #endif + ::type packed_options; //Scapegoat trees can't be auto unlink trees BOOST_STATIC_ASSERT(((int)packed_options::link_mode != (int)auto_unlink)); @@ -75,15 +80,22 @@ struct make_bs_set_base_hook //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class bs_set_base_hook - : public make_bs_set_base_hook::type + : public make_bs_set_base_hook + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type + { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -152,7 +164,7 @@ class bs_set_base_hook //! Helper metafunction to define a \c bs_set_member_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -161,7 +173,13 @@ struct make_bs_set_member_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + < hook_defaults, O1, O2, O3> + #else + < hook_defaults, Options...> + #endif + + ::type packed_options; //Scapegoat trees can't be auto unlink trees BOOST_STATIC_ASSERT(((int)packed_options::link_mode != (int)auto_unlink)); @@ -187,15 +205,21 @@ struct make_bs_set_member_hook //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class bs_set_member_hook - : public make_bs_set_member_hook::type + : public make_bs_set_member_hook + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -262,24 +286,6 @@ class bs_set_member_hook #endif }; -/// @cond - -template -struct internal_default_bs_set_hook -{ - template static detail::one test(...); - template static detail::two test(typename U::default_bs_set_hook* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); -}; - -template -struct get_default_bs_set_hook -{ - typedef typename T::default_bs_set_hook type; -}; - -/// @endcond - } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/circular_slist_algorithms.hpp b/include/boost/intrusive/circular_slist_algorithms.hpp index f74a641..5247f57 100644 --- a/include/boost/intrusive/circular_slist_algorithms.hpp +++ b/include/boost/intrusive/circular_slist_algorithms.hpp @@ -59,7 +59,7 @@ class circular_slist_algorithms typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef NodeTraits node_traits; - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: Constructs an non-used list element, putting the next //! pointer to null: @@ -128,7 +128,7 @@ class circular_slist_algorithms //! Throws: Nothing. static void transfer_after(node_ptr p, node_ptr b, node_ptr e); - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: Constructs an empty list, making this_node the only //! node of the circular list: diff --git a/include/boost/intrusive/detail/any_node_and_algorithms.hpp b/include/boost/intrusive/detail/any_node_and_algorithms.hpp index 9662138..6a3d955 100644 --- a/include/boost/intrusive/detail/any_node_and_algorithms.hpp +++ b/include/boost/intrusive/detail/any_node_and_algorithms.hpp @@ -18,6 +18,7 @@ #include #include #include +#include namespace boost { namespace intrusive { @@ -238,6 +239,10 @@ class any_node_traits template class any_algorithms { + template + static void function_not_available_for_any_hooks(typename detail::enable_if >::type) + {} + public: typedef any_node node; typedef typename boost::pointer_to_other @@ -269,28 +274,18 @@ class any_algorithms static bool unique(const_node_ptr node) { return 0 == node->node_ptr_1; } - -#if defined(__EDG__) && defined(__STD_STRICT_ANSI) - // For compilers checking the full source code at compile time, regardless - // of whether the code is instantiated or not, we turn the compile error - // below into a link error. - static void unlink(node_ptr); - static void swap_nodes(node_ptr l, node_ptr r); -#else static void unlink(node_ptr) { - //Auto-unlink hooks and unlink() call for safe hooks are not - //available for any hooks!!! - any_algorithms::unlink_not_available_for_any_hooks(); + //Auto-unlink hooks and unlink() are not available for any hooks + any_algorithms::template function_not_available_for_any_hooks(); } static void swap_nodes(node_ptr l, node_ptr r) { //Any nodes have no swap_nodes capability because they don't know - //what algorithm they must use from unlink them from the container - any_algorithms::swap_nodes_not_available_for_any_hooks(); + //what algorithm they must use to unlink the node from the container + any_algorithms::template function_not_available_for_any_hooks(); } -#endif }; } //namespace intrusive diff --git a/include/boost/intrusive/detail/assert.hpp b/include/boost/intrusive/detail/assert.hpp index 076343e..e742b7e 100644 --- a/include/boost/intrusive/detail/assert.hpp +++ b/include/boost/intrusive/detail/assert.hpp @@ -18,18 +18,24 @@ #endif #if !defined(BOOST_INTRUSIVE_INVARIANT_ASSERT) -#include -#define BOOST_INTRUSIVE_INVARIANT_ASSERT BOOST_ASSERT + #include + #define BOOST_INTRUSIVE_INVARIANT_ASSERT BOOST_ASSERT +#elif defined(BOOST_INTRUSIVE_INVARIANT_ASSERT_INCLUDE) + #include BOOST_INTRUSIVE_INVARIANT_ASSERT_INCLUDE #endif #if !defined(BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT) -#include -#define BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT BOOST_ASSERT + #include + #define BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT BOOST_ASSERT +#elif defined(BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE) + #include BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE #endif #if !defined(BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT) -#include -#define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT BOOST_ASSERT + #include + #define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT BOOST_ASSERT +#elif defined(BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE) + #include BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE #endif #endif //BOOST_INTRUSIVE_DETAIL_ASSERT_HPP diff --git a/include/boost/intrusive/detail/list_node.hpp b/include/boost/intrusive/detail/list_node.hpp index 371224e..a0bc8ba 100644 --- a/include/boost/intrusive/detail/list_node.hpp +++ b/include/boost/intrusive/detail/list_node.hpp @@ -161,6 +161,9 @@ class list_iterator return 0; } + list_iterator unconst() const + { return list_iterator(this->pointed_node(), this->get_container()); } + private: struct members : public detail::select_constptr diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index ed68350..27e7f37 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -51,6 +51,12 @@ struct enable_if_c {}; template struct enable_if : public enable_if_c{}; +template +struct apply +{ + typedef typename F::template apply::type type; +}; + template class is_convertible { @@ -127,83 +133,127 @@ struct identity #define BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS #endif -no_type BOOST_INTRUSIVE_TT_DECL is_function_ptr_tester(...); - -template -yes_type is_function_ptr_tester(R (*)()); - -template -yes_type is_function_ptr_tester(R (*)( ...)); - -#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS -template -yes_type is_function_ptr_tester(R (__stdcall*)()); -template -yes_type is_function_ptr_tester(R (__stdcall*)( ...)); - -template -yes_type is_function_ptr_tester(R (__fastcall*)()); -template -yes_type is_function_ptr_tester(R (__fastcall*)( ...)); - -template -yes_type is_function_ptr_tester(R (__cdecl*)()); -template -yes_type is_function_ptr_tester(R (__cdecl*)( ...)); -#endif - -template -yes_type is_function_ptr_tester(R (*)( T0)); - -template -yes_type is_function_ptr_tester(R (*)( T0 ...)); - -#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS -template -yes_type is_function_ptr_tester(R (__stdcall*)( T0)); -template -yes_type is_function_ptr_tester(R (__stdcall*)( T0 ...)); - -template -yes_type is_function_ptr_tester(R (__fastcall*)( T0)); -template -yes_type is_function_ptr_tester(R (__fastcall*)( T0 ...)); - -template -yes_type is_function_ptr_tester(R (__cdecl*)( T0)); -#endif -template -yes_type is_function_ptr_tester(R (*)( T0 , T1)); - -#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS -template -yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1)); - -template -yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1)); - -template -yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1)); -#endif - template struct is_unary_or_binary_function_impl -{ - static T* t; - static const bool value = sizeof(is_function_ptr_tester(t)) == sizeof(yes_type); -}; +{ static const bool value = false; }; +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; +/* +#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; +#endif +*/ +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; +/* +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; +*/ +#endif + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; +/* +#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_or_binary_function_impl +{ static const bool value = true; }; +#endif +*/ template struct is_unary_or_binary_function_impl -{ - static const bool value = false; -}; +{ static const bool value = false; }; template struct is_unary_or_binary_function -{ - static const bool value = is_unary_or_binary_function_impl::value; -}; +{ static const bool value = is_unary_or_binary_function_impl::value; }; //boost::alignment_of yields to 10K lines of preprocessed code, so we //need an alternative diff --git a/include/boost/intrusive/detail/slist_node.hpp b/include/boost/intrusive/detail/slist_node.hpp index 8195e54..c0636e1 100644 --- a/include/boost/intrusive/detail/slist_node.hpp +++ b/include/boost/intrusive/detail/slist_node.hpp @@ -128,6 +128,9 @@ class slist_iterator return 0; } + slist_iterator unconst() const + { return slist_iterator(this->pointed_node(), this->get_container()); } + const real_value_traits *get_real_value_traits() const { if(store_container_ptr) diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/detail/tree_algorithms.hpp index 65e673f..0aa06f7 100644 --- a/include/boost/intrusive/detail/tree_algorithms.hpp +++ b/include/boost/intrusive/detail/tree_algorithms.hpp @@ -1391,14 +1391,14 @@ class tree_algorithms //Taken from: //"Tree rebalancing in optimal time and space" //Quentin F. Stout and Bette L. Warren - std::size_t len; + std::size_t len = 0; subtree_to_vine(NodeTraits::get_parent(header), &len); vine_to_subtree(NodeTraits::get_parent(header), len); } static node_ptr rebalance_subtree(node_ptr old_root) { - std::size_t len; + std::size_t len = 0; node_ptr new_root = subtree_to_vine(old_root, &len); return vine_to_subtree(new_root, len); } diff --git a/include/boost/intrusive/detail/workaround.hpp b/include/boost/intrusive/detail/workaround.hpp new file mode 100644 index 0000000..a4c0974 --- /dev/null +++ b/include/boost/intrusive/detail/workaround.hpp @@ -0,0 +1,30 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_WRKRND_HPP +#define BOOST_INTRUSIVE_DETAIL_WRKRND_HPP + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) +// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are +// passed on the command line, which in turn defines +// __GXX_EXPERIMENTAL_CXX0X__. Note: __GXX_EXPERIMENTAL_CPP0X__ is +// defined by some very early development versions of GCC 4.3; we will +// remove this part of the check in the near future. +# if defined(__GXX_EXPERIMENTAL_CPP0X__) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_INTRUSIVE_RVALUE_REFERENCE +# define BOOST_INTRUSIVE_VARIADIC_TEMPLATES +# endif +#endif + +#if defined(BOOST_INTRUSIVE_RVALUE_REFERENCE) && defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#define BOOST_INTRUSIVE_PERFECT_FORWARDING +#endif + +#endif //#ifndef BOOST_INTRUSIVE_DETAIL_WRKRND_HPP diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index 2d51e79..c0ef630 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -43,6 +43,50 @@ namespace intrusive { namespace detail { +struct hash_bool_flags +{ + static const std::size_t unique_keys_pos = 1u; + static const std::size_t constant_time_size_pos = 2u; + static const std::size_t power_2_buckets_pos = 4u; + static const std::size_t cache_begin_pos = 8u; + static const std::size_t compare_hash_pos = 16u; + static const std::size_t incremental_pos = 32u; +}; + +template + < class ValueTraits + , class Hash + , class Equal + , class SizeType + , class BucketTraits + , std::size_t BoolFlags + > +struct usetopt +{ + typedef ValueTraits value_traits; + typedef Hash hash; + typedef Equal equal; + typedef SizeType size_type; + typedef BucketTraits bucket_traits; + static const std::size_t bool_flags = BoolFlags; +}; + +template + < class UsetOpt + , std::size_t BoolMask + > +struct usetopt_mask +{ + typedef usetopt + type; +}; + template struct hash_reduced_slist_node_traits { @@ -109,7 +153,6 @@ struct get_slist_impl_from_supposed_value_traits >::type type; }; - template struct unordered_bucket_impl { @@ -173,11 +216,11 @@ struct optimize_multikey_is_true template struct bucket_plus_size : public detail::size_holder - < Config::constant_time_size + < 0 != (Config::bool_flags & hash_bool_flags::constant_time_size_pos) , typename Config::size_type> { typedef detail::size_holder - < Config::constant_time_size + < 0 != (Config::bool_flags & hash_bool_flags::constant_time_size_pos) , typename Config::size_type> size_traits; typedef typename Config::bucket_traits bucket_traits; @@ -188,11 +231,12 @@ struct bucket_plus_size }; template -struct bucket_hash_t : public detail::ebo_functor_holder +struct bucket_hash_t + : public detail::ebo_functor_holder { typedef typename Config::hash hasher; typedef detail::size_holder - < Config::constant_time_size + < 0 != (Config::bool_flags & hash_bool_flags::constant_time_size_pos) , typename Config::size_type> size_traits; typedef typename Config::bucket_traits bucket_traits; @@ -236,6 +280,7 @@ struct bucket_hash_equal_t template struct hashtable_data_t : public Config::value_traits { + static const std::size_t bool_flags = Config::bool_flags; typedef typename Config::value_traits value_traits; typedef typename Config::equal equal; typedef typename Config::hash hasher; @@ -243,9 +288,27 @@ struct hashtable_data_t : public Config::value_traits hashtable_data_t( const bucket_traits &b_traits, const hasher & h , const equal &e, const value_traits &val_traits) - : Config::value_traits(val_traits), bucket_hash_equal_(b_traits, h, e) + : Config::value_traits(val_traits), internal_(b_traits, h, e) {} - bucket_hash_equal_t bucket_hash_equal_; + typedef typename detail::usetopt_mask + < Config + , detail::hash_bool_flags::constant_time_size_pos + | detail::hash_bool_flags::incremental_pos + >::type masked_config_t; + struct internal + : public detail::size_holder + < 0 != (Config::bool_flags & hash_bool_flags::incremental_pos) + , typename Config::size_type> + { + internal(const bucket_traits &b_traits, const hasher & h, const equal &e) + : bucket_hash_equal_(b_traits, h, e) + {} + + bucket_hash_equal_t + < masked_config_t + , 0 != (bool_flags & hash_bool_flags::cache_begin_pos) + > bucket_hash_equal_; + } internal_; }; struct insert_commit_data_impl @@ -253,12 +316,154 @@ struct insert_commit_data_impl std::size_t hash; }; -template -struct internal_default_uset_hook +template +struct group_functions { - template static detail::one test(...); - template static detail::two test(typename U::default_uset_hook* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); + typedef NodeTraits node_traits; + typedef unordered_group_adapter group_traits; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::node node; + typedef typename reduced_slist_node_traits + ::type reduced_node_traits; + typedef typename reduced_node_traits::node_ptr slist_node_ptr; + typedef typename reduced_node_traits::node slist_node; + typedef circular_slist_algorithms group_algorithms; + + static node_ptr dcast_bucket_ptr(slist_node_ptr p) + { return node_ptr(&static_cast(*p)); } + + static slist_node_ptr priv_get_bucket_before_begin + (slist_node_ptr bucket_beg, slist_node_ptr bucket_end, node_ptr p) + { + //First find the last node of p's group. + //This requires checking the first node of the next group or + //the bucket node. + node_ptr prev_node = p; + node_ptr nxt(node_traits::get_next(p)); + while(!(bucket_beg <= nxt && nxt <= bucket_end) && + (group_traits::get_next(nxt) == prev_node)){ + prev_node = nxt; + nxt = node_traits::get_next(nxt); + } + + //If we've reached the bucket node just return it. + if(bucket_beg <= nxt && nxt <= bucket_end){ + return nxt; + } + + //Otherwise, iterate using group links until the bucket node + node_ptr first_node_of_group = nxt; + node_ptr last_node_group = group_traits::get_next(first_node_of_group); + slist_node_ptr possible_end = node_traits::get_next(last_node_group); + + while(!(bucket_beg <= possible_end && possible_end <= bucket_end)){ + first_node_of_group = dcast_bucket_ptr(possible_end); + last_node_group = group_traits::get_next(first_node_of_group); + possible_end = node_traits::get_next(last_node_group); + } + return possible_end; + } + + static node_ptr priv_get_prev_to_first_in_group(slist_node_ptr bucket_node, node_ptr first_in_group) + { + //Just iterate using group links and obtain the node + //before "first_in_group)" + node_ptr prev_node = 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 priv_get_first_in_group_of_last_in_group(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); + } + return possible_first; + } + + + static void priv_erase_from_group(slist_node_ptr end_ptr, 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 first_in_group = node_traits::get_next(prev_in_group_ptr) != to_erase_ptr; + + if(first_in_group && last_in_group){ + group_algorithms::init(to_erase_ptr); + } + else if(first_in_group){ + group_algorithms::unlink_after(nxt_ptr); + } + else if(last_in_group){ + node_ptr first_in_group = + priv_get_first_in_group_of_last_in_group(to_erase_ptr); + group_algorithms::unlink_after(first_in_group); + } + else{ + group_algorithms::unlink_after(nxt_ptr); + } + } + + static void priv_erase_from_group(slist_node_ptr, node_ptr, detail::false_) + {} + + static node_ptr priv_get_last_in_group(node_ptr first_in_group, detail::true_) + { return group_traits::get_next(first_in_group); } + + static node_ptr priv_get_last_in_group(node_ptr n, detail::false_) + { return n; } +}; + +template +class incremental_rehash_rollback +{ + private: + typedef BucketType bucket_type; + typedef SplitTraits split_traits; + + incremental_rehash_rollback(); + incremental_rehash_rollback & operator=(const incremental_rehash_rollback &); + incremental_rehash_rollback (const incremental_rehash_rollback &); + + public: + incremental_rehash_rollback + (bucket_type &source_bucket, bucket_type &destiny_bucket, split_traits &split_traits) + : source_bucket_(source_bucket), destiny_bucket_(destiny_bucket) + , split_traits_(split_traits), released_(false) + {} + + void release() + { released_ = true; } + + ~incremental_rehash_rollback() + { + if(!released_){ + //If an exception is thrown, just put all moved nodes back in the old bucket + //and move back the split mark. + destiny_bucket_.splice_after(destiny_bucket_.before_begin(), source_bucket_); + split_traits_.decrement(); + } + } + + private: + bucket_type &source_bucket_; + bucket_type &destiny_bucket_; + split_traits &split_traits_; + bool released_; }; } //namespace detail { @@ -304,50 +509,13 @@ struct unordered_default_bucket_traits typedef implementation_defined type; }; -template -struct get_default_uset_hook -{ - typedef typename T::default_uset_hook type; -}; - -template < class ValueTraits - , bool UniqueKeys - , class Hash - , class Equal - , class SizeType - , bool ConstantTimeSize - , class BucketTraits - , bool Power2Buckets - , bool CacheBegin - , bool CompareHash - > -struct usetopt -{ - typedef ValueTraits value_traits; - typedef Hash hash; - typedef Equal equal; - typedef SizeType size_type; - typedef BucketTraits bucket_traits; - static const bool constant_time_size = ConstantTimeSize; - static const bool power_2_buckets = Power2Buckets; - static const bool unique_keys = UniqueKeys; - static const bool cache_begin = CacheBegin; - static const bool compare_hash = CompareHash; -}; - struct default_bucket_traits; template struct uset_defaults : pack_options < none - , base_hook - < typename detail::eval_if_c - < detail::internal_default_uset_hook::value - , get_default_uset_hook - , detail::identity - >::type - > + , base_hook , constant_time_size , size_type , equal > @@ -356,6 +524,7 @@ struct uset_defaults , power_2_buckets , cache_begin , compare_hash + , incremental >::type {}; @@ -380,7 +549,7 @@ struct uset_defaults //! The container supports the following options: //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> -//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>. +//! \c bucket_traits<>, power_2_buckets<>, cache_begin<> and incremental<>. //! //! hashtable only provides forward iterators but it provides 4 iterator types: //! iterator and const_iterator to navigate through the whole container and @@ -397,13 +566,12 @@ struct uset_defaults //! //! Since no automatic rehashing is done, iterators are never invalidated when //! inserting or erasing elements. Iterators are only invalidated when rehashing. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif class hashtable_impl - : private detail::hashtable_data_t { public: typedef typename Config::value_traits value_traits; @@ -455,18 +623,22 @@ class hashtable_impl ::type const_node_ptr; typedef typename slist_impl::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; static const bool store_hash = detail::store_hash_is_true::value; - static const bool unique_keys = Config::unique_keys; + + static const bool unique_keys = 0 != (Config::bool_flags & detail::hash_bool_flags::unique_keys_pos); + static const bool constant_time_size = 0 != (Config::bool_flags & detail::hash_bool_flags::constant_time_size_pos); + static const bool cache_begin = 0 != (Config::bool_flags & detail::hash_bool_flags::cache_begin_pos); + static const bool compare_hash = 0 != (Config::bool_flags & detail::hash_bool_flags::compare_hash_pos); + static const bool incremental = 0 != (Config::bool_flags & detail::hash_bool_flags::incremental_pos); + static const bool power_2_buckets = incremental || (0 != (Config::bool_flags & detail::hash_bool_flags::power_2_buckets_pos)); + static const bool optimize_multikey = detail::optimize_multikey_is_true::value && !unique_keys; - static const bool power_2_buckets = Config::power_2_buckets; - static const bool cache_begin = Config::cache_begin; - static const bool compare_hash = Config::compare_hash; /// @cond private: + //Configuration error: compare_hash<> can't be specified without store_hash<> //See documentation for more explanations BOOST_STATIC_ASSERT((!compare_hash || store_hash)); @@ -483,7 +655,17 @@ class hashtable_impl typedef detail::bool_ cache_begin_t; typedef detail::bool_ power_2_buckets_t; typedef detail::size_holder size_traits; - typedef detail::hashtable_data_t base_type; + typedef detail::size_holder split_traits; + typedef detail::group_functions group_functions_t; + + static const std::size_t hashtable_data_bool_flags_mask = + ( detail::hash_bool_flags::cache_begin_pos + | detail::hash_bool_flags::constant_time_size_pos + | detail::hash_bool_flags::incremental_pos + ); + typedef typename detail::usetopt_mask + ::type masked_config_t; + detail::hashtable_data_t data_; template struct downcast_node_to_value @@ -555,16 +737,16 @@ class hashtable_impl /// @cond const real_value_traits &get_real_value_traits(detail::bool_) const - { return *this; } + { return this->data_; } const real_value_traits &get_real_value_traits(detail::bool_) const - { return base_type::get_value_traits(*this); } + { return data_.get_value_traits(*this); } real_value_traits &get_real_value_traits(detail::bool_) - { return *this; } + { return this->data_; } real_value_traits &get_real_value_traits(detail::bool_) - { return base_type::get_value_traits(*this); } + { return data_.get_value_traits(*this); } /// @endcond @@ -593,14 +775,16 @@ class hashtable_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : base_type(b_traits, hash_func, equal_func, v_traits) + : data_(b_traits, hash_func, equal_func, v_traits) { priv_initialize_buckets(); this->priv_size_traits().set_size(size_type(0)); - BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_buckets_len() != 0); + size_type bucket_size = this->priv_buckets_len(); + BOOST_INTRUSIVE_INVARIANT_ASSERT(bucket_size != 0); //Check power of two bucket array if the option is activated BOOST_INTRUSIVE_INVARIANT_ASSERT - (!power_2_buckets || (0 == (this->priv_buckets_len() & (this->priv_buckets_len()-1)))); + (!power_2_buckets || (0 == (bucket_size & (bucket_size-1)))); + priv_split_traits().set_size(bucket_size>>1); } //! Effects: Detaches all elements from this. The objects in the unordered_set @@ -620,10 +804,7 @@ class hashtable_impl //! //! Throws: Nothing. iterator begin() - { - size_type bucket_num; - return iterator(this->priv_begin(bucket_num), this); - } + { return iterator(this->priv_begin(), this); } //! Effects: Returns a const_iterator pointing to the beginning //! of the unordered_set. @@ -643,10 +824,7 @@ class hashtable_impl //! //! Throws: Nothing. const_iterator cbegin() const - { - size_type bucket_num; - return const_iterator(this->priv_begin(bucket_num), this); - } + { return const_iterator(this->priv_begin(), this); } //! Effects: Returns an iterator pointing to the end of the unordered_set. //! @@ -760,21 +938,32 @@ class hashtable_impl this->priv_size_traits().set_size(other.priv_size_traits().get_size()); other.priv_size_traits().set_size(backup); } + else 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); + } } - //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! 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. + //! and inserts them on *this. The hash function and the equality + //! predicate are copied from the source. //! - //! If cloner throws, all cloned elements are unlinked and disposed + //! 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 throws. Basic guarantee. + //! Throws: If cloner or hasher throw or hash or equality predicate copying + //! throws. Basic guarantee. template void clone_from(const hashtable_impl &src, Cloner cloner, Disposer disposer) { @@ -789,7 +978,7 @@ class hashtable_impl (!power_2_buckets || (0 == (dst_bucket_count & (dst_bucket_count-1)))); //If src bucket count is bigger or equal, structural copy is possible - if(src_bucket_count >= dst_bucket_count){ + if(!incremental && (src_bucket_count >= dst_bucket_count)){ //First clone the first ones const bucket_ptr src_buckets = src.priv_buckets(); const bucket_ptr dst_buckets = this->priv_buckets(); @@ -813,7 +1002,7 @@ class hashtable_impl ; constructed < src_bucket_count ; ++constructed){ bucket_type &dst_b = - dst_buckets[priv_hash_to_bucket(constructed, dst_bucket_count)]; + dst_buckets[priv_hash_to_bucket(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 @@ -822,14 +1011,29 @@ class hashtable_impl } } } + 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); priv_insertion_update_cache(0u); 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.begin()), e(src.end()); + 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, the hasher or comparison functor throw + //if cloner, hasher or comparison functor throw const_iterator b(src.begin()), e(src.end()); detail::exception_disposer rollback(*this, disposer); @@ -848,23 +1052,7 @@ class hashtable_impl siterator prev; siterator it = this->priv_find (value, this->priv_hasher(), this->priv_equal(), bucket_num, hash_value, prev); - bucket_type &b = this->priv_buckets()[bucket_num]; - bool found_equal = it != priv_invalid_local_it(); - node_ptr n = node_ptr(&priv_value_to_node(value)); - this->priv_store_hash(n, hash_value, store_hash_t()); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); - if(!found_equal){ - it = b.before_begin(); - } - if(optimize_multikey){ - node_ptr first_in_group = found_equal ? - dcast_bucket_ptr(it.pointed_node()) : node_ptr(0); - this->priv_insert_in_group(first_in_group, n, optimize_multikey_t()); - } - priv_insertion_update_cache(bucket_num); - this->priv_size_traits().increment(); - return iterator(b.insert_after(it, *n), this); + return priv_insert_equal_find(value, bucket_num, hash_value, it); } template @@ -968,7 +1156,7 @@ class hashtable_impl this->priv_find(key, hash_func, equal_func, bucket_num, commit_data.hash, prev); bool success = prev_pos == priv_invalid_local_it(); if(success){ - prev_pos = this->priv_buckets()[bucket_num].before_begin(); + prev_pos = prev; } return std::pair(iterator(prev_pos, this),success); } @@ -1177,8 +1365,8 @@ class hashtable_impl } else if(optimize_multikey){ siterator last = bucket_type::s_iterator_to - (*node_traits::get_next(priv_get_last_in_group - (dcast_bucket_ptr(it.pointed_node())))); + (*node_traits::get_next(group_functions_t::priv_get_last_in_group + (dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t()))); this->priv_erase_range_impl(bucket_num, prev, last, disposer, count); } else{ @@ -1188,7 +1376,7 @@ class hashtable_impl slist_node_ptr n(it.pointed_node()); const value_type &v = priv_value_from_slist_node(n); if(compare_hash){ - std::size_t vh = this->priv_stored_hash(v, store_hash_t()); + std::size_t vh = this->priv_stored_or_compute_hash(v, store_hash_t()); if(h != vh || !equal_func(key, v)){ break; } @@ -1676,9 +1864,15 @@ class hashtable_impl //! 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(). + //! 'new_bucket_traits' copy constructor should not throw. //! //! Effects: Updates the internal reference with the new bucket erases - //! the values from the old bucket and inserts then in the new one. + //! the values from the old bucket and inserts then in the new one. + //! Bucket traits hold by *this is assigned from new_bucket_traits. + //! If the container is configured as incremental<>, the split bucket is set + //! to the new bucket_len(). + //! + //! If store_hash option is true, this method does not use the hash function. //! //! Complexity: Average case linear in this->size(), worst case quadratic. //! @@ -1698,7 +1892,7 @@ class hashtable_impl 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 = (old_buckets_len > new_buckets_len) && + const bool fast_shrink = (!incremental) && (old_buckets_len > new_buckets_len) && (power_2_buckets ||(old_buckets_len % new_buckets_len) == 0); //If we are shrinking the same bucket array and it's //is a fast shrink, just rehash the last nodes @@ -1708,7 +1902,9 @@ class hashtable_impl new_first_bucket_num = priv_get_cache_bucket_num(); } - //Anti-exception stuff: they destroy the elements if something goes wrong + //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; NodeDisposer node_disp; detail::exception_array_disposer @@ -1733,12 +1929,13 @@ class hashtable_impl siterator i(old_bucket.begin()); for(;i != end; ++i){ const value_type &v = priv_value_from_slist_node(i.pointed_node()); - const std::size_t hash_value = this->priv_stored_hash(v, store_hash_t()); - const size_type new_n = priv_hash_to_bucket(hash_value, new_buckets_len); + const std::size_t hash_value = this->priv_stored_or_compute_hash(v, store_hash_t()); + const size_type new_n = priv_hash_to_bucket(hash_value, new_buckets_len, new_buckets_len); if(cache_begin && new_n < new_first_bucket_num) new_first_bucket_num = new_n; siterator last = bucket_type::s_iterator_to - (*priv_get_last_in_group(dcast_bucket_ptr(i.pointed_node()))); + (*group_functions_t::priv_get_last_in_group + (dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t())); if(same_buffer && new_n == n){ before_i = last; } @@ -1750,7 +1947,7 @@ class hashtable_impl } } else{ - const size_type new_n = priv_hash_to_bucket(n, new_buckets_len); + const size_type new_n = priv_hash_to_bucket(n, new_buckets_len, new_buckets_len); if(cache_begin && new_n < new_first_bucket_num) new_first_bucket_num = new_n; bucket_type &new_b = new_buckets[new_n]; @@ -1764,14 +1961,148 @@ class hashtable_impl } this->priv_size_traits().set_size(size_backup); + this->priv_split_traits().set_size(new_buckets_len); this->priv_real_bucket_traits() = new_bucket_traits; priv_initialize_cache(); priv_insertion_update_cache(new_first_bucket_num); - //priv_erasure_update_cache(); rollback1.release(); rollback2.release(); } + //! Requires: + //! + //! Effects: + //! + //! Complexity: + //! + //! Throws: + //! + //! Note: this method is only available if incremental option is activated. + bool incremental_rehash(bool grow = true) + { + //This function is only available for containers with incremental hashing + BOOST_STATIC_ASSERT(( incremental && power_2_buckets )); + size_type split_idx = priv_split_traits().get_size(); + size_type bucket_len = priv_buckets_len(); + + if(grow){ + //Test if the split variable can be changed + if(split_idx >= bucket_len) + return false; + + size_type bucket_len = priv_buckets_len(); + size_type bucket_to_rehash = split_idx - bucket_len/2; + bucket_type &old_bucket = this->priv_buckets()[bucket_to_rehash]; + siterator before_i(old_bucket.before_begin()); + siterator end(old_bucket.end()); + siterator i(old_bucket.begin()); + 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 + ( this->priv_buckets()[split_idx], old_bucket, priv_split_traits()); + for(;i != end; ++i){ + const value_type &v = 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 = priv_hash_to_bucket(hash_value); + siterator last = bucket_type::s_iterator_to + (*group_functions_t::priv_get_last_in_group + (dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t())); + if(new_n == bucket_to_rehash){ + before_i = last; + } + else{ + bucket_type &new_b = this->priv_buckets()[new_n]; + new_b.splice_after(new_b.before_begin(), old_bucket, before_i, last); + } + i = before_i; + } + rollback.release(); + priv_erasure_update_cache(); + return true; + } + else{ + //Test if the split variable can be changed + if(split_idx <= bucket_len/2) + return false; + const size_type target_bucket_num = split_idx - 1 - bucket_len/2; + bucket_type &target_bucket = this->priv_buckets()[target_bucket_num]; + bucket_type &source_bucket = this->priv_buckets()[split_idx-1]; + target_bucket.splice_after(target_bucket.cbefore_begin(), source_bucket); + priv_split_traits().decrement(); + priv_insertion_update_cache(target_bucket_num); + return true; + } + } + + //! Effects: If new_bucket_traits.bucket_count() is not + //! this->bucket_count()/2 or this->bucket_count()*2, or + //! this->split_bucket() != new_bucket_traits.bucket_count() returns false + //! and does nothing. + //! + //! Otherwise, copy assigns new_bucket_traits to the internal bucket_traits + //! and transfers all the objects from old buckets to the new ones. + //! + //! Complexity: Linear to size(). + //! + //! Throws: Nothing + //! + //! Note: this method is only available if incremental option is activated. + bool incremental_rehash(const bucket_traits &new_bucket_traits) + { + //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_buckets_len(); + if(new_bucket_traits_size/2 != cur_bucket_traits && new_bucket_traits_size != cur_bucket_traits/2){ + return false; + } + + const size_type split_idx = this->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)) + return false; + } + + const size_type ini_n = priv_get_cache_bucket_num(); + const bucket_ptr old_buckets = this->priv_buckets(); + this->priv_real_bucket_traits() = new_bucket_traits; + if(new_bucket_traits.bucket_begin() != old_buckets){ + for(size_type n = ini_n; n < split_idx; ++n){ + bucket_type &new_bucket = new_bucket_traits.bucket_begin()[n]; + bucket_type &old_bucket = old_buckets[n]; + new_bucket.splice_after(new_bucket.cbefore_begin(), old_bucket); + } + //Put cache to safe position + priv_initialize_cache(); + priv_insertion_update_cache(ini_n); + } + return true; + } + + //! Requires: + //! + //! Effects: + //! + //! Complexity: + //! + //! 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(); + } + //! 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 @@ -1812,29 +2143,30 @@ class hashtable_impl /// @cond private: + std::size_t priv_hash_to_bucket(std::size_t hash_value) const - { return priv_hash_to_bucket(hash_value, power_2_buckets_t()); } + { return priv_hash_to_bucket(hash_value, this->priv_real_bucket_traits().bucket_count(), priv_split_traits().get_size()); } - std::size_t priv_hash_to_bucket(std::size_t hash_value, detail::bool_) const - { return hash_value % this->priv_real_bucket_traits().bucket_count(); } + std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, std::size_t split) const + { + std::size_t bucket_number = priv_hash_to_bucket_impl(hash_value, bucket_len, power_2_buckets_t()); + if(incremental) + if(bucket_number >= split) + bucket_number -= bucket_len/2; + return bucket_number; + } - std::size_t priv_hash_to_bucket(std::size_t hash_value, detail::bool_) const - { return hash_value & (this->priv_real_bucket_traits().bucket_count() - 1); } - - std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len) const - { return priv_hash_to_bucket(hash_value, bucket_len, power_2_buckets_t()); } - - std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, detail::bool_) const + std::size_t priv_hash_to_bucket_impl(std::size_t hash_value, std::size_t bucket_len, detail::bool_) const { return hash_value % bucket_len; } - std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, detail::bool_) const + std::size_t priv_hash_to_bucket_impl(std::size_t hash_value, std::size_t bucket_len, detail::bool_) const { return hash_value & (bucket_len - 1); } const key_equal &priv_equal() const - { return static_cast(this->bucket_hash_equal_.get()); } + { return static_cast(this->data_.internal_.bucket_hash_equal_.get()); } key_equal &priv_equal() - { return static_cast(this->bucket_hash_equal_.get()); } + { return static_cast(this->data_.internal_.bucket_hash_equal_.get()); } value_type &priv_value_from_slist_node(slist_node_ptr n) { return *this->get_real_value_traits().to_value_ptr(dcast_bucket_ptr(n)); } @@ -1843,16 +2175,16 @@ class hashtable_impl { return *this->get_real_value_traits().to_value_ptr(dcast_bucket_ptr(n)); } const real_bucket_traits &priv_real_bucket_traits(detail::bool_) const - { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } + { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } const real_bucket_traits &priv_real_bucket_traits(detail::bool_) const - { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); } + { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); } real_bucket_traits &priv_real_bucket_traits(detail::bool_) - { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } + { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } real_bucket_traits &priv_real_bucket_traits(detail::bool_) - { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); } + { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); } const real_bucket_traits &priv_real_bucket_traits() const { return this->priv_real_bucket_traits(detail::bool_()); } @@ -1861,10 +2193,10 @@ class hashtable_impl { return this->priv_real_bucket_traits(detail::bool_()); } const hasher &priv_hasher() const - { return static_cast(this->bucket_hash_equal_.bucket_hash.get()); } + { return static_cast(this->data_.internal_.bucket_hash_equal_.bucket_hash.get()); } hasher &priv_hasher() - { return static_cast(this->bucket_hash_equal_.bucket_hash.get()); } + { return static_cast(this->data_.internal_.bucket_hash_equal_.bucket_hash.get()); } bucket_ptr priv_buckets() const { return this->priv_real_bucket_traits().bucket_begin(); } @@ -1882,10 +2214,16 @@ class hashtable_impl { return *this->get_real_value_traits().to_node_ptr(v); } size_traits &priv_size_traits() - { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; } + { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_; } const size_traits &priv_size_traits() const - { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; } + { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_; } + + split_traits &priv_split_traits() + { return this->data_.internal_; } + + const split_traits &priv_split_traits() const + { return this->data_.internal_; } template void priv_erase_range_impl @@ -1903,7 +2241,7 @@ class hashtable_impl ++to_erase; slist_node_ptr end_ptr = end.pointed_node(); while(to_erase != end){ - priv_erase_from_group(end_ptr, dcast_bucket_ptr(to_erase.pointed_node()), optimize_multikey_t()); + group_functions_t::priv_erase_from_group(end_ptr, 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; } @@ -1955,10 +2293,10 @@ class hashtable_impl static node_ptr dcast_bucket_ptr(typename slist_impl::node_ptr p) { return node_ptr(&static_cast(*p)); } - std::size_t priv_stored_hash(const value_type &v, detail::true_) const + std::size_t priv_stored_or_compute_hash(const value_type &v, detail::true_) const { return node_traits::get_hash(this->get_real_value_traits().to_node_ptr(v)); } - std::size_t priv_stored_hash(const value_type &v, detail::false_) const + std::size_t priv_stored_or_compute_hash(const value_type &v, detail::false_) const { return priv_hasher()(v); } std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) const @@ -2002,10 +2340,10 @@ class hashtable_impl std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_) { return priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); } - std::size_t priv_get_bucket_num_no_hash_store( siterator it, detail::true_) + std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::true_) { bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1); - slist_node_ptr bb = priv_get_bucket_before_begin + slist_node_ptr bb = group_functions_t::priv_get_bucket_before_begin ( f->end().pointed_node() , l->end().pointed_node() , dcast_bucket_ptr(it.pointed_node())); @@ -2016,7 +2354,7 @@ class hashtable_impl return static_cast(&b - &*f); } - std::size_t priv_get_bucket_num_no_hash_store( siterator it, detail::false_) + std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::false_) { bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1); slist_node_ptr first_ptr(f->cend().pointed_node()) @@ -2035,34 +2373,6 @@ class hashtable_impl return static_cast(&b - &*f); } - void priv_erase_from_group(slist_node_ptr end_ptr, 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 first_in_group = node_traits::get_next(prev_in_group_ptr) != to_erase_ptr; - - if(first_in_group && last_in_group){ - group_algorithms::init(to_erase_ptr); - } - else if(first_in_group){ - group_algorithms::unlink_after(nxt_ptr); - } - else if(last_in_group){ - node_ptr first_in_group = //possible_first_in_group ? possible_first_in_group : - priv_get_first_in_group_of_last_in_group(to_erase_ptr); - group_algorithms::unlink_after(first_in_group); - //possible_first_in_group = 0; - } - else{ - group_algorithms::unlink_after(nxt_ptr); - } - } - - void priv_erase_from_group(slist_node_ptr, node_ptr, detail::false_) - {} - void priv_init_group(slist_node_ptr n, detail::true_) { group_algorithms::init(dcast_bucket_ptr(n)); } @@ -2083,79 +2393,9 @@ class hashtable_impl } } - static slist_node_ptr priv_get_bucket_before_begin - (slist_node_ptr bucket_beg, slist_node_ptr bucket_end, node_ptr p) - { - //First find the last node of p's group. - //This requires checking the first node of the next group or - //the bucket node. - node_ptr prev_node = p; - node_ptr nxt(node_traits::get_next(p)); - while(!(bucket_beg <= nxt && nxt <= bucket_end) && - (group_traits::get_next(nxt) == prev_node)){ - prev_node = nxt; - nxt = node_traits::get_next(nxt); - } - - //If we've reached the bucket node just return it. - if(bucket_beg <= nxt && nxt <= bucket_end){ - return nxt; - } - - //Otherwise, iterate using group links until the bucket node - node_ptr first_node_of_group = nxt; - node_ptr last_node_group = group_traits::get_next(first_node_of_group); - slist_node_ptr possible_end = node_traits::get_next(last_node_group); - - while(!(bucket_beg <= possible_end && possible_end <= bucket_end)){ - first_node_of_group = dcast_bucket_ptr(possible_end); - last_node_group = group_traits::get_next(first_node_of_group); - possible_end = node_traits::get_next(last_node_group); - } - return possible_end; - } - - static node_ptr priv_get_prev_to_first_in_group(slist_node_ptr bucket_node, node_ptr first_in_group) - { - //Just iterate using group links and obtain the node - //before "first_in_group)" - node_ptr prev_node = 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 priv_get_first_in_group_of_last_in_group(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); - } - return possible_first; - } - void priv_insert_in_group(node_ptr, node_ptr, detail::false_) {} - static node_ptr priv_get_last_in_group(node_ptr first_in_group) - { return priv_get_last_in_group(first_in_group, optimize_multikey_t()); } - - static node_ptr priv_get_last_in_group(node_ptr first_in_group, detail::true_) - { return group_traits::get_next(first_in_group); } - - static node_ptr priv_get_last_in_group(node_ptr n, detail::false_) - { return n; } - siterator priv_get_previous (bucket_type &b, siterator i) { return priv_get_previous(b, i, optimize_multikey_t()); } @@ -2166,9 +2406,8 @@ class hashtable_impl node_ptr elem(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; - typename bucket_type::node &n = first_in_group - ? *priv_get_prev_to_first_in_group(b.end().pointed_node(), elem) + ? *group_functions_t::priv_get_prev_to_first_in_group(b.end().pointed_node(), elem) : *group_traits::get_next(elem) ; return bucket_type::s_iterator_to(n); @@ -2234,15 +2473,15 @@ class hashtable_impl ].before_begin().pointed_node(); } else{ - bucket_node = priv_get_bucket_before_begin + bucket_node = group_functions_t::priv_get_bucket_before_begin (first_end_ptr, last_end_ptr, start_pos); } prev = bucket_type::s_iterator_to - (*priv_get_prev_to_first_in_group(bucket_node, elem)); + (*group_functions_t::priv_get_prev_to_first_in_group(bucket_node, elem)); } else{ if(last_in_group){ - nxt_in_group = priv_get_first_in_group_of_last_in_group(elem); + nxt_in_group = group_functions_t::priv_get_first_in_group_of_last_in_group(elem); } else{ nxt_in_group = node_traits::get_next(elem); @@ -2283,32 +2522,29 @@ class hashtable_impl siterator priv_invalid_local_it() const { return priv_invalid_bucket()->end(); } - siterator priv_begin(size_type &bucket_num) const - { return priv_begin(bucket_num, cache_begin_t()); } + siterator priv_begin() const + { return priv_begin(cache_begin_t()); } - siterator priv_begin(size_type &bucket_num, detail::bool_) const + siterator priv_begin(detail::bool_) const { size_type n = 0; size_type buckets_len = this->priv_buckets_len(); for (n = 0; n < buckets_len; ++n){ bucket_type &b = this->priv_buckets()[n]; if(!b.empty()){ - bucket_num = n; return b.begin(); } } - bucket_num = n; return priv_invalid_local_it(); } - siterator priv_begin(size_type &bucket_num, detail::bool_) const + siterator priv_begin(detail::bool_) const { - bucket_num = this->bucket_hash_equal_.cached_begin_ - this->priv_buckets(); - if(this->bucket_hash_equal_.cached_begin_ == priv_invalid_bucket()){ + if(this->data_.internal_.bucket_hash_equal_.cached_begin_ == priv_invalid_bucket()){ return priv_invalid_local_it(); } else{ - return this->bucket_hash_equal_.cached_begin_->begin(); + return this->data_.internal_.bucket_hash_equal_.cached_begin_->begin(); } } @@ -2316,7 +2552,7 @@ class hashtable_impl { priv_initialize_cache(cache_begin_t()); } void priv_initialize_cache(detail::bool_) - { this->bucket_hash_equal_.cached_begin_ = priv_invalid_bucket(); } + { this->data_.internal_.bucket_hash_equal_.cached_begin_ = priv_invalid_bucket(); } void priv_initialize_cache(detail::bool_) {} @@ -2327,8 +2563,8 @@ class hashtable_impl void priv_insertion_update_cache(size_type insertion_bucket, detail::bool_) { bucket_ptr p = priv_buckets() + insertion_bucket; - if(p < this->bucket_hash_equal_.cached_begin_){ - this->bucket_hash_equal_.cached_begin_ = p; + if(p < this->data_.internal_.bucket_hash_equal_.cached_begin_){ + this->data_.internal_.bucket_hash_equal_.cached_begin_ = p; } } @@ -2361,11 +2597,11 @@ class hashtable_impl priv_initialize_cache(); } else{ - size_type current_n = this->bucket_hash_equal_.cached_begin_ - priv_buckets(); + size_type current_n = this->data_.internal_.bucket_hash_equal_.cached_begin_ - priv_buckets(); for( const size_type num_buckets = this->priv_buckets_len() ; current_n < num_buckets - ; ++current_n, ++this->bucket_hash_equal_.cached_begin_){ - if(!this->bucket_hash_equal_.cached_begin_->empty()){ + ; ++current_n, ++this->data_.internal_.bucket_hash_equal_.cached_begin_){ + if(!this->data_.internal_.bucket_hash_equal_.cached_begin_->empty()){ return; } } @@ -2378,8 +2614,8 @@ class hashtable_impl void priv_swap_cache(detail::bool_, hashtable_impl &other) { - std::swap( this->bucket_hash_equal_.cached_begin_ - , other.bucket_hash_equal_.cached_begin_); + std::swap( this->data_.internal_.bucket_hash_equal_.cached_begin_ + , other.data_.internal_.bucket_hash_equal_.cached_begin_); } void priv_swap_cache(detail::bool_, hashtable_impl &) @@ -2389,7 +2625,7 @@ class hashtable_impl { return priv_get_cache(cache_begin_t()); } bucket_ptr priv_get_cache(detail::bool_) - { return this->bucket_hash_equal_.cached_begin_; } + { return this->data_.internal_.bucket_hash_equal_.cached_begin_; } bucket_ptr priv_get_cache(detail::bool_) { return this->priv_buckets(); } @@ -2398,7 +2634,7 @@ class hashtable_impl { priv_set_cache(p, cache_begin_t()); } void priv_set_cache(bucket_ptr p, detail::bool_) - { this->bucket_hash_equal_.cached_begin_ = p; } + { this->data_.internal_.bucket_hash_equal_.cached_begin_ = p; } void priv_set_cache(bucket_ptr, detail::bool_) {} @@ -2407,7 +2643,7 @@ class hashtable_impl { return priv_get_cache_bucket_num(cache_begin_t()); } size_type priv_get_cache_bucket_num(detail::bool_) - { return this->bucket_hash_equal_.cached_begin_ - this->priv_buckets(); } + { return this->data_.internal_.bucket_hash_equal_.cached_begin_ - this->priv_buckets(); } size_type priv_get_cache_bucket_num(detail::bool_) { return 0u; } @@ -2420,10 +2656,7 @@ class hashtable_impl } void priv_initialize_buckets() - { - this->priv_clear_buckets - ( priv_buckets(), this->priv_buckets_len()); - } + { this->priv_clear_buckets(priv_buckets(), this->priv_buckets_len()); } void priv_clear_buckets(bucket_ptr buckets_ptr, size_type buckets_len) { @@ -2444,21 +2677,28 @@ class hashtable_impl ( const KeyType &key, KeyHasher hash_func , KeyValueEqual equal_func, size_type &bucket_number, std::size_t &h, siterator &previt) const { - bucket_number = priv_hash_to_bucket((h = hash_func(key))); + h = hash_func(key); + return priv_find_with_hash(key, equal_func, bucket_number, h, previt); + } + template + siterator priv_find_with_hash + ( const KeyType &key, KeyValueEqual equal_func, size_type &bucket_number, const std::size_t h, siterator &previt) const + { + bucket_number = priv_hash_to_bucket(h); + bucket_type &b = this->priv_buckets()[bucket_number]; + previt = b.before_begin(); if(constant_time_size && this->empty()){ return priv_invalid_local_it(); } - bucket_type &b = this->priv_buckets()[bucket_number]; - previt = b.before_begin(); siterator it = previt; ++it; while(it != b.end()){ const value_type &v = priv_value_from_slist_node(it.pointed_node()); if(compare_hash){ - std::size_t vh = this->priv_stored_hash(v, store_hash_t()); + std::size_t vh = this->priv_stored_or_compute_hash(v, store_hash_t()); if(h == vh && equal_func(key, v)){ return it; } @@ -2468,7 +2708,8 @@ class hashtable_impl } if(optimize_multikey){ previt = bucket_type::s_iterator_to - (*priv_get_last_in_group(dcast_bucket_ptr(it.pointed_node()))); + (*group_functions_t::priv_get_last_in_group + (dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t())); it = previt; } else{ @@ -2476,10 +2717,45 @@ class hashtable_impl } ++it; } - + previt = b.before_begin(); return 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 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_buckets()[bucket_num]; + bool found_equal = it != priv_invalid_local_it(); + if(!found_equal){ + it = b.before_begin(); + } + //Now store hash if needed + node_ptr n = node_ptr(&priv_value_to_node(value)); + this->priv_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)); + //Shorcut for optimize_multikey cases + if(optimize_multikey){ + node_ptr first_in_group = found_equal ? + dcast_bucket_ptr(it.pointed_node()) : node_ptr(0); + this->priv_insert_in_group(first_in_group, n, optimize_multikey_t()); + } + //Update cache and increment size if needed + 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); + } + template std::pair priv_equal_range ( const KeyType &key @@ -2506,8 +2782,8 @@ class hashtable_impl siterator it = to_return.first; if(optimize_multikey){ to_return.second = bucket_type::s_iterator_to - (*node_traits::get_next(priv_get_last_in_group - (dcast_bucket_ptr(it.pointed_node())))); + (*node_traits::get_next(group_functions_t::priv_get_last_in_group + (dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t()))); count = std::distance(it, to_return.second); if(to_return.second != b.end()){ bucket_number_second = bucket_number_first; @@ -2520,7 +2796,7 @@ class hashtable_impl while(it != b.end()){ const value_type &v = priv_value_from_slist_node(it.pointed_node()); if(compare_hash){ - std::size_t hv = this->priv_stored_hash(v, store_hash_t()); + 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; @@ -2556,18 +2832,28 @@ class hashtable_impl }; /// @cond +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , bool UniqueKeys , class O1 = none, class O2 = none , class O3 = none, class O4 = none , class O5 = none, class O6 = none , class O7 = none, class O8 = none - , class O9 = none + , class O9 = none, class O10= none > +#else +template +#endif struct make_hashtable_opt { typedef typename pack_options - < uset_defaults, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type packed_options; + < uset_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4, O5, O6, O7, O8, O9, O10 + #else + Options... + #endif + >::type packed_options; //Real value traits must be calculated from options typedef typename detail::get_value_traits @@ -2598,31 +2884,32 @@ struct make_hashtable_opt , specified_bucket_traits >::type real_bucket_traits; - typedef usetopt + typedef detail::usetopt < value_traits - , UniqueKeys , typename packed_options::hash , typename packed_options::equal , typename packed_options::size_type - , packed_options::constant_time_size , real_bucket_traits - , packed_options::power_2_buckets - , packed_options::cache_begin - , packed_options::compare_hash + , (std::size_t(UniqueKeys)*detail::hash_bool_flags::unique_keys_pos) + | (std::size_t(packed_options::constant_time_size)*detail::hash_bool_flags::constant_time_size_pos) + | (std::size_t(packed_options::power_2_buckets)*detail::hash_bool_flags::power_2_buckets_pos) + | (std::size_t(packed_options::cache_begin)*detail::hash_bool_flags::cache_begin_pos) + | (std::size_t(packed_options::compare_hash)*detail::hash_bool_flags::compare_hash_pos) + | (std::size_t(packed_options::incremental)*detail::hash_bool_flags::incremental_pos) > type; }; /// @endcond //! Helper metafunction to define a \c hashtable that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif struct make_hashtable @@ -2630,20 +2917,42 @@ struct make_hashtable /// @cond typedef hashtable_impl < typename make_hashtable_opt - ::type + ::type > implementation_defined; /// @endcond typedef implementation_defined type; }; -#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED -template +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + +#if defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif class hashtable - : public make_hashtable::type + : public make_hashtable::type { - typedef typename make_hashtable - ::type Base; + typedef typename make_hashtable::type Base; public: typedef typename Base::value_traits value_traits; @@ -2669,7 +2978,6 @@ class hashtable #endif - } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/intrusive_fwd.hpp b/include/boost/intrusive/intrusive_fwd.hpp index 0642fff..38a622f 100644 --- a/include/boost/intrusive/intrusive_fwd.hpp +++ b/include/boost/intrusive/intrusive_fwd.hpp @@ -15,26 +15,12 @@ #include #include +#include /// @cond -//std predeclarations -namespace std{ - -template -struct equal_to; - -template -struct less; - -} //namespace std{ - namespace boost { -//Hash predeclaration -template -struct hash; - namespace intrusive { struct none; @@ -64,6 +50,7 @@ class rbtree_algorithms; //////////////////////////// //slist +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -72,46 +59,70 @@ template , class O4 = none , class O5 = none > +#else +template +#endif class slist; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class slist_base_hook; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class slist_member_hook; //list +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class list; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class list_base_hook; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class list_member_hook; //rbtree/set/multiset +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -119,8 +130,12 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class rbtree; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -128,8 +143,12 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class set; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -137,25 +156,37 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class multiset; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none , class O4 = none > +#else +template +#endif class set_base_hook; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none , class O4 = none > +#else +template +#endif class set_member_hook; //splaytree/splay_set/splay_multiset +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -163,8 +194,12 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class splaytree; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -172,8 +207,12 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class splay_set; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -181,23 +220,35 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class splay_multiset; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class splay_set_base_hook; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class splay_set_member_hook; //avltree/avl_set/avl_multiset +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -205,8 +256,12 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class avltree; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -214,8 +269,12 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class avl_set; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -223,25 +282,37 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class avl_multiset; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none , class O4 = none > +#else +template +#endif class avl_set_base_hook; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none , class O4 = none > +#else +template +#endif class avl_set_member_hook; //sgtree/sg_set/sg_multiset +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -249,8 +320,12 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class sgtree; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -258,8 +333,12 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class sg_set; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -267,23 +346,36 @@ template , class O3 = none , class O4 = none > +#else +template +#endif class sg_multiset; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class bs_set_base_hook; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class bs_set_member_hook; //hashtable/unordered_set/unordered_multiset + +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -295,9 +387,14 @@ template , class O7 = none , class O8 = none , class O9 = none + , class O10 = none > +#else +template +#endif class hashtable; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -309,9 +406,14 @@ template , class O7 = none , class O8 = none , class O9 = none + , class O10 = none > +#else +template +#endif class unordered_set; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class T , class O1 = none @@ -323,37 +425,57 @@ template , class O7 = none , class O8 = none , class O9 = none + , class O10 = none > +#else +template +#endif class unordered_multiset; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none , class O4 = none > +#else +template +#endif class unordered_set_base_hook; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none , class O4 = none > +#else +template +#endif class unordered_set_member_hook; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class any_base_hook; +#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES template < class O1 = none , class O2 = none , class O3 = none > +#else +template +#endif class any_member_hook; } //namespace intrusive { diff --git a/include/boost/intrusive/linear_slist_algorithms.hpp b/include/boost/intrusive/linear_slist_algorithms.hpp index b52a7ba..a181a51 100644 --- a/include/boost/intrusive/linear_slist_algorithms.hpp +++ b/include/boost/intrusive/linear_slist_algorithms.hpp @@ -58,7 +58,7 @@ class linear_slist_algorithms typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef NodeTraits node_traits; - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: Constructs an non-used list element, putting the next //! pointer to null: @@ -127,7 +127,7 @@ class linear_slist_algorithms //! Throws: Nothing. static void transfer_after(node_ptr p, node_ptr b, node_ptr e); - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: Constructs an empty list, making this_node the only //! node of the circular list: diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index 2b28923..c6d94f2 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -35,20 +35,6 @@ namespace intrusive { /// @cond -template -struct internal_default_list_hook -{ - template static detail::one test(...); - template static detail::two test(typename U::default_list_hook* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); -}; - -template -struct get_default_list_hook -{ - typedef typename T::default_list_hook type; -}; - template struct listopt { @@ -57,17 +43,12 @@ struct listopt static const bool constant_time_size = ConstantTimeSize; }; + template struct list_defaults : pack_options < none - , base_hook - < typename detail::eval_if_c - < internal_default_list_hook::value - , get_default_list_hook - , detail::identity - >::type - > + , base_hook , constant_time_size , size_type >::type @@ -85,7 +66,7 @@ struct list_defaults //! The container supports the following options: //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<> and \c size_type<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -225,7 +206,7 @@ class list_impl { this->priv_size_traits().set_size(size_type(0)); node_algorithms::init_header(this->get_root_node()); - this->insert(this->end(), b, e); + this->insert(this->cend(), b, e); } //! Effects: If it's not a safe-mode or an auto-unlink value_type @@ -583,7 +564,7 @@ class list_impl //! //! Note: Invalidates the iterators (but not the references) to the //! erased element. - iterator erase(iterator i) + iterator erase(const_iterator i) { return this->erase_and_dispose(i, detail::null_disposer()); } //! Requires: b and e must be valid iterators to elements in *this. @@ -601,14 +582,14 @@ class list_impl //! //! Note: Invalidates the iterators (but not the references) to the //! erased elements. - iterator erase(iterator b, iterator e) + iterator erase(const_iterator b, const_iterator e) { if(safemode_or_autounlink || constant_time_size){ return this->erase_and_dispose(b, e, detail::null_disposer()); } else{ node_algorithms::unlink(b.pointed_node(), e.pointed_node()); - return e; + return e.unconst(); } } @@ -628,7 +609,7 @@ class list_impl //! //! Note: Invalidates the iterators (but not the references) to the //! erased elements. - iterator erase(iterator b, iterator e, difference_type n) + iterator erase(const_iterator b, const_iterator e, difference_type n) { BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(b, e) == difference_type(n)); if(safemode_or_autounlink || constant_time_size){ @@ -639,7 +620,7 @@ class list_impl this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n); } node_algorithms::unlink(b.pointed_node(), e.pointed_node()); - return e; + return e.unconst(); } } @@ -658,7 +639,7 @@ class list_impl //! //! Note: Invalidates the iterators to the erased element. template - iterator erase_and_dispose(iterator i, Disposer disposer) + iterator erase_and_dispose(const_iterator i, Disposer disposer) { node_ptr to_erase(i.pointed_node()); ++i; @@ -667,7 +648,7 @@ class list_impl if(safemode_or_autounlink) node_algorithms::init(to_erase); disposer(this->get_real_value_traits().to_value_ptr(to_erase)); - return i; + return i.unconst(); } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -685,7 +666,7 @@ class list_impl //! //! Note: Invalidates the iterators to the erased elements. template - iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) { node_ptr bp(b.pointed_node()), ep(e.pointed_node()); node_algorithms::unlink(bp, ep); @@ -697,7 +678,7 @@ class list_impl disposer(get_real_value_traits().to_value_ptr(to_erase)); this->priv_size_traits().decrement(); } - return e; + return e.unconst(); } //! Effects: Erases all the elements of the container. @@ -734,7 +715,7 @@ class list_impl template void clear_and_dispose(Disposer disposer) { - iterator it(this->begin()), itend(this->end()); + const_iterator it(this->begin()), itend(this->end()); while(it != itend){ node_ptr to_erase(it.pointed_node()); ++it; @@ -747,6 +728,7 @@ class list_impl } //! 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 @@ -783,7 +765,7 @@ class list_impl //! Complexity: Constant time. No copy constructors are called. //! //! Note: Does not affect the validity of iterators and references. - iterator insert(iterator p, reference value) + iterator insert(const_iterator p, reference value) { node_ptr to_insert = this->get_real_value_traits().to_node_ptr(value); if(safemode_or_autounlink) @@ -805,7 +787,7 @@ class list_impl //! //! Note: Does not affect the validity of iterators and references. template - void insert(iterator p, Iterator b, Iterator e) + void insert(const_iterator p, Iterator b, Iterator e) { for (; b != e; ++b) this->insert(p, *b); @@ -830,7 +812,7 @@ class list_impl void assign(Iterator b, Iterator e) { this->clear(); - this->insert(this->end(), b, e); + this->insert(this->cend(), b, e); } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -853,7 +835,7 @@ class list_impl void dispose_and_assign(Disposer disposer, Iterator b, Iterator e) { this->clear_and_dispose(disposer); - this->insert(this->end(), b, e); + this->insert(this->cend(), b, e); } //! Requires: p must be a valid iterator of *this. @@ -867,7 +849,7 @@ class list_impl //! //! Note: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice(iterator p, list_impl& x) + void splice(const_iterator p, list_impl& x) { if(!x.empty()){ size_traits &thist = this->priv_size_traits(); @@ -892,7 +874,7 @@ class list_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(iterator p, list_impl&x, iterator new_ele) + void splice(const_iterator p, list_impl&x, const_iterator new_ele) { node_algorithms::transfer(p.pointed_node(), new_ele.pointed_node()); x.priv_size_traits().decrement(); @@ -912,7 +894,7 @@ class list_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(iterator p, list_impl&x, iterator start, iterator end) + void splice(const_iterator p, list_impl&x, const_iterator start, const_iterator end) { if(constant_time_size) this->splice(p, x, start, end, std::distance(start, end)); @@ -933,7 +915,7 @@ class list_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(iterator p, list_impl&x, iterator start, iterator end, difference_type n) + void splice(const_iterator p, list_impl&x, const_iterator start, const_iterator end, difference_type n) { if(n){ if(constant_time_size){ @@ -988,7 +970,7 @@ class list_impl list_impl counter[64]; int fill = 0; while(!this->empty()){ - carry.splice(carry.begin(), *this, this->begin()); + carry.splice(carry.cbegin(), *this, this->cbegin()); int i = 0; while(i < fill && !counter[i].empty()) { carry.merge(counter[i++], p); @@ -1034,13 +1016,13 @@ class list_impl template void merge(list_impl& x, Predicate p) { - iterator e(this->end()); - iterator bx(x.begin()); - iterator ex(x.end()); + const_iterator e(this->end()); + const_iterator bx(x.begin()); + const_iterator ex(x.end()); - for (iterator b = this->begin(); b != e; ++b) { + for (const_iterator b = this->cbegin(); b != e; ++b) { size_type n(0); - iterator ix(bx); + const_iterator ix(bx); while(ix != ex && p(*ix, *b)){ ++ix; ++n; } @@ -1116,8 +1098,8 @@ class list_impl template void remove_and_dispose_if(Pred pred, Disposer disposer) { - iterator cur(this->begin()); - iterator last(this->end()); + const_iterator cur(this->cbegin()); + const_iterator last(this->cend()); while(cur != last) { if(pred(*cur)){ cur = this->erase_and_dispose(cur, disposer); @@ -1185,11 +1167,11 @@ class list_impl template void unique_and_dispose(BinaryPredicate pred, Disposer disposer) { - iterator itend(this->end()); - iterator cur(this->begin()); + const_iterator itend(this->cend()); + const_iterator cur(this->cbegin()); if(cur != itend){ - iterator after(cur); + const_iterator after(cur); ++after; while(after != itend){ if(pred(*cur, *after)){ @@ -1284,26 +1266,26 @@ class list_impl /// @endcond }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator< -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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 std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif bool operator== -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const list_impl &x, const list_impl &y) #else (const list_impl &x, const list_impl &y) @@ -1336,65 +1318,65 @@ bool operator== } } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (list_impl &x, list_impl &y) #else (list_impl &x, list_impl &y) @@ -1403,7 +1385,7 @@ inline void swap //! Helper metafunction to define a \c list that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -1412,7 +1394,14 @@ struct make_list { /// @cond typedef typename pack_options - < list_defaults, O1, O2, O3>::type packed_options; + < list_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type packed_options; + typedef typename detail::get_value_traits ::type value_traits; @@ -1430,12 +1419,29 @@ struct make_list #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class list - : public make_list::type + : public make_list::type { typedef typename make_list - ::type Base; + ::type Base; typedef typename Base::real_value_traits real_value_traits; //Assert if passed value traits are compatible with the type BOOST_STATIC_ASSERT((detail::is_same::value)); diff --git a/include/boost/intrusive/list_hook.hpp b/include/boost/intrusive/list_hook.hpp index 1133b4b..86745cf 100644 --- a/include/boost/intrusive/list_hook.hpp +++ b/include/boost/intrusive/list_hook.hpp @@ -35,7 +35,7 @@ struct get_list_node_algo //! Helper metafunction to define a \c \c list_base_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -44,7 +44,13 @@ struct make_list_base_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_list_node_algo @@ -72,15 +78,21 @@ struct make_list_base_hook //! //! \c void_pointer<> is the pointer type that will be used internally in the hook //! and the the container configured to use this hook. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class list_base_hook - : public make_list_base_hook::type + : public make_list_base_hook + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -149,7 +161,7 @@ class list_base_hook //! Helper metafunction to define a \c \c list_member_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -158,7 +170,13 @@ struct make_list_member_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_list_node_algo @@ -181,15 +199,21 @@ struct make_list_member_hook //! //! \c void_pointer<> is the pointer type that will be used internally in the hook //! and the the container configured to use this hook. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class list_member_hook - : public make_list_member_hook::type + : public make_list_member_hook + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + + #else + + #endif + ::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index ab9535a..b937698 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -31,6 +31,26 @@ struct member_tag; namespace detail{ +struct default_hook_tag{}; + +#define BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER) \ +struct BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER : public default_hook_tag\ +{\ + template \ + struct apply\ + { typedef typename T::BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER type; };\ +}\ + +BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_list_hook); +BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_slist_hook); +BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_set_hook); +BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_uset_hook); +BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_avl_set_hook); +BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_splay_set_hook); +BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bs_set_hook); + +#undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION + template struct eval_value_traits { @@ -116,8 +136,12 @@ struct get_member_node_traits template struct get_value_traits { - typedef SupposedValueTraits supposed_value_traits; - //...if it's a base hook + typedef typename detail::eval_if_c + ::value + ,detail::apply + ,detail::identity + >::type supposed_value_traits; + //...if it's a default hook typedef typename detail::eval_if_c < internal_base_hook_bool_is_true::value //...get it's internal value traits using @@ -336,7 +360,7 @@ struct void_pointer }; //!This option setter specifies the type of -//!the tag of a base hook. A type can not have two +//!the tag of a base hook. A type cannot have two //!base hooks of the same type, so a tag can be used //!to differentiate two base hooks with otherwise same type template @@ -509,8 +533,29 @@ struct compare_hash /// @endcond }; +//!This option setter specifies if the hash container will use incremental +//!hashing. With incremental hashing the cost of hash table expansion is spread +//!out across each hash table insertion operation, as opposed to be incurred all at once. +//!Therefore linear hashing is well suited for interactive applications or real-time +//!appplications where the worst-case insertion time of non-incremental hash containers +//!(rehashing the whole bucket array) is not admisible. +template +struct incremental +{ + /// @cond + template + struct pack : Base + { + static const bool incremental = Enabled; + }; + /// @endcond +}; + /// @cond +//To-do: pass to variadic templates +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + template struct do_pack { @@ -525,7 +570,6 @@ struct do_pack typedef Prev type; }; - template < class DefaultOptions , class O1 = none @@ -537,7 +581,8 @@ template , class O7 = none , class O8 = none , class O9 = none - , class Option10 = none + , class O10 = none + , class O11 = none > struct pack_options { @@ -553,29 +598,164 @@ struct pack_options < typename do_pack < typename do_pack < typename do_pack - < DefaultOptions - , O1 + < typename do_pack + < DefaultOptions + , O1 + >::type + , O2 >::type - , O2 + , O3 >::type - , O3 + , O4 >::type - , O4 + , O5 >::type - , O5 + , O6 >::type - , O6 + , O7 >::type - , O7 + , O8 >::type - , O8 + , O9 >::type - , O9 - >::type - , Option10 + , O10 + >::type + , O11 >::type type; }; +#else + +//index_tuple +template +struct index_tuple{}; + +//build_number_seq +template > +struct build_number_seq; + +template +struct build_number_seq > + : build_number_seq > +{}; + +template +struct build_number_seq<0, index_tuple > +{ typedef index_tuple type; }; + +template +struct typelist +{}; + +//invert_typelist +template +struct invert_typelist; + +template +struct typelist_element; + +template +struct typelist_element > +{ + typedef typename typelist_element >::type type; +}; + +template +struct typelist_element<0, typelist > +{ + typedef Head type; +}; + +template +typelist >::type...> + inverted_typelist(index_tuple, typelist) +{ + return typelist >::type...>(); +} + +//sizeof_typelist +template +struct sizeof_typelist; + +template +struct sizeof_typelist< typelist > +{ + static const std::size_t value = sizeof...(Types); +}; + +//invert_typelist_impl +template +struct invert_typelist_impl; + + +template +struct invert_typelist_impl< Typelist, index_tuple > +{ + static const std::size_t last_idx = sizeof_typelist::value - 1; + typedef typelist + ::type...> type; +}; + +template +struct invert_typelist_impl< Typelist, index_tuple > +{ + typedef Typelist type; +}; + +template +struct invert_typelist_impl< Typelist, index_tuple<> > +{ + typedef Typelist type; +}; + +//invert_typelist +template +struct invert_typelist; + +template +struct invert_typelist< typelist > +{ + typedef typelist typelist_t; + typedef typename build_number_seq::type indexes_t; + typedef typename invert_typelist_impl::type type; +}; + +//Do pack +template +struct do_pack; + +template<> +struct do_pack >; + +template +struct do_pack > +{ + typedef Prev type; +}; + +template +struct do_pack > +{ + typedef typename Prev::template pack type; +}; + +template +struct do_pack > +{ + typedef typename Prev::template pack + >::type> type; +}; + + +template +struct pack_options +{ + typedef typelist typelist_t; + typedef typename invert_typelist::type inverted_typelist; + typedef typename do_pack::type type; +}; + +#endif struct hook_defaults : public pack_options diff --git a/include/boost/intrusive/pointer_plus_bits.hpp b/include/boost/intrusive/pointer_plus_bits.hpp index 7c77e90..ec1fe51 100644 --- a/include/boost/intrusive/pointer_plus_bits.hpp +++ b/include/boost/intrusive/pointer_plus_bits.hpp @@ -14,6 +14,7 @@ #define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP #include //ls_zeros +#include //BOOST_INTRUSIVE_INVARIANT_ASSERT namespace boost { namespace intrusive { @@ -28,7 +29,7 @@ struct max_pointer_plus_bits static const std::size_t value = 0; }; -//!This is an specialization for raw pointers. +//!This is a specialization for raw pointers. //!Raw pointers can embed extra bits in the lower bits //!if the alignment is multiple of 2pow(NumBits). template @@ -61,7 +62,7 @@ struct pointer_plus_bits static void set_pointer(pointer &n, pointer p) { - assert(0 == (std::size_t(p) & Mask)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(0 == (std::size_t(p) & Mask)); n = pointer(std::size_t(p) | (std::size_t(n) & Mask)); } @@ -70,7 +71,7 @@ struct pointer_plus_bits static void set_bits(pointer &n, std::size_t c) { - assert(c <= Mask); + BOOST_INTRUSIVE_INVARIANT_ASSERT(c <= Mask); n = pointer(std::size_t(get_pointer(n)) | c); } }; diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 4ec26ab..94d1a39 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -36,20 +36,6 @@ namespace intrusive { /// @cond -template -struct internal_default_set_hook -{ - template static detail::one test(...); - template static detail::two test(typename U::default_set_hook* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); -}; - -template -struct get_default_set_hook -{ - typedef typename T::default_set_hook type; -}; - template struct setopt { @@ -63,13 +49,7 @@ template struct set_defaults : pack_options < none - , base_hook - < typename detail::eval_if_c - < internal_default_set_hook::value - , get_default_set_hook - , detail::identity - >::type - > + , base_hook , constant_time_size , size_type , compare > @@ -91,7 +71,7 @@ struct set_defaults //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -1055,29 +1035,34 @@ class rbtree_impl } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const rbtree_impl &src, Cloner cloner, Disposer disposer) { this->clear_and_dispose(disposer); if(!src.empty()){ + detail::exception_disposer + rollback(*this, disposer); node_algorithms::clone (const_node_ptr(&src.priv_header()) ,node_ptr(&this->priv_header()) ,detail::node_cloner(cloner, this) ,detail::node_disposer(disposer, this)); this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + this->priv_comp() = src.priv_comp(); + rollback.release(); } } @@ -1253,26 +1238,26 @@ class rbtree_impl { return priv_container_from_end_iterator(it.end_iterator_from_it()); } }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator< -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const rbtree_impl &x, const rbtree_impl &y) #else (const rbtree_impl &x, const rbtree_impl &y) #endif { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif bool operator== -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const rbtree_impl &x, const rbtree_impl &y) #else (const rbtree_impl &x, const rbtree_impl &y) @@ -1304,65 +1289,65 @@ bool operator== } } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const rbtree_impl &x, const rbtree_impl &y) #else (const rbtree_impl &x, const rbtree_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const rbtree_impl &x, const rbtree_impl &y) #else (const rbtree_impl &x, const rbtree_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const rbtree_impl &x, const rbtree_impl &y) #else (const rbtree_impl &x, const rbtree_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const rbtree_impl &x, const rbtree_impl &y) #else (const rbtree_impl &x, const rbtree_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (rbtree_impl &x, rbtree_impl &y) #else (rbtree_impl &x, rbtree_impl &y) @@ -1370,15 +1355,23 @@ inline void swap { x.swap(y); } /// @cond +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif struct make_rbtree_opt { typedef typename pack_options - < set_defaults, O1, O2, O3, O4>::type packed_options; + < set_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; typedef typename detail::get_value_traits ::type value_traits; @@ -1393,7 +1386,7 @@ struct make_rbtree_opt //! Helper metafunction to define a \c rbtree that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_rbtree_opt::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class rbtree - : public make_rbtree::type + : public make_rbtree::type { typedef typename make_rbtree - ::type Base; + ::type Base; public: typedef typename Base::value_compare value_compare; diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index de0b6c7..d2dff1e 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -32,7 +32,7 @@ namespace intrusive { //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -324,18 +324,19 @@ class set_impl { tree_.swap(other.tree_); } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const set_impl &src, Cloner cloner, Disposer disposer) { tree_.clone_from(src.tree_, cloner, disposer); } @@ -997,65 +998,65 @@ class set_impl /// @endcond }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const set_impl &x, const set_impl &y) #else (const set_impl &x, const set_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const set_impl &x, const set_impl &y) #else (const set_impl &x, const set_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const set_impl &x, const set_impl &y) #else (const set_impl &x, const set_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const set_impl &x, const set_impl &y) #else (const set_impl &x, const set_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (set_impl &x, set_impl &y) #else (set_impl &x, set_impl &y) @@ -1064,7 +1065,7 @@ inline void swap //! Helper metafunction to define a \c set that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_rbtree_opt::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class set - : public make_set::type + : public make_set::type { typedef typename make_set - ::type Base; + ::type Base; public: typedef typename Base::value_compare value_compare; @@ -1135,7 +1158,7 @@ class set //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -1423,18 +1446,19 @@ class multiset_impl { tree_.swap(other.tree_); } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. Basic guarantee. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const multiset_impl &src, Cloner cloner, Disposer disposer) { tree_.clone_from(src.tree_, cloner, disposer); } @@ -2018,65 +2042,65 @@ class multiset_impl /// @endcond }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const multiset_impl &x, const multiset_impl &y) #else (const multiset_impl &x, const multiset_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const multiset_impl &x, const multiset_impl &y) #else (const multiset_impl &x, const multiset_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const multiset_impl &x, const multiset_impl &y) #else (const multiset_impl &x, const multiset_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const multiset_impl &x, const multiset_impl &y) #else (const multiset_impl &x, const multiset_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (multiset_impl &x, multiset_impl &y) #else (multiset_impl &x, multiset_impl &y) @@ -2085,7 +2109,7 @@ inline void swap //! Helper metafunction to define a \c multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_rbtree_opt::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class multiset - : public make_multiset::type + : public make_multiset::type { - typedef typename make_multiset - ::type Base; + typedef typename make_multiset::type Base; public: typedef typename Base::value_compare value_compare; diff --git a/include/boost/intrusive/set_hook.hpp b/include/boost/intrusive/set_hook.hpp index f439866..473dfe3 100644 --- a/include/boost/intrusive/set_hook.hpp +++ b/include/boost/intrusive/set_hook.hpp @@ -35,7 +35,7 @@ struct get_set_node_algo //! Helper metafunction to define a \c set_base_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -44,7 +44,13 @@ struct make_set_base_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3, O4>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_set_node_algo will tell the hook to optimize the hook for size instead //! of speed. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class set_base_hook - : public make_set_base_hook::type + : public make_set_base_hook< + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -154,7 +166,7 @@ class set_base_hook //! Helper metafunction to define a \c set_member_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -163,7 +175,13 @@ struct make_set_member_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3, O4>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_set_node_algo will tell the hook to optimize the hook for size instead //! of speed. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class set_member_hook - : public make_set_member_hook::type + : public make_set_member_hook< + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/sg_set.hpp b/include/boost/intrusive/sg_set.hpp index 66d461d..b3570fb 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -31,7 +31,7 @@ namespace intrusive { //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -323,18 +323,19 @@ class sg_set_impl { tree_.swap(other.tree_); } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const sg_set_impl &src, Cloner cloner, Disposer disposer) { tree_.clone_from(src.tree_, cloner, disposer); } @@ -1035,65 +1036,65 @@ class sg_set_impl /// @endcond }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sg_set_impl &x, const sg_set_impl &y) #else (const sg_set_impl &x, const sg_set_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sg_set_impl &x, const sg_set_impl &y) #else (const sg_set_impl &x, const sg_set_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sg_set_impl &x, const sg_set_impl &y) #else (const sg_set_impl &x, const sg_set_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sg_set_impl &x, const sg_set_impl &y) #else (const sg_set_impl &x, const sg_set_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (sg_set_impl &x, sg_set_impl &y) #else (sg_set_impl &x, sg_set_impl &y) @@ -1102,7 +1103,7 @@ inline void swap //! Helper metafunction to define a \c sg_set that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_sgtree_opt::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class sg_set - : public make_sg_set::type + : public make_sg_set::type { typedef typename make_sg_set - ::type Base; + ::type Base; public: typedef typename Base::value_compare value_compare; @@ -1173,7 +1197,7 @@ class sg_set //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -1461,18 +1485,19 @@ class sg_multiset_impl { tree_.swap(other.tree_); } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. Basic guarantee. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const sg_multiset_impl &src, Cloner cloner, Disposer disposer) { tree_.clone_from(src.tree_, cloner, disposer); } @@ -2080,65 +2105,65 @@ class sg_multiset_impl /// @endcond }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sg_multiset_impl &x, const sg_multiset_impl &y) #else (const sg_multiset_impl &x, const sg_multiset_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sg_multiset_impl &x, const sg_multiset_impl &y) #else (const sg_multiset_impl &x, const sg_multiset_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sg_multiset_impl &x, const sg_multiset_impl &y) #else (const sg_multiset_impl &x, const sg_multiset_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sg_multiset_impl &x, const sg_multiset_impl &y) #else (const sg_multiset_impl &x, const sg_multiset_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (sg_multiset_impl &x, sg_multiset_impl &y) #else (sg_multiset_impl &x, sg_multiset_impl &y) @@ -2147,7 +2172,7 @@ inline void swap //! Helper metafunction to define a \c sg_multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_sgtree_opt::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class sg_multiset - : public make_sg_multiset::type + : public make_sg_multiset::type { typedef typename make_sg_multiset - ::type Base; + ::type Base; public: typedef typename Base::value_compare value_compare; diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 70d4b61..63022a4 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -151,7 +151,7 @@ struct alpha_holder void set_alpha(float) { //alpha CAN't be changed. - assert(0); + BOOST_INTRUSIVE_INVARIANT_ASSERT(0); } h_alpha_t get_h_alpha_t() const @@ -176,13 +176,7 @@ template struct sg_set_defaults : pack_options < none - , base_hook - < typename detail::eval_if_c - < internal_default_bs_set_hook::value - , get_default_bs_set_hook - , detail::identity - >::type - > + , base_hook , floating_point , size_type , compare > @@ -204,7 +198,7 @@ struct sg_set_defaults //! \c base_hook<>/member_hook<>/value_traits<>, //! \c floating_point<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -1212,29 +1206,34 @@ class sgtree_impl } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const sgtree_impl &src, Cloner cloner, Disposer disposer) { this->clear_and_dispose(disposer); if(!src.empty()){ + detail::exception_disposer + rollback(*this, disposer); node_algorithms::clone (const_node_ptr(&src.priv_header()) ,node_ptr(&this->priv_header()) ,detail::node_cloner(cloner, this) ,detail::node_disposer(disposer, this)); this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + this->priv_comp() = src.priv_comp(); + rollback.release(); } } @@ -1469,26 +1468,26 @@ class sgtree_impl { return priv_container_from_end_iterator(it.end_iterator_from_it()); } }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator< -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sgtree_impl &x, const sgtree_impl &y) #else (const sgtree_impl &x, const sgtree_impl &y) #endif { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif bool operator== -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sgtree_impl &x, const sgtree_impl &y) #else (const sgtree_impl &x, const sgtree_impl &y) @@ -1520,65 +1519,65 @@ bool operator== } } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sgtree_impl &x, const sgtree_impl &y) #else (const sgtree_impl &x, const sgtree_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sgtree_impl &x, const sgtree_impl &y) #else (const sgtree_impl &x, const sgtree_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sgtree_impl &x, const sgtree_impl &y) #else (const sgtree_impl &x, const sgtree_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const sgtree_impl &x, const sgtree_impl &y) #else (const sgtree_impl &x, const sgtree_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (sgtree_impl &x, sgtree_impl &y) #else (sgtree_impl &x, sgtree_impl &y) @@ -1586,15 +1585,22 @@ inline void swap { x.swap(y); } /// @cond +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template + , class O3 = none, class O4 = none> +#else +template +#endif struct make_sgtree_opt { typedef typename pack_options - < sg_set_defaults, O1, O2, O3, O4>::type packed_options; + < sg_set_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; typedef typename detail::get_value_traits ::type value_traits; @@ -1609,7 +1615,7 @@ struct make_sgtree_opt //! Helper metafunction to define a \c sgtree that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_sgtree_opt::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class sgtree - : public make_sgtree::type + : public make_sgtree::type { typedef typename make_sgtree - ::type Base; + ::type Base; public: typedef typename Base::value_compare value_compare; diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index 18c0884..c9af84f 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -683,7 +683,7 @@ class sgtree_algorithms for(std::size_t i = 1; true; ++i){ bool rebalance = false; if(i == depth){ - assert(tree_size == count(s)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(tree_size == count(s)); rebalance = true; } else if(i > h_alpha(size)){ diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index bab8308..0577d71 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -36,18 +36,6 @@ namespace intrusive { /// @cond -template -struct internal_default_slist_hook -{ - template static detail::one test(...); - template static detail::two test(typename U::default_slist_hook* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); -}; - -template -struct get_default_slist_hook -{ typedef typename T::default_slist_hook type; }; - template struct slistopt { @@ -75,13 +63,7 @@ template struct slist_defaults : pack_options < none - , base_hook - < typename detail::eval_if_c - < internal_default_slist_hook::value - , get_default_slist_hook - , detail::identity - >::type - > + , base_hook , constant_time_size , linear , size_type @@ -114,7 +96,7 @@ struct slist_defaults //! the '*_after' functions, ++end() == begin() and previous(begin()) == end() //! are defined. An new special function "before_begin()" is defined, which returns //! an iterator that points one less the beginning of the list: ++before_begin() == begin() -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -300,7 +282,7 @@ class slist_impl : data_(v_traits) { this->set_default_constructed_state(); - this->insert_after(this->before_begin(), b, e); + this->insert_after(this->cbefore_begin(), b, e); } //! Effects: If it's a safe-mode @@ -346,7 +328,7 @@ class slist_impl template void clear_and_dispose(Disposer disposer) { - iterator it(this->begin()), itend(this->end()); + const_iterator it(this->begin()), itend(this->end()); while(it != itend){ node_ptr to_erase(it.pointed_node()); ++it; @@ -395,7 +377,7 @@ class slist_impl void push_back(reference value) { BOOST_STATIC_ASSERT((cache_last != 0)); - this->insert_after(iterator(this->get_last_node(), this), value); + this->insert_after(const_iterator(this->get_last_node(), this), value); } //! Effects: Erases the first element of the list. @@ -650,6 +632,7 @@ class slist_impl { this->priv_shift_forward(n, detail::bool_()); } //! 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 @@ -668,7 +651,7 @@ class slist_impl this->clear_and_dispose(disposer); detail::exception_disposer rollback(*this, disposer); - iterator prev(this->before_begin()); + const_iterator prev(this->cbefore_begin()); const_iterator b(src.begin()), e(src.end()); for(; b != e; ++b){ prev = this->insert_after(prev, *cloner(*b)); @@ -689,7 +672,7 @@ class slist_impl //! Complexity: Constant. //! //! Note: Does not affect the validity of iterators and references. - iterator insert_after(iterator prev_p, reference value) + iterator insert_after(const_iterator prev_p, reference value) { node_ptr n = get_real_value_traits().to_node_ptr(value); if(safemode_or_autounlink) @@ -716,7 +699,7 @@ class slist_impl //! //! Note: Does not affect the validity of iterators and references. template - void insert_after(iterator prev_p, Iterator first, Iterator last) + void insert_after(const_iterator prev_p, Iterator first, Iterator last) { for (; first != last; ++first) prev_p = this->insert_after(prev_p, *first); @@ -734,7 +717,7 @@ class slist_impl //! Constant-time if cache_last<> is true and p == end(). //! //! Note: Does not affect the validity of iterators and references. - iterator insert(iterator p, reference value) + iterator insert(const_iterator p, reference value) { return this->insert_after(this->previous(p), value); } //! Requires: Dereferencing iterator must yield @@ -752,7 +735,7 @@ class slist_impl //! //! Note: Does not affect the validity of iterators and references. template - void insert(iterator p, Iterator b, Iterator e) + void insert(const_iterator p, Iterator b, Iterator e) { return this->insert_after(this->previous(p), b, e); } //! Effects: Erases the element after the element pointed by prev of @@ -767,7 +750,7 @@ class slist_impl //! //! Note: Invalidates the iterators (but not the references) to the //! erased element. - iterator erase_after(iterator prev) + iterator erase_after(const_iterator prev) { return this->erase_after_and_dispose(prev, detail::null_disposer()); } //! Effects: Erases the range (before_first, last) from @@ -783,7 +766,7 @@ class slist_impl //! //! Note: Invalidates the iterators (but not the references) to the //! erased element. - iterator erase_after(iterator before_first, iterator last) + iterator erase_after(const_iterator before_first, const_iterator last) { if(safemode_or_autounlink || constant_time_size){ return this->erase_after_and_dispose(before_first, last, detail::null_disposer()); @@ -797,7 +780,7 @@ class slist_impl } } node_algorithms::unlink_after(bfp, lp); - return last; + return last.unconst(); } } @@ -815,9 +798,9 @@ class slist_impl //! //! Note: Invalidates the iterators (but not the references) to the //! erased element. - iterator erase_after(iterator before_first, iterator last, difference_type n) + iterator erase_after(const_iterator before_first, const_iterator last, difference_type n) { - BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(++iterator(before_first), last) == difference_type(n)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(++const_iterator(before_first), last) == difference_type(n)); if(safemode_or_autounlink){ return this->erase_after(before_first, last); } @@ -833,7 +816,7 @@ class slist_impl if(constant_time_size){ this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n); } - return last; + return last.unconst(); } } @@ -849,7 +832,7 @@ class slist_impl //! //! Note: Invalidates the iterators (but not the references) to the //! erased element. - iterator erase(iterator i) + iterator erase(const_iterator i) { return this->erase_after(this->previous(i)); } //! Requires: first and last must be valid iterator to elements in *this. @@ -866,7 +849,7 @@ class slist_impl //! //! Note: Invalidates the iterators (but not the references) to the //! erased elements. - iterator erase(iterator first, iterator last) + iterator erase(const_iterator first, const_iterator last) { return this->erase_after(this->previous(first), last); } //! Effects: Erases the range [first, last) from @@ -883,7 +866,7 @@ class slist_impl //! //! Note: Invalidates the iterators (but not the references) to the //! erased element. - iterator erase(iterator first, iterator last, difference_type n) + iterator erase(const_iterator first, const_iterator last, difference_type n) { return this->erase_after(this->previous(first), last, n); } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -901,9 +884,9 @@ class slist_impl //! //! Note: Invalidates the iterators to the erased element. template - iterator erase_after_and_dispose(iterator prev, Disposer disposer) + iterator erase_after_and_dispose(const_iterator prev, Disposer disposer) { - iterator it(prev); + const_iterator it(prev); ++it; node_ptr to_erase(it.pointed_node()); ++it; @@ -916,16 +899,16 @@ class slist_impl node_algorithms::init(to_erase); disposer(get_real_value_traits().to_value_ptr(to_erase)); this->priv_size_traits().decrement(); - return it; + return it.unconst(); } /// @cond template - static iterator s_erase_after_and_dispose(iterator prev, Disposer disposer) + static iterator s_erase_after_and_dispose(const_iterator prev, Disposer disposer) { BOOST_STATIC_ASSERT(((!cache_last)&&(!constant_time_size)&&(!stateful_value_traits))); - iterator it(prev); + const_iterator it(prev); ++it; node_ptr to_erase(it.pointed_node()); ++it; @@ -934,10 +917,10 @@ class slist_impl if(safemode_or_autounlink) node_algorithms::init(to_erase); disposer(real_value_traits::to_value_ptr(to_erase)); - return it; + return it.unconst(); } - static iterator s_erase_after(iterator prev) + static iterator s_erase_after(const_iterator prev) { return s_erase_after_and_dispose(prev, detail::null_disposer()); } /// @endcond @@ -957,7 +940,7 @@ class slist_impl //! //! Note: Invalidates the iterators to the erased element. template - iterator erase_after_and_dispose(iterator before_first, iterator last, Disposer disposer) + iterator erase_after_and_dispose(const_iterator before_first, const_iterator last, Disposer disposer) { node_ptr bfp(before_first.pointed_node()), lp(last.pointed_node()); node_ptr fp(node_traits::get_next(bfp)); @@ -973,7 +956,7 @@ class slist_impl if(cache_last && (node_traits::get_next(bfp) == this->get_end_node())){ this->set_last_node(bfp); } - return last; + return last.unconst(); } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -992,7 +975,7 @@ class slist_impl //! Note: Invalidates the iterators (but not the references) to the //! erased element. template - iterator erase_and_dispose(iterator i, Disposer disposer) + iterator erase_and_dispose(const_iterator i, Disposer disposer) { return this->erase_after_and_dispose(this->previous(i), disposer); } //! Requires: first and last must be valid iterator to elements in *this. @@ -1013,7 +996,7 @@ class slist_impl //! Note: Invalidates the iterators (but not the references) to the //! erased elements. template - iterator erase_and_dispose(iterator first, iterator last, Disposer disposer) + iterator erase_and_dispose(const_iterator first, const_iterator last, Disposer disposer) { return this->erase_after_and_dispose(this->previous(first), last, disposer); } //! Requires: Dereferencing iterator must yield @@ -1035,7 +1018,7 @@ class slist_impl void assign(Iterator b, Iterator e) { this->clear(); - this->insert_after(this->before_begin(), b, e); + this->insert_after(this->cbefore_begin(), b, e); } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -1058,7 +1041,7 @@ class slist_impl void dispose_and_assign(Disposer disposer, Iterator b, Iterator e) { this->clear_and_dispose(disposer); - this->insert_after(this->before_begin(), b, e, disposer); + this->insert_after(this->cbefore_begin(), b, e, disposer); } //! Requires: prev is an iterator to an element or x.end()/x.before_begin() in x. @@ -1077,10 +1060,10 @@ class slist_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - iterator splice_after(iterator prev, slist_impl &x) + iterator splice_after(const_iterator prev, slist_impl &x) { if (!x.empty()){ - iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active + const_iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active node_ptr prev_n(prev.pointed_node()); node_ptr last_x_n(last_x.pointed_node()); if(cache_last){ @@ -1092,10 +1075,10 @@ class slist_impl node_algorithms::transfer_after( prev_n, x.before_begin().pointed_node(), last_x_n); this->priv_size_traits().set_size(this->priv_size_traits().get_size() + x.priv_size_traits().get_size()); x.priv_size_traits().set_size(size_type(0)); - return last_x; + return last_x.unconst(); } else{ - return prev; + return prev.unconst(); } } @@ -1112,9 +1095,9 @@ class slist_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice_after(iterator prev_pos, slist_impl &x, iterator prev_ele) + void splice_after(const_iterator prev_pos, slist_impl &x, const_iterator prev_ele) { - iterator elem = prev_ele; + const_iterator elem = prev_ele; this->splice_after(prev_pos, x, prev_ele, ++elem, 1); } @@ -1133,7 +1116,7 @@ class slist_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last) + void splice_after(const_iterator prev_pos, slist_impl &x, const_iterator before_first, const_iterator before_last) { if(constant_time_size) this->splice_after(prev_pos, x, before_first, before_last, std::distance(before_first, before_last)); @@ -1156,7 +1139,7 @@ class slist_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last, difference_type n) + void splice_after(const_iterator prev_pos, slist_impl &x, const_iterator before_first, const_iterator before_last, difference_type n) { if(n){ BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(before_first, before_last) == n); @@ -1188,7 +1171,7 @@ class slist_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - iterator splice(iterator it, slist_impl &x) + iterator splice(const_iterator it, slist_impl &x) { return this->splice_after(this->previous(it), x); } //! Requires: it p must be a valid iterator of *this. @@ -1205,7 +1188,7 @@ class slist_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(iterator pos, slist_impl &x, iterator elem) + void splice(const_iterator pos, slist_impl &x, const_iterator elem) { return this->splice_after(this->previous(pos), x, x.previous(elem)); } //! Requires: pos must be a dereferenceable iterator in *this @@ -1225,7 +1208,7 @@ class slist_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(iterator pos, slist_impl &x, iterator first, iterator last) + void splice(const_iterator pos, slist_impl &x, const_iterator first, const_iterator last) { return this->splice_after(this->previous(pos), x, x.previous(first), x.previous(last)); } //! Requires: pos must be a dereferenceable iterator in *this @@ -1244,7 +1227,7 @@ class slist_impl //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(iterator pos, slist_impl &x, iterator first, iterator last, difference_type n) + void splice(const_iterator pos, slist_impl &x, const_iterator first, const_iterator last, difference_type n) { return this->splice_after(this->previous(pos), x, x.previous(first), x.previous(last), n); } //! Effects: This function sorts the list *this according to std::less. @@ -1266,10 +1249,10 @@ class slist_impl slist_impl carry; slist_impl counter[64]; int fill = 0; - iterator last_inserted; + const_iterator last_inserted; while(!this->empty()){ - last_inserted = this->begin(); - carry.splice_after(carry.before_begin(), *this, this->before_begin()); + last_inserted = this->cbegin(); + carry.splice_after(carry.cbefore_begin(), *this, this->cbefore_begin()); int i = 0; while(i < fill && !counter[i].empty()) { last_inserted = carry.merge(counter[i++], p); @@ -1277,16 +1260,16 @@ class slist_impl BOOST_INTRUSIVE_INVARIANT_ASSERT(counter[i].empty()); node_ptr p = node_algorithms::get_previous_node - (last_inserted.pointed_node(), carry.end().pointed_node()); - iterator last_element(p, this); + (last_inserted.pointed_node(), carry.cend().pointed_node()); + const_iterator last_element(p, this); if(constant_time_size){ - counter[i].splice_after( counter[i].before_begin(), carry - , carry.before_begin(), last_element + counter[i].splice_after( counter[i].cbefore_begin(), carry + , carry.cbefore_begin(), last_element , carry.size()); } else{ - counter[i].splice_after( counter[i].before_begin(), carry - , carry.before_begin(), last_element); + counter[i].splice_after( counter[i].cbefore_begin(), carry + , carry.cbefore_begin(), last_element); } if(i == fill) ++fill; @@ -1298,13 +1281,13 @@ class slist_impl node_ptr p = node_algorithms::get_previous_node (last_inserted.pointed_node(), counter[--fill].end().pointed_node()); - iterator last_element(p, this); + const_iterator last_element(p, this); if(constant_time_size){ - this->splice_after( before_begin(), counter[fill], counter[fill].before_begin() + this->splice_after( cbefore_begin(), counter[fill], counter[fill].cbefore_begin() , last_element, counter[fill].size()); } else{ - this->splice_after( before_begin(), counter[fill], counter[fill].before_begin() + this->splice_after( cbefore_begin(), counter[fill], counter[fill].cbefore_begin() , last_element); } } @@ -1348,12 +1331,12 @@ class slist_impl template iterator merge(slist_impl& x, Predicate p) { - iterator a(before_begin()), e(end()), ax(x.before_begin()), ex(x.end()); - iterator last_inserted(e); - iterator a_next; + const_iterator a(cbefore_begin()), e(cend()), ax(x.cbefore_begin()), ex(x.cend()); + const_iterator last_inserted(e); + const_iterator a_next; while(++(a_next = a) != e && !x.empty()) { - iterator ix(ax); - iterator cx; + const_iterator ix(ax); + const_iterator cx; size_type n(0); while(++(cx = ix) != ex && p(*cx, *a_next)){ ++ix; ++n; @@ -1367,7 +1350,7 @@ class slist_impl if (!x.empty()){ last_inserted = this->splice_after(a, x); } - return last_inserted; + return last_inserted.unconst(); } //! Effects: This function removes all of x's elements and inserts them @@ -1455,7 +1438,7 @@ class slist_impl template void remove_and_dispose_if(Pred pred, Disposer disposer) { - iterator bcur(this->before_begin()), cur(this->begin()), e(this->end()); + const_iterator bcur(this->before_begin()), cur(this->begin()), e(this->end()); while(cur != e){ if (pred(*cur)){ @@ -1528,10 +1511,10 @@ class slist_impl template void unique_and_dispose(BinaryPredicate pred, Disposer disposer) { - iterator end_n(this->end()); - iterator bcur(this->begin()); + const_iterator end_n(this->cend()); + const_iterator bcur(this->cbegin()); if(bcur != end_n){ - iterator cur(bcur); + const_iterator cur(bcur); ++cur; while(cur != end_n) { if (pred(*bcur, *cur)){ @@ -1643,7 +1626,7 @@ class slist_impl const_iterator previous(const_iterator i) const { if(cache_last && (i.pointed_node() == this->get_end_node())){ - return iterator(uncast(this->get_last_node()), this); + return const_iterator(uncast(this->get_last_node()), this); } return const_iterator (node_algorithms::get_previous_node @@ -1760,26 +1743,26 @@ class slist_impl } }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator< -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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 std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif bool operator== -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const slist_impl &x, const slist_impl &y) #else (const slist_impl &x, const slist_impl &y) @@ -1812,65 +1795,65 @@ bool operator== } } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#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); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (slist_impl &x, slist_impl &y) #else (slist_impl &x, slist_impl &y) @@ -1879,7 +1862,7 @@ inline void swap //! Helper metafunction to define a \c slist that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -1888,7 +1871,13 @@ struct make_slist { /// @cond typedef typename pack_options - < slist_defaults, O1, O2, O3, O4, O5>::type packed_options; + < slist_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4, O5 + #else + Options... + #endif + >::type packed_options; typedef typename detail::get_value_traits ::type value_traits; typedef slist_impl @@ -1907,12 +1896,29 @@ struct make_slist #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class slist - : public make_slist::type + : public make_slist::type { typedef typename make_slist - ::type Base; + ::type Base; typedef typename Base::real_value_traits real_value_traits; //Assert if passed value traits are compatible with the type BOOST_STATIC_ASSERT((detail::is_same::value)); diff --git a/include/boost/intrusive/slist_hook.hpp b/include/boost/intrusive/slist_hook.hpp index b7d5344..8164d62 100644 --- a/include/boost/intrusive/slist_hook.hpp +++ b/include/boost/intrusive/slist_hook.hpp @@ -37,7 +37,7 @@ struct get_slist_node_algo //! Helper metafunction to define a \c slist_base_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -46,7 +46,13 @@ struct make_slist_base_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_slist_node_algo @@ -75,15 +81,21 @@ struct make_slist_base_hook //! //! \c void_pointer<> is the pointer type that will be used internally in the hook //! and the the container configured to use this hook. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class slist_base_hook - : public make_slist_base_hook::type + : public make_slist_base_hook< + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -152,7 +164,7 @@ class slist_base_hook //! Helper metafunction to define a \c slist_member_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -161,7 +173,13 @@ struct make_slist_member_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_slist_node_algo @@ -185,15 +203,21 @@ struct make_slist_member_hook //! //! \c void_pointer<> is the pointer type that will be used internally in the hook //! and the the container configured to use this hook. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class slist_member_hook - : public make_slist_member_hook::type + : public make_slist_member_hook< + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index 104063a..f86ae8b 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -31,7 +31,7 @@ namespace intrusive { //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -323,18 +323,19 @@ class splay_set_impl { tree_.swap(other.tree_); } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const splay_set_impl &src, Cloner cloner, Disposer disposer) { tree_.clone_from(src.tree_, cloner, disposer); } @@ -1072,65 +1073,65 @@ class splay_set_impl /// @endcond }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splay_set_impl &x, const splay_set_impl &y) #else (const splay_set_impl &x, const splay_set_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splay_set_impl &x, const splay_set_impl &y) #else (const splay_set_impl &x, const splay_set_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splay_set_impl &x, const splay_set_impl &y) #else (const splay_set_impl &x, const splay_set_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splay_set_impl &x, const splay_set_impl &y) #else (const splay_set_impl &x, const splay_set_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (splay_set_impl &x, splay_set_impl &y) #else (splay_set_impl &x, splay_set_impl &y) @@ -1139,7 +1140,7 @@ inline void swap //! Helper metafunction to define a \c splay_set that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_splaytree_opt::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class splay_set - : public make_splay_set::type + : public make_splay_set::type { typedef typename make_splay_set - ::type Base; + ::type Base; public: typedef typename Base::value_compare value_compare; @@ -1210,7 +1233,7 @@ class splay_set //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -1498,18 +1521,19 @@ class splay_multiset_impl { tree_.swap(other.tree_); } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. Basic guarantee. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const splay_multiset_impl &src, Cloner cloner, Disposer disposer) { tree_.clone_from(src.tree_, cloner, disposer); } @@ -2154,65 +2178,65 @@ class splay_multiset_impl /// @endcond }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splay_multiset_impl &x, const splay_multiset_impl &y) #else (const splay_multiset_impl &x, const splay_multiset_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splay_multiset_impl &x, const splay_multiset_impl &y) #else (const splay_multiset_impl &x, const splay_multiset_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splay_multiset_impl &x, const splay_multiset_impl &y) #else (const splay_multiset_impl &x, const splay_multiset_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splay_multiset_impl &x, const splay_multiset_impl &y) #else (const splay_multiset_impl &x, const splay_multiset_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (splay_multiset_impl &x, splay_multiset_impl &y) #else (splay_multiset_impl &x, splay_multiset_impl &y) @@ -2221,7 +2245,7 @@ inline void swap //! Helper metafunction to define a \c splay_multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_splaytree_opt::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class splay_multiset - : public make_splay_multiset::type + : public make_splay_multiset::type { typedef typename make_splay_multiset - ::type Base; + ::type Base; public: typedef typename Base::value_compare value_compare; diff --git a/include/boost/intrusive/splay_set_hook.hpp b/include/boost/intrusive/splay_set_hook.hpp index ddd7031..17f18bc 100644 --- a/include/boost/intrusive/splay_set_hook.hpp +++ b/include/boost/intrusive/splay_set_hook.hpp @@ -34,7 +34,7 @@ struct get_splay_set_node_algo //! Helper metafunction to define a \c splay_set_base_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -43,7 +43,13 @@ struct make_splay_set_base_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_splay_set_node_algo @@ -72,15 +78,21 @@ struct make_splay_set_base_hook //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class splay_set_base_hook - : public make_splay_set_base_hook::type + : public make_splay_set_base_hook< + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -149,7 +161,7 @@ class splay_set_base_hook //! Helper metafunction to define a \c splay_set_member_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -158,7 +170,13 @@ struct make_splay_set_member_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_splay_set_node_algo @@ -183,15 +201,21 @@ struct make_splay_set_member_hook //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class splay_set_member_hook - : public make_splay_set_member_hook::type + : public make_splay_set_member_hook< + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3 + #else + Options... + #endif + >::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index e356963..94a0985 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -35,20 +35,6 @@ namespace intrusive { /// @cond -template -struct internal_default_splay_set_hook -{ - template static detail::one test(...); - template static detail::two test(typename U::default_splay_set_hook* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); -}; - -template -struct get_default_splay_set_hook -{ - typedef typename T::default_splay_set_hook type; -}; - template struct splaysetopt { @@ -62,13 +48,7 @@ template struct splay_set_defaults : pack_options < none - , base_hook - < typename detail::eval_if_c - < internal_default_splay_set_hook::value - , get_default_splay_set_hook - , detail::identity - >::type - > + , base_hook , constant_time_size , size_type , compare > @@ -90,7 +70,7 @@ struct splay_set_defaults //! \c base_hook<>/member_hook<>/value_traits<>, //! \c constant_time_size<>, \c size_type<> and //! \c compare<>. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -1072,29 +1052,34 @@ class splaytree_impl } //! 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()(const_reference ) - //! and inserts them on *this. + //! 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. + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. template void clone_from(const splaytree_impl &src, Cloner cloner, Disposer disposer) { this->clear_and_dispose(disposer); if(!src.empty()){ + detail::exception_disposer + rollback(*this, disposer); node_algorithms::clone (const_node_ptr(&src.priv_header()) ,node_ptr(&this->priv_header()) ,detail::node_cloner(cloner, this) ,detail::node_disposer(disposer, this)); this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + this->priv_comp() = src.priv_comp(); + rollback.release(); } } @@ -1339,26 +1324,26 @@ class splaytree_impl { return priv_container_from_end_iterator(it.end_iterator_from_it()); } }; -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator< -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splaytree_impl &x, const splaytree_impl &y) #else (const splaytree_impl &x, const splaytree_impl &y) #endif { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif bool operator== -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splaytree_impl &x, const splaytree_impl &y) #else (const splaytree_impl &x, const splaytree_impl &y) @@ -1390,65 +1375,65 @@ bool operator== } } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator!= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splaytree_impl &x, const splaytree_impl &y) #else (const splaytree_impl &x, const splaytree_impl &y) #endif { return !(x == y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator> -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splaytree_impl &x, const splaytree_impl &y) #else (const splaytree_impl &x, const splaytree_impl &y) #endif { return y < x; } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator<= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splaytree_impl &x, const splaytree_impl &y) #else (const splaytree_impl &x, const splaytree_impl &y) #endif { return !(y < x); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline bool operator>= -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const splaytree_impl &x, const splaytree_impl &y) #else (const splaytree_impl &x, const splaytree_impl &y) #endif { return !(x < y); } -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template #endif inline void swap -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (splaytree_impl &x, splaytree_impl &y) #else (splaytree_impl &x, splaytree_impl &y) @@ -1456,15 +1441,23 @@ inline void swap { x.swap(y); } /// @cond + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template + , class O3 = none, class O4 = none> +#else +template +#endif struct make_splaytree_opt { typedef typename pack_options - < splay_set_defaults, O1, O2, O3, O4>::type packed_options; + < splay_set_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; typedef typename detail::get_value_traits ::type value_traits; @@ -1479,7 +1472,7 @@ struct make_splaytree_opt //! Helper metafunction to define a \c splaytree that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template::type + < typename make_splaytree_opt::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template +#else +template +#endif class splaytree - : public make_splaytree::type + : public make_splaytree::type { typedef typename make_splaytree - ::type Base; + ::type Base; public: typedef typename Base::value_compare value_compare; diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index 409449f..e727ab6 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -870,7 +870,7 @@ class splaytree_algorithms if(NodeTraits::get_parent(g) == p) NodeTraits::set_parent(g, n); else{//must be ( g->right == p ) - assert(0); + BOOST_INTRUSIVE_INVARIANT_ASSERT(0); NodeTraits::set_right(g, n); } } diff --git a/include/boost/intrusive/unordered_set.hpp b/include/boost/intrusive/unordered_set.hpp index 6ec56fc..8f1f9d1 100644 --- a/include/boost/intrusive/unordered_set.hpp +++ b/include/boost/intrusive/unordered_set.hpp @@ -56,7 +56,7 @@ namespace intrusive { //! //! Since no automatic rehashing is done, iterators are never invalidated when //! inserting or erasing elements. Iterators are only invalidated when rehasing. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -268,18 +268,24 @@ class unordered_set_impl { table_.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. + //! and inserts them on *this. The hash function and the equality + //! predicate are copied from the source. //! - //! If cloner throws, all cloned elements are unlinked and disposed + //! 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 throws. Basic guarantee. + //! Throws: If cloner or hasher throw or hash or equality predicate copying + //! throws. Basic guarantee. template void clone_from(const unordered_set_impl &src, Cloner cloner, Disposer disposer) { table_.clone_from(src.table_, cloner, disposer); } @@ -920,6 +926,8 @@ class unordered_set_impl //! //! 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. //! @@ -927,6 +935,32 @@ class unordered_set_impl void rehash(const bucket_traits &new_bucket_traits) { table_.rehash(new_bucket_traits); } + //! Requires: + //! + //! Effects: + //! + //! Complexity: + //! + //! Throws: + //! + //! Note: this method is only available if incremental option is activated. + bool incremental_rehash(bool grow = true) + { return table_.incremental_rehash(grow); } + + //! Note: this method is only available if incremental option is activated. + bool incremental_rehash(const bucket_traits &new_bucket_traits) + { return table_.incremental_rehash(new_bucket_traits); } + + //! Requires: + //! + //! Effects: + //! + //! Complexity: + //! + //! Throws: + size_type split_count() const + { return table_.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 @@ -954,14 +988,14 @@ class unordered_set_impl //! Helper metafunction to define an \c unordered_set that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif struct make_unordered_set @@ -969,19 +1003,42 @@ struct make_unordered_set /// @cond typedef unordered_set_impl < typename make_hashtable_opt - ::type + ::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED -template + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif class unordered_set - : public make_unordered_set::type + : public make_unordered_set::type { typedef typename make_unordered_set - ::type Base; + ::type Base; //Assert if passed value traits are compatible with the type BOOST_STATIC_ASSERT((detail::is_same::value)); @@ -1052,7 +1109,7 @@ class unordered_set //! //! Since no automatic rehashing is done, iterators are never invalidated when //! inserting or erasing elements. Iterators are only invalidated when rehasing. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else template @@ -1265,18 +1322,24 @@ class unordered_multiset_impl { table_.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. + //! and inserts them on *this. The hash function and the equality + //! predicate are copied from the source. //! - //! If cloner throws, all cloned elements are unlinked and disposed + //! 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 throws. + //! Throws: If cloner or hasher throw or hash or equality predicate copying + //! throws. Basic guarantee. template void clone_from(const unordered_multiset_impl &src, Cloner cloner, Disposer disposer) { table_.clone_from(src.table_, cloner, disposer); } @@ -1854,6 +1917,8 @@ class unordered_multiset_impl //! //! 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. //! @@ -1861,6 +1926,32 @@ class unordered_multiset_impl void rehash(const bucket_traits &new_bucket_traits) { table_.rehash(new_bucket_traits); } + //! Requires: + //! + //! Effects: + //! + //! Complexity: + //! + //! Throws: + //! + //! Note: this method is only available if incremental option is activated. + bool incremental_rehash(bool grow = true) + { return table_.incremental_rehash(grow); } + + //! Note: this method is only available if incremental option is activated. + bool incremental_rehash(const bucket_traits &new_bucket_traits) + { return table_.incremental_rehash(new_bucket_traits); } + + //! Requires: + //! + //! Effects: + //! + //! Complexity: + //! + //! Throws: + size_type split_count() const + { return table_.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 @@ -1888,14 +1979,14 @@ class unordered_multiset_impl //! Helper metafunction to define an \c unordered_multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif struct make_unordered_multiset @@ -1903,19 +1994,42 @@ struct make_unordered_multiset /// @cond typedef unordered_multiset_impl < typename make_hashtable_opt - ::type + ::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED -template + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif class unordered_multiset - : public make_unordered_multiset::type + : public make_unordered_multiset::type { typedef typename make_unordered_multiset - ::type Base; + ::type Base; //Assert if passed value traits are compatible with the type BOOST_STATIC_ASSERT((detail::is_same::value)); diff --git a/include/boost/intrusive/unordered_set_hook.hpp b/include/boost/intrusive/unordered_set_hook.hpp index 7f6f5bd..0d5d4e8 100644 --- a/include/boost/intrusive/unordered_set_hook.hpp +++ b/include/boost/intrusive/unordered_set_hook.hpp @@ -153,7 +153,7 @@ struct get_uset_node_algo //! Helper metafunction to define a \c unordered_set_base_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -162,7 +162,13 @@ struct make_unordered_set_base_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3, O4>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_uset_node_algo will tell the hook to store a link to form a group //! with other value with the same value to speed up searches and insertions //! in unordered_multisets with a great number of with equivalent keys. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class unordered_set_base_hook - : public make_unordered_set_base_hook::type + : public make_unordered_set_base_hook< + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -279,7 +291,7 @@ class unordered_set_base_hook //! Helper metafunction to define a \c unordered_set_member_hook that yields to the same //! type when the same options (either explicitly or implicitly) are used. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template @@ -288,7 +300,13 @@ struct make_unordered_set_member_hook { /// @cond typedef typename pack_options - < hook_defaults, O1, O2, O3, O4>::type packed_options; + < hook_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; typedef detail::generic_hook < get_uset_node_algo< typename packed_options::void_pointer @@ -318,15 +336,21 @@ struct make_unordered_set_member_hook //! //! \c store_hash<> will tell the hook to store the hash of the value //! to speed up rehashings. -#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class unordered_set_member_hook - : public make_unordered_set_member_hook::type + : public make_unordered_set_member_hook< + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type { - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //!