Move boost/intrusive to senf/boost_intrusive
[senf.git] / senf / boost_intrusive / detail / irbtree.hpp
diff --git a/senf/boost_intrusive/detail/irbtree.hpp b/senf/boost_intrusive/detail/irbtree.hpp
new file mode 100644 (file)
index 0000000..0aff738
--- /dev/null
@@ -0,0 +1,1188 @@
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright Ion Gaztañaga  2006-2007\r
+//\r
+// Distributed under the Boost Software License, Version 1.0.\r
+//    (See accompanying file LICENSE_1_0.txt or copy at\r
+//          http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+// See http://www.boost.org/libs/intrusive for documentation.\r
+//\r
+/////////////////////////////////////////////////////////////////////////////\r
+#ifndef BOOST_INTRUSIVE_IRBTREE_HPP\r
+#define BOOST_INTRUSIVE_IRBTREE_HPP\r
+\r
+#include "config_begin.hpp"\r
+#include <functional>\r
+#include <iterator>\r
+#include <boost/utility.hpp>\r
+#include <boost/compressed_pair.hpp>\r
+#include <utility>\r
+#include <boost/assert.hpp>\r
+#include <boost/static_assert.hpp>\r
+#include "pointer_type.hpp"\r
+#include "pointer_to_other.hpp"\r
+#include "../iset_hook.hpp"\r
+#include "rbtree_node.hpp"\r
+#include "ebo_holder.hpp"\r
+#include "../rbtree_algorithms.hpp"\r
+#include "../linking_policy.hpp"\r
+#include <cstddef>\r
+#include <iterator>\r
+\r
+namespace boost {\r
+namespace intrusive {\r
+namespace detail {\r
+\r
+//! The class template irbtree is an intrusive red-black tree container, that\r
+//! is used to construct intrusive set and tree containers. The no-throw \r
+//! guarantee holds only, if the Compare object \r
+//! doesn't throw.\r
+template < class ValueTraits\r
+         , class Compare         = std::less<typename ValueTraits::value_type>\r
+         , bool ConstantTimeSize = true\r
+         , class SizeType = std::size_t\r
+         >\r
+class irbtree\r
+   :  private detail::size_holder<ConstantTimeSize, SizeType>\r
+{\r
+   private:\r
+   typedef irbtree<ValueTraits, Compare\r
+                  ,ConstantTimeSize, SizeType>              this_type; \r
+   typedef typename ValueTraits::node_traits                node_traits;\r
+   typedef detail::size_holder<ConstantTimeSize, SizeType>    size_traits;\r
+\r
+   //noncopyable\r
+   irbtree (const irbtree&);\r
+   irbtree operator =(const irbtree&);\r
+\r
+   public:\r
+   typedef typename ValueTraits::value_type        value_type;\r
+   typedef typename ValueTraits::pointer           pointer;\r
+   typedef typename ValueTraits::const_pointer     const_pointer;\r
+   typedef value_type&                             reference;\r
+   typedef const value_type&                       const_reference;\r
+   typedef SizeType                                size_type;\r
+   typedef typename std::iterator_traits\r
+      <pointer>::difference_type                   difference_type;\r
+   typedef value_type                              key_type;\r
+   typedef Compare                                 value_compare;\r
+   class iterator;\r
+   class const_iterator;\r
+   friend class iterator;\r
+   friend class const_iterator;\r
+\r
+   private:\r
+   typedef typename node_traits::node              node;\r
+   typedef typename boost::pointer_to_other\r
+      <pointer, node>::type                        node_ptr;\r
+   typedef typename boost::pointer_to_other\r
+      <node_ptr, const node>::type                 const_node_ptr;\r
+   typedef rbtree_algorithms<node_traits>          node_algorithms;\r
+   enum { safemode_or_autounlink  = \r
+            (int)ValueTraits::linking_policy == (int)auto_unlink   ||\r
+            (int)ValueTraits::linking_policy == (int)safe_mode_link     };\r
+\r
+   //Constant-time size is incompatible with auto-unlink hooks!\r
+   BOOST_STATIC_ASSERT(!(ConstantTimeSize && ((int)ValueTraits::linking_policy == (int)auto_unlink)));\r
+\r
+   template<class KeyValueCompare>\r
+   struct key_node_ptr_compare\r
+      :  private ebo_holder<KeyValueCompare>\r
+   {\r
+      typedef ebo_holder<KeyValueCompare> base_t;\r
+      key_node_ptr_compare(KeyValueCompare kcomp)\r
+         :  base_t(kcomp)\r
+      {}\r
+\r
+      template<class KeyType>\r
+      bool operator()(node_ptr node, const KeyType &key) const\r
+      {  return base_t::get()(*ValueTraits::to_value_ptr(node), key); }\r
+\r
+      template<class KeyType>\r
+      bool operator()(const KeyType &key, node_ptr node) const\r
+      {  return base_t::get()(key, *ValueTraits::to_value_ptr(node)); }\r
+\r
+      bool operator()(node_ptr node1, node_ptr node2) const\r
+      {\r
+         return base_t::get()\r
+            (*ValueTraits::to_value_ptr(node1), *ValueTraits::to_value_ptr(node2)); \r
+      }\r
+   };\r
+\r
+   //Use boost::compressed_pair to get EBO if possible\r
+   boost::compressed_pair<node, Compare> members_;\r
+   \r
+   const Compare &priv_comp() const\r
+   {  return members_.second();  }\r
+\r
+   Compare &priv_comp()\r
+   {  return members_.second();  }\r
+\r
+   const node &priv_header() const\r
+   {  return members_.first();  }\r
+\r
+   node &priv_header()\r
+   {  return members_.first();  }\r
+\r
+   template<class F>\r
+   struct value_to_node_cloner\r
+      :  private ebo_holder<F>\r
+   {\r
+      typedef ebo_holder<F> base_t;\r
+      value_to_node_cloner(F f)\r
+         :  base_t(f)\r
+      {}\r
+      \r
+      node_ptr operator()(node_ptr p)\r
+      {  return ValueTraits::to_node_ptr(*base_t::get()(*ValueTraits::to_value_ptr(p))); }\r
+   };\r
+\r
+   template<class F>\r
+   struct value_to_node_destroyer\r
+      :  private ebo_holder<F>\r
+   {\r
+      typedef ebo_holder<F> base_t;\r
+      value_to_node_destroyer(F f)\r
+         :  base_t(f)\r
+      {}\r
+\r
+      void operator()(node_ptr p)\r
+      {  base_t::get()(ValueTraits::to_value_ptr(p));   }\r
+   };\r
+\r
+   static node_ptr uncast(const_node_ptr ptr)\r
+   {\r
+      using boost::get_pointer;\r
+      return node_ptr(const_cast<node*>(get_pointer(ptr)));\r
+   }\r
+\r
+   public:\r
+   typedef typename node_algorithms::insert_commit_data insert_commit_data;\r
+\r
+   class iterator\r
+      :  public detail::rbtree_iterator <value_type, iterator, node_traits>\r
+    {\r
+      private:\r
+      typedef typename irbtree<ValueTraits, Compare, ConstantTimeSize, SizeType>::value_type   private_vt;\r
+      typedef typename irbtree<ValueTraits, Compare, ConstantTimeSize, SizeType>::pointer      private_pointer;\r
+      typedef typename irbtree<ValueTraits, Compare, ConstantTimeSize, SizeType>::reference    private_reference;\r
+      typedef detail::rbtree_iterator<private_vt, iterator, node_traits>   inherited;\r
+\r
+      public:\r
+      iterator ()\r
+      {}\r
+\r
+      private_pointer operator->() const\r
+      { return  ValueTraits::to_value_ptr(this->tree_node()); }\r
+\r
+      private_reference operator*() const\r
+      { return *ValueTraits::to_value_ptr(this->tree_node()); }\r
+\r
+      private:\r
+      explicit iterator(node_ptr node)\r
+         :  inherited(node)\r
+      {}\r
+      \r
+      friend class irbtree<ValueTraits, Compare, ConstantTimeSize, SizeType>; \r
+      friend class detail::rbtree_iterator<private_vt, iterator, node_traits>;\r
+      friend class const_iterator;\r
+   };\r
+\r
+   class const_iterator\r
+      :  public detail::rbtree_iterator<const value_type, const_iterator, node_traits>\r
+   {\r
+      private:\r
+      typedef const typename irbtree<ValueTraits, Compare, ConstantTimeSize, SizeType>::value_type private_vt;\r
+      typedef typename irbtree<ValueTraits, Compare, ConstantTimeSize, SizeType>::const_pointer    private_pointer;\r
+      typedef typename irbtree<ValueTraits, Compare, ConstantTimeSize, SizeType>::const_reference  private_reference;\r
+      typedef detail::rbtree_iterator<private_vt, const_iterator, node_traits>   inherited;\r
+\r
+      public:\r
+      const_iterator ()\r
+      {}\r
+\r
+      const_iterator(const typename irbtree::iterator& it)\r
+         :  inherited (it.tree_node())\r
+      {}\r
+\r
+      const_iterator & operator=(const typename irbtree::iterator& it)\r
+      {  return inherited::operator=(it.tree_node());  }\r
+\r
+      private_pointer   operator->()\r
+      { return  ValueTraits::to_value_ptr(this->tree_node()); }\r
+\r
+      private_reference operator*()\r
+      { return *ValueTraits::to_value_ptr(this->tree_node()); }\r
+\r
+      private:\r
+      explicit const_iterator (const_node_ptr p)\r
+         :  inherited (uncast(p))\r
+      {}\r
+\r
+      friend class irbtree<ValueTraits, Compare, ConstantTimeSize, SizeType>; \r
+      friend class detail::rbtree_iterator<private_vt, const_iterator, node_traits>;\r
+   };\r
+\r
+   typedef std::reverse_iterator<iterator>         reverse_iterator;\r
+   typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;\r
+\r
+   public:\r
+\r
+   //! <b>Effects</b>: Constructs an empty tree. \r
+   //!   \r
+   //! <b>Complexity</b>: Constant. \r
+   //! \r
+   //! <b>Throws</b>: Nothing unless the copy constructor of the Compare object throws. \r
+   irbtree(Compare cmp = Compare()) \r
+      :  members_(cmp)\r
+   {  \r
+      node_algorithms::init_header(&priv_header());  \r
+      size_traits::set_size(size_type(0));\r
+   }\r
+\r
+   //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type. \r
+   //!   cmp must be a comparison function that induces a strict weak ordering.\r
+   //! \r
+   //! <b>Effects</b>: Constructs an empty tree and inserts elements from \r
+   //!   [b, e).\r
+   //! \r
+   //! <b>Complexity</b>: Linear in N if [b, e) is already sorted using \r
+   //!   comp and otherwise N * log N, where N is last ­ first.\r
+   //! \r
+   //! <b>Throws</b>: Nothing unless the copy constructor of the Compare object throws. \r
+   template<class Iterator>\r
+   irbtree(bool unique, Iterator b, Iterator e, Compare cmp = Compare())\r
+      : members_(cmp)\r
+   {\r
+      node_algorithms::init_header(&priv_header());\r
+      size_traits::set_size(size_type(0));\r
+      if(unique)\r
+         this->insert_unique(b, e);\r
+      else\r
+         this->insert_equal(b, e);\r
+   }\r
+\r
+   //! <b>Effects</b>: Detaches all elements from this. The objects in the set \r
+   //!   are not deleted (i.e. no destructors are called), but the nodes according to \r
+   //!   the ValueTraits template parameter are reinitialized and thus can be reused. \r
+   //! \r
+   //! <b>Complexity</b>: Linear to elements contained in *this. \r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   ~irbtree() \r
+   {  this->clear(); }\r
+\r
+   //! <b>Effects</b>: Returns an iterator pointing to the beginning of the tree.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   iterator begin()\r
+   {  return iterator (node_traits::get_left(node_ptr(&priv_header())));   }\r
+\r
+   //! <b>Effects</b>: Returns a const_iterator pointing to the beginning of the tree.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   const_iterator begin() const\r
+   {  return const_iterator (node_traits::get_left(const_node_ptr(&priv_header())));   }\r
+\r
+   //! <b>Effects</b>: Returns an iterator pointing to the end of the tree.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   iterator end()\r
+   {  return iterator (node_ptr(&priv_header()));  }\r
+\r
+   //! <b>Effects</b>: Returns a const_iterator pointing to the end of the tree.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   const_iterator end() const\r
+   {  return const_iterator (const_node_ptr(&priv_header()));  }\r
+\r
+   //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning of the\r
+   //!    reversed tree.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   reverse_iterator rbegin()\r
+   {  return reverse_iterator(end());  }\r
+\r
+   //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning\r
+   //!    of the reversed tree.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   const_reverse_iterator rbegin() const\r
+   {  return const_reverse_iterator(end());  }\r
+\r
+   //! <b>Effects</b>: Returns a reverse_iterator pointing to the end\r
+   //!    of the reversed tree.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   reverse_iterator rend()\r
+   {  return reverse_iterator(begin());   }\r
+\r
+   //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end\r
+   //!    of the reversed tree.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   const_reverse_iterator rend() const\r
+   {  return const_reverse_iterator(begin());   }\r
+\r
+   //! <b>Effects</b>: Returns the value_compare object used by the tree.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: If value_compare copy-constructor throws.\r
+   value_compare value_comp() const\r
+   {  return priv_comp();   }\r
+\r
+   //! <b>Effects</b>: Returns true is the container is empty.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   bool empty() const\r
+   {  return node_algorithms::unique(const_node_ptr(&priv_header()));   }\r
+\r
+   //! <b>Effects</b>: Returns the number of elements stored in the tree.\r
+   //! \r
+   //! <b>Complexity</b>: Linear to elements contained in *this.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   size_type size() const\r
+   {\r
+      if(ConstantTimeSize)\r
+         return size_traits::get_size();\r
+      else\r
+         return empty() ? 0 : node_algorithms::count(node_traits::get_parent(const_node_ptr(&priv_header())));\r
+   }\r
+\r
+   //! <b>Effects</b>: Swaps the contents of two multisets.\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: If the comparison functor's unspecified swap call throws.\r
+   void swap(irbtree& other)\r
+   {\r
+      //This can throw\r
+      using std::swap;\r
+      swap(priv_comp(), priv_comp());\r
+      //These can't throw\r
+      node_algorithms::swap_tree(node_ptr(&priv_header()), node_ptr(&other.priv_header()));\r
+      if(ConstantTimeSize){\r
+         size_type backup = size_traits::get_size();\r
+         size_traits::set_size(other.get_size());\r
+         other.set_size(backup);\r
+      }\r
+   }\r
+\r
+   //! <b>Requires</b>: value must be an lvalue\r
+   //! \r
+   //! <b>Effects</b>: Inserts value into the tree before the upper bound.\r
+   //! \r
+   //! <b>Complexity</b>: Average complexity for insert element is at\r
+   //!   most logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+   //!   No copy-constructors are called.\r
+   iterator insert_equal_upper_bound(value_type &value)\r
+   {\r
+      key_node_ptr_compare<value_compare> key_node_comp(priv_comp());\r
+      node_ptr to_insert(ValueTraits::to_node_ptr(value));\r
+      if(safemode_or_autounlink)\r
+         BOOST_ASSERT(node_algorithms::unique(to_insert));\r
+      size_traits::increment();\r
+      return iterator(node_algorithms::insert_equal_upper_bound\r
+         (node_ptr(&priv_header()), to_insert, key_node_comp));\r
+   }\r
+\r
+   //! <b>Requires</b>: value must be an lvalue\r
+   //! \r
+   //! <b>Effects</b>: Inserts value into the tree before the lower bound.\r
+   //! \r
+   //! <b>Complexity</b>: Average complexity for insert element is at\r
+   //!   most logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+   //!   No copy-constructors are called.\r
+   iterator insert_equal_lower_bound(value_type &value)\r
+   {\r
+      key_node_ptr_compare<value_compare> key_node_comp(priv_comp());\r
+      node_ptr to_insert(ValueTraits::to_node_ptr(value));\r
+      if(safemode_or_autounlink)\r
+         BOOST_ASSERT(node_algorithms::unique(to_insert));\r
+      size_traits::increment();\r
+      return iterator(node_algorithms::insert_equal_lower_bound\r
+         (node_ptr(&priv_header()), to_insert, key_node_comp));\r
+   }\r
+\r
+   //! <b>Requires</b>: value must be an lvalue, and "hint" must be\r
+   //!   a valid iterator.\r
+   //! \r
+   //! <b>Effects</b>: Inserts x into the tree, using "hint" as a hint to\r
+   //!   where it will be inserted. If "hint" is the upper_bound\r
+   //!   the insertion takes constant time (two comparisons in the worst case)\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic in general, but it is amortized\r
+   //!   constant time if t is inserted immediately before hint.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+   //!   No copy-constructors are called.\r
+   iterator insert_equal(const_iterator hint, value_type &value)\r
+   {\r
+      key_node_ptr_compare<value_compare> key_node_comp(priv_comp());\r
+      node_ptr to_insert(ValueTraits::to_node_ptr(value));\r
+      if(safemode_or_autounlink)\r
+         BOOST_ASSERT(node_algorithms::unique(to_insert));\r
+      size_traits::increment();\r
+      return iterator(node_algorithms::insert_equal\r
+         (node_ptr(&priv_header()), hint.tree_node(), to_insert, key_node_comp));\r
+   }\r
+\r
+   //! <b>Requires</b>: Dereferencing iterator must yield an lvalue \r
+   //!   of type value_type.\r
+   //! \r
+   //! <b>Effects</b>: Inserts a each element of a range into the tree\r
+   //!   before the upper bound of the key of each element.\r
+   //! \r
+   //! <b>Complexity</b>: Insert range is in general O(N * log(N)), where N is the \r
+   //!   size of the range. However, it is linear in N if the range is already sorted \r
+   //!   by value_comp().\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+   //!   No copy-constructors are called.\r
+   template<class Iterator>\r
+   void insert_equal(Iterator b, Iterator e)\r
+   {\r
+      if(this->empty()){\r
+         iterator end(this->end());\r
+         for (; b != e; ++b)\r
+            this->insert_equal(end, *b);\r
+      }\r
+      else{\r
+         for (; b != e; ++b)\r
+            this->insert_equal_upper_bound(*b);\r
+      }\r
+   }\r
+\r
+   //! <b>Requires</b>: value must be an lvalue\r
+   //! \r
+   //! <b>Effects</b>: Inserts value into the tree if the value\r
+   //!   is not already present.\r
+   //! \r
+   //! <b>Complexity</b>: Average complexity for insert element is at\r
+   //!   most logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+   //!   No copy-constructors are called.\r
+   std::pair<iterator, bool> insert_unique(value_type &value)\r
+   {\r
+      insert_commit_data commit_data;\r
+      std::pair<iterator, bool> ret = insert_unique_check(value, commit_data);\r
+      if(!ret.second)\r
+         return ret;\r
+      return std::pair<iterator, bool> (insert_unique_commit(value, commit_data), true);\r
+   }\r
+\r
+   //! <b>Requires</b>: value must be an lvalue, and "hint" must be\r
+   //!   a valid iterator\r
+   //! \r
+   //! <b>Effects</b>: Tries to insert x into the tree, using "hint" as a hint\r
+   //!   to where it will be inserted.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic in general, but it is amortized\r
+   //!   constant time (two comparisons in the worst case)\r
+   //!   if t is inserted immediately before hint.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+   //!   No copy-constructors are called.\r
+   iterator insert_unique(const_iterator hint, value_type &value)\r
+   {\r
+      insert_commit_data commit_data;\r
+      std::pair<iterator, bool> ret = insert_unique_check(hint, value, commit_data);\r
+      if(!ret.second)\r
+         return ret.first;\r
+      return insert_unique_commit(value, commit_data);\r
+   }\r
+\r
+   //! <b>Requires</b>: Dereferencing iterator must yield an lvalue \r
+   //!   of type value_type.\r
+   //! \r
+   //! <b>Effects</b>: Tries to insert each element of a range into the tree.\r
+   //! \r
+   //! <b>Complexity</b>: Insert range is in general O(N * log(N)), where N is the \r
+   //!   size of the range. However, it is linear in N if the range is already sorted \r
+   //!   by value_comp().\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Does not affect the validity of iterators and references.\r
+   //!   No copy-constructors are called.\r
+   template<class Iterator>\r
+   void insert_unique(Iterator b, Iterator e)\r
+   {\r
+      if(this->empty()){\r
+         iterator end(this->end());\r
+         for (; b != e; ++b)\r
+            this->insert_unique(end, *b);\r
+      }\r
+      else{\r
+         for (; b != e; ++b)\r
+            this->insert_unique(*b);\r
+      }\r
+   }\r
+\r
+   std::pair<iterator, bool> insert_unique_check\r
+      (const value_type &value, insert_commit_data &commit_data)\r
+   {  return insert_unique_check(value, priv_comp(), commit_data); }\r
+\r
+   template<class KeyType, class KeyValueCompare>\r
+   std::pair<iterator, bool> insert_unique_check\r
+      (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data)\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> comp(key_value_comp);\r
+      std::pair<node_ptr, bool> ret = \r
+         (node_algorithms::insert_unique_check\r
+            (node_ptr(&priv_header()), key, comp, commit_data));\r
+      return std::pair<iterator, bool>(iterator(ret.first), ret.second);\r
+   }\r
+\r
+   std::pair<iterator, bool> insert_unique_check\r
+      (const_iterator hint, const value_type &value, insert_commit_data &commit_data)\r
+   {  return insert_unique_check(hint, value, priv_comp(), commit_data); }\r
+\r
+   template<class KeyType, class KeyValueCompare>\r
+   std::pair<iterator, bool> insert_unique_check\r
+      (const_iterator hint, const KeyType &key\r
+      ,KeyValueCompare key_value_comp, insert_commit_data &commit_data)\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> comp(key_value_comp);\r
+      std::pair<node_ptr, bool> ret = \r
+         (node_algorithms::insert_unique_check\r
+            (node_ptr(&priv_header()), hint.tree_node(), key, comp, commit_data));\r
+      return std::pair<iterator, bool>(iterator(ret.first), ret.second);\r
+   }\r
+\r
+   iterator insert_unique_commit(value_type &value, const insert_commit_data &commit_data)\r
+   {\r
+      node_ptr to_insert(ValueTraits::to_node_ptr(value));\r
+      if(safemode_or_autounlink)\r
+         BOOST_ASSERT(node_algorithms::unique(to_insert));\r
+      size_traits::increment();\r
+      node_algorithms::insert_unique_commit\r
+               (node_ptr(&priv_header()), to_insert, commit_data);\r
+      return iterator(to_insert);\r
+   }\r
+\r
+   //! <b>Effects</b>: Erases the element pointed to by pos. \r
+   //! \r
+   //! <b>Complexity</b>: Average complexity for erase element is constant time. \r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators (but not the references)\r
+   //!    to the erased elements. No destructors are called.\r
+   iterator erase(iterator i)\r
+   {\r
+      iterator ret(i);\r
+      ++ret;\r
+      node_ptr to_erase(i.tree_node());\r
+      if(safemode_or_autounlink)\r
+         BOOST_ASSERT(!node_algorithms::unique(to_erase));\r
+      node_algorithms::erase(&priv_header(), to_erase);\r
+      size_traits::decrement();\r
+      if(safemode_or_autounlink)\r
+         node_algorithms::init(to_erase);\r
+      return ret;\r
+   }\r
+\r
+   //! <b>Effects</b>: Erases the range pointed to by b end e. \r
+   //! \r
+   //! <b>Complexity</b>: Average complexity for erase range is at most \r
+   //!   O(log(size() + N)), where N is the number of elements in the range.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators (but not the references)\r
+   //!    to the erased elements. No destructors are called.\r
+   iterator erase(iterator b, iterator e)\r
+   {  size_type n;   return private_erase(b, e, n);   }\r
+\r
+   //! <b>Effects</b>: Erases all the elements with the given value.\r
+   //! \r
+   //! <b>Returns</b>: The number of erased elements.\r
+   //! \r
+   //! <b>Complexity</b>: O(log(size() + N).\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators (but not the references)\r
+   //!    to the erased elements. No destructors are called.\r
+   size_type erase(const value_type &value)\r
+   {  return this->erase(value, priv_comp());   }\r
+\r
+   //! <b>Effects</b>: Erases all the elements with the given key.\r
+   //!   according to the comparison functor "comp".\r
+   //!\r
+   //! <b>Returns</b>: The number of erased elements.\r
+   //! \r
+   //! <b>Complexity</b>: O(log(size() + N).\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators (but not the references)\r
+   //!    to the erased elements. No destructors are called.\r
+   template<class KeyType, class KeyValueCompare>\r
+   size_type erase(const KeyType& key, KeyValueCompare comp)\r
+   {\r
+      std::pair<iterator,iterator> p = this->equal_range(key, comp);\r
+      size_type n;\r
+      private_erase(p.first, p.second, n);\r
+      return n;\r
+   }\r
+\r
+   //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+   //!\r
+   //! <b>Effects</b>: Erases the element pointed to by pos. \r
+   //!   Destroyer::operator()(pointer) is called for the removed element.\r
+   //! \r
+   //! <b>Complexity</b>: Average complexity for erase element is constant time. \r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators \r
+   //!    to the erased elements.\r
+   template<class Destroyer>\r
+   iterator erase_and_destroy(iterator i, Destroyer destroyer)\r
+   {\r
+      node_ptr to_erase(i.tree_node());\r
+      iterator ret(this->erase(i));\r
+      destroyer(ValueTraits::to_value_ptr(to_erase));\r
+      return ret;\r
+   }\r
+\r
+   //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+   //!\r
+   //! <b>Effects</b>: Erases the range pointed to by b end e.\r
+   //!   Destroyer::operator()(pointer) is called for the removed elements.\r
+   //! \r
+   //! <b>Complexity</b>: Average complexity for erase range is at most \r
+   //!   O(log(size() + N)), where N is the number of elements in the range.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators\r
+   //!    to the erased elements.\r
+   template<class Destroyer>\r
+   iterator erase_and_destroy(iterator b, iterator e, Destroyer destroyer)\r
+   {  size_type n;   return private_erase(b, e, n, destroyer);   }\r
+\r
+   //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+   //!\r
+   //! <b>Effects</b>: Erases all the elements with the given value.\r
+   //!   Destroyer::operator()(pointer) is called for the removed elements.\r
+   //! \r
+   //! <b>Returns</b>: The number of erased elements.\r
+   //! \r
+   //! <b>Complexity</b>: O(log(size() + N).\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators (but not the references)\r
+   //!    to the erased elements. No destructors are called.\r
+   template<class Destroyer>\r
+   size_type erase_and_destroy(const value_type &value, Destroyer destroyer)\r
+   {\r
+      std::pair<iterator,iterator> p = this->equal_range(value);\r
+      size_type n;\r
+      private_erase(p.first, p.second, n, destroyer);\r
+      return n;\r
+   }\r
+\r
+   //! <b>Requires</b>: Destroyer::operator()(pointer) shouldn't throw.\r
+   //!\r
+   //! <b>Effects</b>: Erases all the elements with the given key.\r
+   //!   according to the comparison functor "comp".\r
+   //!   Destroyer::operator()(pointer) is called for the removed elements.\r
+   //!\r
+   //! <b>Returns</b>: The number of erased elements.\r
+   //! \r
+   //! <b>Complexity</b>: O(log(size() + N).\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators\r
+   //!    to the erased elements.\r
+   template<class KeyType, class KeyValueCompare, class Destroyer>\r
+   size_type erase_and_destroy(const KeyType& key, KeyValueCompare comp, Destroyer destroyer)\r
+   {\r
+      std::pair<iterator,iterator> p = this->equal_range(key, comp);\r
+      size_type n;\r
+      private_erase(p.first, p.second, n, destroyer);\r
+      return n;\r
+   }\r
+\r
+   //! <b>Effects</b>: Erases all of the elements. \r
+   //! \r
+   //! <b>Complexity</b>: Linear to the number of elements on the container.\r
+   //!   if it's a safe-mode or auto-unlink value_type. Constant time otherwise.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators (but not the references)\r
+   //!    to the erased elements. No destructors are called.\r
+   void clear()\r
+   {\r
+      if(safemode_or_autounlink){\r
+         while(1){\r
+            node_ptr leftmost\r
+               (node_algorithms::unlink_leftmost_without_rebalance\r
+                  (node_ptr(&priv_header())));\r
+            if(!leftmost)\r
+               break;\r
+            size_traits::decrement();\r
+            if(safemode_or_autounlink)\r
+               node_algorithms::init(leftmost);\r
+         }\r
+      }\r
+      else{\r
+         node_algorithms::init_header(&priv_header());\r
+         size_traits::set_size(0);\r
+      }\r
+   }\r
+\r
+   //! <b>Effects</b>: Erases all of the elements calling destroyer(p) for\r
+   //!   each node to be erased.\r
+   //! <b>Complexity</b>: Average complexity for is at most O(log(size() + N)),\r
+   //!   where N is the number of elements in the container.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Note</b>: Invalidates the iterators (but not the references)\r
+   //!    to the erased elements. Calls N times to destroyer functor.\r
+   template<class Destroyer>\r
+   void clear_and_destroy(Destroyer destroyer)\r
+   {\r
+      while(1){\r
+         node_ptr leftmost\r
+            (node_algorithms::unlink_leftmost_without_rebalance\r
+               (node_ptr(&priv_header())));\r
+         if(!leftmost)\r
+            break;\r
+         size_traits::decrement();\r
+         if(safemode_or_autounlink)\r
+            node_algorithms::init(leftmost);\r
+         destroyer(ValueTraits::to_value_ptr(leftmost));\r
+      }\r
+   }\r
+\r
+   //! <b>Effects</b>: Returns the number of contained elements with the given value\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic to the number of elements contained plus lineal\r
+   //!   to number of objects with the given value.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   size_type count(const value_type &value) const\r
+   {  return this->count(value, priv_comp());   }\r
+\r
+   //! <b>Effects</b>: Returns the number of contained elements with the given key\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic to the number of elements contained plus lineal\r
+   //!   to number of objects with the given key.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   template<class KeyType, class KeyValueCompare>\r
+   size_type count(const KeyType &key, KeyValueCompare comp) const\r
+   {\r
+      std::pair<const_iterator, const_iterator> ret = this->equal_range(key, comp);\r
+      return std::distance(ret.first, ret.second);\r
+   }\r
+\r
+   //! <b>Effects</b>: Returns an iterator to the first element whose\r
+   //!   key is not less than k or end() if that element does not exist.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   iterator lower_bound(const value_type &value)\r
+   {  return this->lower_bound(value, priv_comp());   }\r
+\r
+   //! <b>Effects</b>: Returns an iterator to the first element whose\r
+   //!   key is not less than k or end() if that element does not exist.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   const_iterator lower_bound(const value_type &value) const\r
+   {  return this->lower_bound(value, priv_comp());   }\r
+\r
+   //! <b>Effects</b>: Returns an iterator to the first element whose\r
+   //!   key is not less than k or end() if that element does not exist.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   template<class KeyType, class KeyValueCompare>\r
+   iterator lower_bound(const KeyType &key, KeyValueCompare comp)\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> key_node_comp(comp);\r
+      return iterator(node_algorithms::lower_bound\r
+         (const_node_ptr(&priv_header()), key, key_node_comp));\r
+   }\r
+\r
+   //! <b>Effects</b>: Returns a const iterator to the first element whose\r
+   //!   key is not less than k or end() if that element does not exist.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   template<class KeyType, class KeyValueCompare>\r
+   const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> key_node_comp(comp);\r
+      return const_iterator(node_algorithms::lower_bound\r
+         (const_node_ptr(&priv_header()), key, key_node_comp));\r
+   }\r
+\r
+   //! <b>Effects</b>: Returns an iterator to the first element whose\r
+   //!   key is greater than k or end() if that element does not exist.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   iterator upper_bound(const value_type &value)\r
+   {  return this->upper_bound(value, priv_comp());   }\r
+\r
+   //! <b>Effects</b>: Returns an iterator to the first element whose\r
+   //!   key is greater than k according to comp or end() if that element\r
+   //!   does not exist.\r
+   //!\r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   template<class KeyType, class KeyValueCompare>\r
+   iterator upper_bound(const KeyType &key, KeyValueCompare comp)\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> key_node_comp(comp);\r
+      return iterator(node_algorithms::upper_bound\r
+         (const_node_ptr(&priv_header()), key, key_node_comp));\r
+   }\r
+\r
+   //! <b>Effects</b>: Returns an iterator to the first element whose\r
+   //!   key is greater than k or end() if that element does not exist.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   const_iterator upper_bound(const value_type &value) const\r
+   {  return this->upper_bound(value, priv_comp());   }\r
+\r
+   //! <b>Effects</b>: Returns an iterator to the first element whose\r
+   //!   key is greater than k according to comp or end() if that element\r
+   //!   does not exist.\r
+   //!\r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   template<class KeyType, class KeyValueCompare>\r
+   const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> key_node_comp(comp);\r
+      return const_iterator(node_algorithms::upper_bound\r
+         (const_node_ptr(&priv_header()), key, key_node_comp));\r
+   }\r
+\r
+   //! <b>Effects</b>: Finds an iterator to the first element whose key is \r
+   //!   k or end() if that element does not exist.\r
+   //!\r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   iterator find(const value_type &value)\r
+   {  return this->find(value, priv_comp()); }\r
+\r
+   //! <b>Effects</b>: Finds an iterator to the first element whose key is \r
+   //!   k or end() if that element does not exist.\r
+   //!\r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   template<class KeyType, class KeyValueCompare>\r
+   iterator find(const KeyType &key, KeyValueCompare comp)\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> key_node_comp(comp);\r
+      return iterator\r
+         (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp));\r
+   }\r
+\r
+   //! <b>Effects</b>: Finds a const_iterator to the first element whose key is \r
+   //!   k or end() if that element does not exist.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   const_iterator find(const value_type &value) const\r
+   {  return this->find(value, priv_comp()); }\r
+\r
+   //! <b>Effects</b>: Finds a const_iterator to the first element whose key is \r
+   //!   k or end() if that element does not exist.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   template<class KeyType, class KeyValueCompare>\r
+   const_iterator find(const KeyType &key, KeyValueCompare comp) const\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> key_node_comp(comp);\r
+      return const_iterator\r
+         (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp));\r
+   }\r
+\r
+   //! <b>Effects</b>: Finds a range containing all elements whose key is k or\r
+   //!   an empty range that indicates the position where those elements would be\r
+   //!   if they there is no elements with key k.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   std::pair<iterator,iterator> equal_range(const value_type &value)\r
+   {  return this->equal_range(value, priv_comp());   }\r
+\r
+   //! <b>Effects</b>: Finds a range containing all elements whose key is k or\r
+   //!   an empty range that indicates the position where those elements would be\r
+   //!   if they there is no elements with key k.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   template<class KeyType, class KeyValueCompare>\r
+   std::pair<iterator,iterator> equal_range(const KeyType &key, KeyValueCompare comp)\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> key_node_comp(comp);\r
+      std::pair<node_ptr, node_ptr> ret\r
+         (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp));\r
+      return std::pair<iterator, iterator>(iterator(ret.first), iterator(ret.second));\r
+   }\r
+\r
+   //! <b>Effects</b>: Finds a range containing all elements whose key is k or\r
+   //!   an empty range that indicates the position where those elements would be\r
+   //!   if they there is no elements with key k.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   std::pair<const_iterator, const_iterator>\r
+      equal_range(const value_type &value) const\r
+   {  return this->equal_range(value, priv_comp());   }\r
+\r
+   //! <b>Effects</b>: Finds a range containing all elements whose key is k or\r
+   //!   an empty range that indicates the position where those elements would be\r
+   //!   if they there is no elements with key k.\r
+   //! \r
+   //! <b>Complexity</b>: Logarithmic.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   template<class KeyType, class KeyValueCompare>\r
+   std::pair<const_iterator, const_iterator>\r
+      equal_range(const KeyType &key, KeyValueCompare comp) const\r
+   {\r
+      key_node_ptr_compare<KeyValueCompare> key_node_comp(comp);\r
+      std::pair<node_ptr, node_ptr> ret\r
+         (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp));\r
+      return std::pair<const_iterator, const_iterator>(const_iterator(ret.first), const_iterator(ret.second));\r
+   }\r
+\r
+   template <class Cloner, class Destroyer>\r
+   void clone_from(const irbtree &src, Cloner cloner, Destroyer destroyer)\r
+   {\r
+      this->clear_and_destroy(destroyer);\r
+      if(!src.empty()){\r
+         node_algorithms::clone_tree\r
+            (const_node_ptr(&src.priv_header())\r
+            ,node_ptr(&this->priv_header())\r
+            ,value_to_node_cloner<Cloner>(cloner)\r
+            ,value_to_node_destroyer<Destroyer>(destroyer));\r
+         size_traits::set_size(src.get_size());\r
+      }\r
+   }\r
+\r
+   pointer unlink_leftmost_without_rebalance()\r
+   {\r
+      node_ptr to_destroy(node_algorithms::unlink_leftmost_without_rebalance\r
+                           (node_ptr(&priv_header())));\r
+      if(!to_destroy)\r
+         return 0;\r
+      size_traits::decrement();\r
+      if(safemode_or_autounlink)\r
+         node_algorithms::init(to_destroy);\r
+      return ValueTraits::to_value_ptr(to_destroy);\r
+   }\r
+\r
+   //! <b>Requires</b>: value must be an lvalue and shall be in a set of\r
+   //!   appropriate type. Otherwise the behavior is undefined.\r
+   //! \r
+   //! <b>Effects</b>: Returns: a valid iterator i belonging to the set\r
+   //!   that points to the value\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   static iterator current(value_type &value)\r
+   {  return iterator (ValueTraits::to_node_ptr(value));  }\r
+\r
+   //! <b>Requires</b>: value must be an lvalue and shall be in a set of\r
+   //!   appropriate type. Otherwise the behavior is undefined.\r
+   //! \r
+   //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the\r
+   //!   set that points to the value\r
+   //! \r
+   //! <b>Complexity</b>: Constant.\r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   static const_iterator current(const value_type &value) \r
+   {  return const_iterator (ValueTraits::to_node_ptr(const_cast<value_type&> (value))); }\r
+/*\r
+   //! <b>Requires</b>: value shall not be in a tree of the appropriate type.\r
+   //! \r
+   //! <b>Effects</b>: init_node post-constructs the node data in x used by multisets of \r
+   //! the appropriate type. For the accessors multiset_derived_node and multiset_member_node \r
+   //! init_node has no effect, since the constructors of multiset_node_d and multiset_node_m \r
+   //! have already initialized the node data. \r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Complexity</b>: Constant time.\r
+   //! \r
+   //! <b>Note</b>: This function is meant to be used mainly with the member value_traits, \r
+   //! where no implicit node initialization during construction occurs.\r
+   static void init_node(reference value)\r
+   { node_algorithms::init(node_ptr(&*ValueTraits::to_node_ptr(value))); }\r
+\r
+   //! <b>Effects</b>: removes x from a tree of the appropriate type. It has no effect,\r
+   //! if x is not in such a tree. \r
+   //! \r
+   //! <b>Throws</b>: Nothing.\r
+   //! \r
+   //! <b>Complexity</b>: Constant time.\r
+   //! \r
+   //! <b>Note</b>: This static function is only usable with the "safe mode"\r
+   //! hook and non-constant time size lists. Otherwise, the user must use\r
+   //! the non-static "erase(value_type &)" member. If the user calls\r
+   //! this function with a non "safe mode" or constant time size list\r
+   //! a compilation error will be issued.\r
+   template<class T>\r
+   static void remove_node(T& value)\r
+   {\r
+      //This function is only usable for safe mode hooks and non-constant\r
+      //time lists. \r
+      //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && ConstantTimeSize)));\r
+      BOOST_STATIC_ASSERT((!ConstantTimeSize));\r
+      BOOST_STATIC_ASSERT((boost::is_convertible<T, value_type>::value));\r
+      node_ptr to_remove(ValueTraits::to_node_ptr(value));\r
+      node_algorithms::unlink_and_rebalance(to_remove);\r
+      if(safemode_or_autounlink)\r
+         node_algorithms::init(to_remove);\r
+   }\r
+*/\r
+   private:\r
+   template<class Destroyer>\r
+   iterator private_erase(iterator b, iterator e, size_type &n, Destroyer destroyer)\r
+   {\r
+      for(n = 0; b != e; ++n)\r
+        this->erase_and_destroy(b++, destroyer);\r
+      return b;\r
+   }\r
+\r
+   iterator private_erase(iterator b, iterator e, size_type &n)\r
+   {\r
+      for(n = 0; b != e; ++n)\r
+        this->erase(b++);\r
+      return b;\r
+   }\r
+};\r
+\r
+template <class V, class P, bool C, class S>\r
+inline bool operator==(const irbtree<V, P, C, S>& x, const irbtree<V, P, C, S>& y)\r
+{\r
+   if(C && x.size() != y.size()){\r
+      return false;\r
+   }\r
+   typedef typename irbtree<V, P, C, S>::const_iterator const_iterator;\r
+   const_iterator end1 = x.end();\r
+\r
+   const_iterator i1 = x.begin();\r
+   const_iterator i2 = y.begin();\r
+   if(C){\r
+      while (i1 != end1 && *i1 == *i2) {\r
+         ++i1;\r
+         ++i2;\r
+      }\r
+      return i1 == end1;\r
+   }\r
+   else{\r
+      const_iterator end2 = y.end();\r
+      while (i1 != end1 && i2 != end2 && *i1 == *i2) {\r
+         ++i1;\r
+         ++i2;\r
+      }\r
+      return i1 == end1 && i2 == end2;\r
+   }\r
+}\r
+\r
+template <class V, class P, bool C, class S>\r
+inline bool operator<(const irbtree<V, P, C, S>& x,\r
+                      const irbtree<V, P, C, S>& y)\r
+{  return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());  }\r
+\r
+template <class V, class P, bool C, class S>\r
+inline bool operator!=(const irbtree<V, P, C, S>& x, const irbtree<V, P, C, S>& y) \r
+{  return !(x == y); }\r
+\r
+template <class V, class P, bool C, class S>\r
+inline bool operator>(const irbtree<V, P, C, S>& x, const irbtree<V, P, C, S>& y) \r
+{  return y < x;  }\r
+\r
+template <class V, class P, bool C, class S>\r
+inline bool operator<=(const irbtree<V, P, C, S>& x, const irbtree<V, P, C, S>& y) \r
+{  return !(y < x);  }\r
+\r
+template <class V, class P, bool C, class S>\r
+inline bool operator>=(const irbtree<V, P, C, S>& x, const irbtree<V, P, C, S>& y) \r
+{  return !(x < y);  }\r
+\r
+template <class V, class P, bool C, class S>\r
+inline void swap(irbtree<V, P, C, S>& x, irbtree<V, P, C, S>& y)\r
+{  x.swap(y);  }\r
+\r
+} //namespace detail\r
+} //namespace intrusive \r
+} //namespace boost \r
+\r
+#include "config_end.hpp"\r
+\r
+#endif //BOOST_INTRUSIVE_IRBTREE_HPP\r