williamr@2: /* Copyright 2003-2007 Joaquín M López Muñoz. williamr@2: * Distributed under the Boost Software License, Version 1.0. williamr@2: * (See accompanying file LICENSE_1_0.txt or copy at williamr@2: * http://www.boost.org/LICENSE_1_0.txt) williamr@2: * williamr@2: * See http://www.boost.org/libs/multi_index for library home page. williamr@2: */ williamr@2: williamr@2: #ifndef BOOST_MULTI_INDEX_RANDOM_ACCESS_INDEX_HPP williamr@2: #define BOOST_MULTI_INDEX_RANDOM_ACCESS_INDEX_HPP williamr@2: williamr@2: #if defined(_MSC_VER)&&(_MSC_VER>=1200) williamr@2: #pragma once williamr@2: #endif williamr@2: williamr@2: #include /* keep it first to prevent nasty warns in MSVC */ williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) williamr@2: #include williamr@2: #include williamr@2: #endif williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) williamr@2: #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT \ williamr@2: detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \ williamr@2: detail::make_obj_guard(*this,&random_access_index::check_invariant_); \ williamr@2: BOOST_JOIN(check_invariant_,__LINE__).touch(); williamr@2: #else williamr@2: #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT williamr@2: #endif williamr@2: williamr@2: namespace boost{ williamr@2: williamr@2: namespace multi_index{ williamr@2: williamr@2: namespace detail{ williamr@2: williamr@2: /* random_access_index adds a layer of random access indexing williamr@2: * to a given Super williamr@2: */ williamr@2: williamr@2: template williamr@2: class random_access_index: williamr@2: BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC,<1300) williamr@2: ,public safe_ctr_proxy_impl< williamr@2: rnd_node_iterator< williamr@2: random_access_index_node >, williamr@2: random_access_index > williamr@2: #else williamr@2: ,public safe_mode::safe_container< williamr@2: random_access_index > williamr@2: #endif williamr@2: #endif williamr@2: williamr@2: { williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\ williamr@2: BOOST_WORKAROUND(__MWERKS__,<=0x3003) williamr@2: /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the williamr@2: * lifetime of const references bound to temporaries --precisely what williamr@2: * scopeguards are. williamr@2: */ williamr@2: williamr@2: #pragma parse_mfunc_templ off williamr@2: #endif williamr@2: williamr@2: typedef typename SuperMeta::type super; williamr@2: williamr@2: protected: williamr@2: typedef random_access_index_node< williamr@2: typename super::node_type> node_type; williamr@2: williamr@2: public: williamr@2: /* types */ williamr@2: williamr@2: typedef typename node_type::value_type value_type; williamr@2: typedef tuples::null_type ctor_args; williamr@2: typedef typename super::final_allocator_type allocator_type; williamr@2: typedef typename allocator_type::reference reference; williamr@2: typedef typename allocator_type::const_reference const_reference; williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC,<1300) williamr@2: typedef safe_mode::safe_iterator< williamr@2: rnd_node_iterator, williamr@2: safe_ctr_proxy< williamr@2: rnd_node_iterator > > iterator; williamr@2: #else williamr@2: typedef safe_mode::safe_iterator< williamr@2: rnd_node_iterator, williamr@2: random_access_index> iterator; williamr@2: #endif williamr@2: #else williamr@2: typedef rnd_node_iterator iterator; williamr@2: #endif williamr@2: williamr@2: typedef iterator const_iterator; williamr@2: williamr@2: typedef std::size_t size_type; williamr@2: typedef std::ptrdiff_t difference_type; williamr@2: typedef typename allocator_type::pointer pointer; williamr@2: typedef typename allocator_type::const_pointer const_pointer; williamr@2: typedef typename williamr@2: boost::reverse_iterator reverse_iterator; williamr@2: typedef typename williamr@2: boost::reverse_iterator const_reverse_iterator; williamr@2: typedef TagList tag_list; williamr@2: williamr@2: protected: williamr@2: typedef typename super::final_node_type final_node_type; williamr@2: typedef tuples::cons< williamr@2: ctor_args, williamr@2: typename super::ctor_args_list> ctor_args_list; williamr@2: typedef typename mpl::push_front< williamr@2: typename super::index_type_list, williamr@2: random_access_index>::type index_type_list; williamr@2: typedef typename mpl::push_front< williamr@2: typename super::iterator_type_list, williamr@2: iterator>::type iterator_type_list; williamr@2: typedef typename mpl::push_front< williamr@2: typename super::const_iterator_type_list, williamr@2: const_iterator>::type const_iterator_type_list; williamr@2: typedef typename super::copy_map_type copy_map_type; williamr@2: williamr@2: #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) williamr@2: typedef typename super::index_saver_type index_saver_type; williamr@2: typedef typename super::index_loader_type index_loader_type; williamr@2: #endif williamr@2: williamr@2: private: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC,<1300) williamr@2: typedef safe_ctr_proxy_impl< williamr@2: rnd_node_iterator, williamr@2: random_access_index> safe_super; williamr@2: #else williamr@2: typedef safe_mode::safe_container< williamr@2: random_access_index> safe_super; williamr@2: #endif williamr@2: #endif williamr@2: williamr@2: typedef typename call_traits< williamr@2: value_type>::param_type value_param_type; williamr@2: williamr@2: public: williamr@2: williamr@2: /* construct/copy/destroy williamr@2: * Default and copy ctors are in the protected section as indices are williamr@2: * not supposed to be created on their own. No range ctor either. williamr@2: */ williamr@2: williamr@2: random_access_index& operator=( williamr@2: const random_access_index& x) williamr@2: { williamr@2: this->final()=x.final(); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: template williamr@2: void assign(InputIterator first,InputIterator last) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: clear(); williamr@2: for(;first!=last;++first)push_back(*first); williamr@2: } williamr@2: williamr@2: void assign(size_type n,value_param_type value) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: clear(); williamr@2: for(size_type i=0;ifinal().get_allocator(); williamr@2: } williamr@2: williamr@2: /* iterators */ williamr@2: williamr@2: iterator begin() williamr@2: {return make_iterator(node_type::from_impl(*ptrs.begin()));} williamr@2: const_iterator begin()const williamr@2: {return make_iterator(node_type::from_impl(*ptrs.begin()));} williamr@2: iterator end(){return make_iterator(header());} williamr@2: const_iterator end()const{return make_iterator(header());} williamr@2: reverse_iterator rbegin(){return make_reverse_iterator(end());} williamr@2: const_reverse_iterator rbegin()const{return make_reverse_iterator(end());} williamr@2: reverse_iterator rend(){return make_reverse_iterator(begin());} williamr@2: const_reverse_iterator rend()const{return make_reverse_iterator(begin());} williamr@2: williamr@2: /* capacity */ williamr@2: williamr@2: bool empty()const{return this->final_empty_();} williamr@2: size_type size()const{return this->final_size_();} williamr@2: size_type max_size()const{return this->final_max_size_();} williamr@2: size_type capacity()const{return ptrs.capacity();} williamr@2: void reserve(size_type n){ptrs.reserve(n);} williamr@2: williamr@2: void resize(size_type n,value_param_type x=value_type()) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: if(n>size())insert(end(),n-size(),x); williamr@2: else if(nvalue(); williamr@2: } williamr@2: williamr@2: const_reference at(size_type n)const williamr@2: { williamr@2: if(n>=size())throw_exception(std::out_of_range("random access index")); williamr@2: return node_type::from_impl(*ptrs.at(n))->value(); williamr@2: } williamr@2: williamr@2: const_reference front()const{return operator[](0);} williamr@2: const_reference back()const{return operator[](size()-1);} williamr@2: williamr@2: /* modifiers */ williamr@2: williamr@2: std::pair push_front(value_param_type x) williamr@2: {return insert(begin(),x);} williamr@2: void pop_front(){erase(begin());} williamr@2: std::pair push_back(value_param_type x) williamr@2: {return insert(end(),x);} williamr@2: void pop_back(){erase(--end());} williamr@2: williamr@2: std::pair insert(iterator position,value_param_type x) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: std::pair p=this->final_insert_(x); williamr@2: if(p.second&&position.get_node()!=header()){ williamr@2: relocate(position.get_node(),p.first); williamr@2: } williamr@2: return std::pair(make_iterator(p.first),p.second); williamr@2: } williamr@2: williamr@2: void insert(iterator position,size_type n,value_param_type x) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: size_type s=0; williamr@2: BOOST_TRY{ williamr@2: while(n--){ williamr@2: if(push_back(x).second)++s; williamr@2: } williamr@2: } williamr@2: BOOST_CATCH(...){ williamr@2: relocate(position,end()-s,end()); williamr@2: BOOST_RETHROW; williamr@2: } williamr@2: BOOST_CATCH_END williamr@2: relocate(position,end()-s,end()); williamr@2: } williamr@2: williamr@2: template williamr@2: void insert(iterator position,InputIterator first,InputIterator last) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: size_type s=0; williamr@2: BOOST_TRY{ williamr@2: for(;first!=last;++first){ williamr@2: if(push_back(*first).second)++s; williamr@2: } williamr@2: } williamr@2: BOOST_CATCH(...){ williamr@2: relocate(position,end()-s,end()); williamr@2: BOOST_RETHROW; williamr@2: } williamr@2: BOOST_CATCH_END williamr@2: relocate(position,end()-s,end()); williamr@2: } williamr@2: williamr@2: iterator erase(iterator position) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: this->final_erase_(static_cast(position++.get_node())); williamr@2: return position; williamr@2: } williamr@2: williamr@2: iterator erase(iterator first,iterator last) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: difference_type n=last-first; williamr@2: relocate(end(),first,last); williamr@2: while(n--)pop_back(); williamr@2: return last; williamr@2: } williamr@2: williamr@2: bool replace(iterator position,value_param_type x) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: return this->final_replace_( williamr@2: x,static_cast(position.get_node())); williamr@2: } williamr@2: williamr@2: template williamr@2: bool modify(iterator position,Modifier mod) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: /* MSVC++ 6.0 optimizer on safe mode code chokes if this williamr@2: * this is not added. Left it for all compilers as it does no williamr@2: * harm. williamr@2: */ williamr@2: williamr@2: position.detach(); williamr@2: #endif williamr@2: williamr@2: return this->final_modify_( williamr@2: mod,static_cast(position.get_node())); williamr@2: } williamr@2: williamr@2: void swap(random_access_index& x) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: this->final_swap_(x.final()); williamr@2: } williamr@2: williamr@2: void clear() williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: this->final_clear_(); williamr@2: } williamr@2: williamr@2: /* list operations */ williamr@2: williamr@2: void splice(iterator position,random_access_index& x) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(*this,x); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: iterator first=x.begin(),last=x.end(); williamr@2: size_type n=0; williamr@2: BOOST_TRY{ williamr@2: while(first!=last){ williamr@2: if(push_back(*first).second){ williamr@2: first=x.erase(first); williamr@2: ++n; williamr@2: } williamr@2: else ++first; williamr@2: } williamr@2: } williamr@2: BOOST_CATCH(...){ williamr@2: relocate(position,end()-n,end()); williamr@2: BOOST_RETHROW; williamr@2: } williamr@2: BOOST_CATCH_END williamr@2: relocate(position,end()-n,end()); williamr@2: } williamr@2: williamr@2: void splice( williamr@2: iterator position,random_access_index& x,iterator i) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i); williamr@2: BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: if(&x==this)relocate(position,i); williamr@2: else{ williamr@2: if(insert(position,*i).second){ williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: /* MSVC++ 6.0 optimizer has a hard time with safe mode, and the following williamr@2: * workaround is needed. Left it for all compilers as it does no williamr@2: * harm. williamr@2: */ williamr@2: i.detach(); williamr@2: x.erase(x.make_iterator(i.get_node())); williamr@2: #else williamr@2: x.erase(i); williamr@2: #endif williamr@2: williamr@2: } williamr@2: } williamr@2: } williamr@2: williamr@2: void splice( williamr@2: iterator position,random_access_index& x, williamr@2: iterator first,iterator last) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: if(&x==this)relocate(position,first,last); williamr@2: else{ williamr@2: size_type n=0; williamr@2: BOOST_TRY{ williamr@2: while(first!=last){ williamr@2: if(push_back(*first).second){ williamr@2: first=x.erase(first); williamr@2: ++n; williamr@2: } williamr@2: else ++first; williamr@2: } williamr@2: } williamr@2: BOOST_CATCH(...){ williamr@2: relocate(position,end()-n,end()); williamr@2: BOOST_RETHROW; williamr@2: } williamr@2: BOOST_CATCH_END williamr@2: relocate(position,end()-n,end()); williamr@2: } williamr@2: } williamr@2: williamr@2: void remove(value_param_type value) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: difference_type n= williamr@2: end()-make_iterator( williamr@2: random_access_index_remove( williamr@2: ptrs,std::bind2nd(std::equal_to(),value))); williamr@2: while(n--)pop_back(); williamr@2: } williamr@2: williamr@2: template williamr@2: void remove_if(Predicate pred) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: difference_type n= williamr@2: end()-make_iterator(random_access_index_remove(ptrs,pred)); williamr@2: while(n--)pop_back(); williamr@2: } williamr@2: williamr@2: void unique() williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: difference_type n= williamr@2: end()-make_iterator( williamr@2: random_access_index_unique( williamr@2: ptrs,std::equal_to())); williamr@2: while(n--)pop_back(); williamr@2: } williamr@2: williamr@2: template williamr@2: void unique(BinaryPredicate binary_pred) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: difference_type n= williamr@2: end()-make_iterator( williamr@2: random_access_index_unique(ptrs,binary_pred)); williamr@2: while(n--)pop_back(); williamr@2: } williamr@2: williamr@2: void merge(random_access_index& x) williamr@2: { williamr@2: if(this!=&x){ williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: size_type s=size(); williamr@2: splice(end(),x); williamr@2: random_access_index_inplace_merge( williamr@2: get_allocator(),ptrs,ptrs.at(s),std::less()); williamr@2: } williamr@2: } williamr@2: williamr@2: template williamr@2: void merge(random_access_index& x,Compare comp) williamr@2: { williamr@2: if(this!=&x){ williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: size_type s=size(); williamr@2: splice(end(),x); williamr@2: random_access_index_inplace_merge( williamr@2: get_allocator(),ptrs,ptrs.at(s),comp); williamr@2: } williamr@2: } williamr@2: williamr@2: void sort() williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: random_access_index_sort( williamr@2: get_allocator(),ptrs,std::less()); williamr@2: } williamr@2: williamr@2: template williamr@2: void sort(Compare comp) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: random_access_index_sort( williamr@2: get_allocator(),ptrs,comp); williamr@2: } williamr@2: williamr@2: void reverse() williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: random_access_index_node_impl::reverse(ptrs.begin(),ptrs.end()); williamr@2: } williamr@2: williamr@2: /* rearrange operations */ williamr@2: williamr@2: void relocate(iterator position,iterator i) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i); williamr@2: BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,*this); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: if(position!=i)relocate(position.get_node(),i.get_node()); williamr@2: } williamr@2: williamr@2: void relocate(iterator position,iterator first,iterator last) williamr@2: { williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this); williamr@2: BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this); williamr@2: BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last); williamr@2: BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last); williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: if(position!=last)relocate( williamr@2: position.get_node(),first.get_node(),last.get_node()); williamr@2: } williamr@2: williamr@2: template williamr@2: void rearrange(InputIterator first) williamr@2: { williamr@2: BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; williamr@2: for(random_access_index_node_impl** p0=ptrs.begin(),** p0_end=ptrs.end(); williamr@2: p0!=p0_end;++first,++p0){ williamr@2: const value_type& v1=*first; williamr@2: random_access_index_node_impl** p1=node_from_value(&v1)->up(); williamr@2: williamr@2: std::swap(*p0,*p1); williamr@2: (*p0)->up()=p0; williamr@2: (*p1)->up()=p1; williamr@2: } williamr@2: } williamr@2: williamr@2: BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS: williamr@2: random_access_index( williamr@2: const ctor_args_list& args_list,const allocator_type& al): williamr@2: super(args_list.get_tail(),al), williamr@2: ptrs(al,header()->impl(),0) williamr@2: { williamr@2: } williamr@2: williamr@2: random_access_index(const random_access_index& x): williamr@2: super(x), williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: safe_super(), williamr@2: #endif williamr@2: williamr@2: ptrs(x.get_allocator(),header()->impl(),x.size()) williamr@2: { williamr@2: /* The actual copying takes place in subsequent call to copy_(). williamr@2: */ williamr@2: } williamr@2: williamr@2: ~random_access_index() williamr@2: { williamr@2: /* the container is guaranteed to be empty by now */ williamr@2: } williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: iterator make_iterator(node_type* node){return iterator(node,this);} williamr@2: const_iterator make_iterator(node_type* node)const williamr@2: {return const_iterator(node,const_cast(this));} williamr@2: #else williamr@2: iterator make_iterator(node_type* node){return iterator(node);} williamr@2: const_iterator make_iterator(node_type* node)const williamr@2: {return const_iterator(node);} williamr@2: #endif williamr@2: williamr@2: void copy_( williamr@2: const random_access_index& x,const copy_map_type& map) williamr@2: { williamr@2: for(random_access_index_node_impl** begin_org=x.ptrs.begin(), williamr@2: ** begin_cpy=ptrs.begin(), williamr@2: ** end_org=x.ptrs.end(); williamr@2: begin_org!=end_org;++begin_org,++begin_cpy){ williamr@2: *begin_cpy= williamr@2: static_cast( williamr@2: map.find( williamr@2: static_cast( williamr@2: node_type::from_impl(*begin_org))))->impl(); williamr@2: (*begin_cpy)->up()=begin_cpy; williamr@2: } williamr@2: williamr@2: super::copy_(x,map); williamr@2: } williamr@2: williamr@2: node_type* insert_(value_param_type v,node_type* x) williamr@2: { williamr@2: ptrs.room_for_one(); williamr@2: node_type* res=static_cast(super::insert_(v,x)); williamr@2: if(res==x)ptrs.push_back(x->impl()); williamr@2: return res; williamr@2: } williamr@2: williamr@2: node_type* insert_(value_param_type v,node_type* position,node_type* x) williamr@2: { williamr@2: ptrs.room_for_one(); williamr@2: node_type* res=static_cast(super::insert_(v,position,x)); williamr@2: if(res==x)ptrs.push_back(x->impl()); williamr@2: return res; williamr@2: } williamr@2: williamr@2: void erase_(node_type* x) williamr@2: { williamr@2: ptrs.erase(x->impl()); williamr@2: super::erase_(x); williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: detach_iterators(x); williamr@2: #endif williamr@2: } williamr@2: williamr@2: void delete_all_nodes_() williamr@2: { williamr@2: for(random_access_index_node_impl** x=ptrs.begin(),**x_end=ptrs.end(); williamr@2: x!=x_end;++x){ williamr@2: this->final_delete_node_( williamr@2: static_cast(node_type::from_impl(*x))); williamr@2: } williamr@2: } williamr@2: williamr@2: void clear_() williamr@2: { williamr@2: super::clear_(); williamr@2: ptrs.clear(); williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: safe_super::detach_dereferenceable_iterators(); williamr@2: #endif williamr@2: } williamr@2: williamr@2: void swap_(random_access_index& x) williamr@2: { williamr@2: ptrs.swap(x.ptrs); williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: safe_super::swap(x); williamr@2: #endif williamr@2: williamr@2: super::swap_(x); williamr@2: } williamr@2: williamr@2: bool replace_(value_param_type v,node_type* x) williamr@2: { williamr@2: return super::replace_(v,x); williamr@2: } williamr@2: williamr@2: bool modify_(node_type* x) williamr@2: { williamr@2: BOOST_TRY{ williamr@2: if(!super::modify_(x)){ williamr@2: ptrs.erase(x->impl()); williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: detach_iterators(x); williamr@2: #endif williamr@2: williamr@2: return false; williamr@2: } williamr@2: else return true; williamr@2: } williamr@2: BOOST_CATCH(...){ williamr@2: ptrs.erase(x->impl()); williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: detach_iterators(x); williamr@2: #endif williamr@2: williamr@2: BOOST_RETHROW; williamr@2: } williamr@2: BOOST_CATCH_END williamr@2: } williamr@2: williamr@2: #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) williamr@2: /* serialization */ williamr@2: williamr@2: template williamr@2: void save_( williamr@2: Archive& ar,const unsigned int version,const index_saver_type& sm)const williamr@2: { williamr@2: sm.save(begin(),end(),ar,version); williamr@2: super::save_(ar,version,sm); williamr@2: } williamr@2: williamr@2: template williamr@2: void load_( williamr@2: Archive& ar,const unsigned int version,const index_loader_type& lm) williamr@2: { williamr@2: { williamr@2: typedef random_access_index_loader loader; williamr@2: williamr@2: loader ld(get_allocator(),ptrs); williamr@2: lm.load(::boost::bind(&loader::rearrange,&ld,_1,_2),ar,version); williamr@2: } /* exit scope so that ld frees its resources */ williamr@2: super::load_(ar,version,lm); williamr@2: } williamr@2: #endif williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) williamr@2: /* invariant stuff */ williamr@2: williamr@2: bool invariant_()const williamr@2: { williamr@2: if(size()>capacity())return false; williamr@2: if(size()==0||begin()==end()){ williamr@2: if(size()!=0||begin()!=end())return false; williamr@2: } williamr@2: else{ williamr@2: size_type s=0; williamr@2: for(const_iterator it=begin(),it_end=end();;++it,++s){ williamr@2: if(*(it.get_node()->up())!=it.get_node()->impl())return false; williamr@2: if(it==it_end)break; williamr@2: } williamr@2: if(s!=size())return false; williamr@2: } williamr@2: williamr@2: return super::invariant_(); williamr@2: } williamr@2: williamr@2: /* This forwarding function eases things for the boost::mem_fn construct williamr@2: * in BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT. Actually, williamr@2: * final_check_invariant is already an inherited member function of index. williamr@2: */ williamr@2: void check_invariant_()const{this->final_check_invariant_();} williamr@2: #endif williamr@2: williamr@2: private: williamr@2: node_type* header()const{return this->final_header();} williamr@2: williamr@2: static void relocate(node_type* position,node_type* x) williamr@2: { williamr@2: random_access_index_node_impl::relocate(position->up(),x->up()); williamr@2: } williamr@2: williamr@2: static void relocate(node_type* position,node_type* first,node_type* last) williamr@2: { williamr@2: random_access_index_node_impl::relocate( williamr@2: position->up(),first->up(),last->up()); williamr@2: } williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE) williamr@2: void detach_iterators(node_type* x) williamr@2: { williamr@2: iterator it=make_iterator(x); williamr@2: safe_mode::detach_equivalent_iterators(it); williamr@2: } williamr@2: #endif williamr@2: williamr@2: random_access_index_ptr_array ptrs; williamr@2: williamr@2: #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\ williamr@2: BOOST_WORKAROUND(__MWERKS__,<=0x3003) williamr@2: #pragma parse_mfunc_templ reset williamr@2: #endif williamr@2: }; williamr@2: williamr@2: /* comparison */ williamr@2: williamr@2: template< williamr@2: typename SuperMeta1,typename TagList1, williamr@2: typename SuperMeta2,typename TagList2 williamr@2: > williamr@2: bool operator==( williamr@2: const random_access_index& x, williamr@2: const random_access_index& y) williamr@2: { williamr@2: return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin()); williamr@2: } williamr@2: williamr@2: template< williamr@2: typename SuperMeta1,typename TagList1, williamr@2: typename SuperMeta2,typename TagList2 williamr@2: > williamr@2: bool operator<( williamr@2: const random_access_index& x, williamr@2: const random_access_index& y) williamr@2: { williamr@2: return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end()); williamr@2: } williamr@2: williamr@2: template< williamr@2: typename SuperMeta1,typename TagList1, williamr@2: typename SuperMeta2,typename TagList2 williamr@2: > williamr@2: bool operator!=( williamr@2: const random_access_index& x, williamr@2: const random_access_index& y) williamr@2: { williamr@2: return !(x==y); williamr@2: } williamr@2: williamr@2: template< williamr@2: typename SuperMeta1,typename TagList1, williamr@2: typename SuperMeta2,typename TagList2 williamr@2: > williamr@2: bool operator>( williamr@2: const random_access_index& x, williamr@2: const random_access_index& y) williamr@2: { williamr@2: return y williamr@2: bool operator>=( williamr@2: const random_access_index& x, williamr@2: const random_access_index& y) williamr@2: { williamr@2: return !(x williamr@2: bool operator<=( williamr@2: const random_access_index& x, williamr@2: const random_access_index& y) williamr@2: { williamr@2: return !(x>y); williamr@2: } williamr@2: williamr@2: /* specialized algorithms */ williamr@2: williamr@2: template williamr@2: void swap( williamr@2: random_access_index& x, williamr@2: random_access_index& y) williamr@2: { williamr@2: x.swap(y); williamr@2: } williamr@2: williamr@2: } /* namespace multi_index::detail */ williamr@2: williamr@2: /* random access index specifier */ williamr@2: williamr@2: template williamr@2: struct random_access williamr@2: { williamr@2: BOOST_STATIC_ASSERT(detail::is_tag::value); williamr@2: williamr@2: template williamr@2: struct node_class williamr@2: { williamr@2: typedef detail::random_access_index_node type; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct index_class williamr@2: { williamr@2: typedef detail::random_access_index< williamr@2: SuperMeta,typename TagList::type> type; williamr@2: }; williamr@2: }; williamr@2: williamr@2: } /* namespace multi_index */ williamr@2: williamr@2: } /* namespace boost */ williamr@2: williamr@2: #undef BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT williamr@2: williamr@2: #endif