]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/multi_index/sequenced_index.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / multi_index / sequenced_index.hpp
CommitLineData
92f5a8d4 1/* Copyright 2003-2019 Joaquin M Lopez Munoz.
7c673cae
FG
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>
11fdf7f2 19#include <boost/core/addressof.hpp>
7c673cae
FG
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>
92f5a8d4 25#include <boost/move/utility_core.hpp>
7c673cae
FG
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>
92f5a8d4 30#include <boost/multi_index/detail/allocator_traits.hpp>
7c673cae
FG
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>
7c673cae
FG
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
65namespace boost{
66
67namespace multi_index{
68
69namespace detail{
70
71/* sequenced_index adds a layer of sequenced indexing to a given Super */
72
73template<typename SuperMeta,typename TagList>
74class 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
92f5a8d4 93 typedef typename SuperMeta::type super;
7c673cae
FG
94
95protected:
96 typedef sequenced_index_node<
92f5a8d4 97 typename super::node_type> node_type;
7c673cae
FG
98
99private:
92f5a8d4 100 typedef typename node_type::impl_type node_impl_type;
7c673cae
FG
101
102public:
103 /* types */
104
92f5a8d4
TL
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;
7c673cae
FG
110
111#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
112 typedef safe_mode::safe_iterator<
113 bidir_node_iterator<node_type>,
92f5a8d4 114 sequenced_index> iterator;
7c673cae 115#else
92f5a8d4 116 typedef bidir_node_iterator<node_type> iterator;
7c673cae
FG
117#endif
118
92f5a8d4 119 typedef iterator const_iterator;
7c673cae 120
92f5a8d4
TL
121private:
122 typedef allocator_traits<allocator_type> alloc_traits;
123
124public:
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;
7c673cae 129 typedef typename
92f5a8d4 130 boost::reverse_iterator<iterator> reverse_iterator;
7c673cae 131 typedef typename
92f5a8d4
TL
132 boost::reverse_iterator<const_iterator> const_reverse_iterator;
133 typedef TagList tag_list;
7c673cae
FG
134
135protected:
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
156private:
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
170public:
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
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)
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>
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)
200 void assign(std::initializer_list<value_type> list)
201 {
202 assign(list.begin(),list.end());
203 }
204#endif
205
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
213 allocator_type get_allocator()const BOOST_NOEXCEPT
214 {
215 return this->final().get_allocator();
216 }
217
218 /* iterators */
219
220 iterator begin()BOOST_NOEXCEPT
221 {return make_iterator(node_type::from_impl(header()->next()));}
222 const_iterator begin()const BOOST_NOEXCEPT
223 {return make_iterator(node_type::from_impl(header()->next()));}
224 iterator
225 end()BOOST_NOEXCEPT{return make_iterator(header());}
226 const_iterator
227 end()const BOOST_NOEXCEPT{return make_iterator(header());}
228 reverse_iterator
229 rbegin()BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
230 const_reverse_iterator
231 rbegin()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
232 reverse_iterator
233 rend()BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
234 const_reverse_iterator
235 rend()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
236 const_iterator
237 cbegin()const BOOST_NOEXCEPT{return begin();}
238 const_iterator
239 cend()const BOOST_NOEXCEPT{return end();}
240 const_reverse_iterator
241 crbegin()const BOOST_NOEXCEPT{return rbegin();}
242 const_reverse_iterator
243 crend()const BOOST_NOEXCEPT{return rend();}
244
245 iterator iterator_to(const value_type& x)
246 {
11fdf7f2 247 return make_iterator(node_from_value<node_type>(boost::addressof(x)));
7c673cae
FG
248 }
249
250 const_iterator iterator_to(const value_type& x)const
251 {
11fdf7f2 252 return make_iterator(node_from_value<node_type>(boost::addressof(x)));
7c673cae
FG
253 }
254
255 /* capacity */
256
257 bool empty()const BOOST_NOEXCEPT{return this->final_empty_();}
258 size_type size()const BOOST_NOEXCEPT{return this->final_size_();}
259 size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}
260
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
271 void resize(size_type n,value_param_type x)
272 {
273 BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
92f5a8d4 274 if(n>size())insert(end(),static_cast<size_type>(n-size()),x);
7c673cae
FG
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
282 const_reference front()const{return *begin();}
283 const_reference back()const{return *--end();}
284
285 /* modifiers */
286
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);}
292 std::pair<iterator,bool> push_front(BOOST_RV_REF(value_type) x)
293 {return insert(begin(),boost::move(x));}
294 void pop_front(){erase(begin());}
295
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);}
301 std::pair<iterator,bool> push_back(BOOST_RV_REF(value_type) x)
302 {return insert(end(),boost::move(x));}
303 void pop_back(){erase(--end());}
304
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
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
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>
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)
347 void insert(iterator position,std::initializer_list<value_type> list)
348 {
349 insert(position,list.begin(),list.end());
350 }
351#endif
352
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
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
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
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>
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>
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
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
446 void clear()BOOST_NOEXCEPT
447 {
448 BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
449 this->final_clear_();
450 }
451
452 /* list operations */
453
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
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
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
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>
529 void remove_if(Predicate pred)
530 {
531 sequenced_index_remove(*this,pred);
532 }
533
534 void unique()
535 {
536 sequenced_index_unique(*this,std::equal_to<value_type>());
537 }
538
539 template <class BinaryPredicate>
540 void unique(BinaryPredicate binary_pred)
541 {
542 sequenced_index_unique(*this,binary_pred);
543 }
544
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>
551 void merge(sequenced_index<SuperMeta,TagList>& x,Compare comp)
552 {
553 sequenced_index_merge(*this,x,comp);
554 }
555
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>
563 void sort(Compare comp)
564 {
565 BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
566 sequenced_index_sort(header(),comp);
567 }
568
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
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
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>
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
614BOOST_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
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
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
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)
650 iterator make_iterator(node_type* node){return iterator(node,this);}
651 const_iterator make_iterator(node_type* node)const
652 {return const_iterator(node,const_cast<sequenced_index*>(this));}
653#else
654 iterator make_iterator(node_type* node){return iterator(node);}
655 const_iterator make_iterator(node_type* node)const
656 {return const_iterator(node);}
657#endif
658
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>
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>
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
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
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
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
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
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>
742 bool replace_(value_param_type v,node_type* x,Variant variant)
743 {
744 return super::replace_(v,x,variant);
745 }
746
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
773 bool modify_rollback_(node_type* x)
774 {
775 return super::modify_rollback_(x);
776 }
777
b32b8144
FG
778 bool check_rollback_(node_type* x)const
779 {
780 return super::check_rollback_(x);
781 }
782
7c673cae
FG
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(
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
809 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 */
832 void check_invariant_()const{this->final_check_invariant_();}
833#endif
834
835private:
836 node_type* header()const{return this->final_header();}
837
838 void empty_initialize()
839 {
840 header()->prior()=header()->next()=header()->impl();
841 }
842
843 void link(node_type* x)
844 {
845 node_impl_type::link(x->impl(),header()->impl());
92f5a8d4 846 }
7c673cae
FG
847
848 static void unlink(node_type* x)
849 {
850 node_impl_type::unlink(x->impl());
851 }
852
853 static void relink(node_type* position,node_type* x)
854 {
855 node_impl_type::relink(position->impl(),x->impl());
856 }
857
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)
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)
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>
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
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>
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
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>
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>
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>
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
956template<
957 typename SuperMeta1,typename TagList1,
958 typename SuperMeta2,typename TagList2
959>
960bool 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
967template<
968 typename SuperMeta1,typename TagList1,
969 typename SuperMeta2,typename TagList2
970>
971bool 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
978template<
979 typename SuperMeta1,typename TagList1,
980 typename SuperMeta2,typename TagList2
981>
982bool operator!=(
983 const sequenced_index<SuperMeta1,TagList1>& x,
984 const sequenced_index<SuperMeta2,TagList2>& y)
985{
986 return !(x==y);
987}
988
989template<
990 typename SuperMeta1,typename TagList1,
991 typename SuperMeta2,typename TagList2
992>
993bool operator>(
994 const sequenced_index<SuperMeta1,TagList1>& x,
995 const sequenced_index<SuperMeta2,TagList2>& y)
996{
997 return y<x;
998}
999
1000template<
1001 typename SuperMeta1,typename TagList1,
1002 typename SuperMeta2,typename TagList2
1003>
1004bool operator>=(
1005 const sequenced_index<SuperMeta1,TagList1>& x,
1006 const sequenced_index<SuperMeta2,TagList2>& y)
1007{
1008 return !(x<y);
1009}
1010
1011template<
1012 typename SuperMeta1,typename TagList1,
1013 typename SuperMeta2,typename TagList2
1014>
1015bool 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
1024template<typename SuperMeta,typename TagList>
1025void 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
1036template <typename TagList>
1037struct 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
1060template<typename SuperMeta,typename TagList>
1061inline 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