epoc32/include/stdapis/boost/multi_index/hashed_index.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
     1 /* Copyright 2003-2007 Joaquín M López Muñoz.
     2  * Distributed under the Boost Software License, Version 1.0.
     3  * (See accompanying file LICENSE_1_0.txt or copy at
     4  * http://www.boost.org/LICENSE_1_0.txt)
     5  *
     6  * See http://www.boost.org/libs/multi_index for library home page.
     7  */
     8 
     9 #ifndef BOOST_MULTI_INDEX_HASHED_INDEX_HPP
    10 #define BOOST_MULTI_INDEX_HASHED_INDEX_HPP
    11 
    12 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
    13 #pragma once
    14 #endif
    15 
    16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
    17 #include <algorithm>
    18 #include <boost/call_traits.hpp>
    19 #include <boost/detail/allocator_utilities.hpp>
    20 #include <boost/detail/no_exceptions_support.hpp>
    21 #include <boost/detail/workaround.hpp>
    22 #include <boost/limits.hpp>
    23 #include <boost/mpl/push_front.hpp>
    24 #include <boost/multi_index/detail/access_specifier.hpp>
    25 #include <boost/multi_index/detail/auto_space.hpp>
    26 #include <boost/multi_index/detail/bucket_array.hpp>
    27 #include <boost/multi_index/detail/hash_index_iterator.hpp>
    28 #include <boost/multi_index/detail/modify_key_adaptor.hpp>
    29 #include <boost/multi_index/detail/safe_ctr_proxy.hpp>
    30 #include <boost/multi_index/detail/safe_mode.hpp>
    31 #include <boost/multi_index/detail/scope_guard.hpp>
    32 #include <boost/multi_index/hashed_index_fwd.hpp>
    33 #include <boost/tuple/tuple.hpp>
    34 #include <cstddef>
    35 #include <functional>
    36 #include <utility>
    37 
    38 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
    39 #include <boost/serialization/nvp.hpp>
    40 #endif
    41 
    42 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
    43 #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT                       \
    44   detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
    45     detail::make_obj_guard(*this,&hashed_index::check_invariant_);           \
    46   BOOST_JOIN(check_invariant_,__LINE__).touch();
    47 #else
    48 #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
    49 #endif
    50 
    51 namespace boost{
    52 
    53 namespace multi_index{
    54 
    55 namespace detail{
    56 
    57 /* hashed_index adds a layer of hashed indexing to a given Super */
    58 
    59 /* Most of the implementation of unique and non-unique indices is
    60  * shared. We tell from one another on instantiation time by using
    61  * these tags.
    62  */
    63 
    64 struct hashed_unique_tag{};
    65 struct hashed_non_unique_tag{};
    66 
    67 template<
    68   typename KeyFromValue,typename Hash,typename Pred,
    69   typename SuperMeta,typename TagList,typename Category
    70 >
    71 class hashed_index:
    72   BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
    73 
    74 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
    75 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
    76   ,public safe_ctr_proxy_impl<
    77     hashed_index_iterator<
    78       hashed_index_node<typename SuperMeta::type::node_type>,
    79       bucket_array<typename SuperMeta::type::final_allocator_type> >,
    80     hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
    81 #else
    82   ,public safe_mode::safe_container<
    83     hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
    84 #endif
    85 #endif
    86 
    87 { 
    88 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
    89     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
    90 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
    91  * lifetime of const references bound to temporaries --precisely what
    92  * scopeguards are.
    93  */
    94 
    95 #pragma parse_mfunc_templ off
    96 #endif
    97 
    98   typedef typename SuperMeta::type                   super;
    99 
   100 protected:
   101   typedef hashed_index_node<
   102     typename super::node_type>                       node_type;
   103   typedef bucket_array<
   104     typename super::final_allocator_type>            bucket_array_type;
   105 
   106 public:
   107   /* types */
   108 
   109   typedef typename KeyFromValue::result_type         key_type;
   110   typedef typename node_type::value_type             value_type;
   111   typedef KeyFromValue                               key_from_value;
   112   typedef Hash                                       hasher;
   113   typedef Pred                                       key_equal;
   114   typedef tuple<std::size_t,
   115     key_from_value,hasher,key_equal>                 ctor_args;
   116   typedef typename super::final_allocator_type       allocator_type;
   117   typedef typename allocator_type::pointer           pointer;
   118   typedef typename allocator_type::const_pointer     const_pointer;
   119   typedef typename allocator_type::reference         reference;
   120   typedef typename allocator_type::const_reference   const_reference;
   121   typedef std::size_t                                size_type;      
   122   typedef std::ptrdiff_t                             difference_type;
   123 
   124 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   125 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
   126   typedef safe_mode::safe_iterator<
   127     hashed_index_iterator<
   128       node_type,bucket_array_type>,
   129     safe_ctr_proxy<
   130       hashed_index_iterator<
   131         node_type,bucket_array_type> > >             iterator;
   132 #else
   133   typedef safe_mode::safe_iterator<
   134     hashed_index_iterator<
   135       node_type,bucket_array_type>,
   136     hashed_index>                                    iterator;
   137 #endif
   138 #else
   139   typedef hashed_index_iterator<
   140     node_type,bucket_array_type>                     iterator;
   141 #endif
   142 
   143   typedef iterator                                   const_iterator;
   144 
   145   typedef iterator                                   local_iterator;
   146   typedef const_iterator                             const_local_iterator;
   147   typedef TagList                                    tag_list;
   148 
   149 protected:
   150   typedef typename super::final_node_type     final_node_type;
   151   typedef tuples::cons<
   152     ctor_args, 
   153     typename super::ctor_args_list>           ctor_args_list;
   154   typedef typename mpl::push_front<
   155     typename super::index_type_list,
   156     hashed_index>::type                       index_type_list;
   157   typedef typename mpl::push_front<
   158     typename super::iterator_type_list,
   159     iterator>::type                           iterator_type_list;
   160   typedef typename mpl::push_front<
   161     typename super::const_iterator_type_list,
   162     const_iterator>::type                     const_iterator_type_list;
   163   typedef typename super::copy_map_type       copy_map_type;
   164 
   165 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   166   typedef typename super::index_saver_type    index_saver_type;
   167   typedef typename super::index_loader_type   index_loader_type;
   168 #endif
   169 
   170 private:
   171 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   172 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
   173   typedef safe_ctr_proxy_impl<
   174     hashed_index_iterator<
   175       node_type,
   176       bucket_array_type>,
   177     hashed_index>                             safe_super;
   178 #else
   179   typedef safe_mode::safe_container<
   180     hashed_index>                             safe_super;
   181 #endif
   182 #endif
   183 
   184   typedef typename call_traits<value_type>::param_type value_param_type;
   185   typedef typename call_traits<
   186     key_type>::param_type                              key_param_type;
   187 
   188 public:
   189 
   190   /* construct/destroy/copy
   191    * Default and copy ctors are in the protected section as indices are
   192    * not supposed to be created on their own. No range ctor either.
   193    */
   194 
   195   hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
   196     const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
   197   {
   198     this->final()=x.final();
   199     return *this;
   200   }
   201 
   202   allocator_type get_allocator()const
   203   {
   204     return this->final().get_allocator();
   205   }
   206 
   207   /* size and capacity */
   208 
   209   bool      empty()const{return this->final_empty_();}
   210   size_type size()const{return this->final_size_();}
   211   size_type max_size()const{return this->final_max_size_();}
   212 
   213   /* iterators */
   214 
   215   iterator begin()
   216   {
   217     return make_iterator(
   218       node_type::from_impl(buckets.at(first_bucket)->next()));
   219   }
   220 
   221   const_iterator begin()const
   222   {
   223     return make_iterator(
   224       node_type::from_impl(buckets.at(first_bucket)->next()));
   225   }
   226 
   227   iterator       end(){return make_iterator(header());}
   228   const_iterator end()const{return make_iterator(header());}
   229 
   230   /* modifiers */
   231 
   232   std::pair<iterator,bool> insert(value_param_type x)
   233   {
   234     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   235     std::pair<final_node_type*,bool> p=this->final_insert_(x);
   236     return std::pair<iterator,bool>(make_iterator(p.first),p.second);
   237   }
   238 
   239   iterator insert(iterator position,value_param_type x)
   240   {
   241     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
   242     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
   243     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   244     std::pair<final_node_type*,bool> p=this->final_insert_(
   245       x,static_cast<final_node_type*>(position.get_node()));
   246     return make_iterator(p.first);
   247   }
   248     
   249   template<typename InputIterator>
   250   void insert(InputIterator first,InputIterator last)
   251   {
   252     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   253     iterator hint=end();
   254     for(;first!=last;++first)hint=insert(hint,*first);
   255   }
   256 
   257   iterator erase(iterator position)
   258   {
   259     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
   260     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
   261     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
   262     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   263     this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
   264     return position;
   265   }
   266 
   267   size_type erase(key_param_type k)
   268   {
   269     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   270 
   271     size_type               s=0;
   272     std::size_t             buc=buckets.position(hash(k));
   273     hashed_index_node_impl* x=buckets.at(buc);
   274     hashed_index_node_impl* y=x->next();
   275     while(y!=x){
   276       if(eq(k,key(node_type::from_impl(y)->value()))){
   277         bool b;
   278         do{
   279           hashed_index_node_impl* z=y->next();
   280           b=z!=x&&eq(
   281             key(node_type::from_impl(y)->value()),
   282             key(node_type::from_impl(z)->value()));
   283           this->final_erase_(
   284             static_cast<final_node_type*>(node_type::from_impl(y)));
   285           y=z;
   286           ++s;
   287         }while(b);
   288         break;
   289       }
   290       y=y->next();
   291     }
   292     return s;
   293   }
   294 
   295   iterator erase(iterator first,iterator last)
   296   {
   297     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
   298     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
   299     BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
   300     BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
   301     BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
   302     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   303     while(first!=last){
   304       first=erase(first);
   305     }
   306     return first;
   307   }
   308 
   309   bool replace(iterator position,value_param_type x)
   310   {
   311     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
   312     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
   313     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
   314     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   315     return this->final_replace_(
   316       x,static_cast<final_node_type*>(position.get_node()));
   317   }
   318 
   319   template<typename Modifier>
   320   bool modify(iterator position,Modifier mod)
   321   {
   322     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
   323     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
   324     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
   325     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   326 
   327 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   328     /* MSVC++ 6.0 optimizer on safe mode code chokes if this
   329      * this is not added. Left it for all compilers as it does no
   330      * harm.
   331      */
   332 
   333     position.detach();
   334 #endif
   335 
   336     return this->final_modify_(
   337       mod,static_cast<final_node_type*>(position.get_node()));
   338   }
   339 
   340   template<typename Modifier>
   341   bool modify_key(iterator position,Modifier mod)
   342   {
   343     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
   344     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
   345     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
   346     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   347     return modify(
   348       position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
   349   }
   350 
   351   void clear()
   352   {
   353     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   354     this->final_clear_();
   355   }
   356 
   357   void swap(hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
   358   {
   359     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   360     this->final_swap_(x.final());
   361   }
   362 
   363   /* observers */
   364 
   365   key_from_value key_extractor()const{return key;}
   366   hasher         hash_function()const{return hash;}
   367   key_equal      key_eq()const{return eq;}
   368   
   369   /* lookup */
   370 
   371   /* Internally, these ops rely on const_iterator being the same
   372    * type as iterator.
   373    */
   374 
   375   template<typename CompatibleKey>
   376   iterator find(const CompatibleKey& k)const
   377   {
   378     return find(k,hash,eq);
   379   }
   380 
   381   template<
   382     typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
   383   >
   384   iterator find(
   385     const CompatibleKey& k,
   386     const CompatibleHash& hash,const CompatiblePred& eq)const
   387   {
   388     std::size_t             buc=buckets.position(hash(k));
   389     hashed_index_node_impl* x=buckets.at(buc);
   390     hashed_index_node_impl* y=x->next();
   391     while(y!=x){
   392       if(eq(k,key(node_type::from_impl(y)->value()))){
   393         return make_iterator(node_type::from_impl(y));
   394       }
   395       y=y->next();
   396     }
   397     return end();
   398   }
   399 
   400   template<typename CompatibleKey>
   401   size_type count(const CompatibleKey& k)const
   402   {
   403     return count(k,hash,eq);
   404   }
   405 
   406   template<
   407     typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
   408   >
   409   size_type count(
   410     const CompatibleKey& k,
   411     const CompatibleHash& hash,const CompatiblePred& eq)const
   412   {
   413     size_type               res=0;
   414     std::size_t             buc=buckets.position(hash(k));
   415     hashed_index_node_impl* x=buckets.at(buc);
   416     hashed_index_node_impl* y=x->next();
   417     while(y!=x){
   418       if(eq(k,key(node_type::from_impl(y)->value()))){
   419         do{
   420           ++res;
   421           y=y->next();
   422         }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
   423         break;
   424       }
   425       y=y->next();
   426     }
   427     return res;
   428   }
   429 
   430   template<typename CompatibleKey>
   431   std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const
   432   {
   433     return equal_range(k,hash,eq);
   434   }
   435 
   436   template<
   437     typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
   438   >
   439   std::pair<iterator,iterator> equal_range(
   440     const CompatibleKey& k,
   441     const CompatibleHash& hash,const CompatiblePred& eq)const
   442   {
   443     std::size_t             buc=buckets.position(hash(k));
   444     hashed_index_node_impl* x=buckets.at(buc);
   445     hashed_index_node_impl* y=x->next();
   446     while(y!=x){
   447       if(eq(k,key(node_type::from_impl(y)->value()))){
   448         hashed_index_node_impl* y0=y;
   449         do{
   450           y=y->next();
   451         }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
   452         if(y==x){
   453           do{
   454             ++y;
   455           }while(y==y->next());
   456           y=y->next();
   457         }
   458         return std::pair<iterator,iterator>(
   459           make_iterator(node_type::from_impl(y0)),
   460           make_iterator(node_type::from_impl(y)));
   461       }
   462       y=y->next();
   463     }
   464     return std::pair<iterator,iterator>(end(),end());
   465   }
   466 
   467   /* bucket interface */
   468 
   469   size_type bucket_count()const{return buckets.size();}
   470   size_type max_bucket_count()const{return static_cast<size_type>(-1);}
   471 
   472   size_type bucket_size(size_type n)const
   473   {
   474     size_type               res=0;
   475     hashed_index_node_impl* x=buckets.at(n);
   476     hashed_index_node_impl* y=x->next();
   477     while(y!=x){
   478       ++res;
   479       y=y->next();
   480     }
   481     return res;
   482   }
   483 
   484   size_type bucket(key_param_type k)const
   485   {
   486     return buckets.position(hash(k));
   487   }
   488 
   489   local_iterator begin(size_type n)
   490   {
   491     return const_cast<const hashed_index*>(this)->begin(n);
   492   }
   493 
   494   const_local_iterator begin(size_type n)const
   495   {
   496     hashed_index_node_impl* x=buckets.at(n);
   497     hashed_index_node_impl* y=x->next();
   498     if(y==x)return end();
   499     return make_iterator(node_type::from_impl(y));
   500   }
   501 
   502   local_iterator end(size_type n)
   503   {
   504     return const_cast<const hashed_index*>(this)->end(n);
   505   }
   506 
   507   const_local_iterator end(size_type n)const
   508   {
   509     hashed_index_node_impl* x=buckets.at(n);
   510     if(x==x->next())return end();
   511     do{
   512       ++x;
   513     }while(x==x->next());
   514     return make_iterator(node_type::from_impl(x->next()));
   515   }
   516 
   517   /* hash policy */
   518 
   519   float load_factor()const{return static_cast<float>(size())/bucket_count();}
   520   float max_load_factor()const{return mlf;}
   521   void  max_load_factor(float z){mlf=z;calculate_max_load();}
   522 
   523   void rehash(size_type n)
   524   {
   525     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
   526     if(size()<max_load&&n<=bucket_count())return;
   527 
   528     size_type bc =(std::numeric_limits<size_type>::max)();
   529     float     fbc=static_cast<float>(1+size()/mlf);
   530     if(bc>fbc){
   531       bc=static_cast<size_type>(fbc);
   532       if(bc<n)bc=n;
   533     }
   534     unchecked_rehash(bc);
   535   }
   536 
   537 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
   538   hashed_index(const ctor_args_list& args_list,const allocator_type& al):
   539     super(args_list.get_tail(),al),
   540     key(tuples::get<1>(args_list.get_head())),
   541     hash(tuples::get<2>(args_list.get_head())),
   542     eq(tuples::get<3>(args_list.get_head())),
   543     buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
   544     mlf(1.0),
   545     first_bucket(buckets.size())
   546   {
   547     calculate_max_load();
   548   }
   549 
   550   hashed_index(
   551     const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
   552     super(x),
   553 
   554 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   555     safe_super(),
   556 #endif
   557 
   558     key(x.key),
   559     hash(x.hash),
   560     eq(x.eq),
   561     buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
   562     mlf(x.mlf),
   563     max_load(x.max_load),
   564     first_bucket(x.first_bucket)
   565   {
   566     /* Copy ctor just takes the internal configuration objects from x. The rest
   567      * is done in subsequent call to copy_().
   568      */
   569   }
   570 
   571   ~hashed_index()
   572   {
   573     /* the container is guaranteed to be empty by now */
   574   }
   575 
   576 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   577   iterator make_iterator(node_type* node)
   578   {
   579     return iterator(node,&buckets,this);
   580   }
   581 
   582   const_iterator make_iterator(node_type* node)const
   583   {
   584     return const_iterator(
   585       node,
   586       &const_cast<bucket_array_type&>(buckets),
   587       const_cast<hashed_index*>(this));
   588   }
   589 #else
   590   iterator make_iterator(node_type* node)
   591   {
   592     return iterator(node,&buckets);
   593   }
   594 
   595   const_iterator make_iterator(node_type* node)const
   596   {
   597     return const_iterator(node,&const_cast<bucket_array_type&>(buckets));
   598   }
   599 #endif
   600 
   601   void copy_(
   602     const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
   603     const copy_map_type& map)
   604   {
   605     for(hashed_index_node_impl* begin_org=x.buckets.begin(),
   606                               * begin_cpy=buckets.begin(),
   607                               * end_org=x.buckets.end();
   608         begin_org!=end_org;++begin_org,++begin_cpy){
   609 
   610       hashed_index_node_impl* next_org=begin_org->next();
   611       hashed_index_node_impl* cpy=begin_cpy;
   612       while(next_org!=begin_org){
   613         cpy->next()=
   614           static_cast<node_type*>(
   615             map.find(
   616               static_cast<final_node_type*>(
   617                 node_type::from_impl(next_org))))->impl();
   618         next_org=next_org->next();
   619         cpy=cpy->next();
   620       }
   621       cpy->next()=begin_cpy;
   622     }
   623 
   624     super::copy_(x,map);
   625   }
   626 
   627   node_type* insert_(value_param_type v,node_type* x)
   628   {
   629     reserve(size()+1);
   630 
   631     std::size_t             buc=find_bucket(v);
   632     hashed_index_node_impl* pos=buckets.at(buc);
   633     if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
   634 
   635     node_type* res=static_cast<node_type*>(super::insert_(v,x));
   636     if(res==x){
   637       link(x,pos);
   638       if(first_bucket>buc)first_bucket=buc;
   639     }
   640     return res;
   641   }
   642 
   643   node_type* insert_(value_param_type v,node_type* position,node_type* x)
   644   {
   645     reserve(size()+1);
   646 
   647     std::size_t             buc=find_bucket(v);
   648     hashed_index_node_impl* pos=buckets.at(buc);
   649     if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
   650 
   651     node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
   652     if(res==x){
   653       link(x,pos);
   654       if(first_bucket>buc)first_bucket=buc;
   655     }
   656     return res;
   657   }
   658 
   659   void erase_(node_type* x)
   660   {
   661     unlink(x);
   662     first_bucket=buckets.first_nonempty(first_bucket);
   663     super::erase_(x);
   664 
   665 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   666     detach_iterators(x);
   667 #endif
   668   }
   669 
   670   void delete_all_nodes_()
   671   {
   672     for(hashed_index_node_impl* x=buckets.begin(),*x_end=buckets.end();
   673         x!=x_end;++x){
   674       hashed_index_node_impl* y=x->next();
   675       while(y!=x){
   676         hashed_index_node_impl* z=y->next();
   677         this->final_delete_node_(
   678           static_cast<final_node_type*>(node_type::from_impl(y)));
   679         y=z;
   680       }
   681     }
   682   }
   683 
   684   void clear_()
   685   {
   686     super::clear_();
   687     buckets.clear();
   688     first_bucket=buckets.size();
   689 
   690 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   691     safe_super::detach_dereferenceable_iterators();
   692 #endif
   693   }
   694 
   695   void swap_(
   696     hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
   697   {
   698     std::swap(key,x.key);
   699     std::swap(hash,x.hash);
   700     std::swap(eq,x.eq);
   701     buckets.swap(x.buckets);
   702     std::swap(mlf,x.mlf);
   703     std::swap(max_load,x.max_load);
   704     std::swap(first_bucket,x.first_bucket);
   705 
   706 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   707     safe_super::swap(x);
   708 #endif
   709 
   710     super::swap_(x);
   711   }
   712 
   713   bool replace_(value_param_type v,node_type* x)
   714   {
   715     if(eq(key(v),key(x->value()))){
   716       return super::replace_(v,x);
   717     }
   718 
   719     hashed_index_node_impl* y=prev(x);
   720     unlink_next(y);
   721 
   722     BOOST_TRY{
   723       std::size_t             buc=find_bucket(v);
   724       hashed_index_node_impl* pos=buckets.at(buc);
   725       if(link_point(v,pos,Category())&&super::replace_(v,x)){
   726         link(x,pos);
   727         if(first_bucket>buc){
   728           first_bucket=buc;
   729         }
   730         else if(first_bucket<buc){
   731           first_bucket=buckets.first_nonempty(first_bucket);
   732         }
   733         return true;
   734       }
   735       link(x,y);
   736       return false;
   737     }
   738     BOOST_CATCH(...){
   739       link(x,y);
   740       BOOST_RETHROW;
   741     }
   742     BOOST_CATCH_END
   743   }
   744 
   745   bool modify_(node_type* x)
   746   {
   747     unlink(x);
   748 
   749     std::size_t             buc;
   750     hashed_index_node_impl* pos;
   751     BOOST_TRY
   752     {
   753       buc=find_bucket(x->value());
   754       pos=buckets.at(buc);
   755       if(!link_point(x->value(),pos,Category())){
   756         first_bucket=buckets.first_nonempty(first_bucket);
   757         super::erase_(x);
   758 
   759 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   760         detach_iterators(x);
   761 #endif
   762         return false;
   763       }
   764 
   765     }
   766     BOOST_CATCH(...){
   767       first_bucket=buckets.first_nonempty(first_bucket);
   768       super::erase_(x);
   769 
   770 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   771       detach_iterators(x);
   772 #endif
   773 
   774       BOOST_RETHROW;
   775     }
   776     BOOST_CATCH_END
   777 
   778     BOOST_TRY{
   779       if(super::modify_(x)){
   780         link(x,pos);
   781         if(first_bucket>buc){
   782           first_bucket=buc;
   783         }
   784         else if(first_bucket<buc){
   785           first_bucket=buckets.first_nonempty(first_bucket);
   786         }
   787         return true;
   788       }
   789 
   790       first_bucket=buckets.first_nonempty(first_bucket);
   791 
   792 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   793       detach_iterators(x);
   794 #endif
   795       return false;
   796     }
   797     BOOST_CATCH(...){
   798       first_bucket=buckets.first_nonempty(first_bucket);
   799 
   800 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   801       detach_iterators(x);
   802 #endif
   803 
   804       BOOST_RETHROW;
   805     }
   806     BOOST_CATCH_END
   807   }
   808 
   809 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   810   /* serialization */
   811 
   812   template<typename Archive>
   813   void save_(
   814     Archive& ar,const unsigned int version,const index_saver_type& sm)const
   815   {
   816     ar<<serialization::make_nvp("position",buckets);
   817     super::save_(ar,version,sm);
   818   }
   819 
   820   template<typename Archive>
   821   void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
   822   {
   823     ar>>serialization::make_nvp("position",buckets);
   824     super::load_(ar,version,lm);
   825   }
   826 #endif
   827 
   828 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
   829   /* invariant stuff */
   830 
   831   bool invariant_()const
   832   {
   833     if(size()==0||begin()==end()){
   834       if(size()!=0||begin()!=end())return false;
   835     }
   836     else{
   837       size_type s0=0;
   838       for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s0){}
   839       if(s0!=size())return false;
   840 
   841       size_type s1=0;
   842       for(size_type buc=0;buc<bucket_count();++buc){
   843         size_type ss1=0;
   844         for(const_local_iterator it=begin(buc),it_end=end(buc);
   845             it!=it_end;++it,++ss1){
   846           if(find_bucket(*it)!=buc)return false;
   847         }
   848         if(ss1!=bucket_size(buc))return false;
   849         s1+=ss1;
   850       }
   851       if(s1!=size())return false;
   852     }
   853 
   854     if(first_bucket!=buckets.first_nonempty(0))return false;
   855 
   856     return super::invariant_();
   857   }
   858 
   859   /* This forwarding function eases things for the boost::mem_fn construct
   860    * in BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT. Actually,
   861    * final_check_invariant is already an inherited member function of index.
   862    */
   863   void check_invariant_()const{this->final_check_invariant_();}
   864 #endif
   865 
   866 private:
   867   node_type* header()const{return this->final_header();}
   868 
   869   std::size_t find_bucket(value_param_type v)const
   870   {
   871     return bucket(key(v));
   872   }
   873 
   874   bool link_point(
   875     value_param_type v,hashed_index_node_impl*& pos,hashed_unique_tag)
   876   {
   877     hashed_index_node_impl* x=pos->next();
   878     while(x!=pos){
   879       if(eq(key(v),key(node_type::from_impl(x)->value()))){
   880         pos=x;
   881         return false;
   882       }
   883       x=x->next();
   884     }
   885     return true;
   886   }
   887 
   888   bool link_point(
   889     value_param_type v,hashed_index_node_impl*& pos,hashed_non_unique_tag)
   890   {
   891     hashed_index_node_impl* prev=pos;
   892     hashed_index_node_impl* x=pos->next();
   893     while(x!=pos){
   894       if(eq(key(v),key(node_type::from_impl(x)->value()))){
   895         pos=prev;
   896         return true;
   897       }
   898       prev=x;
   899       x=x->next();
   900     }
   901     return true;
   902   }
   903   
   904   void link(node_type* x,hashed_index_node_impl* pos)
   905   {
   906     hashed_index_node_impl::link(x->impl(),pos);
   907   };
   908 
   909   void link(hashed_index_node_impl* x,hashed_index_node_impl* pos)
   910   {
   911     hashed_index_node_impl::link(x,pos);
   912   };
   913 
   914   void unlink(node_type* x)
   915   {
   916     hashed_index_node_impl::unlink(x->impl());
   917   };
   918 
   919   static hashed_index_node_impl* prev(node_type* x)
   920   {
   921     return hashed_index_node_impl::prev(x->impl());
   922   }
   923 
   924   static void unlink_next(hashed_index_node_impl* x)
   925   {
   926     hashed_index_node_impl::unlink_next(x);
   927   }
   928 
   929   void calculate_max_load()
   930   {
   931     float fml=static_cast<float>(mlf*bucket_count());
   932     max_load=(std::numeric_limits<size_type>::max)();
   933     if(max_load>fml)max_load=static_cast<size_type>(fml);
   934   }
   935 
   936   void reserve(size_type n)
   937   {
   938     if(n>max_load){
   939       size_type bc =(std::numeric_limits<size_type>::max)();
   940       float     fbc=static_cast<float>(1+n/mlf);
   941       if(bc>fbc)bc =static_cast<size_type>(fbc);
   942       unchecked_rehash(bc);
   943     }
   944   }
   945 
   946   void unchecked_rehash(size_type n)
   947   {
   948     bucket_array_type buckets1(get_allocator(),header()->impl(),n);
   949     auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
   950 
   951     std::size_t i=0;
   952     hashed_index_node_impl* x=buckets.begin();
   953     hashed_index_node_impl* x_end=buckets.end();
   954     for(;x!=x_end;++x){
   955       hashed_index_node_impl* y=x->next();
   956       while(y!=x){
   957         hashes.data()[i++]=hash(key(node_type::from_impl(y)->value()));
   958         y=y->next();
   959       }
   960     }
   961 
   962     i=0;
   963     x=buckets.begin();
   964     for(;x!=x_end;++x){
   965       hashed_index_node_impl* y=x->next();
   966       while(y!=x){
   967         hashed_index_node_impl* z=y->next();
   968         std::size_t             buc1=buckets1.position(hashes.data()[i++]);
   969         hashed_index_node_impl* x1=buckets1.at(buc1);
   970         link(y,x1);
   971         y=z;
   972       }
   973     }
   974 
   975     buckets.swap(buckets1);
   976     calculate_max_load();
   977     first_bucket=buckets.first_nonempty(0);
   978   }
   979 
   980 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   981   void detach_iterators(node_type* x)
   982   {
   983     iterator it=make_iterator(x);
   984     safe_mode::detach_equivalent_iterators(it);
   985   }
   986 #endif
   987 
   988   key_from_value               key;
   989   hasher                       hash;
   990   key_equal                    eq;
   991   bucket_array_type            buckets;
   992   float                        mlf;
   993   size_type                    max_load;
   994   std::size_t                  first_bucket;
   995       
   996 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
   997     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
   998 #pragma parse_mfunc_templ reset
   999 #endif
  1000 };
  1001 
  1002 /*  specialized algorithms */
  1003 
  1004 template<
  1005   typename KeyFromValue,typename Hash,typename Pred,
  1006   typename SuperMeta,typename TagList,typename Category
  1007 >
  1008 void swap(
  1009   hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  1010   hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
  1011 {
  1012   x.swap(y);
  1013 }
  1014 
  1015 } /* namespace multi_index::detail */
  1016 
  1017 /* sequenced index specifiers */
  1018 
  1019 template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
  1020 struct hashed_unique
  1021 {
  1022   typedef typename detail::hashed_index_args<
  1023     Arg1,Arg2,Arg3,Arg4>                           index_args;
  1024   typedef typename index_args::tag_list_type::type tag_list_type;
  1025   typedef typename index_args::key_from_value_type key_from_value_type;
  1026   typedef typename index_args::hash_type           hash_type;
  1027   typedef typename index_args::pred_type           pred_type;
  1028 
  1029   template<typename Super>
  1030   struct node_class
  1031   {
  1032     typedef detail::hashed_index_node<Super> type;
  1033   };
  1034 
  1035   template<typename SuperMeta>
  1036   struct index_class
  1037   {
  1038     typedef detail::hashed_index<
  1039       key_from_value_type,hash_type,pred_type,
  1040       SuperMeta,tag_list_type,detail::hashed_unique_tag> type;
  1041   };
  1042 };
  1043 
  1044 template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
  1045 struct hashed_non_unique
  1046 {
  1047   typedef typename detail::hashed_index_args<
  1048     Arg1,Arg2,Arg3,Arg4>                           index_args;
  1049   typedef typename index_args::tag_list_type::type tag_list_type;
  1050   typedef typename index_args::key_from_value_type key_from_value_type;
  1051   typedef typename index_args::hash_type           hash_type;
  1052   typedef typename index_args::pred_type           pred_type;
  1053 
  1054   template<typename Super>
  1055   struct node_class
  1056   {
  1057     typedef detail::hashed_index_node<Super> type;
  1058   };
  1059 
  1060   template<typename SuperMeta>
  1061   struct index_class
  1062   {
  1063     typedef detail::hashed_index<
  1064       key_from_value_type,hash_type,pred_type,
  1065       SuperMeta,tag_list_type,detail::hashed_non_unique_tag> type;
  1066   };
  1067 };
  1068 
  1069 } /* namespace multi_index */
  1070 
  1071 } /* namespace boost */
  1072 
  1073 #undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
  1074 
  1075 #endif