]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/multi_index/sequenced_index.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / multi_index / sequenced_index.hpp
CommitLineData
f67539c2 1/* Copyright 2003-2020 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 */
f67539c2 17#include <boost/bind/bind.hpp>
7c673cae 18#include <boost/call_traits.hpp>
11fdf7f2 19#include <boost/core/addressof.hpp>
20effc67 20#include <boost/core/no_exceptions_support.hpp>
7c673cae
FG
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>
20effc67 34#include <boost/multi_index/detail/node_handle.hpp>
7c673cae
FG
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>
7c673cae
FG
43#include <functional>
44#include <utility>
45
46#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
47#include<initializer_list>
48#endif
49
7c673cae
FG
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
62namespace boost{
63
64namespace multi_index{
65
66namespace detail{
67
68/* sequenced_index adds a layer of sequenced indexing to a given Super */
69
70template<typename SuperMeta,typename TagList>
71class 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
92f5a8d4 90 typedef typename SuperMeta::type super;
7c673cae
FG
91
92protected:
93 typedef sequenced_index_node<
20effc67 94 typename super::index_node_type> index_node_type;
7c673cae
FG
95
96private:
20effc67 97 typedef typename index_node_type::impl_type node_impl_type;
7c673cae
FG
98
99public:
100 /* types */
101
20effc67 102 typedef typename index_node_type::value_type value_type;
92f5a8d4
TL
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;
7c673cae
FG
107
108#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
109 typedef safe_mode::safe_iterator<
20effc67 110 bidir_node_iterator<index_node_type>,
92f5a8d4 111 sequenced_index> iterator;
7c673cae 112#else
20effc67 113 typedef bidir_node_iterator<index_node_type> iterator;
7c673cae
FG
114#endif
115
92f5a8d4 116 typedef iterator const_iterator;
7c673cae 117
92f5a8d4
TL
118private:
119 typedef allocator_traits<allocator_type> alloc_traits;
120
121public:
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;
7c673cae 126 typedef typename
92f5a8d4 127 boost::reverse_iterator<iterator> reverse_iterator;
7c673cae 128 typedef typename
92f5a8d4 129 boost::reverse_iterator<const_iterator> const_reverse_iterator;
20effc67
TL
130 typedef typename super::final_node_handle_type node_type;
131 typedef detail::insert_return_type<
132 iterator,node_type> insert_return_type;
92f5a8d4 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
20effc67 221 {return make_iterator(index_node_type::from_impl(header()->next()));}
7c673cae 222 const_iterator begin()const BOOST_NOEXCEPT
20effc67 223 {return make_iterator(index_node_type::from_impl(header()->next()));}
7c673cae
FG
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 {
20effc67
TL
247 return make_iterator(
248 node_from_value<index_node_type>(boost::addressof(x)));
7c673cae
FG
249 }
250
251 const_iterator iterator_to(const value_type& x)const
252 {
20effc67
TL
253 return make_iterator(
254 node_from_value<index_node_type>(boost::addressof(x)));
7c673cae
FG
255 }
256
257 /* capacity */
258
259 bool empty()const BOOST_NOEXCEPT{return this->final_empty_();}
260 size_type size()const BOOST_NOEXCEPT{return this->final_size_();}
261 size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}
262
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
273 void resize(size_type n,value_param_type x)
274 {
275 BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
92f5a8d4 276 if(n>size())insert(end(),static_cast<size_type>(n-size()),x);
7c673cae
FG
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
284 const_reference front()const{return *begin();}
285 const_reference back()const{return *--end();}
286
287 /* modifiers */
288
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);}
294 std::pair<iterator,bool> push_front(BOOST_RV_REF(value_type) x)
295 {return insert(begin(),boost::move(x));}
296 void pop_front(){erase(begin());}
297
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);}
303 std::pair<iterator,bool> push_back(BOOST_RV_REF(value_type) x)
304 {return insert(end(),boost::move(x));}
305 void pop_back(){erase(--end());}
306
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
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
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>
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)
349 void insert(iterator position,std::initializer_list<value_type> list)
350 {
351 insert(position,list.begin(),list.end());
352 }
353#endif
354
20effc67
TL
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
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
7c673cae
FG
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
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
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
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>
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>
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
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
471 void clear()BOOST_NOEXCEPT
472 {
473 BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
474 this->final_clear_();
475 }
476
477 /* list operations */
478
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
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
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
546 void remove(value_param_type value)
547 {
548 sequenced_index_remove(
549 *this,
20effc67
TL
550 ::boost::bind<bool>(
551 std::equal_to<value_type>(),::boost::arg<1>(),value));
7c673cae
FG
552 }
553
554 template<typename Predicate>
555 void remove_if(Predicate pred)
556 {
557 sequenced_index_remove(*this,pred);
558 }
559
560 void unique()
561 {
562 sequenced_index_unique(*this,std::equal_to<value_type>());
563 }
564
565 template <class BinaryPredicate>
566 void unique(BinaryPredicate binary_pred)
567 {
568 sequenced_index_unique(*this,binary_pred);
569 }
570
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>
577 void merge(sequenced_index<SuperMeta,TagList>& x,Compare comp)
578 {
579 sequenced_index_merge(*this,x,comp);
580 }
581
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>
589 void sort(Compare comp)
590 {
591 BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
592 sequenced_index_sort(header(),comp);
593 }
594
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
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
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>
630 void rearrange(InputIterator first)
631 {
632 BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
20effc67 633 index_node_type* pos=header();
7c673cae
FG
634 for(size_type s=size();s--;){
635 const value_type& v=*first++;
20effc67 636 relink(pos,node_from_value<index_node_type>(&v));
7c673cae
FG
637 }
638 }
639
640BOOST_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
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
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
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)
20effc67
TL
676 iterator make_iterator(index_node_type* node)
677 {return iterator(node,this);}
678 const_iterator make_iterator(index_node_type* node)const
7c673cae
FG
679 {return const_iterator(node,const_cast<sequenced_index*>(this));}
680#else
20effc67
TL
681 iterator make_iterator(index_node_type* node){return iterator(node);}
682 const_iterator make_iterator(index_node_type* node)const
7c673cae
FG
683 {return const_iterator(node);}
684#endif
685
686 void copy_(
687 const sequenced_index<SuperMeta,TagList>& x,const copy_map_type& map)
688 {
20effc67
TL
689 index_node_type* org=x.header();
690 index_node_type* cpy=header();
7c673cae 691 do{
20effc67
TL
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));
7c673cae
FG
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>
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);
20effc67 709 if(res==x)link(static_cast<index_node_type*>(x));
7c673cae
FG
710 return res;
711 }
712
713 template<typename Variant>
714 final_node_type* insert_(
20effc67
TL
715 value_param_type v,index_node_type* position,
716 final_node_type*& x,Variant variant)
7c673cae
FG
717 {
718 final_node_type* res=super::insert_(v,position,x,variant);
20effc67 719 if(res==x)link(static_cast<index_node_type*>(x));
7c673cae
FG
720 return res;
721 }
722
20effc67 723 void extract_(index_node_type* x)
7c673cae
FG
724 {
725 unlink(x);
20effc67 726 super::extract_(x);
7c673cae
FG
727
728#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
729 detach_iterators(x);
730#endif
731 }
732
733 void delete_all_nodes_()
734 {
20effc67
TL
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());
7c673cae
FG
738 this->final_delete_node_(static_cast<final_node_type*>(x));
739 x=y;
740 }
741 }
742
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
f67539c2
TL
753 template<typename BoolConstant>
754 void swap_(
755 sequenced_index<SuperMeta,TagList>& x,BoolConstant swap_allocators)
7c673cae
FG
756 {
757#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
758 safe_super::swap(x);
759#endif
760
f67539c2 761 super::swap_(x,swap_allocators);
7c673cae
FG
762 }
763
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>
20effc67 774 bool replace_(value_param_type v,index_node_type* x,Variant variant)
7c673cae
FG
775 {
776 return super::replace_(v,x,variant);
777 }
778
20effc67 779 bool modify_(index_node_type* x)
7c673cae
FG
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
20effc67 805 bool modify_rollback_(index_node_type* x)
7c673cae
FG
806 {
807 return super::modify_rollback_(x);
808 }
809
20effc67 810 bool check_rollback_(index_node_type* x)const
b32b8144
FG
811 {
812 return super::check_rollback_(x);
813 }
814
7c673cae
FG
815#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
816 /* serialization */
817
818 template<typename Archive>
819 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>
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
841 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 */
864 void check_invariant_()const{this->final_check_invariant_();}
865#endif
866
867private:
20effc67 868 index_node_type* header()const{return this->final_header();}
7c673cae
FG
869
870 void empty_initialize()
871 {
872 header()->prior()=header()->next()=header()->impl();
873 }
874
20effc67 875 void link(index_node_type* x)
7c673cae
FG
876 {
877 node_impl_type::link(x->impl(),header()->impl());
92f5a8d4 878 }
7c673cae 879
20effc67 880 static void unlink(index_node_type* x)
7c673cae
FG
881 {
882 node_impl_type::unlink(x->impl());
883 }
884
20effc67 885 static void relink(index_node_type* position,index_node_type* x)
7c673cae
FG
886 {
887 node_impl_type::relink(position->impl(),x->impl());
888 }
889
20effc67
TL
890 static void relink(
891 index_node_type* position,index_node_type* first,index_node_type* last)
7c673cae
FG
892 {
893 node_impl_type::relink(
894 position->impl(),first->impl(),last->impl());
895 }
896
897#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
20effc67 898 void rearranger(index_node_type* position,index_node_type *x)
7c673cae
FG
899 {
900 if(!position)position=header();
20effc67 901 index_node_type::increment(position);
7c673cae
FG
902 if(position!=x)relink(position,x);
903 }
904#endif
905
906#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
20effc67 907 void detach_iterators(index_node_type* x)
7c673cae
FG
908 {
909 iterator it=make_iterator(x);
910 safe_mode::detach_equivalent_iterators(it);
911 }
912#endif
913
914 template <class InputIterator>
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
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>
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
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>
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>
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>
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
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 x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
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 std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
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
1022template<
1023 typename SuperMeta1,typename TagList1,
1024 typename SuperMeta2,typename TagList2
1025>
1026bool operator>(
1027 const sequenced_index<SuperMeta1,TagList1>& x,
1028 const sequenced_index<SuperMeta2,TagList2>& y)
1029{
1030 return y<x;
1031}
1032
1033template<
1034 typename SuperMeta1,typename TagList1,
1035 typename SuperMeta2,typename TagList2
1036>
1037bool operator>=(
1038 const sequenced_index<SuperMeta1,TagList1>& x,
1039 const sequenced_index<SuperMeta2,TagList2>& y)
1040{
1041 return !(x<y);
1042}
1043
1044template<
1045 typename SuperMeta1,typename TagList1,
1046 typename SuperMeta2,typename TagList2
1047>
1048bool 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
1057template<typename SuperMeta,typename TagList>
1058void 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
1069template <typename TagList>
1070struct 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
1093template<typename SuperMeta,typename TagList>
1094inline 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