| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746 | /* Copyright 2003-2020 Joaquin M Lopez Munoz. * 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)#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/core/addressof.hpp>#include <boost/detail/no_exceptions_support.hpp>#include <boost/detail/workaround.hpp>#include <boost/foreach_fwd.hpp>#include <boost/limits.hpp>#include <boost/move/core.hpp>#include <boost/mpl/bool.hpp>#include <boost/mpl/if.hpp>#include <boost/mpl/push_front.hpp>#include <boost/multi_index/detail/access_specifier.hpp>#include <boost/multi_index/detail/adl_swap.hpp>#include <boost/multi_index/detail/allocator_traits.hpp>#include <boost/multi_index/detail/auto_space.hpp>#include <boost/multi_index/detail/bucket_array.hpp>#include <boost/multi_index/detail/do_not_copy_elements_tag.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/promotes_arg.hpp>#include <boost/multi_index/detail/safe_mode.hpp>#include <boost/multi_index/detail/scope_guard.hpp>#include <boost/multi_index/detail/vartempl_support.hpp>#include <boost/multi_index/hashed_index_fwd.hpp>#include <boost/tuple/tuple.hpp>#include <boost/type_traits/is_same.hpp>#include <cmath>#include <cstddef>#include <functional>#include <iterator>#include <utility>#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)#include <initializer_list>#endif#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_OF(x)                 \  detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \    detail::make_obj_guard(x,&hashed_index::check_invariant_);               \  BOOST_JOIN(check_invariant_,__LINE__).touch();#define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT                       \  BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(*this)#else#define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x)#define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT#endifnamespace 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 * Category tags defined in hash_index_node.hpp. */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)  ,public safe_mode::safe_container<    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >#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,Category>          node_type;private:  typedef typename node_type::node_alg           node_alg;  typedef typename node_type::impl_type          node_impl_type;  typedef typename node_impl_type::pointer       node_impl_pointer;  typedef typename node_impl_type::base_pointer  node_impl_base_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 typename super::final_allocator_type   allocator_type;private:  typedef allocator_traits<allocator_type>       alloc_traits;public:  typedef typename alloc_traits::pointer         pointer;  typedef typename alloc_traits::const_pointer   const_pointer;  typedef value_type&                            reference;  typedef const value_type&                      const_reference;  typedef typename alloc_traits::size_type       size_type;  typedef typename alloc_traits::difference_type difference_type;  typedef tuple<size_type,    key_from_value,hasher,key_equal>             ctor_args;#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)  typedef safe_mode::safe_iterator<    hashed_index_iterator<      node_type,bucket_array_type,      hashed_index_global_iterator_tag>,    hashed_index>                                iterator;#else  typedef hashed_index_iterator<    node_type,bucket_array_type,    hashed_index_global_iterator_tag>            iterator;#endif  typedef iterator                               const_iterator;  typedef hashed_index_iterator<    node_type,bucket_array_type,    hashed_index_local_iterator_tag>             local_iterator;  typedef local_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;#endifprivate:#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)  typedef safe_mode::safe_container<    hashed_index>                             safe_super;#endif  typedef typename call_traits<value_type>::param_type value_param_type;  typedef typename call_traits<    key_type>::param_type                              key_param_type;  /* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL   * expansion.   */  typedef std::pair<iterator,bool>                     emplace_return_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;  }#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(    std::initializer_list<value_type> list)  {    this->final()=list;    return *this;  }#endif  allocator_type get_allocator()const BOOST_NOEXCEPT  {    return this->final().get_allocator();  }  /* size and capacity */  bool      empty()const BOOST_NOEXCEPT{return this->final_empty_();}  size_type size()const BOOST_NOEXCEPT{return this->final_size_();}  size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}  /* iterators */  iterator begin()BOOST_NOEXCEPT    {return make_iterator(node_type::from_impl(header()->next()->prior()));}  const_iterator begin()const BOOST_NOEXCEPT    {return make_iterator(node_type::from_impl(header()->next()->prior()));}  iterator       end()BOOST_NOEXCEPT{return make_iterator(header());}  const_iterator end()const BOOST_NOEXCEPT{return make_iterator(header());}  const_iterator cbegin()const BOOST_NOEXCEPT{return begin();}  const_iterator cend()const BOOST_NOEXCEPT{return end();}  iterator iterator_to(const value_type& x)  {    return make_iterator(node_from_value<node_type>(boost::addressof(x)));  }  const_iterator iterator_to(const value_type& x)const  {    return make_iterator(node_from_value<node_type>(boost::addressof(x)));  }  /* modifiers */  BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(    emplace_return_type,emplace,emplace_impl)  BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(    iterator,emplace_hint,emplace_hint_impl,iterator,position)  std::pair<iterator,bool> insert(const value_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);  }  std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)  {    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;    std::pair<final_node_type*,bool> p=this->final_insert_rv_(x);    return std::pair<iterator,bool>(make_iterator(p.first),p.second);  }  iterator insert(iterator position,const value_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);  }      iterator insert(iterator position,BOOST_RV_REF(value_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_rv_(      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;    for(;first!=last;++first)this->final_insert_ref_(*first);  }#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)  void insert(std::initializer_list<value_type> list)  {    insert(list.begin(),list.end());  }#endif  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;    std::size_t buc=buckets.position(hash_(k));    for(node_impl_pointer x=buckets.at(buc)->prior();        x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){      if(eq_(k,key(node_type::from_impl(x)->value()))){        node_impl_pointer y=end_of_range(x);        size_type         s=0;        do{          node_impl_pointer z=node_alg::after(x);          this->final_erase_(            static_cast<final_node_type*>(node_type::from_impl(x)));          x=z;          ++s;        }while(x!=y);        return s;      }    }    return 0;  }  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,const value_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()));  }  bool replace(iterator position,BOOST_RV_REF(value_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_rv_(      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<Rollback,value_type,KeyFromValue>(back_,key));  }  void clear()BOOST_NOEXCEPT  {    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;    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x);    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.   */  /* Implementation note: When CompatibleKey is consistently promoted to   * KeyFromValue::result_type for equality comparison, the promotion is made   * once in advance to increase efficiency.   */  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  {    return find(      k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());  }  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  {    return count(      k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());  }  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  {    return equal_range(      k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());  }  /* bucket interface */  size_type bucket_count()const BOOST_NOEXCEPT  {    return static_cast<size_type>(buckets.size());  }  size_type max_bucket_count()const BOOST_NOEXCEPT{return static_cast<size_type>(-1);}  size_type bucket_size(size_type n)const  {    size_type res=0;    for(node_impl_pointer x=buckets.at(n)->prior();        x!=node_impl_pointer(0);x=node_alg::after_local(x)){      ++res;    }    return res;  }  size_type bucket(key_param_type k)const  {    return static_cast<size_type>(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)->prior();    if(x==node_impl_pointer(0))return end(n);    return make_local_iterator(node_type::from_impl(x));  }  local_iterator end(size_type n)  {    return const_cast<const hashed_index*>(this)->end(n);  }  const_local_iterator end(size_type)const  {    return make_local_iterator(0);  }  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_local_iterator(      node_from_value<node_type>(boost::addressof(x)));  }  const_local_iterator local_iterator_to(const value_type& x)const  {    return make_local_iterator(      node_from_value<node_type>(boost::addressof(x)));  }  /* hash policy */  float load_factor()const BOOST_NOEXCEPT    {return static_cast<float>(size())/bucket_count();}  float max_load_factor()const BOOST_NOEXCEPT{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=1.0f+static_cast<float>(size())/mlf;    if(bc>fbc){      bc=static_cast<size_type>(fbc);      if(bc<n)bc=n;    }    unchecked_rehash(bc);  }  void reserve(size_type n)  {    rehash(static_cast<size_type>(std::ceil(static_cast<float>(n)/mlf)));  }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.0f)  {    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)  {    /* Copy ctor just takes the internal configuration objects from x. The rest     * is done in subsequent call to copy_().     */  }  hashed_index(    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,    do_not_copy_elements_tag):    super(x,do_not_copy_elements_tag()),#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(),0),    mlf(1.0f)  {     calculate_max_load();  }  ~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,this);  }  const_iterator make_iterator(node_type* node)const  {    return const_iterator(node,const_cast<hashed_index*>(this));  }#else  iterator make_iterator(node_type* node)  {    return iterator(node);  }  const_iterator make_iterator(node_type* node)const  {    return const_iterator(node);  }#endif  local_iterator make_local_iterator(node_type* node)  {    return local_iterator(node);  }  const_local_iterator make_local_iterator(node_type* node)const  {    return const_local_iterator(node);  }  void copy_(    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,    const copy_map_type& map)  {    copy_(x,map,Category());  }  void copy_(    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,    const copy_map_type& map,hashed_unique_tag)  {    if(x.size()!=0){      node_impl_pointer end_org=x.header()->impl(),                        org=end_org,                        cpy=header()->impl();      do{        node_impl_pointer prev_org=org->prior(),                          prev_cpy=          static_cast<node_type*>(map.find(static_cast<final_node_type*>(            node_type::from_impl(prev_org))))->impl();        cpy->prior()=prev_cpy;        if(node_alg::is_first_of_bucket(org)){          node_impl_base_pointer buc_org=prev_org->next(),                                 buc_cpy=            buckets.begin()+(buc_org-x.buckets.begin());          prev_cpy->next()=buc_cpy;          buc_cpy->prior()=cpy;        }        else{          prev_cpy->next()=node_impl_type::base_pointer_from(cpy);        }        org=prev_org;        cpy=prev_cpy;      }while(org!=end_org);    }    super::copy_(x,map);  }    void copy_(    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,    const copy_map_type& map,hashed_non_unique_tag)  {    if(x.size()!=0){      node_impl_pointer end_org=x.header()->impl(),                        org=end_org,                        cpy=header()->impl();      do{        node_impl_pointer next_org=node_alg::after(org),                          next_cpy=          static_cast<node_type*>(map.find(static_cast<final_node_type*>(            node_type::from_impl(next_org))))->impl();        if(node_alg::is_first_of_bucket(next_org)){          node_impl_base_pointer buc_org=org->next(),                                 buc_cpy=            buckets.begin()+(buc_org-x.buckets.begin());          cpy->next()=buc_cpy;          buc_cpy->prior()=next_cpy;          next_cpy->prior()=cpy;        }        else{          if(org->next()==node_impl_type::base_pointer_from(next_org)){            cpy->next()=node_impl_type::base_pointer_from(next_cpy);          }          else{            cpy->next()=              node_impl_type::base_pointer_from(                static_cast<node_type*>(map.find(static_cast<final_node_type*>(                  node_type::from_impl(                    node_impl_type::pointer_from(org->next())))))->impl());          }          if(next_org->prior()!=org){            next_cpy->prior()=              static_cast<node_type*>(map.find(static_cast<final_node_type*>(                node_type::from_impl(next_org->prior()))))->impl();          }          else{            next_cpy->prior()=cpy;          }        }        org=next_org;        cpy=next_cpy;      }while(org!=end_org);    }    super::copy_(x,map);  }  template<typename Variant>  final_node_type* insert_(    value_param_type v,final_node_type*& x,Variant variant)  {    reserve_for_insert(size()+1);    std::size_t buc=find_bucket(v);    link_info   pos(buckets.at(buc));    if(!link_point(v,pos)){      return static_cast<final_node_type*>(        node_type::from_impl(node_impl_type::pointer_from(pos)));    }    final_node_type* res=super::insert_(v,x,variant);    if(res==x)link(static_cast<node_type*>(x),pos);    return res;  }  template<typename Variant>  final_node_type* insert_(    value_param_type v,node_type* position,final_node_type*& x,Variant variant)  {    reserve_for_insert(size()+1);    std::size_t buc=find_bucket(v);    link_info   pos(buckets.at(buc));    if(!link_point(v,pos)){      return static_cast<final_node_type*>(        node_type::from_impl(node_impl_type::pointer_from(pos)));    }    final_node_type* res=super::insert_(v,position,x,variant);    if(res==x)link(static_cast<node_type*>(x),pos);    return res;  }  void erase_(node_type* x)  {    unlink(x);    super::erase_(x);#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)    detach_iterators(x);#endif  }  void delete_all_nodes_()  {    delete_all_nodes_(Category());  }  void delete_all_nodes_(hashed_unique_tag)  {    for(node_impl_pointer x_end=header()->impl(),x=x_end->prior();x!=x_end;){      node_impl_pointer y=x->prior();      this->final_delete_node_(        static_cast<final_node_type*>(node_type::from_impl(x)));      x=y;    }  }  void delete_all_nodes_(hashed_non_unique_tag)  {    for(node_impl_pointer x_end=header()->impl(),x=x_end->prior();x!=x_end;){      node_impl_pointer y=x->prior();      if(y->next()!=node_impl_type::base_pointer_from(x)&&         y->next()->prior()!=x){ /* n-1 of group */        /* Make the second node prior() pointer back-linked so that it won't         * refer to a deleted node when the time for its own destruction comes.         */        node_impl_pointer first=node_impl_type::pointer_from(y->next());        first->next()->prior()=first;      }      this->final_delete_node_(        static_cast<final_node_type*>(node_type::from_impl(x)));      x=y;    }  }  void clear_()  {    super::clear_();    buckets.clear(header()->impl());#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)    safe_super::detach_dereferenceable_iterators();#endif  }  template<typename BoolConstant>  void swap_(    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,    BoolConstant swap_allocators)  {    adl_swap(key,x.key);    adl_swap(hash_,x.hash_);    adl_swap(eq_,x.eq_);    buckets.swap(x.buckets,swap_allocators);    std::swap(mlf,x.mlf);    std::swap(max_load,x.max_load);#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)    safe_super::swap(x);#endif    super::swap_(x,swap_allocators);  }  void swap_elements_(    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)  {    buckets.swap(x.buckets);    std::swap(mlf,x.mlf);    std::swap(max_load,x.max_load);#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)    safe_super::swap(x);#endif    super::swap_elements_(x);  }  template<typename Variant>  bool replace_(value_param_type v,node_type* x,Variant variant)  {    if(eq_(key(v),key(x->value()))){      return super::replace_(v,x,variant);    }          unlink_undo undo;    unlink(x,undo);    BOOST_TRY{      std::size_t  buc=find_bucket(v);      link_info    pos(buckets.at(buc));      if(link_point(v,pos)&&super::replace_(v,x,variant)){        link(x,pos);        return true;      }      undo();      return false;    }    BOOST_CATCH(...){      undo();      BOOST_RETHROW;    }    BOOST_CATCH_END  }  bool modify_(node_type* x)  {    std::size_t buc;    bool        b;     BOOST_TRY{      buc=find_bucket(x->value());      b=in_place(x->impl(),key(x->value()),buc);    }    BOOST_CATCH(...){      erase_(x);      BOOST_RETHROW;    }    BOOST_CATCH_END    if(!b){      unlink(x);      BOOST_TRY{        link_info pos(buckets.at(buc));        if(!link_point(x->value(),pos)){          super::erase_(x);#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)          detach_iterators(x);#endif          return false;        }        link(x,pos);      }      BOOST_CATCH(...){        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)){        unlink(x);#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)        detach_iterators(x);#endif        return false;      }      else return true;    }    BOOST_CATCH(...){      unlink(x);#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)      detach_iterators(x);#endif      BOOST_RETHROW;    }    BOOST_CATCH_END  }  bool modify_rollback_(node_type* x)  {    std::size_t buc=find_bucket(x->value());    if(in_place(x->impl(),key(x->value()),buc)){      return super::modify_rollback_(x);    }    unlink_undo undo;    unlink(x,undo);    BOOST_TRY{      link_info pos(buckets.at(buc));      if(link_point(x->value(),pos)&&super::modify_rollback_(x)){        link(x,pos);        return true;      }      undo();      return false;    }    BOOST_CATCH(...){      undo();      BOOST_RETHROW;    }    BOOST_CATCH_END  }  bool check_rollback_(node_type* x)const  {    std::size_t buc=find_bucket(x->value());    return in_place(x->impl(),key(x->value()),buc)&&super::check_rollback_(x);  }  /* comparison */#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)  /* defect macro refers to class, not function, templates, but anyway */  template<typename K,typename H,typename P,typename S,typename T,typename C>  friend bool operator==(    const hashed_index<K,H,P,S,T,C>&,const hashed_index<K,H,P,S,T,C>& y);#endif  bool equals(const hashed_index& x)const{return equals(x,Category());}  bool equals(const hashed_index& x,hashed_unique_tag)const  {    if(size()!=x.size())return false;    for(const_iterator it=begin(),it_end=end(),it2_end=x.end();        it!=it_end;++it){      const_iterator it2=x.find(key(*it));      if(it2==it2_end||!(*it==*it2))return false;    }    return true;  }  bool equals(const hashed_index& x,hashed_non_unique_tag)const  {    if(size()!=x.size())return false;    for(const_iterator it=begin(),it_end=end();it!=it_end;){      const_iterator it2,it2_last;      boost::tie(it2,it2_last)=x.equal_range(key(*it));      if(it2==it2_last)return false;      const_iterator it_last=make_iterator(        node_type::from_impl(end_of_range(it.get_node()->impl())));      if(std::distance(it,it_last)!=std::distance(it2,it2_last))return false;      /* From is_permutation code in       * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3068.pdf       */      for(;it!=it_last;++it,++it2){        if(!(*it==*it2))break;      }      if(it!=it_last){        for(const_iterator scan=it;scan!=it_last;++scan){          if(std::find(it,scan,*scan)!=scan)continue;          difference_type matches=std::count(it2,it2_last,*scan);          if(matches==0||matches!=std::count(scan,it_last,*scan))return false;        }        it=it_last;      }    }    return true;  }#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;    }    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_();}#endifprivate:  node_type* header()const{return this->final_header();}  std::size_t find_bucket(value_param_type v)const  {    return bucket(key(v));  }  struct link_info_non_unique  {    link_info_non_unique(node_impl_base_pointer pos):      first(pos),last(node_impl_base_pointer(0)){}    operator const node_impl_base_pointer&()const{return this->first;}    node_impl_base_pointer first,last;  };  typedef typename mpl::if_<    is_same<Category,hashed_unique_tag>,    node_impl_base_pointer,    link_info_non_unique  >::type                                link_info;  bool link_point(value_param_type v,link_info& pos)  {    return link_point(v,pos,Category());  }  bool link_point(    value_param_type v,node_impl_base_pointer& pos,hashed_unique_tag)  {    for(node_impl_pointer x=pos->prior();x!=node_impl_pointer(0);        x=node_alg::after_local(x)){      if(eq_(key(v),key(node_type::from_impl(x)->value()))){        pos=node_impl_type::base_pointer_from(x);        return false;      }    }    return true;  }  bool link_point(    value_param_type v,link_info_non_unique& pos,hashed_non_unique_tag)  {    for(node_impl_pointer x=pos.first->prior();x!=node_impl_pointer(0);        x=node_alg::next_to_inspect(x)){      if(eq_(key(v),key(node_type::from_impl(x)->value()))){        pos.first=node_impl_type::base_pointer_from(x);        pos.last=node_impl_type::base_pointer_from(last_of_range(x));        return true;      }    }    return true;  }  node_impl_pointer last_of_range(node_impl_pointer x)const  {    return last_of_range(x,Category());  }  node_impl_pointer last_of_range(node_impl_pointer x,hashed_unique_tag)const  {    return x;  }  node_impl_pointer last_of_range(    node_impl_pointer x,hashed_non_unique_tag)const  {    node_impl_base_pointer y=x->next();    node_impl_pointer      z=y->prior();    if(z==x){                      /* range of size 1 or 2 */      node_impl_pointer yy=node_impl_type::pointer_from(y);      return        eq_(          key(node_type::from_impl(x)->value()),          key(node_type::from_impl(yy)->value()))?yy:x;    }    else if(z->prior()==x)               /* last of bucket */      return x;    else                                /* group of size>2 */              return z;  }  node_impl_pointer end_of_range(node_impl_pointer x)const  {    return end_of_range(x,Category());  }  node_impl_pointer end_of_range(node_impl_pointer x,hashed_unique_tag)const  {    return node_alg::after(last_of_range(x));  }  node_impl_pointer end_of_range(    node_impl_pointer x,hashed_non_unique_tag)const  {    node_impl_base_pointer y=x->next();    node_impl_pointer      z=y->prior();    if(z==x){                      /* range of size 1 or 2 */      node_impl_pointer yy=node_impl_type::pointer_from(y);      if(!eq_(           key(node_type::from_impl(x)->value()),           key(node_type::from_impl(yy)->value())))yy=x;      return yy->next()->prior()==yy?               node_impl_type::pointer_from(yy->next()):               yy->next()->prior();    }    else if(z->prior()==x)               /* last of bucket */      return z;    else                                /* group of size>2 */              return z->next()->prior()==z?               node_impl_type::pointer_from(z->next()):               z->next()->prior();  }  void link(node_type* x,const link_info& pos)  {    link(x,pos,Category());  }  void link(node_type* x,node_impl_base_pointer pos,hashed_unique_tag)  {    node_alg::link(x->impl(),pos,header()->impl());  }  void link(node_type* x,const link_info_non_unique& pos,hashed_non_unique_tag)  {    if(pos.last==node_impl_base_pointer(0)){      node_alg::link(x->impl(),pos.first,header()->impl());    }    else{      node_alg::link(        x->impl(),        node_impl_type::pointer_from(pos.first),        node_impl_type::pointer_from(pos.last));    }  }  void unlink(node_type* x)  {    node_alg::unlink(x->impl());  }  typedef typename node_alg::unlink_undo unlink_undo;  void unlink(node_type* x,unlink_undo& undo)  {    node_alg::unlink(x->impl(),undo);  }  void calculate_max_load()  {    float fml=mlf*static_cast<float>(bucket_count());    max_load=(std::numeric_limits<size_type>::max)();    if(max_load>fml)max_load=static_cast<size_type>(fml);  }  void reserve_for_insert(size_type n)  {    if(n>max_load){      size_type bc =(std::numeric_limits<size_type>::max)();      float     fbc=1.0f+static_cast<float>(n)/mlf;      if(bc>fbc)bc =static_cast<size_type>(fbc);      unchecked_rehash(bc);    }  }  void unchecked_rehash(size_type n){unchecked_rehash(n,Category());}  void unchecked_rehash(size_type n,hashed_unique_tag)  {    node_impl_type    cpy_end_node;    node_impl_pointer cpy_end=node_impl_pointer(&cpy_end_node),                      end_=header()->impl();    bucket_array_type buckets_cpy(get_allocator(),cpy_end,n);    if(size()!=0){      auto_space<        std::size_t,allocator_type>       hashes(get_allocator(),size());      auto_space<        node_impl_pointer,allocator_type> node_ptrs(get_allocator(),size());      std::size_t                         i=0,size_=size();      bool                                within_bucket=false;      BOOST_TRY{        for(;i!=size_;++i){          node_impl_pointer x=end_->prior();          /* only this can possibly throw */          std::size_t h=hash_(key(node_type::from_impl(x)->value()));          hashes.data()[i]=h;          node_ptrs.data()[i]=x;          within_bucket=!node_alg::unlink_last(end_);          node_alg::link(x,buckets_cpy.at(buckets_cpy.position(h)),cpy_end);        }      }      BOOST_CATCH(...){        if(i!=0){          std::size_t prev_buc=buckets.position(hashes.data()[i-1]);          if(!within_bucket)prev_buc=~prev_buc;          for(std::size_t j=i;j--;){            std::size_t       buc=buckets.position(hashes.data()[j]);            node_impl_pointer x=node_ptrs.data()[j];            if(buc==prev_buc)node_alg::append(x,end_);            else node_alg::link(x,buckets.at(buc),end_);            prev_buc=buc;          }        }        BOOST_RETHROW;      }      BOOST_CATCH_END    }    end_->prior()=cpy_end->prior()!=cpy_end?cpy_end->prior():end_;    end_->next()=cpy_end->next();    end_->prior()->next()->prior()=end_->next()->prior()->prior()=end_;    buckets.swap(buckets_cpy);    calculate_max_load();  }  void unchecked_rehash(size_type n,hashed_non_unique_tag)  {    node_impl_type    cpy_end_node;    node_impl_pointer cpy_end=node_impl_pointer(&cpy_end_node),                      end_=header()->impl();    bucket_array_type buckets_cpy(get_allocator(),cpy_end,n);    if(size()!=0){      auto_space<        std::size_t,allocator_type>       hashes(get_allocator(),size());      auto_space<        node_impl_pointer,allocator_type> node_ptrs(get_allocator(),size());      std::size_t                         i=0;      bool                                within_bucket=false;      BOOST_TRY{        for(;;++i){          node_impl_pointer x=end_->prior();          if(x==end_)break;          /* only this can possibly throw */          std::size_t h=hash_(key(node_type::from_impl(x)->value()));          hashes.data()[i]=h;          node_ptrs.data()[i]=x;          std::pair<node_impl_pointer,bool> p=            node_alg::unlink_last_group(end_);          node_alg::link_range(            p.first,x,buckets_cpy.at(buckets_cpy.position(h)),cpy_end);          within_bucket=!(p.second);        }      }      BOOST_CATCH(...){        if(i!=0){          std::size_t prev_buc=buckets.position(hashes.data()[i-1]);          if(!within_bucket)prev_buc=~prev_buc;          for(std::size_t j=i;j--;){            std::size_t       buc=buckets.position(hashes.data()[j]);            node_impl_pointer x=node_ptrs.data()[j],                              y=              x->prior()->next()!=node_impl_type::base_pointer_from(x)&&              x->prior()->next()->prior()!=x?                node_impl_type::pointer_from(x->prior()->next()):x;            node_alg::unlink_range(y,x);            if(buc==prev_buc)node_alg::append_range(y,x,end_);            else node_alg::link_range(y,x,buckets.at(buc),end_);            prev_buc=buc;          }        }        BOOST_RETHROW;      }      BOOST_CATCH_END    }    end_->prior()=cpy_end->prior()!=cpy_end?cpy_end->prior():end_;    end_->next()=cpy_end->next();    end_->prior()->next()->prior()=end_->next()->prior()->prior()=end_;    buckets.swap(buckets_cpy);    calculate_max_load();  }  bool in_place(node_impl_pointer x,key_param_type k,std::size_t buc)const  {    return in_place(x,k,buc,Category());  }  bool in_place(    node_impl_pointer x,key_param_type k,std::size_t buc,    hashed_unique_tag)const  {    bool found=false;    for(node_impl_pointer y=buckets.at(buc)->prior();        y!=node_impl_pointer(0);y=node_alg::after_local(y)){      if(y==x)found=true;      else if(eq_(k,key(node_type::from_impl(y)->value())))return false;    }    return found;  }  bool in_place(    node_impl_pointer x,key_param_type k,std::size_t buc,    hashed_non_unique_tag)const  {    bool found=false;    int  range_size=0;    for(node_impl_pointer y=buckets.at(buc)->prior();y!=node_impl_pointer(0);){      if(node_alg::is_first_of_group(y)){ /* group of 3 or more */        if(y==x){          /* in place <-> equal to some other member of the group */          return eq_(            k,            key(node_type::from_impl(              node_impl_type::pointer_from(y->next()))->value()));        }        else{          node_impl_pointer z=            node_alg::after_local(y->next()->prior()); /* end of range */          if(eq_(k,key(node_type::from_impl(y)->value()))){            if(found)return false; /* x lies outside */            do{              if(y==x)return true;              y=node_alg::after_local(y);            }while(y!=z);            return false; /* x not found */          }          else{            if(range_size==1&&!found)return false;            if(range_size==2)return found;            range_size=0;            y=z; /* skip range (and potentially x, too, which is fine) */          }        }      }      else{ /* group of 1 or 2 */        if(y==x){          if(range_size==1)return true;          range_size=1;          found=true;        }        else if(eq_(k,key(node_type::from_impl(y)->value()))){          if(range_size==0&&found)return false;          if(range_size==1&&!found)return false;          if(range_size==2)return false;          ++range_size;        }        else{          if(range_size==1&&!found)return false;          if(range_size==2)return found;          range_size=0;        }        y=node_alg::after_local(y);      }    }    return found;  }#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  template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>  std::pair<iterator,bool> emplace_impl(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)  {    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;    std::pair<final_node_type*,bool>p=      this->final_emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);    return std::pair<iterator,bool>(make_iterator(p.first),p.second);  }  template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>  iterator emplace_hint_impl(    iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)  {    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_emplace_hint_(        static_cast<final_node_type*>(position.get_node()),        BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);    return make_iterator(p.first);  }  template<    typename CompatibleHash,typename CompatiblePred  >  iterator find(    const key_type& k,    const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const  {    return find(k,hash,eq,mpl::false_());  }  template<    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred  >  iterator find(    const CompatibleKey& k,    const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const  {    std::size_t buc=buckets.position(hash(k));    for(node_impl_pointer x=buckets.at(buc)->prior();        x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){      if(eq(k,key(node_type::from_impl(x)->value()))){        return make_iterator(node_type::from_impl(x));      }    }    return end();  }  template<    typename CompatibleHash,typename CompatiblePred  >  size_type count(    const key_type& k,    const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const  {    return count(k,hash,eq,mpl::false_());  }  template<    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred  >  size_type count(    const CompatibleKey& k,    const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const  {    std::size_t buc=buckets.position(hash(k));    for(node_impl_pointer x=buckets.at(buc)->prior();        x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){      if(eq(k,key(node_type::from_impl(x)->value()))){        size_type         res=0;        node_impl_pointer y=end_of_range(x);        do{          ++res;          x=node_alg::after(x);        }while(x!=y);        return res;      }    }    return 0;  }  template<    typename CompatibleHash,typename CompatiblePred  >  std::pair<iterator,iterator> equal_range(    const key_type& k,    const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const  {    return equal_range(k,hash,eq,mpl::false_());  }  template<    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred  >  std::pair<iterator,iterator> equal_range(    const CompatibleKey& k,    const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const  {    std::size_t buc=buckets.position(hash(k));    for(node_impl_pointer x=buckets.at(buc)->prior();        x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){      if(eq(k,key(node_type::from_impl(x)->value()))){        return std::pair<iterator,iterator>(          make_iterator(node_type::from_impl(x)),          make_iterator(node_type::from_impl(end_of_range(x))));      }    }    return std::pair<iterator,iterator>(end(),end());  }  key_from_value               key;  hasher                       hash_;  key_equal                    eq_;  bucket_array_type            buckets;  float                        mlf;  size_type                    max_load;      #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\    BOOST_WORKAROUND(__MWERKS__,<=0x3003)#pragma parse_mfunc_templ reset#endif};/* comparison */template<  typename KeyFromValue,typename Hash,typename Pred,  typename SuperMeta,typename TagList,typename Category>bool operator==(  const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,  const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y){  return x.equals(y);}template<  typename KeyFromValue,typename Hash,typename Pred,  typename SuperMeta,typename TagList,typename Category>bool operator!=(  const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,  const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y){  return !(x==y);}/*  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,detail::hashed_unique_tag> 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,detail::hashed_non_unique_tag> 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 *//* Boost.Foreach compatibility */template<  typename KeyFromValue,typename Hash,typename Pred,  typename SuperMeta,typename TagList,typename Category>inline boost::mpl::true_* boost_foreach_is_noncopyable(  boost::multi_index::detail::hashed_index<    KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>*&,  boost_foreach_argument_dependent_lookup_hack){  return 0;}#undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT#undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF#endif
 |