comparison DEPENDENCIES/generic/include/boost/multi_index/sequenced_index.hpp @ 16:2665513ce2d3

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