• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2003-2020 Joaquin M Lopez Munoz.
2  * Distributed under the Boost Software License, Version 1.0.
3  * (See accompanying file LICENSE_1_0.txt or copy at
4  * http://www.boost.org/LICENSE_1_0.txt)
5  *
6  * See http://www.boost.org/libs/multi_index for library home page.
7  */
8 
9 #ifndef BOOST_MULTI_INDEX_RANDOM_ACCESS_INDEX_HPP
10 #define BOOST_MULTI_INDEX_RANDOM_ACCESS_INDEX_HPP
11 
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15 
16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
17 #include <algorithm>
18 #include <boost/bind/bind.hpp>
19 #include <boost/call_traits.hpp>
20 #include <boost/core/addressof.hpp>
21 #include <boost/core/no_exceptions_support.hpp>
22 #include <boost/detail/workaround.hpp>
23 #include <boost/foreach_fwd.hpp>
24 #include <boost/iterator/reverse_iterator.hpp>
25 #include <boost/move/core.hpp>
26 #include <boost/move/utility_core.hpp>
27 #include <boost/mpl/bool.hpp>
28 #include <boost/mpl/not.hpp>
29 #include <boost/mpl/push_front.hpp>
30 #include <boost/multi_index/detail/access_specifier.hpp>
31 #include <boost/multi_index/detail/allocator_traits.hpp>
32 #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp>
33 #include <boost/multi_index/detail/index_node_base.hpp>
34 #include <boost/multi_index/detail/node_handle.hpp>
35 #include <boost/multi_index/detail/rnd_node_iterator.hpp>
36 #include <boost/multi_index/detail/rnd_index_node.hpp>
37 #include <boost/multi_index/detail/rnd_index_ops.hpp>
38 #include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
39 #include <boost/multi_index/detail/safe_mode.hpp>
40 #include <boost/multi_index/detail/scope_guard.hpp>
41 #include <boost/multi_index/detail/vartempl_support.hpp>
42 #include <boost/multi_index/random_access_index_fwd.hpp>
43 #include <boost/throw_exception.hpp>
44 #include <boost/tuple/tuple.hpp>
45 #include <boost/type_traits/is_integral.hpp>
46 #include <functional>
47 #include <stdexcept>
48 #include <utility>
49 
50 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
51 #include<initializer_list>
52 #endif
53 
54 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
55 #include <boost/multi_index/detail/rnd_index_loader.hpp>
56 #endif
57 
58 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
59 #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF(x)                    \
60   detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
61     detail::make_obj_guard(x,&random_access_index::check_invariant_);        \
62   BOOST_JOIN(check_invariant_,__LINE__).touch();
63 #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT                          \
64   BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF(*this)
65 #else
66 #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF(x)
67 #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT
68 #endif
69 
70 namespace boost{
71 
72 namespace multi_index{
73 
74 namespace detail{
75 
76 /* random_access_index adds a layer of random access indexing
77  * to a given Super
78  */
79 
80 template<typename SuperMeta,typename TagList>
81 class random_access_index:
82   BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
83 
84 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
85   ,public safe_mode::safe_container<
86     random_access_index<SuperMeta,TagList> >
87 #endif
88 
89 {
90 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
91     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
92 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
93  * lifetime of const references bound to temporaries --precisely what
94  * scopeguards are.
95  */
96 
97 #pragma parse_mfunc_templ off
98 #endif
99 
100   typedef typename SuperMeta::type               super;
101 
102 protected:
103   typedef random_access_index_node<
104     typename super::index_node_type>             index_node_type;
105 
106 private:
107   typedef typename index_node_type::impl_type    node_impl_type;
108   typedef random_access_index_ptr_array<
109     typename super::final_allocator_type>        ptr_array;
110   typedef typename ptr_array::pointer            node_impl_ptr_pointer;
111 
112 public:
113   /* types */
114 
115   typedef typename index_node_type::value_type   value_type;
116   typedef tuples::null_type                      ctor_args;
117   typedef typename super::final_allocator_type   allocator_type;
118   typedef value_type&                            reference;
119   typedef const value_type&                      const_reference;
120 
121 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
122   typedef safe_mode::safe_iterator<
123     rnd_node_iterator<index_node_type>,
124     random_access_index>                         iterator;
125 #else
126   typedef rnd_node_iterator<index_node_type>    iterator;
127 #endif
128 
129   typedef iterator                               const_iterator;
130 
131 private:
132   typedef allocator_traits<allocator_type>       alloc_traits;
133 
134 public:
135   typedef typename alloc_traits::pointer         pointer;
136   typedef typename alloc_traits::const_pointer   const_pointer;
137   typedef typename alloc_traits::size_type       size_type;
138   typedef typename alloc_traits::difference_type difference_type;
139   typedef typename
140     boost::reverse_iterator<iterator>            reverse_iterator;
141   typedef typename
142     boost::reverse_iterator<const_iterator>      const_reverse_iterator;
143   typedef typename super::final_node_handle_type node_type;
144   typedef detail::insert_return_type<
145     iterator,node_type>                          insert_return_type;
146   typedef TagList                                tag_list;
147 
148 protected:
149   typedef typename super::final_node_type     final_node_type;
150   typedef tuples::cons<
151     ctor_args,
152     typename super::ctor_args_list>           ctor_args_list;
153   typedef typename mpl::push_front<
154     typename super::index_type_list,
155     random_access_index>::type                index_type_list;
156   typedef typename mpl::push_front<
157     typename super::iterator_type_list,
158     iterator>::type                           iterator_type_list;
159   typedef typename mpl::push_front<
160     typename super::const_iterator_type_list,
161     const_iterator>::type                     const_iterator_type_list;
162   typedef typename super::copy_map_type       copy_map_type;
163 
164 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
165   typedef typename super::index_saver_type    index_saver_type;
166   typedef typename super::index_loader_type   index_loader_type;
167 #endif
168 
169 private:
170 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
171   typedef safe_mode::safe_container<
172     random_access_index>                      safe_super;
173 #endif
174 
175   typedef typename call_traits<
176     value_type>::param_type                   value_param_type;
177 
178   /* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL
179    * expansion.
180    */
181 
182   typedef std::pair<iterator,bool>            emplace_return_type;
183 
184 public:
185 
186   /* construct/copy/destroy
187    * Default and copy ctors are in the protected section as indices are
188    * not supposed to be created on their own. No range ctor either.
189    */
190 
operator =(const random_access_index<SuperMeta,TagList> & x)191   random_access_index<SuperMeta,TagList>& operator=(
192     const random_access_index<SuperMeta,TagList>& x)
193   {
194     this->final()=x.final();
195     return *this;
196   }
197 
198 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
operator =(std::initializer_list<value_type> list)199   random_access_index<SuperMeta,TagList>& operator=(
200     std::initializer_list<value_type> list)
201   {
202     this->final()=list;
203     return *this;
204   }
205 #endif
206 
207   template <class InputIterator>
assign(InputIterator first,InputIterator last)208   void assign(InputIterator first,InputIterator last)
209   {
210     assign_iter(first,last,mpl::not_<is_integral<InputIterator> >());
211   }
212 
213 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
assign(std::initializer_list<value_type> list)214   void assign(std::initializer_list<value_type> list)
215   {
216     assign(list.begin(),list.end());
217   }
218 #endif
219 
assign(size_type n,value_param_type value)220   void assign(size_type n,value_param_type value)
221   {
222     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
223     clear();
224     for(size_type i=0;i<n;++i)push_back(value);
225   }
226 
get_allocator() const227   allocator_type get_allocator()const BOOST_NOEXCEPT
228   {
229     return this->final().get_allocator();
230   }
231 
232   /* iterators */
233 
begin()234   iterator begin()BOOST_NOEXCEPT
235     {return make_iterator(index_node_type::from_impl(*ptrs.begin()));}
begin() const236   const_iterator begin()const BOOST_NOEXCEPT
237     {return make_iterator(index_node_type::from_impl(*ptrs.begin()));}
238   iterator
end()239     end()BOOST_NOEXCEPT{return make_iterator(header());}
240   const_iterator
end() const241     end()const BOOST_NOEXCEPT{return make_iterator(header());}
242   reverse_iterator
rbegin()243     rbegin()BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
244   const_reverse_iterator
rbegin() const245     rbegin()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
246   reverse_iterator
rend()247     rend()BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
248   const_reverse_iterator
rend() const249     rend()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
250   const_iterator
cbegin() const251     cbegin()const BOOST_NOEXCEPT{return begin();}
252   const_iterator
cend() const253     cend()const BOOST_NOEXCEPT{return end();}
254   const_reverse_iterator
crbegin() const255     crbegin()const BOOST_NOEXCEPT{return rbegin();}
256   const_reverse_iterator
crend() const257     crend()const BOOST_NOEXCEPT{return rend();}
258 
iterator_to(const value_type & x)259   iterator iterator_to(const value_type& x)
260   {
261     return make_iterator(
262       node_from_value<index_node_type>(boost::addressof(x)));
263   }
264 
iterator_to(const value_type & x) const265   const_iterator iterator_to(const value_type& x)const
266   {
267     return make_iterator(
268       node_from_value<index_node_type>(boost::addressof(x)));
269   }
270 
271   /* capacity */
272 
empty() const273   bool      empty()const BOOST_NOEXCEPT{return this->final_empty_();}
size() const274   size_type size()const BOOST_NOEXCEPT{return this->final_size_();}
max_size() const275   size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}
capacity() const276   size_type capacity()const BOOST_NOEXCEPT{return ptrs.capacity();}
277 
reserve(size_type n)278   void reserve(size_type n)
279   {
280     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
281     ptrs.reserve(n);
282   }
283 
shrink_to_fit()284   void shrink_to_fit()
285   {
286     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
287     ptrs.shrink_to_fit();
288   }
289 
resize(size_type n)290   void resize(size_type n)
291   {
292     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
293     if(n>size())
294       for(size_type m=n-size();m--;)
295         this->final_emplace_(BOOST_MULTI_INDEX_NULL_PARAM_PACK);
296     else if(n<size())erase(begin()+n,end());
297   }
298 
resize(size_type n,value_param_type x)299   void resize(size_type n,value_param_type x)
300   {
301     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
302     if(n>size())for(size_type m=n-size();m--;)this->final_insert_(x);
303     else if(n<size())erase(begin()+n,end());
304   }
305 
306   /* access: no non-const versions provided as random_access_index
307    * handles const elements.
308    */
309 
operator [](size_type n) const310   const_reference operator[](size_type n)const
311   {
312     BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(n<size(),safe_mode::out_of_bounds);
313     return index_node_type::from_impl(*ptrs.at(n))->value();
314   }
315 
at(size_type n) const316   const_reference at(size_type n)const
317   {
318     if(n>=size())throw_exception(std::out_of_range("random access index"));
319     return index_node_type::from_impl(*ptrs.at(n))->value();
320   }
321 
front() const322   const_reference front()const{return operator[](0);}
back() const323   const_reference back()const{return operator[](size()-1);}
324 
325   /* modifiers */
326 
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(emplace_return_type,emplace_front,emplace_front_impl)327   BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
328     emplace_return_type,emplace_front,emplace_front_impl)
329 
330   std::pair<iterator,bool> push_front(const value_type& x)
331                              {return insert(begin(),x);}
push_front(BOOST_RV_REF (value_type)x)332   std::pair<iterator,bool> push_front(BOOST_RV_REF(value_type) x)
333                              {return insert(begin(),boost::move(x));}
pop_front()334   void                     pop_front(){erase(begin());}
335 
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(emplace_return_type,emplace_back,emplace_back_impl)336   BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
337     emplace_return_type,emplace_back,emplace_back_impl)
338 
339   std::pair<iterator,bool> push_back(const value_type& x)
340                              {return insert(end(),x);}
push_back(BOOST_RV_REF (value_type)x)341   std::pair<iterator,bool> push_back(BOOST_RV_REF(value_type) x)
342                              {return insert(end(),boost::move(x));}
pop_back()343   void                     pop_back(){erase(--end());}
344 
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(emplace_return_type,emplace,emplace_impl,iterator,position)345   BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
346     emplace_return_type,emplace,emplace_impl,iterator,position)
347 
348   std::pair<iterator,bool> insert(iterator position,const value_type& x)
349   {
350     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
351     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
352     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
353     std::pair<final_node_type*,bool> p=this->final_insert_(x);
354     if(p.second&&position.get_node()!=header()){
355       relocate(position.get_node(),p.first);
356     }
357     return std::pair<iterator,bool>(make_iterator(p.first),p.second);
358   }
359 
insert(iterator position,BOOST_RV_REF (value_type)x)360   std::pair<iterator,bool> insert(iterator position,BOOST_RV_REF(value_type) x)
361   {
362     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
363     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
364     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
365     std::pair<final_node_type*,bool> p=this->final_insert_rv_(x);
366     if(p.second&&position.get_node()!=header()){
367       relocate(position.get_node(),p.first);
368     }
369     return std::pair<iterator,bool>(make_iterator(p.first),p.second);
370   }
371 
insert(iterator position,size_type n,value_param_type x)372   void insert(iterator position,size_type n,value_param_type x)
373   {
374     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
375     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
376     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
377     size_type s=0;
378     BOOST_TRY{
379       while(n--){
380         if(push_back(x).second)++s;
381       }
382     }
383     BOOST_CATCH(...){
384       relocate(position,end()-s,end());
385       BOOST_RETHROW;
386     }
387     BOOST_CATCH_END
388     relocate(position,end()-s,end());
389   }
390 
391   template<typename InputIterator>
insert(iterator position,InputIterator first,InputIterator last)392   void insert(iterator position,InputIterator first,InputIterator last)
393   {
394     insert_iter(position,first,last,mpl::not_<is_integral<InputIterator> >());
395   }
396 
397 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
insert(iterator position,std::initializer_list<value_type> list)398   void insert(iterator position,std::initializer_list<value_type> list)
399   {
400     insert(position,list.begin(),list.end());
401   }
402 #endif
403 
insert(const_iterator position,BOOST_RV_REF (node_type)nh)404   insert_return_type insert(const_iterator position,BOOST_RV_REF(node_type) nh)
405   {
406     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
407     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
408     if(nh)BOOST_MULTI_INDEX_CHECK_EQUAL_ALLOCATORS(*this,nh);
409     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
410     std::pair<final_node_type*,bool> p=this->final_insert_nh_(nh);
411     if(p.second&&position.get_node()!=header()){
412       relocate(position.get_node(),p.first);
413     }
414     return insert_return_type(make_iterator(p.first),p.second,boost::move(nh));
415   }
416 
extract(const_iterator position)417   node_type extract(const_iterator position)
418   {
419     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
420     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
421     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
422     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
423     return this->final_extract_(
424       static_cast<final_node_type*>(position.get_node()));
425   }
426 
erase(iterator position)427   iterator erase(iterator position)
428   {
429     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
430     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
431     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
432     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
433     this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
434     return position;
435   }
436 
erase(iterator first,iterator last)437   iterator erase(iterator first,iterator last)
438   {
439     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
440     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
441     BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
442     BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
443     BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
444     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
445     difference_type n=static_cast<difference_type>(last-first);
446     relocate(end(),first,last);
447     while(n--)pop_back();
448     return last;
449   }
450 
replace(iterator position,const value_type & x)451   bool replace(iterator position,const value_type& x)
452   {
453     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
454     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
455     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
456     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
457     return this->final_replace_(
458       x,static_cast<final_node_type*>(position.get_node()));
459   }
460 
replace(iterator position,BOOST_RV_REF (value_type)x)461   bool replace(iterator position,BOOST_RV_REF(value_type) x)
462   {
463     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
464     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
465     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
466     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
467     return this->final_replace_rv_(
468       x,static_cast<final_node_type*>(position.get_node()));
469   }
470 
471   template<typename Modifier>
modify(iterator position,Modifier mod)472   bool modify(iterator position,Modifier mod)
473   {
474     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
475     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
476     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
477     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
478 
479 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
480     /* MSVC++ 6.0 optimizer on safe mode code chokes if this
481      * this is not added. Left it for all compilers as it does no
482      * harm.
483      */
484 
485     position.detach();
486 #endif
487 
488     return this->final_modify_(
489       mod,static_cast<final_node_type*>(position.get_node()));
490   }
491 
492   template<typename Modifier,typename Rollback>
modify(iterator position,Modifier mod,Rollback back_)493   bool modify(iterator position,Modifier mod,Rollback back_)
494   {
495     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
496     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
497     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
498     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
499 
500 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
501     /* MSVC++ 6.0 optimizer on safe mode code chokes if this
502      * this is not added. Left it for all compilers as it does no
503      * harm.
504      */
505 
506     position.detach();
507 #endif
508 
509     return this->final_modify_(
510       mod,back_,static_cast<final_node_type*>(position.get_node()));
511   }
512 
swap(random_access_index<SuperMeta,TagList> & x)513   void swap(random_access_index<SuperMeta,TagList>& x)
514   {
515     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
516     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF(x);
517     this->final_swap_(x.final());
518   }
519 
clear()520   void clear()BOOST_NOEXCEPT
521   {
522     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
523     this->final_clear_();
524   }
525 
526   /* list operations */
527 
splice(iterator position,random_access_index<SuperMeta,TagList> & x)528   void splice(iterator position,random_access_index<SuperMeta,TagList>& x)
529   {
530     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
531     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
532     BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(*this,x);
533     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
534     iterator  first=x.begin(),last=x.end();
535     size_type n=0;
536     BOOST_TRY{
537       while(first!=last){
538         if(push_back(*first).second){
539           first=x.erase(first);
540           ++n;
541         }
542         else ++first;
543       }
544     }
545     BOOST_CATCH(...){
546       relocate(position,end()-n,end());
547       BOOST_RETHROW;
548     }
549     BOOST_CATCH_END
550     relocate(position,end()-n,end());
551   }
552 
splice(iterator position,random_access_index<SuperMeta,TagList> & x,iterator i)553   void splice(
554     iterator position,random_access_index<SuperMeta,TagList>& x,iterator i)
555   {
556     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
557     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
558     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
559     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
560     BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x);
561     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
562     if(&x==this)relocate(position,i);
563     else{
564       if(insert(position,*i).second){
565 
566 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
567     /* MSVC++ 6.0 optimizer has a hard time with safe mode, and the following
568      * workaround is needed. Left it for all compilers as it does no
569      * harm.
570      */
571         i.detach();
572         x.erase(x.make_iterator(i.get_node()));
573 #else
574         x.erase(i);
575 #endif
576 
577       }
578     }
579   }
580 
splice(iterator position,random_access_index<SuperMeta,TagList> & x,iterator first,iterator last)581   void splice(
582     iterator position,random_access_index<SuperMeta,TagList>& x,
583     iterator first,iterator last)
584   {
585     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
586     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
587     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
588     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
589     BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x);
590     BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x);
591     BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
592     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
593     if(&x==this)relocate(position,first,last);
594     else{
595       size_type n=0;
596       BOOST_TRY{
597         while(first!=last){
598           if(push_back(*first).second){
599             first=x.erase(first);
600             ++n;
601           }
602           else ++first;
603         }
604       }
605       BOOST_CATCH(...){
606         relocate(position,end()-n,end());
607         BOOST_RETHROW;
608       }
609       BOOST_CATCH_END
610       relocate(position,end()-n,end());
611     }
612   }
613 
remove(value_param_type value)614   void remove(value_param_type value)
615   {
616     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
617     difference_type n=
618       end()-make_iterator(
619         random_access_index_remove<index_node_type>(
620           ptrs,
621           ::boost::bind<bool>(
622             std::equal_to<value_type>(),::boost::arg<1>(),value)));
623     while(n--)pop_back();
624   }
625 
626   template<typename Predicate>
remove_if(Predicate pred)627   void remove_if(Predicate pred)
628   {
629     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
630     difference_type n=
631       end()-make_iterator(
632         random_access_index_remove<index_node_type>(ptrs,pred));
633     while(n--)pop_back();
634   }
635 
unique()636   void unique()
637   {
638     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
639     difference_type n=
640       end()-make_iterator(
641         random_access_index_unique<index_node_type>(
642           ptrs,std::equal_to<value_type>()));
643     while(n--)pop_back();
644   }
645 
646   template <class BinaryPredicate>
unique(BinaryPredicate binary_pred)647   void unique(BinaryPredicate binary_pred)
648   {
649     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
650     difference_type n=
651       end()-make_iterator(
652         random_access_index_unique<index_node_type>(ptrs,binary_pred));
653     while(n--)pop_back();
654   }
655 
merge(random_access_index<SuperMeta,TagList> & x)656   void merge(random_access_index<SuperMeta,TagList>& x)
657   {
658     if(this!=&x){
659       BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
660       size_type s=size();
661       splice(end(),x);
662       random_access_index_inplace_merge<index_node_type>(
663         get_allocator(),ptrs,ptrs.at(s),std::less<value_type>());
664     }
665   }
666 
667   template <typename Compare>
merge(random_access_index<SuperMeta,TagList> & x,Compare comp)668   void merge(random_access_index<SuperMeta,TagList>& x,Compare comp)
669   {
670     if(this!=&x){
671       BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
672       size_type s=size();
673       splice(end(),x);
674       random_access_index_inplace_merge<index_node_type>(
675         get_allocator(),ptrs,ptrs.at(s),comp);
676     }
677   }
678 
sort()679   void sort()
680   {
681     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
682     random_access_index_sort<index_node_type>(
683       get_allocator(),ptrs,std::less<value_type>());
684   }
685 
686   template <typename Compare>
sort(Compare comp)687   void sort(Compare comp)
688   {
689     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
690     random_access_index_sort<index_node_type>(
691       get_allocator(),ptrs,comp);
692   }
693 
reverse()694   void reverse()BOOST_NOEXCEPT
695   {
696     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
697     node_impl_type::reverse(ptrs.begin(),ptrs.end());
698   }
699 
700   /* rearrange operations */
701 
relocate(iterator position,iterator i)702   void relocate(iterator position,iterator i)
703   {
704     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
705     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
706     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
707     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
708     BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,*this);
709     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
710     if(position!=i)relocate(position.get_node(),i.get_node());
711   }
712 
relocate(iterator position,iterator first,iterator last)713   void relocate(iterator position,iterator first,iterator last)
714   {
715     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
716     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
717     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
718     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
719     BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
720     BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
721     BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
722     BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last);
723     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
724     if(position!=last)relocate(
725       position.get_node(),first.get_node(),last.get_node());
726   }
727 
728   template<typename InputIterator>
rearrange(InputIterator first)729   void rearrange(InputIterator first)
730   {
731     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
732     for(node_impl_ptr_pointer p0=ptrs.begin(),p0_end=ptrs.end();
733         p0!=p0_end;++first,++p0){
734       const value_type& v1=*first;
735       node_impl_ptr_pointer p1=node_from_value<index_node_type>(&v1)->up();
736 
737       std::swap(*p0,*p1);
738       (*p0)->up()=p0;
739       (*p1)->up()=p1;
740     }
741   }
742 
743 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
744   random_access_index(
745     const ctor_args_list& args_list,const allocator_type& al):
746     super(args_list.get_tail(),al),
747     ptrs(al,header()->impl(),0)
748   {
749   }
750 
random_access_index(const random_access_index<SuperMeta,TagList> & x)751   random_access_index(const random_access_index<SuperMeta,TagList>& x):
752     super(x),
753 
754 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
755     safe_super(),
756 #endif
757 
758     ptrs(x.get_allocator(),header()->impl(),x.size())
759   {
760     /* The actual copying takes place in subsequent call to copy_().
761      */
762   }
763 
random_access_index(const random_access_index<SuperMeta,TagList> & x,do_not_copy_elements_tag)764   random_access_index(
765     const random_access_index<SuperMeta,TagList>& x,do_not_copy_elements_tag):
766     super(x,do_not_copy_elements_tag()),
767 
768 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
769     safe_super(),
770 #endif
771 
772     ptrs(x.get_allocator(),header()->impl(),0)
773   {
774   }
775 
~random_access_index()776   ~random_access_index()
777   {
778     /* the container is guaranteed to be empty by now */
779   }
780 
781 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
make_iterator(index_node_type * node)782   iterator       make_iterator(index_node_type* node)
783     {return iterator(node,this);}
make_iterator(index_node_type * node) const784   const_iterator make_iterator(index_node_type* node)const
785     {return const_iterator(node,const_cast<random_access_index*>(this));}
786 #else
make_iterator(index_node_type * node)787   iterator       make_iterator(index_node_type* node){return iterator(node);}
make_iterator(index_node_type * node) const788   const_iterator make_iterator(index_node_type* node)const
789                    {return const_iterator(node);}
790 #endif
791 
copy_(const random_access_index<SuperMeta,TagList> & x,const copy_map_type & map)792   void copy_(
793     const random_access_index<SuperMeta,TagList>& x,const copy_map_type& map)
794   {
795     for(node_impl_ptr_pointer begin_org=x.ptrs.begin(),
796                               begin_cpy=ptrs.begin(),
797                               end_org=x.ptrs.end();
798         begin_org!=end_org;++begin_org,++begin_cpy){
799       *begin_cpy=
800          static_cast<index_node_type*>(
801            map.find(
802              static_cast<final_node_type*>(
803                index_node_type::from_impl(*begin_org))))->impl();
804       (*begin_cpy)->up()=begin_cpy;
805     }
806 
807     super::copy_(x,map);
808   }
809 
810   template<typename Variant>
insert_(value_param_type v,final_node_type * & x,Variant variant)811   final_node_type* insert_(
812     value_param_type v,final_node_type*& x,Variant variant)
813   {
814     ptrs.room_for_one();
815     final_node_type* res=super::insert_(v,x,variant);
816     if(res==x)ptrs.push_back(static_cast<index_node_type*>(x)->impl());
817     return res;
818   }
819 
820   template<typename Variant>
insert_(value_param_type v,index_node_type * position,final_node_type * & x,Variant variant)821   final_node_type* insert_(
822     value_param_type v,index_node_type* position,
823     final_node_type*& x,Variant variant)
824   {
825     ptrs.room_for_one();
826     final_node_type* res=super::insert_(v,position,x,variant);
827     if(res==x)ptrs.push_back(static_cast<index_node_type*>(x)->impl());
828     return res;
829   }
830 
extract_(index_node_type * x)831   void extract_(index_node_type* x)
832   {
833     ptrs.erase(x->impl());
834     super::extract_(x);
835 
836 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
837     detach_iterators(x);
838 #endif
839   }
840 
delete_all_nodes_()841   void delete_all_nodes_()
842   {
843     for(node_impl_ptr_pointer x=ptrs.begin(),x_end=ptrs.end();x!=x_end;++x){
844       this->final_delete_node_(
845         static_cast<final_node_type*>(index_node_type::from_impl(*x)));
846     }
847   }
848 
clear_()849   void clear_()
850   {
851     super::clear_();
852     ptrs.clear();
853 
854 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
855     safe_super::detach_dereferenceable_iterators();
856 #endif
857   }
858 
859   template<typename BoolConstant>
swap_(random_access_index<SuperMeta,TagList> & x,BoolConstant swap_allocators)860   void swap_(
861     random_access_index<SuperMeta,TagList>& x,BoolConstant swap_allocators)
862   {
863     ptrs.swap(x.ptrs,swap_allocators);
864 
865 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
866     safe_super::swap(x);
867 #endif
868 
869     super::swap_(x,swap_allocators);
870   }
871 
swap_elements_(random_access_index<SuperMeta,TagList> & x)872   void swap_elements_(random_access_index<SuperMeta,TagList>& x)
873   {
874     ptrs.swap(x.ptrs);
875 
876 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
877     safe_super::swap(x);
878 #endif
879 
880     super::swap_elements_(x);
881   }
882 
883   template<typename Variant>
replace_(value_param_type v,index_node_type * x,Variant variant)884   bool replace_(value_param_type v,index_node_type* x,Variant variant)
885   {
886     return super::replace_(v,x,variant);
887   }
888 
modify_(index_node_type * x)889   bool modify_(index_node_type* x)
890   {
891     BOOST_TRY{
892       if(!super::modify_(x)){
893         ptrs.erase(x->impl());
894 
895 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
896         detach_iterators(x);
897 #endif
898 
899         return false;
900       }
901       else return true;
902     }
903     BOOST_CATCH(...){
904       ptrs.erase(x->impl());
905 
906 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
907       detach_iterators(x);
908 #endif
909 
910       BOOST_RETHROW;
911     }
912     BOOST_CATCH_END
913   }
914 
modify_rollback_(index_node_type * x)915   bool modify_rollback_(index_node_type* x)
916   {
917     return super::modify_rollback_(x);
918   }
919 
check_rollback_(index_node_type * x) const920   bool check_rollback_(index_node_type* x)const
921   {
922     return super::check_rollback_(x);
923   }
924 
925 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
926   /* serialization */
927 
928   template<typename Archive>
save_(Archive & ar,const unsigned int version,const index_saver_type & sm) const929   void save_(
930     Archive& ar,const unsigned int version,const index_saver_type& sm)const
931   {
932     sm.save(begin(),end(),ar,version);
933     super::save_(ar,version,sm);
934   }
935 
936   template<typename Archive>
load_(Archive & ar,const unsigned int version,const index_loader_type & lm)937   void load_(
938     Archive& ar,const unsigned int version,const index_loader_type& lm)
939   {
940     {
941       typedef random_access_index_loader<
942         index_node_type,allocator_type> loader;
943 
944       loader ld(get_allocator(),ptrs);
945       lm.load(
946         ::boost::bind(
947           &loader::rearrange,&ld,::boost::arg<1>(),::boost::arg<2>()),
948         ar,version);
949     } /* exit scope so that ld frees its resources */
950     super::load_(ar,version,lm);
951   }
952 #endif
953 
954 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
955   /* invariant stuff */
956 
invariant_() const957   bool invariant_()const
958   {
959     if(size()>capacity())return false;
960     if(size()==0||begin()==end()){
961       if(size()!=0||begin()!=end())return false;
962     }
963     else{
964       size_type s=0;
965       for(const_iterator it=begin(),it_end=end();;++it,++s){
966         if(*(it.get_node()->up())!=it.get_node()->impl())return false;
967         if(it==it_end)break;
968       }
969       if(s!=size())return false;
970     }
971 
972     return super::invariant_();
973   }
974 
975   /* This forwarding function eases things for the boost::mem_fn construct
976    * in BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT. Actually,
977    * final_check_invariant is already an inherited member function of index.
978    */
check_invariant_() const979   void check_invariant_()const{this->final_check_invariant_();}
980 #endif
981 
982 private:
header() const983   index_node_type* header()const{return this->final_header();}
984 
relocate(index_node_type * position,index_node_type * x)985   static void relocate(index_node_type* position,index_node_type* x)
986   {
987     node_impl_type::relocate(position->up(),x->up());
988   }
989 
relocate(index_node_type * position,index_node_type * first,index_node_type * last)990   static void relocate(
991     index_node_type* position,index_node_type* first,index_node_type* last)
992   {
993     node_impl_type::relocate(
994       position->up(),first->up(),last->up());
995   }
996 
997 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(index_node_type * x)998   void detach_iterators(index_node_type* x)
999   {
1000     iterator it=make_iterator(x);
1001     safe_mode::detach_equivalent_iterators(it);
1002   }
1003 #endif
1004 
1005   template <class InputIterator>
assign_iter(InputIterator first,InputIterator last,mpl::true_)1006   void assign_iter(InputIterator first,InputIterator last,mpl::true_)
1007   {
1008     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
1009     clear();
1010     for(;first!=last;++first)this->final_insert_ref_(*first);
1011   }
1012 
assign_iter(size_type n,value_param_type value,mpl::false_)1013   void assign_iter(size_type n,value_param_type value,mpl::false_)
1014   {
1015     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
1016     clear();
1017     for(size_type i=0;i<n;++i)push_back(value);
1018   }
1019 
1020   template<typename InputIterator>
insert_iter(iterator position,InputIterator first,InputIterator last,mpl::true_)1021   void insert_iter(
1022     iterator position,InputIterator first,InputIterator last,mpl::true_)
1023   {
1024     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
1025     size_type s=0;
1026     BOOST_TRY{
1027       for(;first!=last;++first){
1028         if(this->final_insert_ref_(*first).second)++s;
1029       }
1030     }
1031     BOOST_CATCH(...){
1032       relocate(position,end()-s,end());
1033       BOOST_RETHROW;
1034     }
1035     BOOST_CATCH_END
1036     relocate(position,end()-s,end());
1037   }
1038 
insert_iter(iterator position,size_type n,value_param_type x,mpl::false_)1039   void insert_iter(
1040     iterator position,size_type n,value_param_type x,mpl::false_)
1041   {
1042     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
1043     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
1044     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
1045     size_type  s=0;
1046     BOOST_TRY{
1047       while(n--){
1048         if(push_back(x).second)++s;
1049       }
1050     }
1051     BOOST_CATCH(...){
1052       relocate(position,end()-s,end());
1053       BOOST_RETHROW;
1054     }
1055     BOOST_CATCH_END
1056     relocate(position,end()-s,end());
1057   }
1058 
1059   template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
emplace_front_impl(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)1060   std::pair<iterator,bool> emplace_front_impl(
1061     BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
1062   {
1063     return emplace_impl(begin(),BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
1064   }
1065 
1066   template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
emplace_back_impl(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)1067   std::pair<iterator,bool> emplace_back_impl(
1068     BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
1069   {
1070     return emplace_impl(end(),BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
1071   }
1072 
1073   template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
emplace_impl(iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)1074   std::pair<iterator,bool> emplace_impl(
1075     iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
1076   {
1077     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
1078     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
1079     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
1080     std::pair<final_node_type*,bool> p=
1081       this->final_emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
1082     if(p.second&&position.get_node()!=header()){
1083       relocate(position.get_node(),p.first);
1084     }
1085     return std::pair<iterator,bool>(make_iterator(p.first),p.second);
1086   }
1087 
1088   ptr_array ptrs;
1089 
1090 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
1091     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
1092 #pragma parse_mfunc_templ reset
1093 #endif
1094 };
1095 
1096 /* comparison */
1097 
1098 template<
1099   typename SuperMeta1,typename TagList1,
1100   typename SuperMeta2,typename TagList2
1101 >
operator ==(const random_access_index<SuperMeta1,TagList1> & x,const random_access_index<SuperMeta2,TagList2> & y)1102 bool operator==(
1103   const random_access_index<SuperMeta1,TagList1>& x,
1104   const random_access_index<SuperMeta2,TagList2>& y)
1105 {
1106   return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
1107 }
1108 
1109 template<
1110   typename SuperMeta1,typename TagList1,
1111   typename SuperMeta2,typename TagList2
1112 >
operator <(const random_access_index<SuperMeta1,TagList1> & x,const random_access_index<SuperMeta2,TagList2> & y)1113 bool operator<(
1114   const random_access_index<SuperMeta1,TagList1>& x,
1115   const random_access_index<SuperMeta2,TagList2>& y)
1116 {
1117   return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
1118 }
1119 
1120 template<
1121   typename SuperMeta1,typename TagList1,
1122   typename SuperMeta2,typename TagList2
1123 >
operator !=(const random_access_index<SuperMeta1,TagList1> & x,const random_access_index<SuperMeta2,TagList2> & y)1124 bool operator!=(
1125   const random_access_index<SuperMeta1,TagList1>& x,
1126   const random_access_index<SuperMeta2,TagList2>& y)
1127 {
1128   return !(x==y);
1129 }
1130 
1131 template<
1132   typename SuperMeta1,typename TagList1,
1133   typename SuperMeta2,typename TagList2
1134 >
operator >(const random_access_index<SuperMeta1,TagList1> & x,const random_access_index<SuperMeta2,TagList2> & y)1135 bool operator>(
1136   const random_access_index<SuperMeta1,TagList1>& x,
1137   const random_access_index<SuperMeta2,TagList2>& y)
1138 {
1139   return y<x;
1140 }
1141 
1142 template<
1143   typename SuperMeta1,typename TagList1,
1144   typename SuperMeta2,typename TagList2
1145 >
operator >=(const random_access_index<SuperMeta1,TagList1> & x,const random_access_index<SuperMeta2,TagList2> & y)1146 bool operator>=(
1147   const random_access_index<SuperMeta1,TagList1>& x,
1148   const random_access_index<SuperMeta2,TagList2>& y)
1149 {
1150   return !(x<y);
1151 }
1152 
1153 template<
1154   typename SuperMeta1,typename TagList1,
1155   typename SuperMeta2,typename TagList2
1156 >
operator <=(const random_access_index<SuperMeta1,TagList1> & x,const random_access_index<SuperMeta2,TagList2> & y)1157 bool operator<=(
1158   const random_access_index<SuperMeta1,TagList1>& x,
1159   const random_access_index<SuperMeta2,TagList2>& y)
1160 {
1161   return !(x>y);
1162 }
1163 
1164 /*  specialized algorithms */
1165 
1166 template<typename SuperMeta,typename TagList>
swap(random_access_index<SuperMeta,TagList> & x,random_access_index<SuperMeta,TagList> & y)1167 void swap(
1168   random_access_index<SuperMeta,TagList>& x,
1169   random_access_index<SuperMeta,TagList>& y)
1170 {
1171   x.swap(y);
1172 }
1173 
1174 } /* namespace multi_index::detail */
1175 
1176 /* random access index specifier */
1177 
1178 template <typename TagList>
1179 struct random_access
1180 {
1181   BOOST_STATIC_ASSERT(detail::is_tag<TagList>::value);
1182 
1183   template<typename Super>
1184   struct node_class
1185   {
1186     typedef detail::random_access_index_node<Super> type;
1187   };
1188 
1189   template<typename SuperMeta>
1190   struct index_class
1191   {
1192     typedef detail::random_access_index<
1193       SuperMeta,typename TagList::type>  type;
1194   };
1195 };
1196 
1197 } /* namespace multi_index */
1198 
1199 } /* namespace boost */
1200 
1201 /* Boost.Foreach compatibility */
1202 
1203 template<typename SuperMeta,typename TagList>
boost_foreach_is_noncopyable(boost::multi_index::detail::random_access_index<SuperMeta,TagList> * &,boost_foreach_argument_dependent_lookup_hack)1204 inline boost::mpl::true_* boost_foreach_is_noncopyable(
1205   boost::multi_index::detail::random_access_index<SuperMeta,TagList>*&,
1206   boost_foreach_argument_dependent_lookup_hack)
1207 {
1208   return 0;
1209 }
1210 
1211 #undef BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT
1212 #undef BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF
1213 
1214 #endif
1215