1 /* Multiply indexed container.
2 *
3 * Copyright 2003-2018 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)
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 <memory>
21 #include <boost/core/addressof.hpp>
22 #include <boost/detail/allocator_utilities.hpp>
23 #include <boost/detail/no_exceptions_support.hpp>
24 #include <boost/detail/workaround.hpp>
25 #include <boost/move/core.hpp>
26 #include <boost/mpl/at.hpp>
27 #include <boost/mpl/contains.hpp>
28 #include <boost/mpl/find_if.hpp>
29 #include <boost/mpl/identity.hpp>
30 #include <boost/mpl/int.hpp>
31 #include <boost/mpl/size.hpp>
32 #include <boost/mpl/deref.hpp>
33 #include <boost/multi_index_container_fwd.hpp>
34 #include <boost/multi_index/detail/access_specifier.hpp>
35 #include <boost/multi_index/detail/adl_swap.hpp>
36 #include <boost/multi_index/detail/base_type.hpp>
37 #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp>
38 #include <boost/multi_index/detail/converter.hpp>
39 #include <boost/multi_index/detail/header_holder.hpp>
40 #include <boost/multi_index/detail/has_tag.hpp>
41 #include <boost/multi_index/detail/no_duplicate_tags.hpp>
42 #include <boost/multi_index/detail/safe_mode.hpp>
43 #include <boost/multi_index/detail/scope_guard.hpp>
44 #include <boost/multi_index/detail/vartempl_support.hpp>
45 #include <boost/static_assert.hpp>
46 #include <boost/type_traits/is_same.hpp>
47 #include <boost/utility/base_from_member.hpp>
48
49 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
50 #include <initializer_list>
51 #endif
52
53 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
54 #include <boost/multi_index/detail/archive_constructed.hpp>
55 #include <boost/multi_index/detail/serialization_version.hpp>
56 #include <boost/serialization/collection_size_type.hpp>
57 #include <boost/serialization/nvp.hpp>
58 #include <boost/serialization/split_member.hpp>
59 #include <boost/serialization/version.hpp>
60 #include <boost/throw_exception.hpp>
61 #endif
62
63 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
64 #include <boost/multi_index/detail/invariant_assert.hpp>
65 #define BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x) \
66 detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
67 detail::make_obj_guard(x,&multi_index_container::check_invariant_); \
68 BOOST_JOIN(check_invariant_,__LINE__).touch();
69 #define BOOST_MULTI_INDEX_CHECK_INVARIANT \
70 BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(*this)
71 #else
72 #define BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x)
73 #define BOOST_MULTI_INDEX_CHECK_INVARIANT
74 #endif
75
76 namespace boost{
77
78 namespace multi_index{
79
80 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
81 #pragma warning(push)
82 #pragma warning(disable:4522) /* spurious warning on multiple operator=()'s */
83 #endif
84
85 template<typename Value,typename IndexSpecifierList,typename Allocator>
86 class multi_index_container:
87 private ::boost::base_from_member<
88 typename boost::detail::allocator::rebind_to<
89 Allocator,
90 typename detail::multi_index_node_type<
91 Value,IndexSpecifierList,Allocator>::type
92 >::type>,
93 BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
94 #ifndef BOOST_NO_CXX11_ALLOCATOR
95 typename std::allocator_traits<
96 #endif
97 typename boost::detail::allocator::rebind_to<
98 Allocator,
99 typename detail::multi_index_node_type<
100 Value,IndexSpecifierList,Allocator>::type
101 >::type
102 #ifdef BOOST_NO_CXX11_ALLOCATOR
103 ::pointer,
104 #else
105 >::pointer,
106 #endif
107 multi_index_container<Value,IndexSpecifierList,Allocator> >,
108 public detail::multi_index_base_type<
109 Value,IndexSpecifierList,Allocator>::type
110 {
111 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
112 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
113 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
114 * lifetime of const references bound to temporaries --precisely what
115 * scopeguards are.
116 */
117
118 #pragma parse_mfunc_templ off
119 #endif
120
121 private:
122 BOOST_COPYABLE_AND_MOVABLE(multi_index_container)
123
124 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
125 template <typename,typename,typename> friend class detail::index_base;
126 template <typename,typename> friend struct detail::header_holder;
127 template <typename,typename> friend struct detail::converter;
128 #endif
129
130 typedef typename detail::multi_index_base_type<
131 Value,IndexSpecifierList,Allocator>::type super;
132 typedef typename
133 boost::detail::allocator::rebind_to<
134 Allocator,
135 typename super::node_type
136 >::type node_allocator;
137 #ifdef BOOST_NO_CXX11_ALLOCATOR
138 typedef typename node_allocator::pointer node_pointer;
139 #else
140 typedef std::allocator_traits<node_allocator> node_allocator_traits;
141 typedef typename node_allocator_traits::pointer node_pointer;
142 #endif
143 typedef ::boost::base_from_member<
144 node_allocator> bfm_allocator;
145 typedef detail::header_holder<
146 node_pointer,
147 multi_index_container> bfm_header;
148
149 public:
150 /* All types are inherited from super, a few are explicitly
151 * brought forward here to save us some typename's.
152 */
153
154 typedef typename super::ctor_args_list ctor_args_list;
155 typedef IndexSpecifierList index_specifier_type_list;
156
157 typedef typename super::index_type_list index_type_list;
158
159 typedef typename super::iterator_type_list iterator_type_list;
160 typedef typename super::const_iterator_type_list const_iterator_type_list;
161 typedef typename super::value_type value_type;
162 typedef typename super::final_allocator_type allocator_type;
163 typedef typename super::iterator iterator;
164 typedef typename super::const_iterator const_iterator;
165
166 BOOST_STATIC_ASSERT(
167 detail::no_duplicate_tags_in_index_list<index_type_list>::value);
168
169 /* global project() needs to see this publicly */
170
171 typedef typename super::node_type node_type;
172
173 /* construct/copy/destroy */
174
multi_index_container()175 multi_index_container():
176 bfm_allocator(allocator_type()),
177 super(ctor_args_list(),bfm_allocator::member),
178 node_count(0)
179 {
180 BOOST_MULTI_INDEX_CHECK_INVARIANT;
181 }
182
multi_index_container(const ctor_args_list & args_list,const allocator_type & al=typename mpl::identity<multi_index_container>::type::allocator_type ())183 explicit multi_index_container(
184 const ctor_args_list& args_list,
185
186 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
187 /* VisualAge seems to have an ETI issue with the default value for
188 * argument al.
189 */
190
191 const allocator_type& al=
192 typename mpl::identity<multi_index_container>::type::
193 allocator_type()):
194 #else
195 const allocator_type& al=allocator_type()):
196 #endif
197
198 bfm_allocator(al),
199 super(args_list,bfm_allocator::member),
200 node_count(0)
201 {
202 BOOST_MULTI_INDEX_CHECK_INVARIANT;
203 }
204
multi_index_container(const allocator_type & al)205 explicit multi_index_container(const allocator_type& al):
206 bfm_allocator(al),
207 super(ctor_args_list(),bfm_allocator::member),
208 node_count(0)
209 {
210 BOOST_MULTI_INDEX_CHECK_INVARIANT;
211 }
212
213 template<typename InputIterator>
multi_index_container(InputIterator first,InputIterator last,const ctor_args_list & args_list=typename mpl::identity<multi_index_container>::type::ctor_args_list (),const allocator_type & al=typename mpl::identity<multi_index_container>::type::allocator_type ())214 multi_index_container(
215 InputIterator first,InputIterator last,
216
217 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
218 /* VisualAge seems to have an ETI issue with the default values
219 * for arguments args_list and al.
220 */
221
222 const ctor_args_list& args_list=
223 typename mpl::identity<multi_index_container>::type::
224 ctor_args_list(),
225 const allocator_type& al=
226 typename mpl::identity<multi_index_container>::type::
227 allocator_type()):
228 #else
229 const ctor_args_list& args_list=ctor_args_list(),
230 const allocator_type& al=allocator_type()):
231 #endif
232
233 bfm_allocator(al),
234 super(args_list,bfm_allocator::member),
235 node_count(0)
236 {
237 BOOST_MULTI_INDEX_CHECK_INVARIANT;
238 BOOST_TRY{
239 iterator hint=super::end();
240 for(;first!=last;++first){
241 hint=super::make_iterator(
242 insert_ref_(*first,hint.get_node()).first);
243 ++hint;
244 }
245 }
246 BOOST_CATCH(...){
247 clear_();
248 BOOST_RETHROW;
249 }
250 BOOST_CATCH_END
251 }
252
253 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
multi_index_container(std::initializer_list<Value> list,const ctor_args_list & args_list=ctor_args_list (),const allocator_type & al=allocator_type ())254 multi_index_container(
255 std::initializer_list<Value> list,
256 const ctor_args_list& args_list=ctor_args_list(),
257 const allocator_type& al=allocator_type()):
258 bfm_allocator(al),
259 super(args_list,bfm_allocator::member),
260 node_count(0)
261 {
262 BOOST_MULTI_INDEX_CHECK_INVARIANT;
263 BOOST_TRY{
264 typedef const Value* init_iterator;
265
266 iterator hint=super::end();
267 for(init_iterator first=list.begin(),last=list.end();
268 first!=last;++first){
269 hint=super::make_iterator(insert_(*first,hint.get_node()).first);
270 ++hint;
271 }
272 }
273 BOOST_CATCH(...){
274 clear_();
275 BOOST_RETHROW;
276 }
277 BOOST_CATCH_END
278 }
279 #endif
280
multi_index_container(const multi_index_container<Value,IndexSpecifierList,Allocator> & x)281 multi_index_container(
282 const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
283 bfm_allocator(x.bfm_allocator::member),
284 bfm_header(),
285 super(x),
286 node_count(0)
287 {
288 copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
289 for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
290 map.clone(it.get_node());
291 }
292 super::copy_(x,map);
293 map.release();
294 node_count=x.size();
295
296 /* Not until this point are the indices required to be consistent,
297 * hence the position of the invariant checker.
298 */
299
300 BOOST_MULTI_INDEX_CHECK_INVARIANT;
301 }
302
multi_index_container(BOOST_RV_REF (multi_index_container)x)303 multi_index_container(BOOST_RV_REF(multi_index_container) x):
304 bfm_allocator(x.bfm_allocator::member),
305 bfm_header(),
306 super(x,detail::do_not_copy_elements_tag()),
307 node_count(0)
308 {
309 BOOST_MULTI_INDEX_CHECK_INVARIANT;
310 BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
311 swap_elements_(x);
312 }
313
~multi_index_container()314 ~multi_index_container()
315 {
316 delete_all_nodes_();
317 }
318
319 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
320 /* As per http://www.boost.org/doc/html/move/emulation_limitations.html
321 * #move.emulation_limitations.assignment_operator
322 */
323
operator =(const multi_index_container<Value,IndexSpecifierList,Allocator> & x)324 multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
325 const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
326 {
327 multi_index_container y(x);
328 this->swap(y);
329 return *this;
330 }
331 #endif
332
operator =(BOOST_COPY_ASSIGN_REF (multi_index_container)x)333 multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
334 BOOST_COPY_ASSIGN_REF(multi_index_container) x)
335 {
336 multi_index_container y(x);
337 this->swap(y);
338 return *this;
339 }
340
operator =(BOOST_RV_REF (multi_index_container)x)341 multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
342 BOOST_RV_REF(multi_index_container) x)
343 {
344 this->swap(x);
345 return *this;
346 }
347
348 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
operator =(std::initializer_list<Value> list)349 multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
350 std::initializer_list<Value> list)
351 {
352 BOOST_MULTI_INDEX_CHECK_INVARIANT;
353 typedef const Value* init_iterator;
354
355 multi_index_container x(*this,detail::do_not_copy_elements_tag());
356 iterator hint=x.end();
357 for(init_iterator first=list.begin(),last=list.end();
358 first!=last;++first){
359 hint=x.make_iterator(x.insert_(*first,hint.get_node()).first);
360 ++hint;
361 }
362 x.swap_elements_(*this);
363 return*this;
364 }
365 #endif
366
get_allocator() const367 allocator_type get_allocator()const BOOST_NOEXCEPT
368 {
369 return allocator_type(bfm_allocator::member);
370 }
371
372 /* retrieval of indices by number */
373
374 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
375 template<int N>
376 struct nth_index
377 {
378 BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
379 typedef typename mpl::at_c<index_type_list,N>::type type;
380 };
381
382 template<int N>
get()383 typename nth_index<N>::type& get()BOOST_NOEXCEPT
384 {
385 BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
386 return *this;
387 }
388
389 template<int N>
get() const390 const typename nth_index<N>::type& get()const BOOST_NOEXCEPT
391 {
392 BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
393 return *this;
394 }
395 #endif
396
397 /* retrieval of indices by tag */
398
399 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
400 template<typename Tag>
401 struct index
402 {
403 typedef typename mpl::find_if<
404 index_type_list,
405 detail::has_tag<Tag>
406 >::type iter;
407
408 BOOST_STATIC_CONSTANT(
409 bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
410 BOOST_STATIC_ASSERT(index_found);
411
412 typedef typename mpl::deref<iter>::type type;
413 };
414
415 template<typename Tag>
get()416 typename index<Tag>::type& get()BOOST_NOEXCEPT
417 {
418 return *this;
419 }
420
421 template<typename Tag>
get() const422 const typename index<Tag>::type& get()const BOOST_NOEXCEPT
423 {
424 return *this;
425 }
426 #endif
427
428 /* projection of iterators by number */
429
430 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
431 template<int N>
432 struct nth_index_iterator
433 {
434 typedef typename nth_index<N>::type::iterator type;
435 };
436
437 template<int N>
438 struct nth_index_const_iterator
439 {
440 typedef typename nth_index<N>::type::const_iterator type;
441 };
442
443 template<int N,typename IteratorType>
project(IteratorType it)444 typename nth_index_iterator<N>::type project(IteratorType it)
445 {
446 typedef typename nth_index<N>::type index_type;
447
448 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
449 BOOST_STATIC_ASSERT(
450 (mpl::contains<iterator_type_list,IteratorType>::value));
451 #endif
452
453 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
454 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
455 it,static_cast<typename IteratorType::container_type&>(*this));
456
457 return index_type::make_iterator(static_cast<node_type*>(it.get_node()));
458 }
459
460 template<int N,typename IteratorType>
project(IteratorType it) const461 typename nth_index_const_iterator<N>::type project(IteratorType it)const
462 {
463 typedef typename nth_index<N>::type index_type;
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_type::make_iterator(static_cast<node_type*>(it.get_node()));
475 }
476 #endif
477
478 /* projection of iterators by tag */
479
480 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
481 template<typename Tag>
482 struct index_iterator
483 {
484 typedef typename index<Tag>::type::iterator type;
485 };
486
487 template<typename Tag>
488 struct index_const_iterator
489 {
490 typedef typename index<Tag>::type::const_iterator type;
491 };
492
493 template<typename Tag,typename IteratorType>
project(IteratorType it)494 typename index_iterator<Tag>::type project(IteratorType it)
495 {
496 typedef typename index<Tag>::type index_type;
497
498 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
499 BOOST_STATIC_ASSERT(
500 (mpl::contains<iterator_type_list,IteratorType>::value));
501 #endif
502
503 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
504 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
505 it,static_cast<typename IteratorType::container_type&>(*this));
506 return index_type::make_iterator(static_cast<node_type*>(it.get_node()));
507 }
508
509 template<typename Tag,typename IteratorType>
project(IteratorType it) const510 typename index_const_iterator<Tag>::type project(IteratorType it)const
511 {
512 typedef typename index<Tag>::type index_type;
513
514 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
515 BOOST_STATIC_ASSERT((
516 mpl::contains<iterator_type_list,IteratorType>::value||
517 mpl::contains<const_iterator_type_list,IteratorType>::value));
518 #endif
519
520 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
521 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
522 it,static_cast<const typename IteratorType::container_type&>(*this));
523 return index_type::make_iterator(static_cast<node_type*>(it.get_node()));
524 }
525 #endif
526
527 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
528 typedef typename super::copy_map_type copy_map_type;
529
530 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
multi_index_container(const multi_index_container<Value,IndexSpecifierList,Allocator> & x,detail::do_not_copy_elements_tag)531 multi_index_container(
532 const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
533 detail::do_not_copy_elements_tag):
534 bfm_allocator(x.bfm_allocator::member),
535 bfm_header(),
536 super(x,detail::do_not_copy_elements_tag()),
537 node_count(0)
538 {
539 BOOST_MULTI_INDEX_CHECK_INVARIANT;
540 }
541 #endif
542
header() const543 node_type* header()const
544 {
545 return &*bfm_header::member;
546 }
547
allocate_node()548 node_type* allocate_node()
549 {
550 #ifdef BOOST_NO_CXX11_ALLOCATOR
551 return &*bfm_allocator::member.allocate(1);
552 #else
553 return &*node_allocator_traits::allocate(bfm_allocator::member,1);
554 #endif
555 }
556
deallocate_node(node_type * x)557 void deallocate_node(node_type* x)
558 {
559 #ifdef BOOST_NO_CXX11_ALLOCATOR
560 bfm_allocator::member.deallocate(static_cast<node_pointer>(x),1);
561 #else
562 node_allocator_traits::deallocate(bfm_allocator::member,static_cast<node_pointer>(x),1);
563 #endif
564 }
565
empty_() const566 bool empty_()const
567 {
568 return node_count==0;
569 }
570
size_() const571 std::size_t size_()const
572 {
573 return node_count;
574 }
575
max_size_() const576 std::size_t max_size_()const
577 {
578 return static_cast<std::size_t >(-1);
579 }
580
581 template<typename Variant>
insert_(const Value & v,Variant variant)582 std::pair<node_type*,bool> insert_(const Value& v,Variant variant)
583 {
584 node_type* x=0;
585 node_type* res=super::insert_(v,x,variant);
586 if(res==x){
587 ++node_count;
588 return std::pair<node_type*,bool>(res,true);
589 }
590 else{
591 return std::pair<node_type*,bool>(res,false);
592 }
593 }
594
insert_(const Value & v)595 std::pair<node_type*,bool> insert_(const Value& v)
596 {
597 return insert_(v,detail::lvalue_tag());
598 }
599
insert_rv_(const Value & v)600 std::pair<node_type*,bool> insert_rv_(const Value& v)
601 {
602 return insert_(v,detail::rvalue_tag());
603 }
604
605 template<typename T>
insert_ref_(T & t)606 std::pair<node_type*,bool> insert_ref_(T& t)
607 {
608 node_type* x=allocate_node();
609 BOOST_TRY{
610 new(boost::addressof(x->value())) value_type(t);
611 BOOST_TRY{
612 node_type* res=super::insert_(x->value(),x,detail::emplaced_tag());
613 if(res==x){
614 ++node_count;
615 return std::pair<node_type*,bool>(res,true);
616 }
617 else{
618 boost::detail::allocator::destroy(boost::addressof(x->value()));
619 deallocate_node(x);
620 return std::pair<node_type*,bool>(res,false);
621 }
622 }
623 BOOST_CATCH(...){
624 boost::detail::allocator::destroy(boost::addressof(x->value()));
625 BOOST_RETHROW;
626 }
627 BOOST_CATCH_END
628 }
629 BOOST_CATCH(...){
630 deallocate_node(x);
631 BOOST_RETHROW;
632 }
633 BOOST_CATCH_END
634 }
635
insert_ref_(const value_type & x)636 std::pair<node_type*,bool> insert_ref_(const value_type& x)
637 {
638 return insert_(x);
639 }
640
insert_ref_(value_type & x)641 std::pair<node_type*,bool> insert_ref_(value_type& x)
642 {
643 return insert_(x);
644 }
645
646 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
emplace_(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)647 std::pair<node_type*,bool> emplace_(
648 BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
649 {
650 node_type* x=allocate_node();
651 BOOST_TRY{
652 detail::vartempl_placement_new(
653 boost::addressof(x->value()),BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
654 BOOST_TRY{
655 node_type* res=super::insert_(x->value(),x,detail::emplaced_tag());
656 if(res==x){
657 ++node_count;
658 return std::pair<node_type*,bool>(res,true);
659 }
660 else{
661 boost::detail::allocator::destroy(boost::addressof(x->value()));
662 deallocate_node(x);
663 return std::pair<node_type*,bool>(res,false);
664 }
665 }
666 BOOST_CATCH(...){
667 boost::detail::allocator::destroy(boost::addressof(x->value()));
668 BOOST_RETHROW;
669 }
670 BOOST_CATCH_END
671 }
672 BOOST_CATCH(...){
673 deallocate_node(x);
674 BOOST_RETHROW;
675 }
676 BOOST_CATCH_END
677 }
678
679 template<typename Variant>
insert_(const Value & v,node_type * position,Variant variant)680 std::pair<node_type*,bool> insert_(
681 const Value& v,node_type* position,Variant variant)
682 {
683 node_type* x=0;
684 node_type* res=super::insert_(v,position,x,variant);
685 if(res==x){
686 ++node_count;
687 return std::pair<node_type*,bool>(res,true);
688 }
689 else{
690 return std::pair<node_type*,bool>(res,false);
691 }
692 }
693
insert_(const Value & v,node_type * position)694 std::pair<node_type*,bool> insert_(const Value& v,node_type* position)
695 {
696 return insert_(v,position,detail::lvalue_tag());
697 }
698
insert_rv_(const Value & v,node_type * position)699 std::pair<node_type*,bool> insert_rv_(const Value& v,node_type* position)
700 {
701 return insert_(v,position,detail::rvalue_tag());
702 }
703
704 template<typename T>
insert_ref_(T & t,node_type * position)705 std::pair<node_type*,bool> insert_ref_(
706 T& t,node_type* position)
707 {
708 node_type* x=allocate_node();
709 BOOST_TRY{
710 new(boost::addressof(x->value())) value_type(t);
711 BOOST_TRY{
712 node_type* res=super::insert_(
713 x->value(),position,x,detail::emplaced_tag());
714 if(res==x){
715 ++node_count;
716 return std::pair<node_type*,bool>(res,true);
717 }
718 else{
719 boost::detail::allocator::destroy(boost::addressof(x->value()));
720 deallocate_node(x);
721 return std::pair<node_type*,bool>(res,false);
722 }
723 }
724 BOOST_CATCH(...){
725 boost::detail::allocator::destroy(boost::addressof(x->value()));
726 BOOST_RETHROW;
727 }
728 BOOST_CATCH_END
729 }
730 BOOST_CATCH(...){
731 deallocate_node(x);
732 BOOST_RETHROW;
733 }
734 BOOST_CATCH_END
735 }
736
insert_ref_(const value_type & x,node_type * position)737 std::pair<node_type*,bool> insert_ref_(
738 const value_type& x,node_type* position)
739 {
740 return insert_(x,position);
741 }
742
insert_ref_(value_type & x,node_type * position)743 std::pair<node_type*,bool> insert_ref_(
744 value_type& x,node_type* position)
745 {
746 return insert_(x,position);
747 }
748
749 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
emplace_hint_(node_type * position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)750 std::pair<node_type*,bool> emplace_hint_(
751 node_type* position,
752 BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
753 {
754 node_type* x=allocate_node();
755 BOOST_TRY{
756 detail::vartempl_placement_new(
757 boost::addressof(x->value()),BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
758 BOOST_TRY{
759 node_type* res=super::insert_(
760 x->value(),position,x,detail::emplaced_tag());
761 if(res==x){
762 ++node_count;
763 return std::pair<node_type*,bool>(res,true);
764 }
765 else{
766 boost::detail::allocator::destroy(boost::addressof(x->value()));
767 deallocate_node(x);
768 return std::pair<node_type*,bool>(res,false);
769 }
770 }
771 BOOST_CATCH(...){
772 boost::detail::allocator::destroy(boost::addressof(x->value()));
773 BOOST_RETHROW;
774 }
775 BOOST_CATCH_END
776 }
777 BOOST_CATCH(...){
778 deallocate_node(x);
779 BOOST_RETHROW;
780 }
781 BOOST_CATCH_END
782 }
783
erase_(node_type * x)784 void erase_(node_type* x)
785 {
786 --node_count;
787 super::erase_(x);
788 deallocate_node(x);
789 }
790
delete_node_(node_type * x)791 void delete_node_(node_type* x)
792 {
793 super::delete_node_(x);
794 deallocate_node(x);
795 }
796
delete_all_nodes_()797 void delete_all_nodes_()
798 {
799 super::delete_all_nodes_();
800 }
801
clear_()802 void clear_()
803 {
804 delete_all_nodes_();
805 super::clear_();
806 node_count=0;
807 }
808
swap_(multi_index_container<Value,IndexSpecifierList,Allocator> & x)809 void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
810 {
811 if(bfm_allocator::member!=x.bfm_allocator::member){
812 detail::adl_swap(bfm_allocator::member,x.bfm_allocator::member);
813 }
814 std::swap(bfm_header::member,x.bfm_header::member);
815 super::swap_(x);
816 std::swap(node_count,x.node_count);
817 }
818
swap_elements_(multi_index_container<Value,IndexSpecifierList,Allocator> & x)819 void swap_elements_(
820 multi_index_container<Value,IndexSpecifierList,Allocator>& x)
821 {
822 std::swap(bfm_header::member,x.bfm_header::member);
823 super::swap_elements_(x);
824 std::swap(node_count,x.node_count);
825 }
826
replace_(const Value & k,node_type * x)827 bool replace_(const Value& k,node_type* x)
828 {
829 return super::replace_(k,x,detail::lvalue_tag());
830 }
831
replace_rv_(const Value & k,node_type * x)832 bool replace_rv_(const Value& k,node_type* x)
833 {
834 return super::replace_(k,x,detail::rvalue_tag());
835 }
836
837 template<typename Modifier>
modify_(Modifier & mod,node_type * x)838 bool modify_(Modifier& mod,node_type* x)
839 {
840 BOOST_TRY{
841 mod(const_cast<value_type&>(x->value()));
842 }
843 BOOST_CATCH(...){
844 this->erase_(x);
845 BOOST_RETHROW;
846 }
847 BOOST_CATCH_END
848
849 BOOST_TRY{
850 if(!super::modify_(x)){
851 deallocate_node(x);
852 --node_count;
853 return false;
854 }
855 else return true;
856 }
857 BOOST_CATCH(...){
858 deallocate_node(x);
859 --node_count;
860 BOOST_RETHROW;
861 }
862 BOOST_CATCH_END
863 }
864
865 template<typename Modifier,typename Rollback>
modify_(Modifier & mod,Rollback & back_,node_type * x)866 bool modify_(Modifier& mod,Rollback& back_,node_type* x)
867 {
868 BOOST_TRY{
869 mod(const_cast<value_type&>(x->value()));
870 }
871 BOOST_CATCH(...){
872 this->erase_(x);
873 BOOST_RETHROW;
874 }
875 BOOST_CATCH_END
876
877 bool b;
878 BOOST_TRY{
879 b=super::modify_rollback_(x);
880 }
881 BOOST_CATCH(...){
882 BOOST_TRY{
883 back_(const_cast<value_type&>(x->value()));
884 if(!super::check_rollback_(x))this->erase_(x);
885 BOOST_RETHROW;
886 }
887 BOOST_CATCH(...){
888 this->erase_(x);
889 BOOST_RETHROW;
890 }
891 BOOST_CATCH_END
892 }
893 BOOST_CATCH_END
894
895 BOOST_TRY{
896 if(!b){
897 back_(const_cast<value_type&>(x->value()));
898 if(!super::check_rollback_(x))this->erase_(x);
899 return false;
900 }
901 else return true;
902 }
903 BOOST_CATCH(...){
904 this->erase_(x);
905 BOOST_RETHROW;
906 }
907 BOOST_CATCH_END
908 }
909
910 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
911 /* serialization */
912
913 friend class boost::serialization::access;
914
915 BOOST_SERIALIZATION_SPLIT_MEMBER()
916
917 typedef typename super::index_saver_type index_saver_type;
918 typedef typename super::index_loader_type index_loader_type;
919
920 template<class Archive>
save(Archive & ar,const unsigned int version) const921 void save(Archive& ar,const unsigned int version)const
922 {
923 const serialization::collection_size_type s(size_());
924 const detail::serialization_version<value_type> value_version;
925 ar<<serialization::make_nvp("count",s);
926 ar<<serialization::make_nvp("value_version",value_version);
927
928 index_saver_type sm(bfm_allocator::member,s);
929
930 for(iterator it=super::begin(),it_end=super::end();it!=it_end;++it){
931 serialization::save_construct_data_adl(
932 ar,boost::addressof(*it),value_version);
933 ar<<serialization::make_nvp("item",*it);
934 sm.add(it.get_node(),ar,version);
935 }
936 sm.add_track(header(),ar,version);
937
938 super::save_(ar,version,sm);
939 }
940
941 template<class Archive>
load(Archive & ar,const unsigned int version)942 void load(Archive& ar,const unsigned int version)
943 {
944 BOOST_MULTI_INDEX_CHECK_INVARIANT;
945
946 clear_();
947 serialization::collection_size_type s;
948 detail::serialization_version<value_type> value_version;
949 if(version<1){
950 std::size_t sz;
951 ar>>serialization::make_nvp("count",sz);
952 s=static_cast<serialization::collection_size_type>(sz);
953 }
954 else{
955 ar>>serialization::make_nvp("count",s);
956 }
957 if(version<2){
958 value_version=0;
959 }
960 else{
961 ar>>serialization::make_nvp("value_version",value_version);
962 }
963
964 index_loader_type lm(bfm_allocator::member,s);
965
966 for(std::size_t n=0;n<s;++n){
967 detail::archive_constructed<Value> value("item",ar,value_version);
968 std::pair<node_type*,bool> p=insert_rv_(
969 value.get(),super::end().get_node());
970 if(!p.second)throw_exception(
971 archive::archive_exception(
972 archive::archive_exception::other_exception));
973 ar.reset_object_address(
974 boost::addressof(p.first->value()),boost::addressof(value.get()));
975 lm.add(p.first,ar,version);
976 }
977 lm.add_track(header(),ar,version);
978
979 super::load_(ar,version,lm);
980 }
981 #endif
982
983 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
984 /* invariant stuff */
985
invariant_() const986 bool invariant_()const
987 {
988 return super::invariant_();
989 }
990
check_invariant_() const991 void check_invariant_()const
992 {
993 BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
994 }
995 #endif
996
997 private:
998 std::size_t node_count;
999
1000 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
1001 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
1002 #pragma parse_mfunc_templ reset
1003 #endif
1004 };
1005
1006 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
1007 #pragma warning(pop) /* C4522 */
1008 #endif
1009
1010 /* retrieval of indices by number */
1011
1012 template<typename MultiIndexContainer,int N>
1013 struct nth_index
1014 {
1015 BOOST_STATIC_CONSTANT(
1016 int,
1017 M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
1018 BOOST_STATIC_ASSERT(N>=0&&N<M);
1019 typedef typename mpl::at_c<
1020 typename MultiIndexContainer::index_type_list,N>::type type;
1021 };
1022
1023 template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
1024 typename nth_index<
1025 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
get(multi_index_container<Value,IndexSpecifierList,Allocator> & m)1026 get(
1027 multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
1028 {
1029 typedef multi_index_container<
1030 Value,IndexSpecifierList,Allocator> multi_index_type;
1031 typedef typename nth_index<
1032 multi_index_container<
1033 Value,IndexSpecifierList,Allocator>,
1034 N
1035 >::type index_type;
1036
1037 BOOST_STATIC_ASSERT(N>=0&&
1038 N<
1039 mpl::size<
1040 BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
1041 >::type::value);
1042
1043 return detail::converter<multi_index_type,index_type>::index(m);
1044 }
1045
1046 template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
1047 const typename nth_index<
1048 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
get(const multi_index_container<Value,IndexSpecifierList,Allocator> & m)1049 get(
1050 const multi_index_container<Value,IndexSpecifierList,Allocator>& m
1051 )BOOST_NOEXCEPT
1052 {
1053 typedef multi_index_container<
1054 Value,IndexSpecifierList,Allocator> multi_index_type;
1055 typedef typename nth_index<
1056 multi_index_container<
1057 Value,IndexSpecifierList,Allocator>,
1058 N
1059 >::type index_type;
1060
1061 BOOST_STATIC_ASSERT(N>=0&&
1062 N<
1063 mpl::size<
1064 BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
1065 >::type::value);
1066
1067 return detail::converter<multi_index_type,index_type>::index(m);
1068 }
1069
1070 /* retrieval of indices by tag */
1071
1072 template<typename MultiIndexContainer,typename Tag>
1073 struct index
1074 {
1075 typedef typename MultiIndexContainer::index_type_list index_type_list;
1076
1077 typedef typename mpl::find_if<
1078 index_type_list,
1079 detail::has_tag<Tag>
1080 >::type iter;
1081
1082 BOOST_STATIC_CONSTANT(
1083 bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
1084 BOOST_STATIC_ASSERT(index_found);
1085
1086 typedef typename mpl::deref<iter>::type type;
1087 };
1088
1089 template<
1090 typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
1091 >
1092 typename ::boost::multi_index::index<
1093 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
get(multi_index_container<Value,IndexSpecifierList,Allocator> & m)1094 get(
1095 multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
1096 {
1097 typedef multi_index_container<
1098 Value,IndexSpecifierList,Allocator> multi_index_type;
1099 typedef typename ::boost::multi_index::index<
1100 multi_index_container<
1101 Value,IndexSpecifierList,Allocator>,
1102 Tag
1103 >::type index_type;
1104
1105 return detail::converter<multi_index_type,index_type>::index(m);
1106 }
1107
1108 template<
1109 typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
1110 >
1111 const typename ::boost::multi_index::index<
1112 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
get(const multi_index_container<Value,IndexSpecifierList,Allocator> & m)1113 get(
1114 const multi_index_container<Value,IndexSpecifierList,Allocator>& m
1115 )BOOST_NOEXCEPT
1116 {
1117 typedef multi_index_container<
1118 Value,IndexSpecifierList,Allocator> multi_index_type;
1119 typedef typename ::boost::multi_index::index<
1120 multi_index_container<
1121 Value,IndexSpecifierList,Allocator>,
1122 Tag
1123 >::type index_type;
1124
1125 return detail::converter<multi_index_type,index_type>::index(m);
1126 }
1127
1128 /* projection of iterators by number */
1129
1130 template<typename MultiIndexContainer,int N>
1131 struct nth_index_iterator
1132 {
1133 typedef typename nth_index<MultiIndexContainer,N>::type::iterator type;
1134 };
1135
1136 template<typename MultiIndexContainer,int N>
1137 struct nth_index_const_iterator
1138 {
1139 typedef typename nth_index<MultiIndexContainer,N>::type::const_iterator type;
1140 };
1141
1142 template<
1143 int N,typename IteratorType,
1144 typename Value,typename IndexSpecifierList,typename Allocator>
1145 typename nth_index_iterator<
1146 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
project(multi_index_container<Value,IndexSpecifierList,Allocator> & m,IteratorType it)1147 project(
1148 multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1149 IteratorType it)
1150 {
1151 typedef multi_index_container<
1152 Value,IndexSpecifierList,Allocator> multi_index_type;
1153 typedef typename nth_index<multi_index_type,N>::type index_type;
1154
1155 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1156 BOOST_STATIC_ASSERT((
1157 mpl::contains<
1158 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1159 IteratorType>::value));
1160 #endif
1161
1162 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1163
1164 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1165 typedef detail::converter<
1166 multi_index_type,
1167 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1168 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1169 #endif
1170
1171 return detail::converter<multi_index_type,index_type>::iterator(
1172 m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
1173 }
1174
1175 template<
1176 int N,typename IteratorType,
1177 typename Value,typename IndexSpecifierList,typename Allocator>
1178 typename nth_index_const_iterator<
1179 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
project(const multi_index_container<Value,IndexSpecifierList,Allocator> & m,IteratorType it)1180 project(
1181 const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1182 IteratorType it)
1183 {
1184 typedef multi_index_container<
1185 Value,IndexSpecifierList,Allocator> multi_index_type;
1186 typedef typename nth_index<multi_index_type,N>::type index_type;
1187
1188 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1189 BOOST_STATIC_ASSERT((
1190 mpl::contains<
1191 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1192 IteratorType>::value||
1193 mpl::contains<
1194 BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
1195 IteratorType>::value));
1196 #endif
1197
1198 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1199
1200 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1201 typedef detail::converter<
1202 multi_index_type,
1203 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1204 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1205 #endif
1206
1207 return detail::converter<multi_index_type,index_type>::const_iterator(
1208 m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
1209 }
1210
1211 /* projection of iterators by tag */
1212
1213 template<typename MultiIndexContainer,typename Tag>
1214 struct index_iterator
1215 {
1216 typedef typename ::boost::multi_index::index<
1217 MultiIndexContainer,Tag>::type::iterator type;
1218 };
1219
1220 template<typename MultiIndexContainer,typename Tag>
1221 struct index_const_iterator
1222 {
1223 typedef typename ::boost::multi_index::index<
1224 MultiIndexContainer,Tag>::type::const_iterator type;
1225 };
1226
1227 template<
1228 typename Tag,typename IteratorType,
1229 typename Value,typename IndexSpecifierList,typename Allocator>
1230 typename index_iterator<
1231 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
project(multi_index_container<Value,IndexSpecifierList,Allocator> & m,IteratorType it)1232 project(
1233 multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1234 IteratorType it)
1235 {
1236 typedef multi_index_container<
1237 Value,IndexSpecifierList,Allocator> multi_index_type;
1238 typedef typename ::boost::multi_index::index<
1239 multi_index_type,Tag>::type index_type;
1240
1241 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1242 BOOST_STATIC_ASSERT((
1243 mpl::contains<
1244 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1245 IteratorType>::value));
1246 #endif
1247
1248 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1249
1250 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1251 typedef detail::converter<
1252 multi_index_type,
1253 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1254 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1255 #endif
1256
1257 return detail::converter<multi_index_type,index_type>::iterator(
1258 m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
1259 }
1260
1261 template<
1262 typename Tag,typename IteratorType,
1263 typename Value,typename IndexSpecifierList,typename Allocator>
1264 typename index_const_iterator<
1265 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
project(const multi_index_container<Value,IndexSpecifierList,Allocator> & m,IteratorType it)1266 project(
1267 const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1268 IteratorType it)
1269 {
1270 typedef multi_index_container<
1271 Value,IndexSpecifierList,Allocator> multi_index_type;
1272 typedef typename ::boost::multi_index::index<
1273 multi_index_type,Tag>::type index_type;
1274
1275 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1276 BOOST_STATIC_ASSERT((
1277 mpl::contains<
1278 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1279 IteratorType>::value||
1280 mpl::contains<
1281 BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
1282 IteratorType>::value));
1283 #endif
1284
1285 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1286
1287 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1288 typedef detail::converter<
1289 multi_index_type,
1290 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1291 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1292 #endif
1293
1294 return detail::converter<multi_index_type,index_type>::const_iterator(
1295 m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
1296 }
1297
1298 /* Comparison. Simple forward to first index. */
1299
1300 template<
1301 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1302 typename Value2,typename IndexSpecifierList2,typename Allocator2
1303 >
operator ==(const multi_index_container<Value1,IndexSpecifierList1,Allocator1> & x,const multi_index_container<Value2,IndexSpecifierList2,Allocator2> & y)1304 bool operator==(
1305 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1306 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1307 {
1308 return get<0>(x)==get<0>(y);
1309 }
1310
1311 template<
1312 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1313 typename Value2,typename IndexSpecifierList2,typename Allocator2
1314 >
operator <(const multi_index_container<Value1,IndexSpecifierList1,Allocator1> & x,const multi_index_container<Value2,IndexSpecifierList2,Allocator2> & y)1315 bool operator<(
1316 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1317 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1318 {
1319 return get<0>(x)<get<0>(y);
1320 }
1321
1322 template<
1323 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1324 typename Value2,typename IndexSpecifierList2,typename Allocator2
1325 >
operator !=(const multi_index_container<Value1,IndexSpecifierList1,Allocator1> & x,const multi_index_container<Value2,IndexSpecifierList2,Allocator2> & y)1326 bool operator!=(
1327 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1328 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1329 {
1330 return get<0>(x)!=get<0>(y);
1331 }
1332
1333 template<
1334 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1335 typename Value2,typename IndexSpecifierList2,typename Allocator2
1336 >
operator >(const multi_index_container<Value1,IndexSpecifierList1,Allocator1> & x,const multi_index_container<Value2,IndexSpecifierList2,Allocator2> & y)1337 bool operator>(
1338 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1339 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1340 {
1341 return get<0>(x)>get<0>(y);
1342 }
1343
1344 template<
1345 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1346 typename Value2,typename IndexSpecifierList2,typename Allocator2
1347 >
operator >=(const multi_index_container<Value1,IndexSpecifierList1,Allocator1> & x,const multi_index_container<Value2,IndexSpecifierList2,Allocator2> & y)1348 bool operator>=(
1349 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1350 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1351 {
1352 return get<0>(x)>=get<0>(y);
1353 }
1354
1355 template<
1356 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1357 typename Value2,typename IndexSpecifierList2,typename Allocator2
1358 >
operator <=(const multi_index_container<Value1,IndexSpecifierList1,Allocator1> & x,const multi_index_container<Value2,IndexSpecifierList2,Allocator2> & y)1359 bool operator<=(
1360 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1361 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1362 {
1363 return get<0>(x)<=get<0>(y);
1364 }
1365
1366 /* specialized algorithms */
1367
1368 template<typename Value,typename IndexSpecifierList,typename Allocator>
swap(multi_index_container<Value,IndexSpecifierList,Allocator> & x,multi_index_container<Value,IndexSpecifierList,Allocator> & y)1369 void swap(
1370 multi_index_container<Value,IndexSpecifierList,Allocator>& x,
1371 multi_index_container<Value,IndexSpecifierList,Allocator>& y)
1372 {
1373 x.swap(y);
1374 }
1375
1376 } /* namespace multi_index */
1377
1378 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
1379 /* class version = 1 : we now serialize the size through
1380 * boost::serialization::collection_size_type.
1381 * class version = 2 : proper use of {save|load}_construct_data.
1382 */
1383
1384 namespace serialization {
1385 template<typename Value,typename IndexSpecifierList,typename Allocator>
1386 struct version<
1387 boost::multi_index_container<Value,IndexSpecifierList,Allocator>
1388 >
1389 {
1390 BOOST_STATIC_CONSTANT(int,value=2);
1391 };
1392 } /* namespace serialization */
1393 #endif
1394
1395 /* Associated global functions are promoted to namespace boost, except
1396 * comparison operators and swap, which are meant to be Koenig looked-up.
1397 */
1398
1399 using multi_index::get;
1400 using multi_index::project;
1401
1402 } /* namespace boost */
1403
1404 #undef BOOST_MULTI_INDEX_CHECK_INVARIANT
1405 #undef BOOST_MULTI_INDEX_CHECK_INVARIANT_OF
1406
1407 #endif
1408