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