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