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