diff options
Diffstat (limited to '3rdParty/Boost/src/boost/multi_index/hashed_index.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/multi_index/hashed_index.hpp | 1656 |
1 files changed, 1656 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/multi_index/hashed_index.hpp b/3rdParty/Boost/src/boost/multi_index/hashed_index.hpp new file mode 100644 index 0000000..ebf55c9 --- /dev/null +++ b/3rdParty/Boost/src/boost/multi_index/hashed_index.hpp @@ -0,0 +1,1656 @@ +/* Copyright 2003-2014 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/detail/allocator_utilities.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/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/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 +#endif + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* hashed_index adds a layer of hashed indexing to a given Super */ + +/* Most of the implementation of unique and non-unique indices is + * shared. We tell from one another on instantiation time by using + * 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 tuple<std::size_t, + key_from_value,hasher,key_equal> ctor_args; + typedef typename super::final_allocator_type allocator_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + +#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) + 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; +#endif + +private: +#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>(&x)); + } + + const_iterator iterator_to(const value_type& x)const + { + return make_iterator(node_from_value<node_type>(&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. + */ + + template<typename CompatibleKey> + iterator find(const CompatibleKey& k)const + { + return find(k,hash_,eq_); + } + + template< + typename CompatibleKey,typename CompatibleHash,typename CompatiblePred + > + iterator find( + const CompatibleKey& k, + const CompatibleHash& hash,const CompatiblePred& eq)const + { + std::size_t buc=buckets.position(hash(k)); + 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 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 + { + 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 CompatibleKey> + std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const + { + return equal_range(k,hash_,eq_); + } + + template< + typename CompatibleKey,typename CompatibleHash,typename CompatiblePred + > + std::pair<iterator,iterator> equal_range( + const CompatibleKey& k, + const CompatibleHash& hash,const CompatiblePred& eq)const + { + std::size_t buc=buckets.position(hash(k)); + 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()); + } + + /* bucket interface */ + + size_type bucket_count()const BOOST_NOEXCEPT{return 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 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>(&x)); + } + + const_local_iterator local_iterator_to(const value_type& x)const + { + return make_local_iterator(node_from_value<node_type>(&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=static_cast<float>(1+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<double>(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 + } + + void swap_( + hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x) + { + std::swap(key,x.key); + std::swap(hash_,x.hash_); + std::swap(eq_,x.eq_); + buckets.swap(x.buckets); + std::swap(mlf,x.mlf); + std::swap(max_load,x.max_load); + +#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) + safe_super::swap(x); +#endif + + super::swap_(x); + } + + 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 + } + + /* 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; + std::ptrdiff_t 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_();} +#endif + +private: + 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=static_cast<float>(mlf*bucket_count()); + max_load=(std::numeric_limits<size_type>::max)(); + if(max_load>fml)max_load=static_cast<size_type>(fml); + } + + void reserve_for_insert(size_type n) + { + if(n>max_load){ + size_type bc =(std::numeric_limits<size_type>::max)(); + float fbc=static_cast<float>(1+static_cast<double>(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); + } + + 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::tag) +{ + return 0; +} + +#undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT +#undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF + +#endif |