Add SCons configure checks
[senf.git] / boost_ext / boost / multi_index / hashed_index.hpp
diff --git a/boost_ext/boost/multi_index/hashed_index.hpp b/boost_ext/boost/multi_index/hashed_index.hpp
new file mode 100644 (file)
index 0000000..456797a
--- /dev/null
@@ -0,0 +1,1167 @@
+/* Copyright 2003-2007 Joaquín M López Muñoz.
+ * 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/multi_index for library home page.
+ */
+
+#ifndef BOOST_MULTI_INDEX_HASHED_INDEX_HPP
+#define BOOST_MULTI_INDEX_HASHED_INDEX_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <algorithm>
+#include <boost/call_traits.hpp>
+#include <boost/detail/allocator_utilities.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/limits.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/multi_index/detail/access_specifier.hpp>
+#include <boost/multi_index/detail/auto_space.hpp>
+#include <boost/multi_index/detail/bucket_array.hpp>
+#include <boost/multi_index/detail/hash_index_iterator.hpp>
+#include <boost/multi_index/detail/index_node_base.hpp>
+#include <boost/multi_index/detail/modify_key_adaptor.hpp>
+#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
+#include <boost/multi_index/detail/safe_mode.hpp>
+#include <boost/multi_index/detail/scope_guard.hpp>
+#include <boost/multi_index/hashed_index_fwd.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <cstddef>
+#include <functional>
+#include <utility>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/serialization/nvp.hpp>
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+#define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT                       \
+  detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
+    detail::make_obj_guard(*this,&hashed_index::check_invariant_);           \
+  BOOST_JOIN(check_invariant_,__LINE__).touch();
+#else
+#define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* hashed_index adds a layer of hashed indexing to a given Super */
+
+/* Most of the implementation of unique and non-unique indices is
+ * shared. We tell from one another on instantiation time by using
+ * these tags.
+ */
+
+struct hashed_unique_tag{};
+struct hashed_non_unique_tag{};
+
+template<
+  typename KeyFromValue,typename Hash,typename Pred,
+  typename SuperMeta,typename TagList,typename Category
+>
+class hashed_index:
+  BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  ,public safe_ctr_proxy_impl<
+    hashed_index_iterator<
+      hashed_index_node<typename SuperMeta::type::node_type>,
+      bucket_array<typename SuperMeta::type::final_allocator_type> >,
+    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
+#else
+  ,public safe_mode::safe_container<
+    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
+#endif
+#endif
+
+{ 
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
+ * lifetime of const references bound to temporaries --precisely what
+ * scopeguards are.
+ */
+
+#pragma parse_mfunc_templ off
+#endif
+
+  typedef typename SuperMeta::type                   super;
+
+protected:
+  typedef hashed_index_node<
+    typename super::node_type>                       node_type;
+
+private:
+  typedef typename node_type::impl_type              node_impl_type;
+  typedef typename node_impl_type::pointer           node_impl_pointer;
+  typedef bucket_array<
+    typename super::final_allocator_type>            bucket_array_type;
+
+public:
+  /* types */
+
+  typedef typename KeyFromValue::result_type         key_type;
+  typedef typename node_type::value_type             value_type;
+  typedef KeyFromValue                               key_from_value;
+  typedef Hash                                       hasher;
+  typedef Pred                                       key_equal;
+  typedef tuple<std::size_t,
+    key_from_value,hasher,key_equal>                 ctor_args;
+  typedef typename super::final_allocator_type       allocator_type;
+  typedef typename allocator_type::pointer           pointer;
+  typedef typename allocator_type::const_pointer     const_pointer;
+  typedef typename allocator_type::reference         reference;
+  typedef typename allocator_type::const_reference   const_reference;
+  typedef std::size_t                                size_type;      
+  typedef std::ptrdiff_t                             difference_type;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  typedef safe_mode::safe_iterator<
+    hashed_index_iterator<
+      node_type,bucket_array_type>,
+    safe_ctr_proxy<
+      hashed_index_iterator<
+        node_type,bucket_array_type> > >             iterator;
+#else
+  typedef safe_mode::safe_iterator<
+    hashed_index_iterator<
+      node_type,bucket_array_type>,
+    hashed_index>                                    iterator;
+#endif
+#else
+  typedef hashed_index_iterator<
+    node_type,bucket_array_type>                     iterator;
+#endif
+
+  typedef iterator                                   const_iterator;
+
+  typedef iterator                                   local_iterator;
+  typedef const_iterator                             const_local_iterator;
+  typedef TagList                                    tag_list;
+
+protected:
+  typedef typename super::final_node_type     final_node_type;
+  typedef tuples::cons<
+    ctor_args, 
+    typename super::ctor_args_list>           ctor_args_list;
+  typedef typename mpl::push_front<
+    typename super::index_type_list,
+    hashed_index>::type                       index_type_list;
+  typedef typename mpl::push_front<
+    typename super::iterator_type_list,
+    iterator>::type                           iterator_type_list;
+  typedef typename mpl::push_front<
+    typename super::const_iterator_type_list,
+    const_iterator>::type                     const_iterator_type_list;
+  typedef typename super::copy_map_type       copy_map_type;
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  typedef typename super::index_saver_type    index_saver_type;
+  typedef typename super::index_loader_type   index_loader_type;
+#endif
+
+private:
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  typedef safe_ctr_proxy_impl<
+    hashed_index_iterator<
+      node_type,bucket_array_type>,
+    hashed_index>                             safe_super;
+#else
+  typedef safe_mode::safe_container<
+    hashed_index>                             safe_super;
+#endif
+#endif
+
+  typedef typename call_traits<value_type>::param_type value_param_type;
+  typedef typename call_traits<
+    key_type>::param_type                              key_param_type;
+
+public:
+
+  /* construct/destroy/copy
+   * Default and copy ctors are in the protected section as indices are
+   * not supposed to be created on their own. No range ctor either.
+   */
+
+  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
+    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
+  {
+    this->final()=x.final();
+    return *this;
+  }
+
+  allocator_type get_allocator()const
+  {
+    return this->final().get_allocator();
+  }
+
+  /* size and capacity */
+
+  bool      empty()const{return this->final_empty_();}
+  size_type size()const{return this->final_size_();}
+  size_type max_size()const{return this->final_max_size_();}
+
+  /* iterators */
+
+  iterator begin()
+  {
+    return make_iterator(
+      node_type::from_impl(buckets.at(first_bucket)->next()));
+  }
+
+  const_iterator begin()const
+  {
+    return make_iterator(
+      node_type::from_impl(buckets.at(first_bucket)->next()));
+  }
+
+  iterator       end(){return make_iterator(header());}
+  const_iterator end()const{return make_iterator(header());}
+
+  const_iterator cbegin()const{return begin();}
+  const_iterator cend()const{return end();}
+
+  iterator iterator_to(const value_type& x)
+  {
+    return make_iterator(node_from_value<node_type>(&x));
+  }
+
+  const_iterator iterator_to(const value_type& x)const
+  {
+    return make_iterator(node_from_value<node_type>(&x));
+  }
+
+  /* modifiers */
+
+  std::pair<iterator,bool> insert(value_param_type x)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    std::pair<final_node_type*,bool> p=this->final_insert_(x);
+    return std::pair<iterator,bool>(make_iterator(p.first),p.second);
+  }
+
+  iterator insert(iterator position,value_param_type x)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    std::pair<final_node_type*,bool> p=this->final_insert_(
+      x,static_cast<final_node_type*>(position.get_node()));
+    return make_iterator(p.first);
+  }
+    
+  template<typename InputIterator>
+  void insert(InputIterator first,InputIterator last)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    iterator hint=end();
+    for(;first!=last;++first)hint=insert(hint,*first);
+  }
+
+  iterator erase(iterator position)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
+    return position;
+  }
+
+  size_type erase(key_param_type k)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+
+    size_type         s=0;
+    std::size_t       buc=buckets.position(hash(k));
+    node_impl_pointer x=buckets.at(buc);
+    node_impl_pointer y=x->next();
+    while(y!=x){
+      if(eq(k,key(node_type::from_impl(y)->value()))){
+        bool b;
+        do{
+          node_impl_pointer z=y->next();
+          b=z!=x&&eq(
+            key(node_type::from_impl(y)->value()),
+            key(node_type::from_impl(z)->value()));
+          this->final_erase_(
+            static_cast<final_node_type*>(node_type::from_impl(y)));
+          y=z;
+          ++s;
+        }while(b);
+        break;
+      }
+      y=y->next();
+    }
+    return s;
+  }
+
+  iterator erase(iterator first,iterator last)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    while(first!=last){
+      first=erase(first);
+    }
+    return first;
+  }
+
+  bool replace(iterator position,value_param_type x)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    return this->final_replace_(
+      x,static_cast<final_node_type*>(position.get_node()));
+  }
+
+  template<typename Modifier>
+  bool modify(iterator position,Modifier mod)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    /* MSVC++ 6.0 optimizer on safe mode code chokes if this
+     * this is not added. Left it for all compilers as it does no
+     * harm.
+     */
+
+    position.detach();
+#endif
+
+    return this->final_modify_(
+      mod,static_cast<final_node_type*>(position.get_node()));
+  }
+
+  template<typename Modifier,typename Rollback>
+  bool modify(iterator position,Modifier mod,Rollback back)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    /* MSVC++ 6.0 optimizer on safe mode code chokes if this
+     * this is not added. Left it for all compilers as it does no
+     * harm.
+     */
+
+    position.detach();
+#endif
+
+    return this->final_modify_(
+      mod,back,static_cast<final_node_type*>(position.get_node()));
+  }
+
+  template<typename Modifier>
+  bool modify_key(iterator position,Modifier mod)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    return modify(
+      position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
+  }
+
+  template<typename Modifier,typename Rollback>
+  bool modify_key(iterator position,Modifier mod,Rollback back)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    return modify(
+      position,
+      modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
+      modify_key_adaptor<Modifier,value_type,KeyFromValue>(back,key));
+  }
+
+  void clear()
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    this->final_clear_();
+  }
+
+  void swap(hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    this->final_swap_(x.final());
+  }
+
+  /* observers */
+
+  key_from_value key_extractor()const{return key;}
+  hasher         hash_function()const{return hash;}
+  key_equal      key_eq()const{return eq;}
+  
+  /* lookup */
+
+  /* Internally, these ops rely on const_iterator being the same
+   * type as iterator.
+   */
+
+  template<typename CompatibleKey>
+  iterator find(const CompatibleKey& k)const
+  {
+    return find(k,hash,eq);
+  }
+
+  template<
+    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
+  >
+  iterator find(
+    const CompatibleKey& k,
+    const CompatibleHash& hash,const CompatiblePred& eq)const
+  {
+    std::size_t       buc=buckets.position(hash(k));
+    node_impl_pointer x=buckets.at(buc);
+    node_impl_pointer y=x->next();
+    while(y!=x){
+      if(eq(k,key(node_type::from_impl(y)->value()))){
+        return make_iterator(node_type::from_impl(y));
+      }
+      y=y->next();
+    }
+    return end();
+  }
+
+  template<typename CompatibleKey>
+  size_type count(const CompatibleKey& k)const
+  {
+    return count(k,hash,eq);
+  }
+
+  template<
+    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
+  >
+  size_type count(
+    const CompatibleKey& k,
+    const CompatibleHash& hash,const CompatiblePred& eq)const
+  {
+    size_type         res=0;
+    std::size_t       buc=buckets.position(hash(k));
+    node_impl_pointer x=buckets.at(buc);
+    node_impl_pointer y=x->next();
+    while(y!=x){
+      if(eq(k,key(node_type::from_impl(y)->value()))){
+        do{
+          ++res;
+          y=y->next();
+        }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
+        break;
+      }
+      y=y->next();
+    }
+    return res;
+  }
+
+  template<typename CompatibleKey>
+  std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const
+  {
+    return equal_range(k,hash,eq);
+  }
+
+  template<
+    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
+  >
+  std::pair<iterator,iterator> equal_range(
+    const CompatibleKey& k,
+    const CompatibleHash& hash,const CompatiblePred& eq)const
+  {
+    std::size_t       buc=buckets.position(hash(k));
+    node_impl_pointer x=buckets.at(buc);
+    node_impl_pointer y=x->next();
+    while(y!=x){
+      if(eq(k,key(node_type::from_impl(y)->value()))){
+        node_impl_pointer y0=y;
+        do{
+          y=y->next();
+        }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
+        if(y==x){
+          do{
+            ++y;
+          }while(y==y->next());
+          y=y->next();
+        }
+        return std::pair<iterator,iterator>(
+          make_iterator(node_type::from_impl(y0)),
+          make_iterator(node_type::from_impl(y)));
+      }
+      y=y->next();
+    }
+    return std::pair<iterator,iterator>(end(),end());
+  }
+
+  /* bucket interface */
+
+  size_type bucket_count()const{return buckets.size();}
+  size_type max_bucket_count()const{return static_cast<size_type>(-1);}
+
+  size_type bucket_size(size_type n)const
+  {
+    size_type         res=0;
+    node_impl_pointer x=buckets.at(n);
+    node_impl_pointer y=x->next();
+    while(y!=x){
+      ++res;
+      y=y->next();
+    }
+    return res;
+  }
+
+  size_type bucket(key_param_type k)const
+  {
+    return buckets.position(hash(k));
+  }
+
+  local_iterator begin(size_type n)
+  {
+    return const_cast<const hashed_index*>(this)->begin(n);
+  }
+
+  const_local_iterator begin(size_type n)const
+  {
+    node_impl_pointer x=buckets.at(n);
+    node_impl_pointer y=x->next();
+    if(y==x)return end();
+    return make_iterator(node_type::from_impl(y));
+  }
+
+  local_iterator end(size_type n)
+  {
+    return const_cast<const hashed_index*>(this)->end(n);
+  }
+
+  const_local_iterator end(size_type n)const
+  {
+    node_impl_pointer x=buckets.at(n);
+    if(x==x->next())return end();
+    do{
+      ++x;
+    }while(x==x->next());
+    return make_iterator(node_type::from_impl(x->next()));
+  }
+
+  const_local_iterator cbegin(size_type n)const{return begin(n);}
+  const_local_iterator cend(size_type n)const{return end(n);}
+
+  local_iterator local_iterator_to(const value_type& x)
+  {
+    return make_iterator(node_from_value<node_type>(&x));
+  }
+
+  const_local_iterator local_iterator_to(const value_type& x)const
+  {
+    return make_iterator(node_from_value<node_type>(&x));
+  }
+
+  /* hash policy */
+
+  float load_factor()const{return static_cast<float>(size())/bucket_count();}
+  float max_load_factor()const{return mlf;}
+  void  max_load_factor(float z){mlf=z;calculate_max_load();}
+
+  void rehash(size_type n)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    if(size()<max_load&&n<=bucket_count())return;
+
+    size_type bc =(std::numeric_limits<size_type>::max)();
+    float     fbc=static_cast<float>(1+size()/mlf);
+    if(bc>fbc){
+      bc=static_cast<size_type>(fbc);
+      if(bc<n)bc=n;
+    }
+    unchecked_rehash(bc);
+  }
+
+BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
+  hashed_index(const ctor_args_list& args_list,const allocator_type& al):
+    super(args_list.get_tail(),al),
+    key(tuples::get<1>(args_list.get_head())),
+    hash(tuples::get<2>(args_list.get_head())),
+    eq(tuples::get<3>(args_list.get_head())),
+    buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
+    mlf(1.0),
+    first_bucket(buckets.size())
+  {
+    calculate_max_load();
+  }
+
+  hashed_index(
+    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
+    super(x),
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super(),
+#endif
+
+    key(x.key),
+    hash(x.hash),
+    eq(x.eq),
+    buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
+    mlf(x.mlf),
+    max_load(x.max_load),
+    first_bucket(x.first_bucket)
+  {
+    /* Copy ctor just takes the internal configuration objects from x. The rest
+     * is done in subsequent call to copy_().
+     */
+  }
+
+  ~hashed_index()
+  {
+    /* the container is guaranteed to be empty by now */
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  iterator make_iterator(node_type* node)
+  {
+    return iterator(node,&buckets,this);
+  }
+
+  const_iterator make_iterator(node_type* node)const
+  {
+    return const_iterator(
+      node,
+      &const_cast<bucket_array_type&>(buckets),
+      const_cast<hashed_index*>(this));
+  }
+#else
+  iterator make_iterator(node_type* node)
+  {
+    return iterator(node,&buckets);
+  }
+
+  const_iterator make_iterator(node_type* node)const
+  {
+    return const_iterator(node,&const_cast<bucket_array_type&>(buckets));
+  }
+#endif
+
+  void copy_(
+    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
+    const copy_map_type& map)
+  {
+    for(node_impl_pointer begin_org=x.buckets.begin(),
+                          begin_cpy=buckets.begin(),
+                          end_org=x.buckets.end();
+        begin_org!=end_org;++begin_org,++begin_cpy){
+
+      node_impl_pointer next_org=begin_org->next();
+      node_impl_pointer cpy=begin_cpy;
+      while(next_org!=begin_org){
+        cpy->next()=
+          static_cast<node_type*>(
+            map.find(
+              static_cast<final_node_type*>(
+                node_type::from_impl(next_org))))->impl();
+        next_org=next_org->next();
+        cpy=cpy->next();
+      }
+      cpy->next()=begin_cpy;
+    }
+
+    super::copy_(x,map);
+  }
+
+  node_type* insert_(value_param_type v,node_type* x)
+  {
+    reserve(size()+1);
+
+    std::size_t       buc=find_bucket(v);
+    node_impl_pointer pos=buckets.at(buc);
+    if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
+
+    node_type* res=static_cast<node_type*>(super::insert_(v,x));
+    if(res==x){
+      link(x,pos);
+      if(first_bucket>buc)first_bucket=buc;
+    }
+    return res;
+  }
+
+  node_type* insert_(value_param_type v,node_type* position,node_type* x)
+  {
+    reserve(size()+1);
+
+    std::size_t       buc=find_bucket(v);
+    node_impl_pointer pos=buckets.at(buc);
+    if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
+
+    node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
+    if(res==x){
+      link(x,pos);
+      if(first_bucket>buc)first_bucket=buc;
+    }
+    return res;
+  }
+
+  void erase_(node_type* x)
+  {
+    unlink(x);
+    first_bucket=buckets.first_nonempty(first_bucket);
+    super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    detach_iterators(x);
+#endif
+  }
+
+  void delete_all_nodes_()
+  {
+    for(node_impl_pointer x=buckets.begin(),x_end=buckets.end();
+        x!=x_end;++x){
+      node_impl_pointer y=x->next();
+      while(y!=x){
+        node_impl_pointer z=y->next();
+        this->final_delete_node_(
+          static_cast<final_node_type*>(node_type::from_impl(y)));
+        y=z;
+      }
+    }
+  }
+
+  void clear_()
+  {
+    super::clear_();
+    buckets.clear();
+    first_bucket=buckets.size();
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::detach_dereferenceable_iterators();
+#endif
+  }
+
+  void swap_(
+    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
+  {
+    std::swap(key,x.key);
+    std::swap(hash,x.hash);
+    std::swap(eq,x.eq);
+    buckets.swap(x.buckets);
+    std::swap(mlf,x.mlf);
+    std::swap(max_load,x.max_load);
+    std::swap(first_bucket,x.first_bucket);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::swap(x);
+#endif
+
+    super::swap_(x);
+  }
+
+  bool replace_(value_param_type v,node_type* x)
+  {
+    if(eq(key(v),key(x->value()))){
+      return super::replace_(v,x);
+    }
+
+    node_impl_pointer y=prev(x);
+    unlink_next(y);
+
+    BOOST_TRY{
+      std::size_t       buc=find_bucket(v);
+      node_impl_pointer pos=buckets.at(buc);
+      if(link_point(v,pos,Category())&&super::replace_(v,x)){
+        link(x,pos);
+        if(first_bucket>buc){
+          first_bucket=buc;
+        }
+        else if(first_bucket<buc){
+          first_bucket=buckets.first_nonempty(first_bucket);
+        }
+        return true;
+      }
+      link(x,y);
+      return false;
+    }
+    BOOST_CATCH(...){
+      link(x,y);
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+  bool modify_(node_type* x)
+  {
+    unlink(x);
+
+    std::size_t       buc;
+    node_impl_pointer pos;
+    BOOST_TRY
+    {
+      buc=find_bucket(x->value());
+      pos=buckets.at(buc);
+      if(!link_point(x->value(),pos,Category())){
+        first_bucket=buckets.first_nonempty(first_bucket);
+        super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+        detach_iterators(x);
+#endif
+        return false;
+      }
+
+    }
+    BOOST_CATCH(...){
+      first_bucket=buckets.first_nonempty(first_bucket);
+      super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+      detach_iterators(x);
+#endif
+
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+
+    BOOST_TRY{
+      if(super::modify_(x)){
+        link(x,pos);
+        if(first_bucket>buc){
+          first_bucket=buc;
+        }
+        else if(first_bucket<buc){
+          first_bucket=buckets.first_nonempty(first_bucket);
+        }
+        return true;
+      }
+
+      first_bucket=buckets.first_nonempty(first_bucket);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+      detach_iterators(x);
+#endif
+      return false;
+    }
+    BOOST_CATCH(...){
+      first_bucket=buckets.first_nonempty(first_bucket);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+      detach_iterators(x);
+#endif
+
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+  bool modify_rollback_(node_type* x)
+  {
+    node_impl_pointer y=prev(x);
+    unlink_next(y);
+
+    BOOST_TRY{
+      std::size_t             buc=find_bucket(x->value());
+      node_impl_pointer pos=buckets.at(buc);
+      if(link_point(x->value(),pos,Category())&&super::modify_rollback_(x)){
+        link(x,pos);
+        if(first_bucket>buc){
+          first_bucket=buc;
+        }
+        else if(first_bucket<buc){
+          first_bucket=buckets.first_nonempty(first_bucket);
+        }
+        return true;
+      }
+      link(x,y);
+      return false;
+    }
+    BOOST_CATCH(...){
+      link(x,y);
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  /* serialization */
+
+  template<typename Archive>
+  void save_(
+    Archive& ar,const unsigned int version,const index_saver_type& sm)const
+  {
+    ar<<serialization::make_nvp("position",buckets);
+    super::save_(ar,version,sm);
+  }
+
+  template<typename Archive>
+  void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
+  {
+    ar>>serialization::make_nvp("position",buckets);
+    super::load_(ar,version,lm);
+  }
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+  /* invariant stuff */
+
+  bool invariant_()const
+  {
+    if(size()==0||begin()==end()){
+      if(size()!=0||begin()!=end())return false;
+    }
+    else{
+      size_type s0=0;
+      for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s0){}
+      if(s0!=size())return false;
+
+      size_type s1=0;
+      for(size_type buc=0;buc<bucket_count();++buc){
+        size_type ss1=0;
+        for(const_local_iterator it=begin(buc),it_end=end(buc);
+            it!=it_end;++it,++ss1){
+          if(find_bucket(*it)!=buc)return false;
+        }
+        if(ss1!=bucket_size(buc))return false;
+        s1+=ss1;
+      }
+      if(s1!=size())return false;
+    }
+
+    if(first_bucket!=buckets.first_nonempty(0))return false;
+
+    return super::invariant_();
+  }
+
+  /* This forwarding function eases things for the boost::mem_fn construct
+   * in BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT. Actually,
+   * final_check_invariant is already an inherited member function of index.
+   */
+  void check_invariant_()const{this->final_check_invariant_();}
+#endif
+
+private:
+  node_type* header()const{return this->final_header();}
+
+  std::size_t find_bucket(value_param_type v)const
+  {
+    return bucket(key(v));
+  }
+
+  bool link_point(
+    value_param_type v,node_impl_pointer& pos,hashed_unique_tag)
+  {
+    node_impl_pointer x=pos->next();
+    while(x!=pos){
+      if(eq(key(v),key(node_type::from_impl(x)->value()))){
+        pos=x;
+        return false;
+      }
+      x=x->next();
+    }
+    return true;
+  }
+
+  bool link_point(
+    value_param_type v,node_impl_pointer& pos,hashed_non_unique_tag)
+  {
+    node_impl_pointer prev=pos;
+    node_impl_pointer x=pos->next();
+    while(x!=pos){
+      if(eq(key(v),key(node_type::from_impl(x)->value()))){
+        pos=prev;
+        return true;
+      }
+      prev=x;
+      x=x->next();
+    }
+    return true;
+  }
+  
+  void link(node_type* x,node_impl_pointer pos)
+  {
+    node_impl_type::link(x->impl(),pos);
+  };
+
+  void link(node_impl_pointer x,node_impl_pointer pos)
+  {
+    node_impl_type::link(x,pos);
+  };
+
+  void unlink(node_type* x)
+  {
+    node_impl_type::unlink(x->impl());
+  };
+
+  static node_impl_pointer prev(node_type* x)
+  {
+    return node_impl_type::prev(x->impl());
+  }
+
+  static void unlink_next(node_impl_pointer x)
+  {
+    node_impl_type::unlink_next(x);
+  }
+
+  void calculate_max_load()
+  {
+    float fml=static_cast<float>(mlf*bucket_count());
+    max_load=(std::numeric_limits<size_type>::max)();
+    if(max_load>fml)max_load=static_cast<size_type>(fml);
+  }
+
+  void reserve(size_type n)
+  {
+    if(n>max_load){
+      size_type bc =(std::numeric_limits<size_type>::max)();
+      float     fbc=static_cast<float>(1+n/mlf);
+      if(bc>fbc)bc =static_cast<size_type>(fbc);
+      unchecked_rehash(bc);
+    }
+  }
+
+  void unchecked_rehash(size_type n)
+  {
+    bucket_array_type buckets1(get_allocator(),header()->impl(),n);
+    auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
+
+    std::size_t i=0;
+    node_impl_pointer x=buckets.begin();
+    node_impl_pointer x_end=buckets.end();
+    for(;x!=x_end;++x){
+      node_impl_pointer y=x->next();
+      while(y!=x){
+        hashes.data()[i++]=hash(key(node_type::from_impl(y)->value()));
+        y=y->next();
+      }
+    }
+
+    i=0;
+    x=buckets.begin();
+    for(;x!=x_end;++x){
+      node_impl_pointer y=x->next();
+      while(y!=x){
+        node_impl_pointer z=y->next();
+        std::size_t       buc1=buckets1.position(hashes.data()[i++]);
+        node_impl_pointer x1=buckets1.at(buc1);
+        link(y,x1);
+        y=z;
+      }
+    }
+
+    buckets.swap(buckets1);
+    calculate_max_load();
+    first_bucket=buckets.first_nonempty(0);
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  void detach_iterators(node_type* x)
+  {
+    iterator it=make_iterator(x);
+    safe_mode::detach_equivalent_iterators(it);
+  }
+#endif
+
+  key_from_value               key;
+  hasher                       hash;
+  key_equal                    eq;
+  bucket_array_type            buckets;
+  float                        mlf;
+  size_type                    max_load;
+  std::size_t                  first_bucket;
+      
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+#pragma parse_mfunc_templ reset
+#endif
+};
+
+/*  specialized algorithms */
+
+template<
+  typename KeyFromValue,typename Hash,typename Pred,
+  typename SuperMeta,typename TagList,typename Category
+>
+void swap(
+  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
+  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
+{
+  x.swap(y);
+}
+
+} /* namespace multi_index::detail */
+
+/* hashed index specifiers */
+
+template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
+struct hashed_unique
+{
+  typedef typename detail::hashed_index_args<
+    Arg1,Arg2,Arg3,Arg4>                           index_args;
+  typedef typename index_args::tag_list_type::type tag_list_type;
+  typedef typename index_args::key_from_value_type key_from_value_type;
+  typedef typename index_args::hash_type           hash_type;
+  typedef typename index_args::pred_type           pred_type;
+
+  template<typename Super>
+  struct node_class
+  {
+    typedef detail::hashed_index_node<Super> type;
+  };
+
+  template<typename SuperMeta>
+  struct index_class
+  {
+    typedef detail::hashed_index<
+      key_from_value_type,hash_type,pred_type,
+      SuperMeta,tag_list_type,detail::hashed_unique_tag> type;
+  };
+};
+
+template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
+struct hashed_non_unique
+{
+  typedef typename detail::hashed_index_args<
+    Arg1,Arg2,Arg3,Arg4>                           index_args;
+  typedef typename index_args::tag_list_type::type tag_list_type;
+  typedef typename index_args::key_from_value_type key_from_value_type;
+  typedef typename index_args::hash_type           hash_type;
+  typedef typename index_args::pred_type           pred_type;
+
+  template<typename Super>
+  struct node_class
+  {
+    typedef detail::hashed_index_node<Super> type;
+  };
+
+  template<typename SuperMeta>
+  struct index_class
+  {
+    typedef detail::hashed_index<
+      key_from_value_type,hash_type,pred_type,
+      SuperMeta,tag_list_type,detail::hashed_non_unique_tag> type;
+  };
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
+
+#endif