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