From 8c6f93eae07abb1a00777372f3f5eb18bf297711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 14 Oct 2009 11:59:32 +0000 Subject: [PATCH] Fixes for 1.41 [SVN r56817] --- include/boost/intrusive/any_hook.hpp | 2 +- include/boost/intrusive/avl_set.hpp | 112 +++++++++- include/boost/intrusive/avl_set_hook.hpp | 4 +- include/boost/intrusive/avltree.hpp | 72 +++++- .../boost/intrusive/avltree_algorithms.hpp | 60 +++++ include/boost/intrusive/bs_set_hook.hpp | 4 +- .../intrusive/circular_list_algorithms.hpp | 4 +- .../intrusive/circular_slist_algorithms.hpp | 4 +- .../intrusive/derivation_value_traits.hpp | 2 +- .../detail/any_node_and_algorithms.hpp | 2 +- include/boost/intrusive/detail/assert.hpp | 2 +- .../detail/clear_on_destructor_base.hpp | 2 +- .../detail/common_slist_algorithms.hpp | 25 ++- .../boost/intrusive/detail/config_begin.hpp | 2 +- include/boost/intrusive/detail/config_end.hpp | 2 +- .../intrusive/detail/ebo_functor_holder.hpp | 5 +- .../intrusive/detail/function_detector.hpp | 87 ++++++++ .../boost/intrusive/detail/generic_hook.hpp | 2 +- .../boost/intrusive/detail/hashtable_node.hpp | 20 +- .../detail/is_stateful_value_traits.hpp | 56 +++++ include/boost/intrusive/detail/list_node.hpp | 18 +- include/boost/intrusive/detail/mpl.hpp | 5 +- .../intrusive/detail/parent_from_member.hpp | 2 +- .../boost/intrusive/detail/rbtree_node.hpp | 2 +- include/boost/intrusive/detail/slist_node.hpp | 18 +- .../intrusive/detail/transform_iterator.hpp | 2 +- .../intrusive/detail/tree_algorithms.hpp | 166 +++++++++----- include/boost/intrusive/detail/tree_node.hpp | 31 +-- include/boost/intrusive/detail/utilities.hpp | 150 +++++++------ include/boost/intrusive/detail/workaround.hpp | 2 +- include/boost/intrusive/hashtable.hpp | 78 +++---- include/boost/intrusive/intrusive_fwd.hpp | 2 +- .../intrusive/linear_slist_algorithms.hpp | 4 +- include/boost/intrusive/link_mode.hpp | 2 +- include/boost/intrusive/list.hpp | 5 +- include/boost/intrusive/list_hook.hpp | 4 +- .../boost/intrusive/member_value_traits.hpp | 2 +- include/boost/intrusive/options.hpp | 2 +- include/boost/intrusive/pointer_plus_bits.hpp | 4 +- include/boost/intrusive/priority_compare.hpp | 2 +- include/boost/intrusive/rbtree.hpp | 76 ++++++- include/boost/intrusive/rbtree_algorithms.hpp | 62 +++++- include/boost/intrusive/set.hpp | 107 ++++++++- include/boost/intrusive/set_hook.hpp | 4 +- include/boost/intrusive/sg_set.hpp | 111 ++++++++- include/boost/intrusive/sgtree.hpp | 87 +++++++- include/boost/intrusive/sgtree_algorithms.hpp | 70 ++++++ include/boost/intrusive/slist.hpp | 210 ++++++++++++++---- include/boost/intrusive/slist_hook.hpp | 4 +- include/boost/intrusive/splay_set.hpp | 4 +- include/boost/intrusive/splay_set_hook.hpp | 4 +- include/boost/intrusive/splaytree.hpp | 5 +- .../boost/intrusive/splaytree_algorithms.hpp | 99 ++++++++- include/boost/intrusive/treap.hpp | 187 +++++++++++----- include/boost/intrusive/treap_algorithms.hpp | 165 +++++++++++--- include/boost/intrusive/treap_set.hpp | 207 ++++++++++++++--- .../boost/intrusive/trivial_value_traits.hpp | 2 +- include/boost/intrusive/unordered_set.hpp | 49 ++-- .../boost/intrusive/unordered_set_hook.hpp | 4 +- 59 files changed, 1956 insertions(+), 471 deletions(-) create mode 100644 include/boost/intrusive/detail/function_detector.hpp create mode 100644 include/boost/intrusive/detail/is_stateful_value_traits.hpp diff --git a/include/boost/intrusive/any_hook.hpp b/include/boost/intrusive/any_hook.hpp index 29a5b08..b1b0194 100644 --- a/include/boost/intrusive/any_hook.hpp +++ b/include/boost/intrusive/any_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index 3998f05..a944077 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -489,6 +489,60 @@ class avl_set_impl void insert(Iterator b, Iterator e) { tree_.insert_unique(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" or "value" is not unique tree ordering and uniqueness + //! invariants will be broken respectively. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than or equal to the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than or equal to the the mimum inserted key tree ordering or uniqueness + //! invariants will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. @@ -1532,9 +1586,63 @@ class avl_multiset_impl void insert(Iterator b, Iterator e) { tree_.insert_equal(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" or "value" is not unique tree ordering and uniqueness + //! invariants will be broken respectively. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than or equal to the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than or equal to the the mimum inserted key tree ordering or uniqueness + //! invariants will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! - //! Complexity: Average complexity is constant time. + //! Complexity: Average complexity is constant time. //! //! Returns: An iterator to the element after the erased element. //! diff --git a/include/boost/intrusive/avl_set_hook.hpp b/include/boost/intrusive/avl_set_hook.hpp index 00d2fc8..23b1f0b 100644 --- a/include/boost/intrusive/avl_set_hook.hpp +++ b/include/boost/intrusive/avl_set_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -96,6 +96,7 @@ class avl_set_base_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -221,6 +222,7 @@ class avl_set_member_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! 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 c247e32..e65f182 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -704,6 +704,76 @@ class avltree_impl return iterator(to_insert, this); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_before + (node_ptr(&priv_header()), pos.pointed_node(), to_insert), this); + } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::push_back(node_ptr(&priv_header()), to_insert); + } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::push_front(node_ptr(&priv_header()), to_insert); + } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity for erase element is constant time. diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 6385ff9..a632581 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -530,6 +530,66 @@ class avltree_algorithms return new_node; } + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid iterator or header (end) node. + //! "pos" must be an iterator pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node) + { + tree_algorithms::insert_before(header, pos, new_node); + rebalance_after_insertion(header, new_node); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_back(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_back(header, new_node); + rebalance_after_insertion(header, new_node); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_front(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_front(header, new_node); + rebalance_after_insertion(header, new_node); + } + //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the diff --git a/include/boost/intrusive/bs_set_hook.hpp b/include/boost/intrusive/bs_set_hook.hpp index 3ab0310..bf8e2de 100644 --- a/include/boost/intrusive/bs_set_hook.hpp +++ b/include/boost/intrusive/bs_set_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -96,6 +96,7 @@ class bs_set_base_hook { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -220,6 +221,7 @@ class bs_set_member_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! 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/circular_list_algorithms.hpp b/include/boost/intrusive/circular_list_algorithms.hpp index aeb0358..16b1971 100644 --- a/include/boost/intrusive/circular_list_algorithms.hpp +++ b/include/boost/intrusive/circular_list_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -110,7 +110,7 @@ class circular_list_algorithms //! Effects: Returns the number of nodes in a circular list. If the circular list //! is empty, returns 1. //! - //! Complexity: Constant + //! Complexity: Linear //! //! Throws: Nothing. static std::size_t count(const_node_ptr this_node) diff --git a/include/boost/intrusive/circular_slist_algorithms.hpp b/include/boost/intrusive/circular_slist_algorithms.hpp index cb9cb3b..ae06396 100644 --- a/include/boost/intrusive/circular_slist_algorithms.hpp +++ b/include/boost/intrusive/circular_slist_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -199,7 +199,7 @@ class circular_slist_algorithms //! Effects: Returns the number of nodes in a circular list. If the circular list //! is empty, returns 1. //! - //! Complexity: Constant + //! Complexity: Linear //! //! Throws: Nothing. static std::size_t count(const_node_ptr this_node) diff --git a/include/boost/intrusive/derivation_value_traits.hpp b/include/boost/intrusive/derivation_value_traits.hpp index 58467d5..88edeab 100644 --- a/include/boost/intrusive/derivation_value_traits.hpp +++ b/include/boost/intrusive/derivation_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/any_node_and_algorithms.hpp b/include/boost/intrusive/detail/any_node_and_algorithms.hpp index 6a3d955..e2fbbfa 100644 --- a/include/boost/intrusive/detail/any_node_and_algorithms.hpp +++ b/include/boost/intrusive/detail/any_node_and_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/assert.hpp b/include/boost/intrusive/detail/assert.hpp index 0fe98f8..cfe392b 100644 --- a/include/boost/intrusive/detail/assert.hpp +++ b/include/boost/intrusive/detail/assert.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/clear_on_destructor_base.hpp b/include/boost/intrusive/detail/clear_on_destructor_base.hpp index 838dd67..6765dfa 100644 --- a/include/boost/intrusive/detail/clear_on_destructor_base.hpp +++ b/include/boost/intrusive/detail/clear_on_destructor_base.hpp @@ -1,6 +1,6 @@ //////} // /////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2008. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2009. 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) // diff --git a/include/boost/intrusive/detail/common_slist_algorithms.hpp b/include/boost/intrusive/detail/common_slist_algorithms.hpp index d837ad0..c6bdb20 100644 --- a/include/boost/intrusive/detail/common_slist_algorithms.hpp +++ b/include/boost/intrusive/detail/common_slist_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -74,15 +74,22 @@ class common_slist_algorithms NodeTraits::set_next(prev_node, this_node); } - static void transfer_after(node_ptr p, node_ptr b, node_ptr e) + static void incorporate_after(node_ptr bp, node_ptr b, node_ptr be) { - if (p != b && p != e && b != e) { - node_ptr next_b = NodeTraits::get_next(b); - node_ptr next_e = NodeTraits::get_next(e); - node_ptr next_p = NodeTraits::get_next(p); - NodeTraits::set_next(b, next_e); - NodeTraits::set_next(e, next_p); - NodeTraits::set_next(p, next_b); + node_ptr p(NodeTraits::get_next(bp)); + NodeTraits::set_next(bp, b); + NodeTraits::set_next(be, p); + } + + static void transfer_after(node_ptr bp, node_ptr bb, node_ptr be) + { + if (bp != bb && bp != be && bb != be) { + node_ptr next_b = NodeTraits::get_next(bb); + node_ptr next_e = NodeTraits::get_next(be); + node_ptr next_p = NodeTraits::get_next(bp); + NodeTraits::set_next(bb, next_e); + NodeTraits::set_next(be, next_p); + NodeTraits::set_next(bp, next_b); } } }; diff --git a/include/boost/intrusive/detail/config_begin.hpp b/include/boost/intrusive/detail/config_begin.hpp index 1c390be..bb126fc 100644 --- a/include/boost/intrusive/detail/config_begin.hpp +++ b/include/boost/intrusive/detail/config_begin.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/config_end.hpp b/include/boost/intrusive/detail/config_end.hpp index f04b2e9..4277cb5 100644 --- a/include/boost/intrusive/detail/config_end.hpp +++ b/include/boost/intrusive/detail/config_end.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/ebo_functor_holder.hpp b/include/boost/intrusive/detail/ebo_functor_holder.hpp index 35628f2..d4c2d15 100644 --- a/include/boost/intrusive/detail/ebo_functor_holder.hpp +++ b/include/boost/intrusive/detail/ebo_functor_holder.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Joaquin M Lopez Munoz 2006-2008 +// (C) Copyright Joaquin M Lopez Munoz 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -13,6 +13,7 @@ #ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP #define BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP +#include #include namespace boost { @@ -89,4 +90,6 @@ class ebo_functor_holder } //namespace intrusive { } //namespace boost { +#include + #endif //#ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP diff --git a/include/boost/intrusive/detail/function_detector.hpp b/include/boost/intrusive/detail/function_detector.hpp new file mode 100644 index 0000000..a20db6d --- /dev/null +++ b/include/boost/intrusive/detail/function_detector.hpp @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2009. +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +// This code was modified from the code posted by Alexandre Courpron in his +// article "Interface Detection" in The Code Project: +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2007 Alexandre Courpron +// +// Permission to use, copy, modify, redistribute and sell this software, +// provided that this copyright notice appears on all copies of the software. +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_FUNCTION_DETECTOR_HPP +#define BOOST_INTRUSIVE_DETAIL_FUNCTION_DETECTOR_HPP + +#include + +namespace boost { +namespace intrusive { +namespace function_detector { + + typedef char NotFoundType; + struct StaticFunctionType { NotFoundType x [2]; }; + struct NonStaticFunctionType { NotFoundType x [3]; }; + + enum + { NotFound = 0, + StaticFunction = sizeof( StaticFunctionType ) - sizeof( NotFoundType ), + NonStaticFunction = sizeof( NonStaticFunctionType ) - sizeof( NotFoundType ) + }; + +} //namespace boost { +} //namespace intrusive { +} //namespace function_detector { + +#define BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(Identifier, InstantiationKey) \ + namespace boost { \ + namespace intrusive { \ + namespace function_detector { \ + template < class T, \ + class NonStaticType, \ + class NonStaticConstType, \ + class StaticType > \ + class DetectMember_##InstantiationKey_##Identifier { \ + template < NonStaticType > \ + struct TestNonStaticNonConst ; \ + \ + template < NonStaticConstType > \ + struct TestNonStaticConst ; \ + \ + template < StaticType > \ + struct TestStatic ; \ + \ + template \ + static NonStaticFunctionType Test( TestNonStaticNonConst<&U::Identifier>*, int ); \ + \ + template \ + static NonStaticFunctionType Test( TestNonStaticConst<&U::Identifier>*, int ); \ + \ + template \ + static StaticFunctionType Test( TestStatic<&U::Identifier>*, int ); \ + \ + template \ + static NotFoundType Test( ... ); \ + public : \ + static const int check = NotFound + (sizeof(Test(0, 0)) - sizeof(NotFoundType));\ + };\ +}}} //namespace boost::intrusive::function_detector { + +#define BOOST_INTRUSIVE_DETECT_FUNCTION(Class, InstantiationKey, ReturnType, Identifier, Params) \ + ::boost::intrusive::function_detector::DetectMember_##InstantiationKey_##Identifier< Class,\ + ReturnType (Class::*)Params,\ + ReturnType (Class::*)Params const,\ + ReturnType (*)Params \ + >::check + +#include + +#endif //@ifndef BOOST_INTRUSIVE_DETAIL_FUNCTION_DETECTOR_HPP diff --git a/include/boost/intrusive/detail/generic_hook.hpp b/include/boost/intrusive/detail/generic_hook.hpp index 1b4736b..ae1282e 100644 --- a/include/boost/intrusive/detail/generic_hook.hpp +++ b/include/boost/intrusive/detail/generic_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index fbb150d..1676b1c 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -100,8 +100,12 @@ template class hashtable_iterator : public std::iterator < std::forward_iterator_tag + , typename Container::value_type + , typename std::iterator_traits::difference_type , typename detail::add_const_if_c - ::type + ::type * + , typename detail::add_const_if_c + ::type & > { typedef typename Container::real_value_traits real_value_traits; @@ -116,8 +120,11 @@ class hashtable_iterator { return typename Container::node_ptr(&static_cast(*p)); } public: + typedef typename Container::value_type value_type; + typedef typename detail::add_const_if_c + ::type *pointer; typedef typename detail::add_const_if_c - ::type value_type; + ::type &reference; hashtable_iterator () {} @@ -133,6 +140,9 @@ class hashtable_iterator const siterator &slist_it() const { return slist_it_; } + hashtable_iterator unconst() const + { return hashtable_iterator(this->slist_it(), this->get_container()); } + public: hashtable_iterator& operator++() { this->increment(); return *this; } @@ -150,10 +160,10 @@ class hashtable_iterator friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2) { return !(i == i2); } - value_type& operator*() const + reference operator*() const { return *this->operator ->(); } - value_type* operator->() const + pointer operator->() const { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node()))); } const Container *get_container() const diff --git a/include/boost/intrusive/detail/is_stateful_value_traits.hpp b/include/boost/intrusive/detail/is_stateful_value_traits.hpp new file mode 100644 index 0000000..a11f988 --- /dev/null +++ b/include/boost/intrusive/detail/is_stateful_value_traits.hpp @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2009. +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP +#define BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP + +#include +#include + +BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(to_node_ptr, boost_intrusive) +BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(to_value_ptr, boost_intrusive) + +namespace boost { +namespace intrusive { +namespace detail { + +template +struct is_stateful_value_traits +{ + typedef typename ValueTraits::node_ptr node_ptr; + typedef typename ValueTraits::pointer pointer; + typedef typename ValueTraits::value_type value_type; + typedef typename ValueTraits::const_node_ptr const_node_ptr; + typedef typename ValueTraits::const_pointer const_pointer; + + typedef ValueTraits value_traits; + + static const bool value = + (boost::intrusive::function_detector::NonStaticFunction == + (BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, node_ptr, to_node_ptr, (value_type&) ))) + || + (boost::intrusive::function_detector::NonStaticFunction == + (BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, pointer, to_value_ptr, (node_ptr) ))) + || + (boost::intrusive::function_detector::NonStaticFunction == + (BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, const_node_ptr, to_node_ptr, (const value_type&) ))) + || + (boost::intrusive::function_detector::NonStaticFunction == + (BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, const_pointer, to_value_ptr, (const_node_ptr) ))) + ; +}; + +}}} + +#include + +#endif //@ifndef BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP diff --git a/include/boost/intrusive/detail/list_node.hpp b/include/boost/intrusive/detail/list_node.hpp index effd36a..935c522 100644 --- a/include/boost/intrusive/detail/list_node.hpp +++ b/include/boost/intrusive/detail/list_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -63,8 +63,12 @@ template class list_iterator : public std::iterator < std::bidirectional_iterator_tag + , typename Container::value_type + , typename std::iterator_traits::difference_type , typename detail::add_const_if_c - ::type + ::type * + , typename detail::add_const_if_c + ::type & > { protected: @@ -78,11 +82,11 @@ class list_iterator detail::store_cont_ptr_on_it::value; public: + typedef typename Container::value_type value_type; + typedef typename detail::add_const_if_c + ::type *pointer; typedef typename detail::add_const_if_c - - ::type value_type; - typedef value_type & reference; - typedef value_type * pointer; + ::type &reference; list_iterator() : members_ (node_ptr(0), 0) @@ -135,7 +139,7 @@ class list_iterator bool operator!= (const list_iterator& i) const { return !operator== (i); } - value_type& operator*() const + reference operator*() const { return *operator->(); } pointer operator->() const diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index 20f50da..5f57e37 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -13,6 +13,7 @@ #ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP #define BOOST_INTRUSIVE_DETAIL_MPL_HPP +#include #include namespace boost { @@ -364,4 +365,6 @@ struct ls_zeros<1> } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_DETAIL_MPL_HPP diff --git a/include/boost/intrusive/detail/parent_from_member.hpp b/include/boost/intrusive/detail/parent_from_member.hpp index c750ad8..0b30867 100644 --- a/include/boost/intrusive/detail/parent_from_member.hpp +++ b/include/boost/intrusive/detail/parent_from_member.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/rbtree_node.hpp b/include/boost/intrusive/detail/rbtree_node.hpp index 6d6dd84..87ba59d 100644 --- a/include/boost/intrusive/detail/rbtree_node.hpp +++ b/include/boost/intrusive/detail/rbtree_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/slist_node.hpp b/include/boost/intrusive/detail/slist_node.hpp index 4101092..a7df9e1 100644 --- a/include/boost/intrusive/detail/slist_node.hpp +++ b/include/boost/intrusive/detail/slist_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -55,8 +55,12 @@ template class slist_iterator : public std::iterator < std::forward_iterator_tag + , typename Container::value_type + , typename std::iterator_traits::difference_type , typename detail::add_const_if_c - ::type + ::type * + , typename detail::add_const_if_c + ::type & > { protected: @@ -70,11 +74,11 @@ class slist_iterator detail::store_cont_ptr_on_it::value; public: + typedef typename Container::value_type value_type; + typedef typename detail::add_const_if_c + ::type *pointer; typedef typename detail::add_const_if_c - - ::type value_type; - typedef value_type & reference; - typedef value_type * pointer; + ::type &reference; slist_iterator() : members_ (node_ptr(0), 0) @@ -114,7 +118,7 @@ class slist_iterator bool operator!= (const slist_iterator& i) const { return !operator== (i); } - value_type& operator*() const + reference operator*() const { return *operator->(); } pointer operator->() const diff --git a/include/boost/intrusive/detail/transform_iterator.hpp b/include/boost/intrusive/detail/transform_iterator.hpp index a4afd77..a9de49e 100644 --- a/include/boost/intrusive/detail/transform_iterator.hpp +++ b/include/boost/intrusive/detail/transform_iterator.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/detail/tree_algorithms.hpp index 57d5206..32bbfb5 100644 --- a/include/boost/intrusive/detail/tree_algorithms.hpp +++ b/include/boost/intrusive/detail/tree_algorithms.hpp @@ -160,7 +160,7 @@ class tree_algorithms //! //! Throws: Nothing. static bool unique(const_node_ptr node) - { return NodeTraits::get_parent(node) == 0; } + { return !NodeTraits::get_parent(node); } static node_ptr get_header(const_node_ptr node) { @@ -460,7 +460,8 @@ class tree_algorithms static node_ptr prev_node(node_ptr p) { if(is_header(p)){ - return maximum(NodeTraits::get_parent(p)); + return NodeTraits::get_right(p); + //return maximum(NodeTraits::get_parent(p)); } else if(NodeTraits::get_left(p)){ return maximum(NodeTraits::get_left(p)); @@ -721,21 +722,19 @@ class tree_algorithms static bool is_header(const_node_ptr p) { - bool is_header = false; - if(NodeTraits::get_parent(p) == p){ - is_header = true; + node_ptr p_left (NodeTraits::get_left(p)); + node_ptr p_right(NodeTraits::get_right(p)); + if(!NodeTraits::get_parent(p) || //Header condition when empty tree + (p_left && p_right && //Header always has leftmost and rightmost + (p_left == p_right || //Header condition when only node + (NodeTraits::get_parent(p_left) != p || + NodeTraits::get_parent(p_right) != p )) + //When tree size > 1 headers can't be leftmost's + //and rightmost's parent + )){ + return true; } - else if(NodeTraits::get_parent(NodeTraits::get_parent(p)) == p){ - if(NodeTraits::get_left(p) != 0){ - if(NodeTraits::get_parent(NodeTraits::get_left(p)) != p){ - is_header = true; - } - if(NodeTraits::get_parent(p) == NodeTraits::get_left(p)){ - is_header = true; - } - } - } - return is_header; + return false; } //! Requires: "header" must be the header node of a tree. @@ -894,10 +893,32 @@ class tree_algorithms //! erased between the "insert_check" and "insert_commit" calls. static void insert_unique_commit (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data) + { return insert_commit(header, new_value, commit_data); } + + static void insert_commit + (node_ptr header, node_ptr new_node, const insert_commit_data &commit_data) { //Check if commit_data has not been initialized by a insert_unique_check call. BOOST_INTRUSIVE_INVARIANT_ASSERT(commit_data.node != 0); - link(header, new_value, commit_data.node, commit_data.link_left); + node_ptr parent_node(commit_data.node); + if(parent_node == header){ + NodeTraits::set_parent(header, new_node); + NodeTraits::set_right(header, new_node); + NodeTraits::set_left(header, new_node); + } + else if(commit_data.link_left){ + NodeTraits::set_left(parent_node, new_node); + if(parent_node == NodeTraits::get_left(header)) + NodeTraits::set_left(header, new_node); + } + else{ + NodeTraits::set_right(parent_node, new_node); + if(parent_node == NodeTraits::get_right(header)) + NodeTraits::set_right(header, new_node); + } + NodeTraits::set_parent(new_node, parent_node); + NodeTraits::set_right(new_node, node_ptr(0)); + NodeTraits::set_left(new_node, node_ptr(0)); } //! Requires: "header" must be the header node of a tree. @@ -979,9 +1000,9 @@ class tree_algorithms { //hint must be bigger than the key if(hint == header || comp(key, hint)){ - node_ptr prev = hint; - //The previous value should be less than the key - if(prev == NodeTraits::get_left(header) || comp((prev = prev_node(hint)), key)){ + node_ptr prev(hint); + //Previous value should be less than the key + if(hint == begin_node(header)|| comp((prev = prev_node(hint)), key)){ commit_data.link_left = unique(header) || !NodeTraits::get_left(hint); commit_data.node = commit_data.link_left ? hint : prev; if(pdepth){ @@ -989,14 +1010,9 @@ class tree_algorithms } return std::pair(node_ptr(), true); } - else{ - return insert_unique_check(header, key, comp, commit_data, pdepth); - } - } - //The hint was wrong, use hintless insert - else{ - return insert_unique_check(header, key, comp, commit_data, pdepth); } + //Hint was wrong, use hintless insertion + return insert_unique_check(header, key, comp, commit_data, pdepth); } template @@ -1040,7 +1056,7 @@ class tree_algorithms { insert_commit_data commit_data; insert_equal_check(h, hint, new_node, comp, commit_data, pdepth); - link(h, new_node, commit_data.node, commit_data.link_left); + insert_commit(h, new_node, commit_data); return new_node; } @@ -1050,7 +1066,7 @@ class tree_algorithms { insert_commit_data commit_data; insert_equal_upper_bound_check(h, new_node, comp, commit_data, pdepth); - link(h, new_node, commit_data.node, commit_data.link_left); + insert_commit(h, new_node, commit_data); return new_node; } @@ -1060,10 +1076,72 @@ class tree_algorithms { insert_commit_data commit_data; insert_equal_lower_bound_check(h, new_node, comp, commit_data, pdepth); - link(h, new_node, commit_data.node, commit_data.link_left); + insert_commit(h, new_node, commit_data); return new_node; } + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node, std::size_t *pdepth = 0) + { + insert_commit_data commit_data; + insert_before_check(header, pos, commit_data, pdepth); + insert_commit(header, new_node, commit_data); + return new_node; + } + + static void insert_before_check + ( node_ptr header, node_ptr pos + , insert_commit_data &commit_data, std::size_t *pdepth = 0) + { + node_ptr prev(pos); + if(pos != NodeTraits::get_left(header)) + prev = prev_node(pos); + bool link_left = unique(header) || !NodeTraits::get_left(pos); + commit_data.link_left = link_left; + commit_data.node = link_left ? pos : prev; + if(pdepth){ + *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1; + } + } + + static void push_back + (node_ptr header, node_ptr new_node, std::size_t *pdepth = 0) + { + insert_commit_data commit_data; + push_back_check(header, commit_data, pdepth); + insert_commit(header, new_node, commit_data); + } + + static void push_back_check + (node_ptr header, insert_commit_data &commit_data, std::size_t *pdepth = 0) + { + node_ptr prev(NodeTraits::get_right(header)); + if(pdepth){ + *pdepth = prev == header ? 0 : depth(prev) + 1; + } + commit_data.link_left = false; + commit_data.node = prev; + } + + static void push_front + (node_ptr header, node_ptr new_node, std::size_t *pdepth = 0) + { + insert_commit_data commit_data; + push_front_check(header, commit_data, pdepth); + insert_commit(header, new_node, commit_data); + } + + static void push_front_check + (node_ptr header, insert_commit_data &commit_data, std::size_t *pdepth = 0) + { + node_ptr pos(NodeTraits::get_left(header)); + if(pdepth){ + *pdepth = pos == header ? 0 : depth(pos) + 1; + } + commit_data.link_left = true; + commit_data.node = pos; + } + //! Requires: p can't be a header node. //! //! Effects: Calculates the depth of a node: the depth of a @@ -1303,32 +1381,10 @@ class tree_algorithms replace_own_impl(p, x, header, p_old_parent, p_was_left); } - static void link(node_ptr header, node_ptr z, node_ptr par, bool left) - { - if(par == header){ - NodeTraits::set_parent(header, z); - NodeTraits::set_right(header, z); - NodeTraits::set_left(header, z); - } - else if(left){ - NodeTraits::set_left(par, z); - if(par == NodeTraits::get_left(header)) - NodeTraits::set_left(header, z); - } - else{ - NodeTraits::set_right(par, z); - if(par == NodeTraits::get_right(header)) - NodeTraits::set_right(header, z); - } - NodeTraits::set_parent(z, par); - NodeTraits::set_right(z, node_ptr(0)); - NodeTraits::set_left(z, node_ptr(0)); - } - static void erase(node_ptr header, node_ptr z) { data_for_rebalance ignored; - erase(header, z, nop_erase_fixup(), ignored); + erase_impl(header, z, ignored); } struct data_for_rebalance @@ -1609,12 +1665,12 @@ class tree_algorithms NodeTraits::set_parent(x, x_parent); tree_algorithms::replace_own (z, x, header); if(NodeTraits::get_left(header) == z){ - NodeTraits::set_left(header, NodeTraits::get_right(z) == 0 ? // z->get_left() must be null also + NodeTraits::set_left(header, !NodeTraits::get_right(z) ? // z->get_left() must be null also NodeTraits::get_parent(z) : // makes leftmost == header if z == root tree_algorithms::minimum (x)); } if(NodeTraits::get_right(header) == z){ - NodeTraits::set_right(header, NodeTraits::get_left(z) == 0 ? // z->get_right() must be null also + NodeTraits::set_right(header, !NodeTraits::get_left(z) ? // z->get_right() must be null also NodeTraits::get_parent(z) : // makes rightmost == header if z == root tree_algorithms::maximum(x)); } diff --git a/include/boost/intrusive/detail/tree_node.hpp b/include/boost/intrusive/detail/tree_node.hpp index 146f758..3508e85 100644 --- a/include/boost/intrusive/detail/tree_node.hpp +++ b/include/boost/intrusive/detail/tree_node.hpp @@ -72,8 +72,12 @@ template class tree_iterator : public std::iterator < std::bidirectional_iterator_tag + , typename Container::value_type + , typename std::iterator_traits::difference_type , typename detail::add_const_if_c - ::type + ::type * + , typename detail::add_const_if_c + ::type & > { protected: @@ -88,12 +92,11 @@ class tree_iterator detail::store_cont_ptr_on_it::value; public: - public: + typedef typename Container::value_type value_type; + typedef typename detail::add_const_if_c + ::type *pointer; typedef typename detail::add_const_if_c - - ::type value_type; - typedef value_type & reference; - typedef value_type * pointer; + ::type &reference; tree_iterator() : members_ (0, 0) @@ -146,27 +149,17 @@ class tree_iterator bool operator!= (const tree_iterator& i) const { return !operator== (i); } - value_type& operator*() const + reference operator*() const { return *operator->(); } pointer operator->() const { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } const Container *get_container() const - { - if(store_container_ptr) - return static_cast(members_.get_ptr()); - else - return 0; - } + { return static_cast(members_.get_ptr()); } const real_value_traits *get_real_value_traits() const - { - if(store_container_ptr) - return &this->get_container()->get_real_value_traits(); - else - return 0; - } + { return &this->get_container()->get_real_value_traits(); } tree_iterator end_iterator_from_it() const { diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index ab974ff..7846716 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -45,8 +46,7 @@ struct internal_base_hook_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -62,8 +62,7 @@ struct internal_any_hook_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -80,8 +79,7 @@ struct external_value_traits_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -91,8 +89,7 @@ struct external_bucket_traits_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -337,16 +334,6 @@ struct select_constptr >::type type; }; -template -struct store_cont_ptr_on_it -{ - typedef typename Container::value_traits value_traits; - static const bool value = - !detail::is_empty_class::value - || detail::external_value_traits_is_true::value - ; -}; - template struct add_const_if_c { @@ -357,58 +344,6 @@ struct add_const_if_c >::type type; }; -template -struct node_to_value - : public detail::select_constptr - < typename boost::pointer_to_other - ::type - , detail::store_cont_ptr_on_it::value - >::type -{ - static const bool store_container_ptr = - detail::store_cont_ptr_on_it::value; - - typedef typename Container::real_value_traits real_value_traits; - typedef typename real_value_traits::value_type value_type; - typedef typename detail::select_constptr - < typename boost::pointer_to_other - ::type - , store_container_ptr >::type Base; - typedef typename real_value_traits::node_traits::node node; - typedef typename detail::add_const_if_c - ::type vtype; - typedef typename detail::add_const_if_c - ::type ntype; - typedef typename boost::pointer_to_other - ::type npointer; - - node_to_value(const Container *cont) - : Base(cont) - {} - - typedef vtype & result_type; - typedef ntype & first_argument_type; - - const Container *get_container() const - { - if(store_container_ptr) - return static_cast(Base::get_ptr()); - else - return 0; - } - - const real_value_traits *get_real_value_traits() const - { - if(store_container_ptr) - return &this->get_container()->get_real_value_traits(); - else - return 0; - } - - result_type operator()(first_argument_type arg) const - { return *(this->get_real_value_traits()->to_value_ptr(npointer(&arg))); } -}; - template struct link_dispatch {}; @@ -625,6 +560,79 @@ class exception_array_disposer } }; +template +struct store_cont_ptr_on_it_impl +{ + static const bool value = is_stateful_value_traits::value; +}; + +template +struct store_cont_ptr_on_it_impl +{ + static const bool value = false; +}; + +template +struct store_cont_ptr_on_it +{ + typedef typename Container::value_traits value_traits; + static const bool value = store_cont_ptr_on_it_impl + ::value>::value; +}; + +template +struct node_to_value + : public detail::select_constptr + < typename boost::pointer_to_other + ::type + , detail::store_cont_ptr_on_it::value + >::type +{ + static const bool store_container_ptr = + detail::store_cont_ptr_on_it::value; + + typedef typename Container::real_value_traits real_value_traits; + typedef typename real_value_traits::value_type value_type; + typedef typename detail::select_constptr + < typename boost::pointer_to_other + ::type + , store_container_ptr >::type Base; + typedef typename real_value_traits::node_traits::node node; + typedef typename detail::add_const_if_c + ::type vtype; + typedef typename detail::add_const_if_c + ::type ntype; + typedef typename boost::pointer_to_other + ::type npointer; + + node_to_value(const Container *cont) + : Base(cont) + {} + + typedef vtype & result_type; + typedef ntype & first_argument_type; + + const Container *get_container() const + { + if(store_container_ptr) + return static_cast(Base::get_ptr()); + else + return 0; + } + + const real_value_traits *get_real_value_traits() const + { + if(store_container_ptr) + return &this->get_container()->get_real_value_traits(); + else + return 0; + } + + result_type operator()(first_argument_type arg) const + { return *(this->get_real_value_traits()->to_value_ptr(npointer(&arg))); } +}; + + } //namespace detail } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/detail/workaround.hpp b/include/boost/intrusive/detail/workaround.hpp index a4c0974..dd70862 100644 --- a/include/boost/intrusive/detail/workaround.hpp +++ b/include/boost/intrusive/detail/workaround.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2009. 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) // diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index 8f016f7..51cc6c1 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -186,8 +186,7 @@ struct store_hash_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -203,8 +202,7 @@ struct optimize_multikey_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -603,7 +601,7 @@ class hashtable_impl typedef typename real_value_traits::pointer pointer; typedef typename real_value_traits::const_pointer const_pointer; - typedef typename std::iterator_traits::value_type value_type; + typedef typename real_value_traits::value_type value_type; typedef typename std::iterator_traits::reference reference; typedef typename std::iterator_traits::reference const_reference; typedef typename std::iterator_traits::difference_type difference_type; @@ -626,7 +624,7 @@ class hashtable_impl ::type const_node_ptr; typedef typename slist_impl::node_algorithms node_algorithms; - static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; static const bool store_hash = detail::store_hash_is_true::value; static const bool unique_keys = 0 != (Config::bool_flags & detail::hash_bool_flags::unique_keys_pos); @@ -1231,8 +1229,8 @@ class hashtable_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. - void erase(const_iterator i) - { this->erase_and_dispose(i, detail::null_disposer()); } + iterator erase(const_iterator i) + { return this->erase_and_dispose(i, detail::null_disposer()); } //! Effects: Erases the range pointed to by b end e. //! @@ -1243,8 +1241,8 @@ class hashtable_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - void erase(const_iterator b, const_iterator e) - { this->erase_and_dispose(b, e, detail::null_disposer()); } + iterator erase(const_iterator b, const_iterator e) + { return this->erase_and_dispose(b, e, detail::null_disposer()); } //! Effects: Erases all the elements with the given value. //! @@ -1297,19 +1295,20 @@ class hashtable_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator i, Disposer disposer) + iterator erase_and_dispose(const_iterator i, Disposer disposer + /// @cond + , typename detail::enable_if_c::value >::type * = 0 + /// @endcond + ) { + iterator ret(i.unconst()); + ++ret; priv_erase(i, disposer, optimize_multikey_t()); this->priv_size_traits().decrement(); priv_erasure_update_cache(); + return ret; } - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif - //! Requires: Disposer::operator()(pointer) shouldn't throw. //! //! Effects: Erases the range pointed to by b end e. @@ -1323,31 +1322,32 @@ class hashtable_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) { - if(b == e) return; + if(b != e){ + //Get the bucket number and local iterator for both iterators + siterator first_local_it(b.slist_it()); + size_type first_bucket_num = this->priv_get_bucket_num(first_local_it); - //Get the bucket number and local iterator for both iterators - siterator first_local_it(b.slist_it()); - size_type first_bucket_num = this->priv_get_bucket_num(first_local_it); + siterator before_first_local_it + = priv_get_previous(priv_buckets()[first_bucket_num], first_local_it); + size_type last_bucket_num; + siterator last_local_it; - siterator before_first_local_it - = priv_get_previous(priv_buckets()[first_bucket_num], first_local_it); - size_type last_bucket_num; - siterator last_local_it; - - //For the end iterator, we will assign the end iterator - //of the last bucket - if(e == this->end()){ - last_bucket_num = this->bucket_count() - 1; - last_local_it = priv_buckets()[last_bucket_num].end(); + //For the end iterator, we will assign the end iterator + //of the last bucket + if(e == this->end()){ + last_bucket_num = this->bucket_count() - 1; + last_local_it = priv_buckets()[last_bucket_num].end(); + } + else{ + last_local_it = e.slist_it(); + last_bucket_num = this->priv_get_bucket_num(last_local_it); + } + priv_erase_range(before_first_local_it, first_bucket_num, last_local_it, last_bucket_num, disposer); + priv_erasure_update_cache(first_bucket_num, last_bucket_num); } - else{ - last_local_it = e.slist_it(); - last_bucket_num = this->priv_get_bucket_num(last_local_it); - } - priv_erase_range(before_first_local_it, first_bucket_num, last_local_it, last_bucket_num, disposer); - priv_erasure_update_cache(first_bucket_num, last_bucket_num); + return e.unconst(); } //! Requires: Disposer::operator()(pointer) shouldn't throw. diff --git a/include/boost/intrusive/intrusive_fwd.hpp b/include/boost/intrusive/intrusive_fwd.hpp index 5b1e451..7c9b2a1 100644 --- a/include/boost/intrusive/intrusive_fwd.hpp +++ b/include/boost/intrusive/intrusive_fwd.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/linear_slist_algorithms.hpp b/include/boost/intrusive/linear_slist_algorithms.hpp index 9d045a5..193b449 100644 --- a/include/boost/intrusive/linear_slist_algorithms.hpp +++ b/include/boost/intrusive/linear_slist_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -156,7 +156,7 @@ class linear_slist_algorithms //! Effects: Returns the number of nodes in a linear list. If the linear list //! is empty, returns 1. //! - //! Complexity: Constant + //! Complexity: Linear //! //! Throws: Nothing. static std::size_t count(const_node_ptr this_node) diff --git a/include/boost/intrusive/link_mode.hpp b/include/boost/intrusive/link_mode.hpp index 16b9649..17012c9 100644 --- a/include/boost/intrusive/link_mode.hpp +++ b/include/boost/intrusive/link_mode.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index d38d960..2cf3fed 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -106,7 +106,8 @@ class list_impl typedef circular_list_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 stateful_value_traits = detail::is_stateful_value_traits::value; + BOOST_STATIC_ASSERT(( stateful_value_traits == false )); /// @cond diff --git a/include/boost/intrusive/list_hook.hpp b/include/boost/intrusive/list_hook.hpp index 2deceb0..ed93434 100644 --- a/include/boost/intrusive/list_hook.hpp +++ b/include/boost/intrusive/list_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -93,6 +93,7 @@ class list_base_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -214,6 +215,7 @@ class list_member_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! 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/member_value_traits.hpp b/include/boost/intrusive/member_value_traits.hpp index 372334c..ce7e56b 100644 --- a/include/boost/intrusive/member_value_traits.hpp +++ b/include/boost/intrusive/member_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index 8ab0890..d692b1e 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/pointer_plus_bits.hpp b/include/boost/intrusive/pointer_plus_bits.hpp index b2b51e8..10b2fe0 100644 --- a/include/boost/intrusive/pointer_plus_bits.hpp +++ b/include/boost/intrusive/pointer_plus_bits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -50,7 +50,7 @@ template struct pointer_plus_bits; //!This is the specialization to embed extra bits of information -//!in a raw pointer. The extra bits are stored in the lower bit of the pointer. +//!in a raw pointer. The extra bits are stored in the lower bits of the pointer. template struct pointer_plus_bits { diff --git a/include/boost/intrusive/priority_compare.hpp b/include/boost/intrusive/priority_compare.hpp index 9689851..abde27a 100644 --- a/include/boost/intrusive/priority_compare.hpp +++ b/include/boost/intrusive/priority_compare.hpp @@ -23,7 +23,7 @@ namespace intrusive { template struct priority_compare - : public std::binary_function + : public std::binary_function { bool operator()(const T &val, const T &val2) const { diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 572b545..8d9cacf 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -116,8 +117,7 @@ class rbtree_impl typedef rbtree_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 stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: typedef detail::size_holder size_traits; @@ -704,6 +704,76 @@ class rbtree_impl return iterator(to_insert, this); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_before + (node_ptr(&priv_header()), pos.pointed_node(), to_insert), this); + } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::push_back(node_ptr(&priv_header()), to_insert); + } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::push_front(node_ptr(&priv_header()), to_insert); + } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity for erase element is constant time. diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 37140a3..ca6f7eb 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -585,6 +585,66 @@ class rbtree_algorithms return new_node; } + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid iterator or header (end) node. + //! "pos" must be an iterator pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node) + { + tree_algorithms::insert_before(header, pos, new_node); + rebalance_after_insertion(header, new_node); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_back(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_back(header, new_node); + rebalance_after_insertion(header, new_node); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_front(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_front(header, new_node); + rebalance_after_insertion(header, new_node); + } + //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index 40d7c6b..54c5a65 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -490,6 +490,60 @@ class set_impl void insert(Iterator b, Iterator e) { tree_.insert_unique(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" or "value" is not unique tree ordering and uniqueness + //! invariants will be broken respectively. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than or equal to the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than or equal to the the mimum inserted key tree ordering or uniqueness + //! invariants will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. @@ -1533,6 +1587,57 @@ class multiset_impl void insert(Iterator b, Iterator e) { tree_.insert_equal(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. diff --git a/include/boost/intrusive/set_hook.hpp b/include/boost/intrusive/set_hook.hpp index 1420480..35746a2 100644 --- a/include/boost/intrusive/set_hook.hpp +++ b/include/boost/intrusive/set_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -98,6 +98,7 @@ class set_base_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -224,6 +225,7 @@ class set_member_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! 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 4c519c1..3a7c77a 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -381,7 +381,7 @@ class sg_set_impl //! Requires: key_value_comp must be a comparison function that induces //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! key_value_comp compares an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the sg_set, using //! a user provided key instead of the value itself. @@ -416,7 +416,7 @@ class sg_set_impl //! Requires: key_value_comp must be a comparison function that induces //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! key_value_comp compares an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the sg_set, using //! a user provided key instead of the value itself, using "hint" @@ -489,6 +489,60 @@ class sg_set_impl void insert(Iterator b, Iterator e) { tree_.insert_unique(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" or "value" is not unique tree ordering and uniqueness + //! invariants will be broken respectively. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than or equal to the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than or equal to the the mimum inserted key tree ordering or uniqueness + //! invariants will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. @@ -1572,6 +1626,57 @@ class sg_multiset_impl void insert(Iterator b, Iterator e) { tree_.insert_equal(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 0d19919..5507893 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -244,7 +244,7 @@ class sgtree_impl static const bool floating_point = Config::floating_point; static const bool constant_time_size = true; - static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: @@ -871,6 +871,88 @@ class sgtree_impl return iterator(to_insert, this); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + node_ptr p = node_algorithms::insert_before + ( node_ptr(&priv_header()), pos.pointed_node(), to_insert + , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); + data_.max_tree_size_ = (size_type)max_tree_size; + return iterator(p, this); + } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + node_algorithms::push_back + ( node_ptr(&priv_header()), to_insert + , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); + data_.max_tree_size_ = (size_type)max_tree_size; + } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + node_algorithms::push_front + ( node_ptr(&priv_header()), to_insert + , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); + data_.max_tree_size_ = (size_type)max_tree_size; + } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity for erase element is constant time. @@ -1071,7 +1153,6 @@ class sgtree_impl { node_algorithms::clear_and_dispose(node_ptr(&priv_header()) , detail::node_disposer(disposer, this)); - node_algorithms::init_header(&priv_header()); this->priv_size_traits().set_size(0); } diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index c9af84f..bb6ef06 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -539,6 +539,76 @@ class sgtree_algorithms return ret; } + + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid iterator or header (end) node. + //! "pos" must be an iterator pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + template + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + tree_algorithms::insert_before(header, pos, new_node, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + template + static void push_back(node_ptr header, node_ptr new_node + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + tree_algorithms::push_back(header, new_node, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + template + static void push_front(node_ptr header, node_ptr new_node + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + tree_algorithms::push_front(header, new_node, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + } + //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index e430fb1..8314a75 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -140,7 +140,7 @@ class slist_impl >::type 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 stateful_value_traits = detail::is_stateful_value_traits::value; static const bool linear = Config::linear; static const bool cache_last = Config::cache_last; @@ -539,6 +539,36 @@ class slist_impl const_iterator cbefore_begin() const { return this->before_begin(); } + //! Effects: Returns an iterator to the last element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: This function is present only if cached_last<> option is true. + iterator last() + { return iterator (this->get_last_node(), this); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: This function is present only if cached_last<> option is true. + const_iterator last() const + { return const_iterator (this->get_last_node(), this); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: This function is present only if cached_last<> option is true. + const_iterator clast() const + { return const_iterator(this->get_last_node(), this); } + //! Precondition: end_iterator must be a valid end iterator //! of slist. //! @@ -1058,20 +1088,31 @@ class slist_impl //! Effects: Transfers all the elements of list x to this list, after the //! the element pointed by prev. No destructors or copy constructors are called. //! - //! Returns: The last element inserted of x or prev if x is empty. - //! This iterator can be used as new "prev" iterator for a new splice_after call. - //! that will splice new values after the previously spliced values. + //! Returns: Nothing. //! //! Throws: Nothing. //! - //! Complexity: Linear to the elements contained in x. - //! Constant-time if cache_last<> option is true. + //! Complexity: In general, linear to the elements contained in x. + //! Constant-time if cache_last<> option is true and also constant-time if + //! linear<> option is true "this" is empty and "last" is not used. //! //! 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(const_iterator prev, slist_impl &x) + //! + //! Additional note: If the optional parameter "last" is provided, it will be + //! assigned to the last spliced element or prev if x is empty. + //! This iterator can be used as new "prev" iterator for a new splice_after call. + //! that will splice new values after the previously spliced values. + void splice_after(const_iterator prev, slist_impl &x, const_iterator *last = 0) { - if (!x.empty()){ + if(x.empty()){ + if(last) *last = prev; + } + else if(linear && this->empty()){ + this->swap(x); + if(last) *last = this->previous(this->cend()); + } + else{ 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()); @@ -1084,10 +1125,7 @@ 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.unconst(); - } - else{ - return prev.unconst(); + if(last) *last = last_x; } } @@ -1166,10 +1204,7 @@ class slist_impl //! Effects: Transfers all the elements of list x to this list, before the //! the element pointed by it. No destructors or copy constructors are called. //! - //! Returns: The last element inserted of x or the previous element - //! of it if x is empty. - //! This iterator can be used as new "prev" iterator for a new splice call. - //! that will splice new values after the previously spliced values. + //! Returns: Nothing. //! //! Throws: Nothing. //! @@ -1180,8 +1215,13 @@ 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(const_iterator it, slist_impl &x) - { return this->splice_after(this->previous(it), x); } + //! + //! Additional note: If the optional parameter "last" is provided, it will be + //! assigned to the last spliced element or prev if x is empty. + //! This iterator can be used as new "prev" iterator for a new splice_after call. + //! that will splice new values after the previously spliced values. + void splice(const_iterator it, slist_impl &x, iterator *last = 0) + { this->splice_after(this->previous(it), x, last); } //! Requires: it p must be a valid iterator of *this. //! elem must point to an element contained in list @@ -1254,7 +1294,7 @@ class slist_impl void sort(Predicate p) { if (node_traits::get_next(node_traits::get_next(this->get_root_node())) - != this->get_root_node()) { + != this->get_root_node()) { slist_impl carry; slist_impl counter[64]; int fill = 0; @@ -1265,33 +1305,28 @@ class slist_impl int i = 0; while(i < fill && !counter[i].empty()) { carry.swap(counter[i]); - last_inserted = carry.merge(counter[i++], p); + carry.merge(counter[i++], p, &last_inserted); } BOOST_INTRUSIVE_INVARIANT_ASSERT(counter[i].empty()); + const_iterator last_element(carry.previous(last_inserted, carry.end())); - node_ptr p = node_algorithms::get_previous_node - (last_inserted.pointed_node(), carry.cend().pointed_node()); - const_iterator last_element(p, this); if(constant_time_size){ counter[i].splice_after( counter[i].cbefore_begin(), carry - , carry.cbefore_begin(), last_element - , carry.size()); + , carry.cbefore_begin(), last_element + , carry.size()); } else{ counter[i].splice_after( counter[i].cbefore_begin(), carry - , carry.cbefore_begin(), last_element); + , carry.cbefore_begin(), last_element); } if(i == fill) ++fill; } for (int i = 1; i < fill; ++i) - last_inserted = counter[i].merge(counter[i-1], p); - BOOST_INTRUSIVE_INVARIANT_ASSERT(this->empty()); - - node_ptr p = node_algorithms::get_previous_node - (last_inserted.pointed_node(), counter[--fill].end().pointed_node()); - const_iterator last_element(p, this); + counter[i].merge(counter[i-1], p, &last_inserted); + --fill; + const_iterator last_element(counter[fill].previous(last_inserted, counter[fill].end())); if(constant_time_size){ this->splice_after( cbefore_begin(), counter[fill], counter[fill].cbefore_begin() , last_element, counter[fill].size()); @@ -1330,7 +1365,7 @@ class slist_impl //! in order into *this. The merge is stable; that is, if an element from *this is //! equivalent to one from x, then the element from *this will precede the one from x. //! - //! Returns: An iterator to the last transferred value, end() is x is empty. + //! Returns: Nothing. //! //! Throws: If the predicate throws. Basic guarantee. //! @@ -1338,11 +1373,15 @@ class slist_impl //! size() + x.size() - 1 comparisons. //! //! Note: Iterators and references are not invalidated. + //! + //! Additional note: If optional "last" argument is passed, it is assigned + //! to an iterator to the last transferred value or end() is x is empty. template - iterator merge(slist_impl& x, Predicate p) + void merge(slist_impl& x, Predicate p, const_iterator *last = 0) { const_iterator e(this->cend()), ex(x.cend()), bb(this->cbefore_begin()), - bb_next, last_inserted(e); + bb_next; + if(last) *last = e.unconst(); while(!x.empty()){ const_iterator ibx_next(x.cbefore_begin()), ibx(ibx_next++); while (++(bb_next = bb) != e && !p(*ibx_next, *bb_next)){ @@ -1350,7 +1389,7 @@ class slist_impl } if(bb_next == e){ //Now transfer the rest to the end of the container - last_inserted = this->splice_after(bb, x); + this->splice_after(bb, x, last); break; } else{ @@ -1359,10 +1398,9 @@ class slist_impl ibx = ibx_next; ++n; } while(++(ibx_next = ibx) != ex && p(*ibx_next, *bb_next)); this->splice_after(bb, x, x.before_begin(), ibx, n); - last_inserted = ibx; + if(last) *last = ibx; } } - return last_inserted.unconst(); } //! Effects: This function removes all of x's elements and inserts them @@ -1618,14 +1656,7 @@ class slist_impl //! Complexity: Linear to the number of elements before i. //! Constant if cache_last<> is true and i == end(). iterator previous(iterator i) - { - if(cache_last && (i.pointed_node() == this->get_end_node())){ - return iterator(this->get_last_node(), this); - } - return iterator - (node_algorithms::get_previous_node - (this->before_begin().pointed_node(), i.pointed_node()), this); - } + { return this->previous(this->cbefore_begin(), i); } //! Returns: The const_iterator to the element before i in the list. //! Returns the end-const_iterator, if either i is the begin-const_iterator or @@ -1636,13 +1667,86 @@ class slist_impl //! Complexity: Linear to the number of elements before i. //! Constant if cache_last<> is true and i == end(). const_iterator previous(const_iterator i) const + { return this->previous(this->cbefore_begin(), i); } + + //! Returns: The iterator to the element before i in the list, + //! starting the search on element after prev_from. + //! Returns the end-iterator, if either i is the begin-iterator or the + //! list is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + //! Constant if cache_last<> is true and i == end(). + iterator previous(const_iterator prev_from, iterator i) + { return this->previous(prev_from, const_iterator(i)).unconst(); } + + //! Returns: The const_iterator to the element before i in the list, + //! starting the search on element after prev_from. + //! Returns the end-const_iterator, if either i is the begin-const_iterator or + //! the list is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + //! Constant if cache_last<> is true and i == end(). + const_iterator previous(const_iterator prev_from, const_iterator i) const { if(cache_last && (i.pointed_node() == this->get_end_node())){ return const_iterator(uncast(this->get_last_node()), this); } return const_iterator (node_algorithms::get_previous_node - (this->before_begin().pointed_node(), i.pointed_node()), this); + (prev_from.pointed_node(), i.pointed_node()), this); + } + + //! Requires: prev_pos must be a dereferenceable iterator in *this or be + //! before_begin(), and before_first and before_last belong to x and + //! ++before_first != x.end() && before_last != x.end(). + //! + //! Effects: Transfers the range (before_first, before_last] to this + //! list, after the element pointed by prev_pos. + //! No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements transferred + //! if constant_time_size is true. Constant-time otherwise. + //! + //! 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 incorporate_after(const_iterator prev_from, node_ptr first, node_ptr before_last) + { + if(constant_time_size) + this->incorporate_after(prev_from, first, before_last, std::distance(first, before_last)+1); + else + this->priv_incorporate_after + (prev_from.pointed_node(), first, before_last); + } + + //! Requires: prev_pos must be a dereferenceable iterator in *this or be + //! before_begin(), and before_first and before_last belong to x and + //! ++before_first != x.end() && before_last != x.end() and + //! n == std::distance(first, before_last) + 1. + //! + //! Effects: Transfers the range (before_first, before_last] from list x to this + //! list, after the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! 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 incorporate_after(const_iterator prev_pos, node_ptr first, node_ptr before_last, difference_type n) + { + if(n){ + BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(iterator(first, this), iterator(before_last, this))+1 == n); + this->priv_incorporate_after(prev_pos.pointed_node(), first, before_last); + if(constant_time_size){ + this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n); + } + } } private: @@ -1662,6 +1766,16 @@ class slist_impl } } + void priv_incorporate_after(node_ptr prev_pos_n, node_ptr first_n, node_ptr before_last_n) + { + if(cache_last){ + if(node_traits::get_next(prev_pos_n) == this->get_end_node()){ + this->set_last_node(before_last_n); + } + } + node_algorithms::incorporate_after(prev_pos_n, first_n, before_last_n); + } + void priv_reverse(detail::bool_) { node_algorithms::reverse(this->get_root_node()); } diff --git a/include/boost/intrusive/slist_hook.hpp b/include/boost/intrusive/slist_hook.hpp index 7779b98..1debe66 100644 --- a/include/boost/intrusive/slist_hook.hpp +++ b/include/boost/intrusive/slist_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -96,6 +96,7 @@ class slist_base_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -218,6 +219,7 @@ class slist_member_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! 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 79bdbc1..9727d14 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -624,7 +624,7 @@ class splay_set_impl /// @cond , typename detail::enable_if_c::value >::type * = 0 /// @endcond -) + ) { return tree_.erase_and_dispose(key, comp, disposer); } //! Effects: Erases all the elements of the container. diff --git a/include/boost/intrusive/splay_set_hook.hpp b/include/boost/intrusive/splay_set_hook.hpp index 472fde3..d42f4c8 100644 --- a/include/boost/intrusive/splay_set_hook.hpp +++ b/include/boost/intrusive/splay_set_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -93,6 +93,7 @@ class splay_set_base_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -216,6 +217,7 @@ class splay_set_member_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! 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 971f846..4020c85 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -115,7 +115,7 @@ class splaytree_impl typedef splaytree_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 stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: @@ -895,7 +895,6 @@ class splaytree_impl { node_algorithms::clear_and_dispose(node_ptr(&priv_header()) , detail::node_disposer(disposer, this)); - node_algorithms::init_header(&priv_header()); this->priv_size_traits().set_size(0); } diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index e727ab6..eb25e9f 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -543,6 +543,79 @@ class splaytree_algorithms return tree_algorithms::insert_equal(header, hint, new_node, comp); } + + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid iterator or header (end) node. + //! "pos" must be an iterator pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node) + { + tree_algorithms::insert_before(header, pos, new_node); + splay_up(new_node, header); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_back(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_back(header, new_node); + splay_up(new_node, header); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_front(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_front(header, new_node); + splay_up(new_node, header); + } + + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the upper bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. template static node_ptr insert_equal_upper_bound (node_ptr header, node_ptr new_node, NodePtrCompare comp) @@ -551,6 +624,18 @@ class splaytree_algorithms return tree_algorithms::insert_equal_upper_bound(header, new_node, comp); } + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the lower bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. template static node_ptr insert_equal_lower_bound (node_ptr header, node_ptr new_node, NodePtrCompare comp) @@ -605,9 +690,8 @@ class splaytree_algorithms // if( data_->parent == t ) // data_->parent = find_leftmost(); //posibility 1 - if(splay && NodeTraits::get_left(z) != 0 ){ - node_ptr l = prev_node(z); - splay_up(l, header); + if(splay && NodeTraits::get_left(z)){ + splay_up(prev_node(z), header); } /* //possibility 2 @@ -644,8 +728,8 @@ class splaytree_algorithms if( n == t ) return; for( ;; ){ - node_ptr p = NodeTraits::get_parent(n); - node_ptr g = NodeTraits::get_parent(p); + node_ptr p(NodeTraits::get_parent(n)); + node_ptr g(NodeTraits::get_parent(p)); if( p == t ) break; @@ -688,9 +772,8 @@ class splaytree_algorithms if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t)) return t; //Backup leftmost/rightmost - node_ptr leftmost = NodeTraits::get_left(header); - node_ptr rightmost = NodeTraits::get_right(header); - + node_ptr leftmost (NodeTraits::get_left(header)); + node_ptr rightmost(NodeTraits::get_right(header)); { detail::splaydown_rollback rollback(&t, header, leftmost, rightmost); node_ptr null = header; diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index 7298db3..b7c9ed2 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -119,7 +119,7 @@ class treap_impl typedef treap_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 stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: @@ -217,7 +217,7 @@ class treap_impl typedef typename node_algorithms::insert_commit_data insert_commit_data; - //! Effects: Constructs an empty tree. + //! Effects: Constructs an empty treap. //! //! Complexity: Constant. //! @@ -236,7 +236,7 @@ class treap_impl //! Requires: Dereferencing iterator must yield an lvalue of type value_type. //! cmp must be a comparison function that induces a strict weak ordering. //! - //! Effects: Constructs an empty tree and inserts elements from + //! Effects: Constructs an empty treap and inserts elements from //! [b, e). //! //! Complexity: Linear in N if [b, e) is already sorted using @@ -272,7 +272,7 @@ class treap_impl ~treap_impl() {} - //! Effects: Returns an iterator pointing to the beginning of the tree. + //! Effects: Returns an iterator pointing to the beginning of the treap. //! //! Complexity: Constant. //! @@ -280,7 +280,7 @@ class treap_impl iterator begin() { return iterator (node_traits::get_left(node_ptr(&priv_header())), this); } - //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! Effects: Returns a const_iterator pointing to the beginning of the treap. //! //! Complexity: Constant. //! @@ -288,7 +288,7 @@ class treap_impl const_iterator begin() const { return this->cbegin(); } - //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! Effects: Returns a const_iterator pointing to the beginning of the treap. //! //! Complexity: Constant. //! @@ -296,7 +296,7 @@ class treap_impl const_iterator cbegin() const { return const_iterator (node_traits::get_left(const_node_ptr(&priv_header())), this); } - //! Effects: Returns an iterator pointing to the end of the tree. + //! Effects: Returns an iterator pointing to the end of the treap. //! //! Complexity: Constant. //! @@ -304,7 +304,7 @@ class treap_impl iterator end() { return iterator (node_ptr(&priv_header()), this); } - //! Effects: Returns a const_iterator pointing to the end of the tree. + //! Effects: Returns a const_iterator pointing to the end of the treap. //! //! Complexity: Constant. //! @@ -312,7 +312,7 @@ class treap_impl const_iterator end() const { return this->cend(); } - //! Effects: Returns a const_iterator pointing to the end of the tree. + //! Effects: Returns a const_iterator pointing to the end of the treap. //! //! Complexity: Constant. //! @@ -321,7 +321,7 @@ class treap_impl { return const_iterator (uncast(const_node_ptr(&priv_header())), this); } - //! Effects: Returns an iterator pointing to the highest priority object of the tree. + //! Effects: Returns an iterator pointing to the highest priority object of the treap. //! //! Complexity: Constant. //! @@ -329,7 +329,7 @@ class treap_impl iterator top() { return this->empty() ? this->end() : iterator (node_traits::get_parent(node_ptr(&priv_header())), this); } - //! Effects: Returns a const_iterator pointing to the highest priority object of the tree.. + //! Effects: Returns a const_iterator pointing to the highest priority object of the treap.. //! //! Complexity: Constant. //! @@ -337,7 +337,7 @@ class treap_impl const_iterator top() const { return this->ctop(); } - //! Effects: Returns a const_iterator pointing to the highest priority object of the tree.. + //! Effects: Returns a const_iterator pointing to the highest priority object of the treap.. //! //! Complexity: Constant. //! @@ -346,7 +346,7 @@ class treap_impl { return this->empty() ? this->cend() : const_iterator (node_traits::get_parent(const_node_ptr(&priv_header())), this); } //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed tree. + //! reversed treap. //! //! Complexity: Constant. //! @@ -355,7 +355,7 @@ class treap_impl { return reverse_iterator(this->end()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -364,7 +364,7 @@ class treap_impl { return const_reverse_iterator(this->end()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -373,7 +373,7 @@ class treap_impl { return const_reverse_iterator(this->end()); } //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -382,7 +382,7 @@ class treap_impl { return reverse_iterator(this->begin()); } //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -391,7 +391,7 @@ class treap_impl { return const_reverse_iterator(this->begin()); } //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -400,7 +400,7 @@ class treap_impl { return const_reverse_iterator(this->begin()); } //! Effects: Returns a reverse_iterator pointing to the highest priority object of the - //! reversed tree. + //! reversed treap. //! //! Complexity: Constant. //! @@ -409,7 +409,7 @@ class treap_impl { return reverse_iterator(this->top()); } //! Effects: Returns a const_reverse_iterator pointing to the highest priority objec - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -418,7 +418,7 @@ class treap_impl { return const_reverse_iterator(this->top()); } //! Effects: Returns a const_reverse_iterator pointing to the highest priority object - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -451,7 +451,7 @@ class treap_impl //! Precondition: it must be a valid iterator //! of treap. //! - //! Effects: Returns a const reference to the tree associated to the iterator + //! Effects: Returns a const reference to the treap associated to the iterator //! //! Throws: Nothing. //! @@ -462,7 +462,7 @@ class treap_impl //! Precondition: it must be a valid end const_iterator //! of treap. //! - //! Effects: Returns a const reference to the tree associated to the end iterator + //! Effects: Returns a const reference to the treap associated to the end iterator //! //! Throws: Nothing. //! @@ -470,7 +470,7 @@ class treap_impl static const treap_impl &container_from_iterator(const_iterator it) { return priv_container_from_iterator(it); } - //! Effects: Returns the value_compare object used by the tree. + //! Effects: Returns the value_compare object used by the treap. //! //! Complexity: Constant. //! @@ -478,7 +478,7 @@ class treap_impl value_compare value_comp() const { return this->priv_comp(); } - //! Effects: Returns the priority_compare object used by the tree. + //! Effects: Returns the priority_compare object used by the treap. //! //! Complexity: Constant. //! @@ -494,7 +494,7 @@ class treap_impl bool empty() const { return node_algorithms::unique(const_node_ptr(&priv_header())); } - //! Effects: Returns the number of elements stored in the tree. + //! Effects: Returns the number of elements stored in the treap. //! //! Complexity: Linear to elements contained in *this //! if constant-time size option is disabled. Constant time otherwise. @@ -531,12 +531,12 @@ class treap_impl //! Requires: value must be an lvalue //! - //! Effects: Inserts value into the tree before the upper bound. + //! Effects: Inserts value into the treap before the upper bound. //! //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare functions throw. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -557,14 +557,14 @@ class treap_impl //! Requires: value must be an lvalue, and "hint" must be //! a valid iterator. //! - //! Effects: Inserts x into the tree, using "hint" as a hint to + //! Effects: Inserts x into the treap, using "hint" as a hint to //! where it will be inserted. If "hint" is the upper_bound //! the insertion takes constant time (two comparisons in the worst case) //! //! Complexity: Logarithmic in general, but it is amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare functions throw. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -585,14 +585,14 @@ class treap_impl //! Requires: Dereferencing iterator must yield an lvalue //! of type value_type. //! - //! Effects: Inserts a each element of a range into the tree + //! Effects: Inserts a each element of a range into the treap //! before the upper bound of the key of each element. //! //! Complexity: Insert range is in general O(N * log(N)), where N is the //! size of the range. However, it is linear in N if the range is already sorted //! by value_comp(). //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. + //! Throws: If the internal value_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -607,13 +607,13 @@ class treap_impl //! Requires: value must be an lvalue //! - //! Effects: Inserts value into the tree if the value + //! Effects: Inserts value into the treap if the value //! is not already present. //! //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. + //! Throws: If the internal value_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -630,14 +630,14 @@ class treap_impl //! Requires: value must be an lvalue, and "hint" must be //! a valid iterator //! - //! Effects: Tries to insert x into the tree, using "hint" as a hint + //! Effects: Tries to insert x into the treap, using "hint" as a hint //! to where it will be inserted. //! //! Complexity: Logarithmic in general, but it is amortized //! constant time (two comparisons in the worst case) //! if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. + //! Throws: If the internal value_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -654,13 +654,13 @@ class treap_impl //! Requires: Dereferencing iterator must yield an lvalue //! of type value_type. //! - //! Effects: Tries to insert each element of a range into the tree. + //! Effects: Tries to insert each element of a range into the treap. //! //! Complexity: Insert range is in general O(N * log(N)), where N is the //! size of the range. However, it is linear in N if the range is already sorted //! by value_comp(). //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. + //! Throws: If the internal value_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -680,8 +680,10 @@ class treap_impl } //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. + //! the same strict weak ordering as value_compare. + //! key_value_pcomp must be a comparison function that induces + //! the same strict weak ordering as priority_compare. The difference is that + //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the container, using //! a user provided key instead of the value itself. @@ -694,7 +696,8 @@ class treap_impl //! //! Complexity: Average complexity is at most logarithmic. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If the key_value_comp or key_value_pcomp + //! ordering functions throw. Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -725,8 +728,10 @@ class treap_impl } //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. + //! the same strict weak ordering as value_compare. + //! key_value_pcomp must be a comparison function that induces + //! the same strict weak ordering as priority_compare. The difference is that + //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the container, using //! a user provided key instead of the value itself, using "hint" @@ -741,7 +746,8 @@ class treap_impl //! Complexity: Logarithmic in general, but it's amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If the key_value_comp or key_value_pcomp + //! ordering functions throw. Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -800,6 +806,82 @@ class treap_impl return iterator(to_insert, this); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the treap before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" treap ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + detail::key_nodeptr_comp + pcomp(priv_pcomp(), this); + return iterator(node_algorithms::insert_before + (node_ptr(&priv_header()), pos.pointed_node(), to_insert, pcomp), this); + } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the treap in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + detail::key_nodeptr_comp + pcomp(priv_pcomp(), this); + node_algorithms::push_back(node_ptr(&priv_header()), to_insert, pcomp); + } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the treap in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + detail::key_nodeptr_comp + pcomp(priv_pcomp(), this); + node_algorithms::push_front(node_ptr(&priv_header()), to_insert, pcomp); + } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity for erase element is constant time. @@ -817,7 +899,7 @@ class treap_impl BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); detail::key_nodeptr_comp key_node_pcomp(priv_pcomp(), this); - node_algorithms::erase(&priv_header(), to_erase,key_node_pcomp); + node_algorithms::erase(&priv_header(), to_erase, key_node_pcomp); this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); @@ -856,7 +938,8 @@ class treap_impl //! //! Complexity: O(log(size() + N). //! - //! Throws: if the internal priority_compare function throws. Strong guarantee. + //! Throws: if the internal priority_compare function throws. + //! Equivalent guarantee to while(beg != end) erase(beg++); //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1260,16 +1343,16 @@ class treap_impl } } - //! Effects: Unlinks the leftmost node from the tree. + //! Effects: Unlinks the leftmost node from the treap. //! //! Complexity: Average complexity is constant time. //! //! Throws: Nothing. //! - //! Notes: This function breaks the tree and the tree can + //! Notes: This function breaks the treap and the treap can //! only be used for more unlink_leftmost_without_rebalance calls. //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. + //! controlled destruction of the treap. pointer unlink_leftmost_without_rebalance() { node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance @@ -1283,10 +1366,10 @@ class treap_impl } //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. + //! and with_this must not be inserted in any treap. //! //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. + //! treap with with_this. The treap does not need to be rebalanced. //! //! Complexity: Constant. //! @@ -1363,7 +1446,7 @@ class treap_impl const_iterator iterator_to(const_reference value) const { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } - //! Requires: value shall not be in a tree. + //! Requires: value shall not be in a treap. //! //! Effects: init_node puts the hook of a value in a well-known default //! state. diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index bdceac2..6c05efa 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -10,8 +10,8 @@ // ///////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTRUSIVE_TRIE_ALGORITHMS_HPP -#define BOOST_INTRUSIVE_TRIE_ALGORITHMS_HPP +#ifndef BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP #include @@ -270,15 +270,15 @@ class treap_algorithms //! //! Complexity: Average complexity is constant time. //! - //! Throws: Nothing. - template - static void unlink(node_ptr node, NodePriorityCompare prio) + //! Throws: If "pcomp" throws, strong guarantee + template + static void unlink(node_ptr node, NodePtrPriorityCompare pcomp) { node_ptr x = NodeTraits::get_parent(node); if(x){ while(!is_header(x)) x = NodeTraits::get_parent(x); - erase(x, node, prio); + erase(x, node, pcomp); } } @@ -383,9 +383,9 @@ class treap_algorithms //! //! Complexity: Amortized constant time. //! - //! Throws: Nothing. - template - static node_ptr erase(node_ptr header, node_ptr z, NodePriorityCompare pcomp) + //! Throws: If "pcomp" throws, strong guarantee. + template + static node_ptr erase(node_ptr header, node_ptr z, NodePtrPriorityCompare pcomp) { rebalance_for_erasure(header, z, pcomp); tree_algorithms::erase(header, z); @@ -503,23 +503,24 @@ class treap_algorithms //! NodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the //! the tree. NodePtrCompare compares two node_ptrs. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. //! //! Effects: Inserts new_node into the tree before the upper bound - //! according to "comp". + //! according to "comp" and rotates the tree according to "pcomp". //! //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If "comp" throws. - template + //! Throws: If "comp" throw or "pcomp" throw. + template static node_ptr insert_equal_upper_bound - (node_ptr h, node_ptr new_node, NodePtrCompare comp, PriorityNodeCompare pcomp) + (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; tree_algorithms::insert_equal_upper_bound_check(h, new_node, comp, commit_data); - rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); - tree_algorithms::insert_unique_commit(h, new_node, commit_data); - rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + rebalance_check_and_commit(h, new_node, pcomp, commit_data); return new_node; } @@ -527,23 +528,24 @@ class treap_algorithms //! NodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the //! the tree. NodePtrCompare compares two node_ptrs. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. //! - //! Effects: Inserts new_node into the tree before the lower bound - //! according to "comp". + //! Effects: Inserts new_node into the tree before the upper bound + //! according to "comp" and rotates the tree according to "pcomp". //! //! Complexity: Average complexity for insert element is at //! most logarithmic. //! //! Throws: If "comp" throws. - template + template static node_ptr insert_equal_lower_bound - (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePriorityCompare pcomp) + (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; tree_algorithms::insert_equal_lower_bound_check(h, new_node, comp, commit_data); - rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); - tree_algorithms::insert_unique_commit(h, new_node, commit_data); - rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + rebalance_check_and_commit(h, new_node, pcomp, commit_data); return new_node; } @@ -552,27 +554,107 @@ class treap_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from //! the "header"'s tree. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. //! //! Effects: Inserts new_node into the tree, using "hint" as a hint to //! where it will be inserted. If "hint" is the upper_bound //! the insertion takes constant time (two comparisons in the worst case). + //! Rotates the tree according to "pcomp". //! //! Complexity: Logarithmic in general, but it is amortized //! constant time if new_node is inserted immediately before "hint". //! - //! Throws: If "comp" throws. - template + //! Throws: If "comp" throw or "pcomp" throw. + template static node_ptr insert_equal - (node_ptr h, node_ptr hint, node_ptr new_node, NodePtrCompare comp, NodePriorityCompare pcomp) + (node_ptr h, node_ptr hint, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; tree_algorithms::insert_equal_check(h, hint, new_node, comp, commit_data); - rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); - tree_algorithms::insert_unique_commit(h, new_node, commit_data); - rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + rebalance_check_and_commit(h, new_node, pcomp, commit_data); return new_node; } + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid node of the tree (including header end) node. + //! "pos" must be a node pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before "pos" + //! and rotates the tree according to "pcomp". + //! + //! Complexity: Constant-time. + //! + //! Throws: If "pcomp" throws, strong guarantee. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + template + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node, NodePtrPriorityCompare pcomp) + { + insert_commit_data commit_data; + tree_algorithms::insert_before_check(header, pos, commit_data); + rebalance_check_and_commit(header, new_node, pcomp, commit_data); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. + //! + //! Effects: Inserts x into the tree in the last position + //! and rotates the tree according to "pcomp". + //! + //! Complexity: Constant-time. + //! + //! Throws: If "pcomp" throws, strong guarantee. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + template + static void push_back(node_ptr header, node_ptr new_node, NodePtrPriorityCompare pcomp) + { + insert_commit_data commit_data; + tree_algorithms::push_back_check(header, commit_data); + rebalance_check_and_commit(header, new_node, pcomp, commit_data); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. + //! + //! Effects: Inserts x into the tree in the first position + //! and rotates the tree according to "pcomp". + //! + //! Complexity: Constant-time. + //! + //! Throws: If "pcomp" throws, strong guarantee. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + template + static void push_front(node_ptr header, node_ptr new_node, NodePtrPriorityCompare pcomp) + { + insert_commit_data commit_data; + tree_algorithms::push_front_check(header, commit_data); + rebalance_check_and_commit(header, new_node, pcomp, commit_data); + } + //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the @@ -720,8 +802,8 @@ class treap_algorithms return tree_algorithms::is_header(p); } - template - static void rebalance_for_erasure(node_ptr header, node_ptr z, NodePriorityCompare pcomp) + template + static void rebalance_for_erasure(node_ptr header, node_ptr z, NodePtrPriorityCompare pcomp) { std::size_t n = 0; rerotate_on_destroy rb(header, z, n); @@ -742,6 +824,17 @@ class treap_algorithms rb.release(); } + template + static void rebalance_check_and_commit + (node_ptr h, node_ptr new_node, NodePtrPriorityCompare pcomp, insert_commit_data &commit_data) + { + rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); + //No-throw + tree_algorithms::insert_unique_commit(h, new_node, commit_data); + rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + } + + template static void rebalance_after_insertion_check ( const_node_ptr header, const_node_ptr upnode, const Key &k @@ -759,7 +852,7 @@ class treap_algorithms static void rebalance_after_insertion_commit(node_ptr header, node_ptr p, std::size_t n) { - // Now to n rotations + // Now execute n rotations for( node_ptr p_parent = NodeTraits::get_parent(p) ; n-- ; p_parent = NodeTraits::get_parent(p)){ @@ -773,8 +866,8 @@ class treap_algorithms } } - template - static bool check_invariant(const_node_ptr header, NodePriorityCompare pcomp) + template + static bool check_invariant(const_node_ptr header, NodePtrPriorityCompare pcomp) { node_ptr beg = begin_node(header); node_ptr end = end_node(header); @@ -798,4 +891,4 @@ class treap_algorithms #include -#endif //BOOST_INTRUSIVE_TRIE_ALGORITHMS_HPP +#endif //BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index 9322a6b..12611ee 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -351,6 +351,14 @@ class treap_set_impl value_compare value_comp() const { return tree_.value_comp(); } + //! Effects: Returns the priority_compare object used by the treap_set. + //! + //! Complexity: Constant. + //! + //! Throws: If priority_compare copy-constructor throws. + priority_compare priority_comp() const + { return tree_.priority_comp(); } + //! Effects: Returns true if the container is empty. //! //! Complexity: Constant. @@ -408,7 +416,8 @@ class treap_set_impl //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare ordering function throw. + //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -426,7 +435,8 @@ class treap_set_impl //! Complexity: Logarithmic in general, but it's amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare ordering + //! functions throw. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -434,8 +444,10 @@ class treap_set_impl { return tree_.insert_unique(hint, value); } //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! the same strict weak ordering as value_compare. + //! key_value_pcomp must be a comparison function that induces + //! the same strict weak ordering as priority_compare. The difference is that + //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the treap_set, using //! a user provided key instead of the value itself. @@ -448,7 +460,8 @@ class treap_set_impl //! //! Complexity: Average complexity is at most logarithmic. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If key_value_comp or key_value_pcomp ordering function throw. + //! Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -463,14 +476,17 @@ class treap_set_impl //! //! "commit_data" remains valid for a subsequent "insert_commit" only if no more //! objects are inserted or erased from the treap_set. - template + template std::pair insert_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + ( const KeyType &key, KeyValueCompare key_value_comp, KeyValuePriorityCompare key_value_pcomp + , insert_commit_data &commit_data) + { return tree_.insert_unique_check(key, key_value_comp, key_value_pcomp, commit_data); } //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! the same strict weak ordering as value_compare. + //! key_value_pcomp must be a comparison function that induces + //! the same strict weak ordering as priority_compare. The difference is that + //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the treap_set, using //! a user provided key instead of the value itself, using "hint" @@ -485,7 +501,8 @@ class treap_set_impl //! Complexity: Logarithmic in general, but it's amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If key_value_comp or key_value_pcomp ordering function throw. + //! Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -500,11 +517,12 @@ class treap_set_impl //! //! "commit_data" remains valid for a subsequent "insert_commit" only if no more //! objects are inserted or erased from the treap_set. - template + template std::pair insert_check - (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + ( const_iterator hint, const KeyType &key + , KeyValueCompare key_value_comp, KeyValuePriorityCompare key_value_pcomp + , insert_commit_data &commit_data) + { return tree_.insert_unique_check(hint, key, key_value_comp, key_value_pcomp, commit_data); } //! Requires: value must be an lvalue of type value_type. commit_data //! must have been obtained from a previous call to "insert_check". @@ -535,7 +553,8 @@ class treap_set_impl //! size of the range. However, it is linear in N if the range is already sorted //! by value_comp(). //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! Throws: If the internal value_compare or priority_compare ordering function + //! throw. Basic guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -543,13 +562,65 @@ class treap_set_impl void insert(Iterator b, Iterator e) { tree_.insert_unique(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the treap before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" treap ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the treap in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the treap in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. //! //! Returns: An iterator to the element after the erased element. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -563,7 +634,7 @@ class treap_set_impl //! //! Returns: An iterator to the element after the erased elements. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -576,7 +647,8 @@ class treap_set_impl //! //! Complexity: O(log(size()) + this->count(value)). //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! Throws: If internal value_compare or priority_compare + //! ordering functions throw. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -590,7 +662,8 @@ class treap_set_impl //! //! Complexity: O(log(size() + this->count(key, comp)). //! - //! Throws: If the comp ordering function throws. Basic guarantee. + //! Throws: If comp or internal priority_compare + //! ordering functions throw. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -611,7 +684,7 @@ class treap_set_impl //! //! Returns: An iterator to the element after the erased element. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -635,7 +708,7 @@ class treap_set_impl //! //! Returns: An iterator to the element after the erased elements. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Basic guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -652,7 +725,7 @@ class treap_set_impl //! //! Complexity: O(log(size() + this->count(value)). Basic guarantee. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -670,7 +743,8 @@ class treap_set_impl //! //! Complexity: O(log(size() + this->count(key, comp)). //! - //! Throws: If comp ordering function throws. Basic guarantee. + //! Throws: If comp or internal priority_compare ordering functions throw. + //! Basic guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -1584,6 +1658,14 @@ class treap_multiset_impl value_compare value_comp() const { return tree_.value_comp(); } + //! Effects: Returns the priority_compare object used by the treap_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If priority_compare copy-constructor throws. + priority_compare priority_comp() const + { return tree_.priority_comp(); } + //! Effects: Returns true if the container is empty. //! //! Complexity: Constant. @@ -1638,7 +1720,8 @@ class treap_multiset_impl //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare ordering + //! function throws. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -1656,7 +1739,8 @@ class treap_multiset_impl //! Complexity: Logarithmic in general, but it is amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If internal value_compare or priority_compare ordering functions throw. + //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -1675,7 +1759,8 @@ class treap_multiset_impl //! size of the range. However, it is linear in N if the range is already sorted //! by value_comp(). //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! Throws: If internal value_compare or priority_compare ordering functions throw. + //! Basic guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -1683,13 +1768,64 @@ class treap_multiset_impl void insert(Iterator b, Iterator e) { tree_.insert_equal(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the treap before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" treap ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key. + //! + //! Effects: Inserts x into the treap in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the treap in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. //! //! Returns: An iterator to the element after the erased element. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1703,7 +1839,7 @@ class treap_multiset_impl //! Complexity: Average complexity for erase range is at most //! O(log(size() + N)), where N is the number of elements in the range. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1716,7 +1852,8 @@ class treap_multiset_impl //! //! Complexity: O(log(size() + this->count(value)). //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! Throws: If the internal value_compare or priority_compare ordering + //! functiona throw. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1730,7 +1867,7 @@ class treap_multiset_impl //! //! Complexity: O(log(size() + this->count(key, comp)). //! - //! Throws: If comp ordering function throws. Basic guarantee. + //! Throws: If comp or internal priority_compare ordering functions throw. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1751,7 +1888,7 @@ class treap_multiset_impl //! //! Complexity: Average complexity for erase element is constant time. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -1775,7 +1912,7 @@ class treap_multiset_impl //! Complexity: Average complexity for erase range is at most //! O(log(size() + N)), where N is the number of elements in the range. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Basic guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -1810,7 +1947,7 @@ class treap_multiset_impl //! //! Complexity: O(log(size() + this->count(key, comp)). //! - //! Throws: If comp ordering function throws. Basic guarantee. + //! Throws: If comp or internal priority_compare ordering functions throw. Basic guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. diff --git a/include/boost/intrusive/trivial_value_traits.hpp b/include/boost/intrusive/trivial_value_traits.hpp index dcf996d..4527d7c 100644 --- a/include/boost/intrusive/trivial_value_traits.hpp +++ b/include/boost/intrusive/trivial_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/unordered_set.hpp b/include/boost/intrusive/unordered_set.hpp index cdca860..47d1aab 100644 --- a/include/boost/intrusive/unordered_set.hpp +++ b/include/boost/intrusive/unordered_set.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -395,8 +395,8 @@ class unordered_set_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. - void erase(const_iterator i) - { table_.erase(i); } + iterator erase(const_iterator i) + { return table_.erase(i); } //! Effects: Erases the range pointed to by b end e. //! @@ -407,8 +407,8 @@ class unordered_set_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - void erase(const_iterator b, const_iterator e) - { table_.erase(b, e); } + iterator erase(const_iterator b, const_iterator e) + { return table_.erase(b, e); } //! Effects: Erases all the elements with the given value. //! @@ -460,15 +460,13 @@ class unordered_set_impl //! Note: Invalidates the iterators //! to the erased elements. template - iterator erase_and_dispose(const_iterator i, Disposer disposer) + iterator erase_and_dispose(const_iterator i, Disposer disposer + /// @cond + , typename detail::enable_if_c::value >::type * = 0 + /// @endcond + ) { return table_.erase_and_dispose(i, disposer); } - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif - //! Requires: Disposer::operator()(pointer) shouldn't throw. //! //! Effects: Erases the range pointed to by b end e. @@ -1370,9 +1368,8 @@ class unordered_multiset_impl //! //! Effects: Equivalent to this->insert(t) for each element in [b, e). //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). + //! Complexity: Average case is O(N), where N is the + //! size of the range. //! //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. //! @@ -1390,8 +1387,8 @@ class unordered_multiset_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. - void erase(const_iterator i) - { table_.erase(i); } + iterator erase(const_iterator i) + { return table_.erase(i); } //! Effects: Erases the range pointed to by b end e. //! @@ -1402,8 +1399,8 @@ class unordered_multiset_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - void erase(const_iterator b, const_iterator e) - { table_.erase(b, e); } + iterator erase(const_iterator b, const_iterator e) + { return table_.erase(b, e); } //! Effects: Erases all the elements with the given value. //! @@ -1456,12 +1453,16 @@ class unordered_multiset_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator i, Disposer disposer) - { table_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer + /// @cond + , typename detail::enable_if_c::value >::type * = 0 + /// @endcond + ) + { return table_.erase_and_dispose(i, disposer); } #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template - iterator erase_and_dispose(iterator i, Disposer disposer) + iterator erase_and_dispose(const_iterator i, Disposer disposer) { return this->erase_and_dispose(const_iterator(i), disposer); } #endif @@ -1478,8 +1479,8 @@ class unordered_multiset_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { table_.erase_and_dispose(b, e, disposer); } + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + { return table_.erase_and_dispose(b, e, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! diff --git a/include/boost/intrusive/unordered_set_hook.hpp b/include/boost/intrusive/unordered_set_hook.hpp index adb3a8d..286b318 100644 --- a/include/boost/intrusive/unordered_set_hook.hpp +++ b/include/boost/intrusive/unordered_set_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -222,6 +222,7 @@ class unordered_set_base_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -351,6 +352,7 @@ class unordered_set_member_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //!