Ticket #4814: multi_index_container.hpp

File multi_index_container.hpp, 34.6 KB (added by Akira Takahashi <faithandbrave@…>, 12 years ago)

patched source file

Line 
1/* Multiply indexed container.
2 *
3 * Copyright 2003-2010 Joaquin M Lopez Munoz.
4 * Distributed under the Boost Software License, Version 1.0.
5 * (See accompanying file LICENSE_1_0.txt or copy at
6 * http://www.boost.org/LICENSE_1_0.txt)
7 *
8 * See http://www.boost.org/libs/multi_index for library home page.
9 */
10
11#ifndef BOOST_MULTI_INDEX_HPP
12#define BOOST_MULTI_INDEX_HPP
13
14#if defined(_MSC_VER)&&(_MSC_VER>=1200)
15#pragma once
16#endif
17
18#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
19#include <algorithm>
20#include <boost/detail/allocator_utilities.hpp>
21#include <boost/detail/no_exceptions_support.hpp>
22#include <boost/detail/workaround.hpp>
23#include <boost/mpl/at.hpp>
24#include <boost/mpl/contains.hpp>
25#include <boost/mpl/find_if.hpp>
26#include <boost/mpl/identity.hpp>
27#include <boost/mpl/int.hpp>
28#include <boost/mpl/size.hpp>
29#include <boost/mpl/deref.hpp>
30#include <boost/multi_index_container_fwd.hpp>
31#include <boost/multi_index/detail/access_specifier.hpp>
32#include <boost/multi_index/detail/adl_swap.hpp>
33#include <boost/multi_index/detail/base_type.hpp>
34#include <boost/multi_index/detail/converter.hpp>
35#include <boost/multi_index/detail/header_holder.hpp>
36#include <boost/multi_index/detail/has_tag.hpp>
37#include <boost/multi_index/detail/no_duplicate_tags.hpp>
38#include <boost/multi_index/detail/prevent_eti.hpp>
39#include <boost/multi_index/detail/safe_mode.hpp>
40#include <boost/multi_index/detail/scope_guard.hpp>
41#include <boost/static_assert.hpp>
42#include <boost/type_traits/is_same.hpp>
43#include <boost/utility/base_from_member.hpp>
44
45#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
46#include <boost/multi_index/detail/archive_constructed.hpp>
47#include <boost/multi_index/detail/serialization_version.hpp>
48#include <boost/serialization/collection_size_type.hpp>
49#include <boost/serialization/nvp.hpp>
50#include <boost/serialization/split_member.hpp>
51#include <boost/serialization/version.hpp>
52#include <boost/throw_exception.hpp>
53#endif
54
55#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
56#include <boost/multi_index/detail/invariant_assert.hpp>
57#define BOOST_MULTI_INDEX_CHECK_INVARIANT \
58 detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
59 detail::make_obj_guard(*this,&multi_index_container::check_invariant_); \
60 BOOST_JOIN(check_invariant_,__LINE__).touch();
61#else
62#define BOOST_MULTI_INDEX_CHECK_INVARIANT
63#endif
64
65#if !defined(BOOST_NO_INITIALIZER_LISTS)
66#include <initializer_list>
67#endif
68
69namespace boost{
70
71namespace multi_index{
72
73template<typename Value,typename IndexSpecifierList,typename Allocator>
74class multi_index_container:
75 private ::boost::base_from_member<
76 typename boost::detail::allocator::rebind_to<
77 Allocator,
78 typename detail::multi_index_node_type<
79 Value,IndexSpecifierList,Allocator>::type
80 >::type>,
81 BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
82 typename detail::prevent_eti<
83 Allocator,
84 typename boost::detail::allocator::rebind_to<
85 Allocator,
86 typename detail::multi_index_node_type<
87 Value,IndexSpecifierList,Allocator>::type
88 >::type
89 >::type::pointer,
90 multi_index_container<Value,IndexSpecifierList,Allocator> >,
91 public detail::multi_index_base_type<
92 Value,IndexSpecifierList,Allocator>::type
93{
94#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
95 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
96/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
97 * lifetime of const references bound to temporaries --precisely what
98 * scopeguards are.
99 */
100
101#pragma parse_mfunc_templ off
102#endif
103
104private:
105#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
106 template <typename,typename,typename> friend class detail::index_base;
107 template <typename,typename> friend struct detail::header_holder;
108 template <typename,typename> friend struct detail::converter;
109#endif
110
111 typedef typename detail::multi_index_base_type<
112 Value,IndexSpecifierList,Allocator>::type super;
113 typedef typename
114 boost::detail::allocator::rebind_to<
115 Allocator,
116 typename super::node_type
117 >::type node_allocator;
118 typedef ::boost::base_from_member<
119 node_allocator> bfm_allocator;
120 typedef detail::header_holder<
121 typename detail::prevent_eti<
122 Allocator,
123 node_allocator
124 >::type::pointer,
125 multi_index_container> bfm_header;
126
127#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
128 /* see definition of index_type_list below */
129 typedef typename super::index_type_list super_index_type_list;
130#endif
131
132 template<typename InputIterator>
133 void iterator_initialize(InputIterator first,InputIterator last)
134 {
135 BOOST_MULTI_INDEX_CHECK_INVARIANT;
136 BOOST_TRY{
137 iterator hint=super::end();
138 for(;first!=last;++first){
139 hint=super::make_iterator(insert_(*first,hint.get_node()).first);
140 }
141 }
142 BOOST_CATCH(...){
143 clear_();
144 BOOST_RETHROW;
145 }
146 BOOST_CATCH_END
147 }
148
149
150public:
151 /* All types are inherited from super, a few are explicitly
152 * brought forward here to save us some typename's.
153 */
154
155 typedef typename super::ctor_args_list ctor_args_list;
156 typedef IndexSpecifierList index_specifier_type_list;
157
158#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
159 /* MSVC++ 6.0 chokes on moderately long index lists (around 6 indices
160 * or more), with errors ranging from corrupt exes to duplicate
161 * comdats. The following type hiding hack alleviates this condition;
162 * best results combined with type hiding of the indexed_by construct
163 * itself, as explained in the "Compiler specifics" section of
164 * the documentation.
165 */
166
167 struct index_type_list:super_index_type_list
168 {
169 typedef index_type_list type;
170 typedef typename super_index_type_list::back back;
171 typedef mpl::v_iter<type,0> begin;
172 typedef mpl::v_iter<
173 type,
174 mpl::size<super_index_type_list>::value> end;
175 };
176#else
177 typedef typename super::index_type_list index_type_list;
178#endif
179
180 typedef typename super::iterator_type_list iterator_type_list;
181 typedef typename super::const_iterator_type_list const_iterator_type_list;
182 typedef typename super::value_type value_type;
183 typedef typename super::final_allocator_type allocator_type;
184 typedef typename super::iterator iterator;
185 typedef typename super::const_iterator const_iterator;
186
187 BOOST_STATIC_ASSERT(
188 detail::no_duplicate_tags_in_index_list<index_type_list>::value);
189
190 /* global project() needs to see this publicly */
191
192 typedef typename super::node_type node_type;
193
194 /* construct/copy/destroy */
195
196 explicit multi_index_container(
197
198#if BOOST_WORKAROUND(__IBMCPP__,<=600)
199 /* VisualAge seems to have an ETI issue with the default values
200 * for arguments args_list and al.
201 */
202
203 const ctor_args_list& args_list=
204 typename mpl::identity<multi_index_container>::type::
205 ctor_args_list(),
206 const allocator_type& al=
207 typename mpl::identity<multi_index_container>::type::
208 allocator_type()):
209#else
210 const ctor_args_list& args_list=ctor_args_list(),
211 const allocator_type& al=allocator_type()):
212#endif
213
214 bfm_allocator(al),
215 super(args_list,bfm_allocator::member),
216 node_count(0)
217 {
218 BOOST_MULTI_INDEX_CHECK_INVARIANT;
219 }
220
221 explicit multi_index_container(const allocator_type& al):
222 bfm_allocator(al),
223 super(ctor_args_list(),bfm_allocator::member),
224 node_count(0)
225 {
226 BOOST_MULTI_INDEX_CHECK_INVARIANT;
227 }
228
229 template<typename InputIterator>
230 multi_index_container(
231 InputIterator first,InputIterator last,
232
233#if BOOST_WORKAROUND(__IBMCPP__,<=600)
234 /* VisualAge seems to have an ETI issue with the default values
235 * for arguments args_list and al.
236 */
237
238 const ctor_args_list& args_list=
239 typename mpl::identity<multi_index_container>::type::
240 ctor_args_list(),
241 const allocator_type& al=
242 typename mpl::identity<multi_index_container>::type::
243 allocator_type()):
244#else
245 const ctor_args_list& args_list=ctor_args_list(),
246 const allocator_type& al=allocator_type()):
247#endif
248
249 bfm_allocator(al),
250 super(args_list,bfm_allocator::member),
251 node_count(0)
252 {
253 iterator_initialize(first, last);
254 }
255
256#if !defined(BOOST_NO_INITIALIZER_LISTS)
257 template<typename U>
258 multi_index_container(std::initializer_list<U> init):
259#if BOOST_WORKAROUND(__IBMCPP__,<=600)
260 bfm_allocator(typename mpl::identity<multi_index_container>::type::allocator_type()),
261 super(typename mpl::identity<multi_index_container>::type::ctor_args_list(),
262 bfm_allocator::member),
263#else
264 bfm_allocator(allocator_type()),
265 super(ctor_args_list(),bfm_allocator::member),
266#endif
267 node_count(0)
268 {
269 iterator_initialize(init.begin(), init.end());
270 }
271#endif
272
273 multi_index_container(
274 const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
275 bfm_allocator(x.bfm_allocator::member),
276 bfm_header(),
277 super(x),
278 node_count(0)
279 {
280 copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
281 for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
282 map.clone(it.get_node());
283 }
284 super::copy_(x,map);
285 map.release();
286 node_count=x.size();
287
288 /* Not until this point are the indices required to be consistent,
289 * hence the position of the invariant checker.
290 */
291
292 BOOST_MULTI_INDEX_CHECK_INVARIANT;
293 }
294
295 ~multi_index_container()
296 {
297 delete_all_nodes_();
298 }
299
300 multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
301 multi_index_container<Value,IndexSpecifierList,Allocator> x)
302 {
303 BOOST_MULTI_INDEX_CHECK_INVARIANT;
304 this->swap(x);
305 return *this;
306 }
307
308 allocator_type get_allocator()const
309 {
310 return allocator_type(bfm_allocator::member);
311 }
312
313 /* retrieval of indices by number */
314
315#if !defined(BOOST_NO_MEMBER_TEMPLATES)
316 template<int N>
317 struct nth_index
318 {
319 BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
320 typedef typename mpl::at_c<index_type_list,N>::type type;
321 };
322
323 template<int N>
324 typename nth_index<N>::type& get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
325 {
326 BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
327 return *this;
328 }
329
330 template<int N>
331 const typename nth_index<N>::type& get(
332 BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
333 {
334 BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
335 return *this;
336 }
337#endif
338
339 /* retrieval of indices by tag */
340
341#if !defined(BOOST_NO_MEMBER_TEMPLATES)
342 template<typename Tag>
343 struct index
344 {
345 typedef typename mpl::find_if<
346 index_type_list,
347 detail::has_tag<Tag>
348 >::type iter;
349
350 BOOST_STATIC_CONSTANT(
351 bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
352 BOOST_STATIC_ASSERT(index_found);
353
354 typedef typename mpl::deref<iter>::type type;
355 };
356
357 template<typename Tag>
358 typename index<Tag>::type& get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
359 {
360 return *this;
361 }
362
363 template<typename Tag>
364 const typename index<Tag>::type& get(
365 BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))const
366 {
367 return *this;
368 }
369#endif
370
371 /* projection of iterators by number */
372
373#if !defined(BOOST_NO_MEMBER_TEMPLATES)
374 template<int N>
375 struct nth_index_iterator
376 {
377 typedef typename nth_index<N>::type::iterator type;
378 };
379
380 template<int N>
381 struct nth_index_const_iterator
382 {
383 typedef typename nth_index<N>::type::const_iterator type;
384 };
385
386 template<int N,typename IteratorType>
387 typename nth_index_iterator<N>::type project(
388 IteratorType it
389 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
390 {
391 typedef typename nth_index<N>::type index;
392
393#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
394 BOOST_STATIC_ASSERT(
395 (mpl::contains<iterator_type_list,IteratorType>::value));
396#endif
397
398 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
399 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
400 it,static_cast<typename IteratorType::container_type&>(*this));
401
402 return index::make_iterator(static_cast<node_type*>(it.get_node()));
403 }
404
405 template<int N,typename IteratorType>
406 typename nth_index_const_iterator<N>::type project(
407 IteratorType it
408 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
409 {
410 typedef typename nth_index<N>::type index;
411
412#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
413 BOOST_STATIC_ASSERT((
414 mpl::contains<iterator_type_list,IteratorType>::value||
415 mpl::contains<const_iterator_type_list,IteratorType>::value));
416#endif
417
418 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
419 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
420 it,static_cast<const typename IteratorType::container_type&>(*this));
421 return index::make_iterator(static_cast<node_type*>(it.get_node()));
422 }
423#endif
424
425 /* projection of iterators by tag */
426
427#if !defined(BOOST_NO_MEMBER_TEMPLATES)
428 template<typename Tag>
429 struct index_iterator
430 {
431 typedef typename index<Tag>::type::iterator type;
432 };
433
434 template<typename Tag>
435 struct index_const_iterator
436 {
437 typedef typename index<Tag>::type::const_iterator type;
438 };
439
440 template<typename Tag,typename IteratorType>
441 typename index_iterator<Tag>::type project(
442 IteratorType it
443 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
444 {
445 typedef typename index<Tag>::type index;
446
447#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
448 BOOST_STATIC_ASSERT(
449 (mpl::contains<iterator_type_list,IteratorType>::value));
450#endif
451
452 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
453 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
454 it,static_cast<typename IteratorType::container_type&>(*this));
455 return index::make_iterator(static_cast<node_type*>(it.get_node()));
456 }
457
458 template<typename Tag,typename IteratorType>
459 typename index_const_iterator<Tag>::type project(
460 IteratorType it
461 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))const
462 {
463 typedef typename index<Tag>::type index;
464
465#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
466 BOOST_STATIC_ASSERT((
467 mpl::contains<iterator_type_list,IteratorType>::value||
468 mpl::contains<const_iterator_type_list,IteratorType>::value));
469#endif
470
471 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
472 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
473 it,static_cast<const typename IteratorType::container_type&>(*this));
474 return index::make_iterator(static_cast<node_type*>(it.get_node()));
475 }
476#endif
477
478BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
479 typedef typename super::copy_map_type copy_map_type;
480
481 node_type* header()const
482 {
483 return &*bfm_header::member;
484 }
485
486 node_type* allocate_node()
487 {
488 return &*bfm_allocator::member.allocate(1);
489 }
490
491 void deallocate_node(node_type* x)
492 {
493 typedef typename node_allocator::pointer node_pointer;
494 bfm_allocator::member.deallocate(static_cast<node_pointer>(x),1);
495 }
496
497 bool empty_()const
498 {
499 return node_count==0;
500 }
501
502 std::size_t size_()const
503 {
504 return node_count;
505 }
506
507 std::size_t max_size_()const
508 {
509 return static_cast<std::size_t >(-1);
510 }
511
512 std::pair<node_type*,bool> insert_(const Value& v)
513 {
514 node_type* x=allocate_node();
515 BOOST_TRY{
516 node_type* res=super::insert_(v,x);
517 if(res==x){
518 ++node_count;
519 return std::pair<node_type*,bool>(res,true);
520 }
521 else{
522 deallocate_node(x);
523 return std::pair<node_type*,bool>(res,false);
524 }
525 }
526 BOOST_CATCH(...){
527 deallocate_node(x);
528 BOOST_RETHROW;
529 }
530 BOOST_CATCH_END
531 }
532
533 std::pair<node_type*,bool> insert_(const Value& v,node_type* position)
534 {
535 node_type* x=allocate_node();
536 BOOST_TRY{
537 node_type* res=super::insert_(v,position,x);
538 if(res==x){
539 ++node_count;
540 return std::pair<node_type*,bool>(res,true);
541 }
542 else{
543 deallocate_node(x);
544 return std::pair<node_type*,bool>(res,false);
545 }
546 }
547 BOOST_CATCH(...){
548 deallocate_node(x);
549 BOOST_RETHROW;
550 }
551 BOOST_CATCH_END
552 }
553
554 void erase_(node_type* x)
555 {
556 --node_count;
557 super::erase_(x);
558 deallocate_node(x);
559 }
560
561 void delete_node_(node_type* x)
562 {
563 super::delete_node_(x);
564 deallocate_node(x);
565 }
566
567 void delete_all_nodes_()
568 {
569 super::delete_all_nodes_();
570 }
571
572 void clear_()
573 {
574 delete_all_nodes_();
575 super::clear_();
576 node_count=0;
577 }
578
579 void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
580 {
581 if(bfm_allocator::member!=x.bfm_allocator::member){
582 detail::adl_swap(bfm_allocator::member,x.bfm_allocator::member);
583 }
584 std::swap(bfm_header::member,x.bfm_header::member);
585 super::swap_(x);
586 std::swap(node_count,x.node_count);
587 }
588
589 bool replace_(const Value& k,node_type* x)
590 {
591 return super::replace_(k,x);
592 }
593
594 template<typename Modifier>
595 bool modify_(Modifier& mod,node_type* x)
596 {
597 mod(const_cast<value_type&>(x->value()));
598
599 BOOST_TRY{
600 if(!super::modify_(x)){
601 deallocate_node(x);
602 --node_count;
603 return false;
604 }
605 else return true;
606 }
607 BOOST_CATCH(...){
608 deallocate_node(x);
609 --node_count;
610 BOOST_RETHROW;
611 }
612 BOOST_CATCH_END
613 }
614
615 template<typename Modifier,typename Rollback>
616 bool modify_(Modifier& mod,Rollback& back,node_type* x)
617 {
618 mod(const_cast<value_type&>(x->value()));
619
620 bool b;
621 BOOST_TRY{
622 b=super::modify_rollback_(x);
623 }
624 BOOST_CATCH(...){
625 BOOST_TRY{
626 back(const_cast<value_type&>(x->value()));
627 BOOST_RETHROW;
628 }
629 BOOST_CATCH(...){
630 this->erase_(x);
631 BOOST_RETHROW;
632 }
633 BOOST_CATCH_END
634 }
635 BOOST_CATCH_END
636
637 BOOST_TRY{
638 if(!b){
639 back(const_cast<value_type&>(x->value()));
640 return false;
641 }
642 else return true;
643 }
644 BOOST_CATCH(...){
645 this->erase_(x);
646 BOOST_RETHROW;
647 }
648 BOOST_CATCH_END
649 }
650
651#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
652 /* serialization */
653
654 friend class boost::serialization::access;
655
656 BOOST_SERIALIZATION_SPLIT_MEMBER()
657
658 typedef typename super::index_saver_type index_saver_type;
659 typedef typename super::index_loader_type index_loader_type;
660
661 template<class Archive>
662 void save(Archive& ar,const unsigned int version)const
663 {
664
665#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
666 const serialization::collection_size_type s(size_());
667 const detail::serialization_version<value_type> value_version;
668 ar<<serialization::make_nvp("count",s);
669 ar<<serialization::make_nvp("value_version",value_version);
670#else
671 const std::size_t s=size_();
672 const unsigned int value_version=0;
673 ar<<serialization::make_nvp("count",s);
674#endif
675
676 index_saver_type sm(bfm_allocator::member,s);
677
678 for(iterator it=super::begin(),it_end=super::end();it!=it_end;++it){
679 serialization::save_construct_data_adl(ar,&*it,value_version);
680 ar<<serialization::make_nvp("item",*it);
681 sm.add(it.get_node(),ar,version);
682 }
683 sm.add_track(header(),ar,version);
684
685 super::save_(ar,version,sm);
686 }
687
688 template<class Archive>
689 void load(Archive& ar,const unsigned int version)
690 {
691 BOOST_MULTI_INDEX_CHECK_INVARIANT;
692
693 clear_();
694
695#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
696 serialization::collection_size_type s;
697 detail::serialization_version<value_type> value_version;
698 if(version<1){
699 std::size_t sz;
700 ar>>serialization::make_nvp("count",sz);
701 s=sz;
702 }
703 else{
704 ar>>serialization::make_nvp("count",s);
705 }
706 if(version<2){
707 value_version=0;
708 }
709 else{
710 ar>>serialization::make_nvp("value_version",value_version);
711 }
712#else
713 std::size_t s;
714 unsigned int value_version=0;
715 ar>>serialization::make_nvp("count",s);
716#endif
717
718 index_loader_type lm(bfm_allocator::member,s);
719
720 for(std::size_t n=0;n<s;++n){
721 detail::archive_constructed<Value> value("item",ar,value_version);
722 std::pair<node_type*,bool> p=insert_(
723 value.get(),super::end().get_node());
724 if(!p.second)throw_exception(
725 archive::archive_exception(
726 archive::archive_exception::other_exception));
727 ar.reset_object_address(&p.first->value(),&value.get());
728 lm.add(p.first,ar,version);
729 }
730 lm.add_track(header(),ar,version);
731
732 super::load_(ar,version,lm);
733 }
734#endif
735
736#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
737 /* invariant stuff */
738
739 bool invariant_()const
740 {
741 return super::invariant_();
742 }
743
744 void check_invariant_()const
745 {
746 BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
747 }
748#endif
749
750private:
751 std::size_t node_count;
752
753#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
754 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
755#pragma parse_mfunc_templ reset
756#endif
757};
758
759/* retrieval of indices by number */
760
761template<typename MultiIndexContainer,int N>
762struct nth_index
763{
764 BOOST_STATIC_CONSTANT(
765 int,
766 M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
767 BOOST_STATIC_ASSERT(N>=0&&N<M);
768 typedef typename mpl::at_c<
769 typename MultiIndexContainer::index_type_list,N>::type type;
770};
771
772template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
773typename nth_index<
774 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
775get(
776 multi_index_container<Value,IndexSpecifierList,Allocator>& m
777 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
778{
779 typedef multi_index_container<
780 Value,IndexSpecifierList,Allocator> multi_index_type;
781 typedef typename nth_index<
782 multi_index_container<
783 Value,IndexSpecifierList,Allocator>,
784 N
785 >::type index;
786
787 BOOST_STATIC_ASSERT(N>=0&&
788 N<
789 mpl::size<
790 BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
791 >::type::value);
792
793 return detail::converter<multi_index_type,index>::index(m);
794}
795
796template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
797const typename nth_index<
798 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
799get(
800 const multi_index_container<Value,IndexSpecifierList,Allocator>& m
801 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
802{
803 typedef multi_index_container<
804 Value,IndexSpecifierList,Allocator> multi_index_type;
805 typedef typename nth_index<
806 multi_index_container<
807 Value,IndexSpecifierList,Allocator>,
808 N
809 >::type index;
810
811 BOOST_STATIC_ASSERT(N>=0&&
812 N<
813 mpl::size<
814 BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
815 >::type::value);
816
817 return detail::converter<multi_index_type,index>::index(m);
818}
819
820/* retrieval of indices by tag */
821
822template<typename MultiIndexContainer,typename Tag>
823struct index
824{
825 typedef typename MultiIndexContainer::index_type_list index_type_list;
826
827 typedef typename mpl::find_if<
828 index_type_list,
829 detail::has_tag<Tag>
830 >::type iter;
831
832 BOOST_STATIC_CONSTANT(
833 bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
834 BOOST_STATIC_ASSERT(index_found);
835
836 typedef typename mpl::deref<iter>::type type;
837};
838
839template<
840 typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
841>
842typename ::boost::multi_index::index<
843 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
844get(
845 multi_index_container<Value,IndexSpecifierList,Allocator>& m
846 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
847{
848 typedef multi_index_container<
849 Value,IndexSpecifierList,Allocator> multi_index_type;
850 typedef typename ::boost::multi_index::index<
851 multi_index_container<
852 Value,IndexSpecifierList,Allocator>,
853 Tag
854 >::type index;
855
856 return detail::converter<multi_index_type,index>::index(m);
857}
858
859template<
860 typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
861>
862const typename ::boost::multi_index::index<
863 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
864get(
865 const multi_index_container<Value,IndexSpecifierList,Allocator>& m
866 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
867{
868 typedef multi_index_container<
869 Value,IndexSpecifierList,Allocator> multi_index_type;
870 typedef typename ::boost::multi_index::index<
871 multi_index_container<
872 Value,IndexSpecifierList,Allocator>,
873 Tag
874 >::type index;
875
876 return detail::converter<multi_index_type,index>::index(m);
877}
878
879/* projection of iterators by number */
880
881template<typename MultiIndexContainer,int N>
882struct nth_index_iterator
883{
884 typedef typename detail::prevent_eti<
885 nth_index<MultiIndexContainer,N>,
886 typename nth_index<MultiIndexContainer,N>::type>::type::iterator type;
887};
888
889template<typename MultiIndexContainer,int N>
890struct nth_index_const_iterator
891{
892 typedef typename detail::prevent_eti<
893 nth_index<MultiIndexContainer,N>,
894 typename nth_index<MultiIndexContainer,N>::type
895 >::type::const_iterator type;
896};
897
898template<
899 int N,typename IteratorType,
900 typename Value,typename IndexSpecifierList,typename Allocator>
901typename nth_index_iterator<
902 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
903project(
904 multi_index_container<Value,IndexSpecifierList,Allocator>& m,
905 IteratorType it
906 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
907{
908 typedef multi_index_container<
909 Value,IndexSpecifierList,Allocator> multi_index_type;
910 typedef typename nth_index<multi_index_type,N>::type index;
911
912#if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
913 (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
914 BOOST_STATIC_ASSERT((
915 mpl::contains<
916 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
917 IteratorType>::value));
918#endif
919
920 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
921
922#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
923 typedef detail::converter<
924 multi_index_type,
925 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
926 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
927#endif
928
929 return detail::converter<multi_index_type,index>::iterator(
930 m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
931}
932
933template<
934 int N,typename IteratorType,
935 typename Value,typename IndexSpecifierList,typename Allocator>
936typename nth_index_const_iterator<
937 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
938project(
939 const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
940 IteratorType it
941 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
942{
943 typedef multi_index_container<
944 Value,IndexSpecifierList,Allocator> multi_index_type;
945 typedef typename nth_index<multi_index_type,N>::type index;
946
947#if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
948 (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
949 BOOST_STATIC_ASSERT((
950 mpl::contains<
951 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
952 IteratorType>::value||
953 mpl::contains<
954 BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
955 IteratorType>::value));
956#endif
957
958 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
959
960#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
961 typedef detail::converter<
962 multi_index_type,
963 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
964 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
965#endif
966
967 return detail::converter<multi_index_type,index>::const_iterator(
968 m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
969}
970
971/* projection of iterators by tag */
972
973template<typename MultiIndexContainer,typename Tag>
974struct index_iterator
975{
976 typedef typename ::boost::multi_index::index<
977 MultiIndexContainer,Tag>::type::iterator type;
978};
979
980template<typename MultiIndexContainer,typename Tag>
981struct index_const_iterator
982{
983 typedef typename ::boost::multi_index::index<
984 MultiIndexContainer,Tag>::type::const_iterator type;
985};
986
987template<
988 typename Tag,typename IteratorType,
989 typename Value,typename IndexSpecifierList,typename Allocator>
990typename index_iterator<
991 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
992project(
993 multi_index_container<Value,IndexSpecifierList,Allocator>& m,
994 IteratorType it
995 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
996{
997 typedef multi_index_container<
998 Value,IndexSpecifierList,Allocator> multi_index_type;
999 typedef typename ::boost::multi_index::index<
1000 multi_index_type,Tag>::type index;
1001
1002#if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
1003 (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
1004 BOOST_STATIC_ASSERT((
1005 mpl::contains<
1006 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1007 IteratorType>::value));
1008#endif
1009
1010 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1011
1012#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1013 typedef detail::converter<
1014 multi_index_type,
1015 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1016 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1017#endif
1018
1019 return detail::converter<multi_index_type,index>::iterator(
1020 m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
1021}
1022
1023template<
1024 typename Tag,typename IteratorType,
1025 typename Value,typename IndexSpecifierList,typename Allocator>
1026typename index_const_iterator<
1027 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
1028project(
1029 const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1030 IteratorType it
1031 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
1032{
1033 typedef multi_index_container<
1034 Value,IndexSpecifierList,Allocator> multi_index_type;
1035 typedef typename ::boost::multi_index::index<
1036 multi_index_type,Tag>::type index;
1037
1038#if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
1039 (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
1040 BOOST_STATIC_ASSERT((
1041 mpl::contains<
1042 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1043 IteratorType>::value||
1044 mpl::contains<
1045 BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
1046 IteratorType>::value));
1047#endif
1048
1049 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1050
1051#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1052 typedef detail::converter<
1053 multi_index_type,
1054 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1055 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1056#endif
1057
1058 return detail::converter<multi_index_type,index>::const_iterator(
1059 m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
1060}
1061
1062/* Comparison. Simple forward to first index. */
1063
1064template<
1065 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1066 typename Value2,typename IndexSpecifierList2,typename Allocator2
1067>
1068bool operator==(
1069 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1070 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1071{
1072 return get<0>(x)==get<0>(y);
1073}
1074
1075template<
1076 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1077 typename Value2,typename IndexSpecifierList2,typename Allocator2
1078>
1079bool operator<(
1080 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1081 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1082{
1083 return get<0>(x)<get<0>(y);
1084}
1085
1086template<
1087 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1088 typename Value2,typename IndexSpecifierList2,typename Allocator2
1089>
1090bool operator!=(
1091 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1092 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1093{
1094 return get<0>(x)!=get<0>(y);
1095}
1096
1097template<
1098 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1099 typename Value2,typename IndexSpecifierList2,typename Allocator2
1100>
1101bool operator>(
1102 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1103 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1104{
1105 return get<0>(x)>get<0>(y);
1106}
1107
1108template<
1109 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1110 typename Value2,typename IndexSpecifierList2,typename Allocator2
1111>
1112bool operator>=(
1113 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1114 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1115{
1116 return get<0>(x)>=get<0>(y);
1117}
1118
1119template<
1120 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1121 typename Value2,typename IndexSpecifierList2,typename Allocator2
1122>
1123bool operator<=(
1124 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1125 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1126{
1127 return get<0>(x)<=get<0>(y);
1128}
1129
1130/* specialized algorithms */
1131
1132template<typename Value,typename IndexSpecifierList,typename Allocator>
1133void swap(
1134 multi_index_container<Value,IndexSpecifierList,Allocator>& x,
1135 multi_index_container<Value,IndexSpecifierList,Allocator>& y)
1136{
1137 x.swap(y);
1138}
1139
1140} /* namespace multi_index */
1141
1142#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)&&\
1143 !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
1144/* class version = 1 : we now serialize the size through
1145 * boost::serialization::collection_size_type.
1146 * class version = 2 : proper use of {save|load}_construct_data.
1147 */
1148
1149namespace serialization {
1150template<typename Value,typename IndexSpecifierList,typename Allocator>
1151struct version<
1152 boost::multi_index_container<Value,IndexSpecifierList,Allocator>
1153>
1154{
1155 BOOST_STATIC_CONSTANT(int,value=2);
1156};
1157} /* namespace serialization */
1158#endif
1159
1160/* Associated global functions are promoted to namespace boost, except
1161 * comparison operators and swap, which are meant to be Koenig looked-up.
1162 */
1163
1164using multi_index::get;
1165using multi_index::project;
1166
1167} /* namespace boost */
1168
1169#undef BOOST_MULTI_INDEX_CHECK_INVARIANT
1170
1171#endif