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