1 /* Multiply indexed container.
3 * Copyright 2003-2020 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)
8 * See http://www.boost.org/libs/multi_index for library home page.
11 #ifndef BOOST_MULTI_INDEX_HPP
12 #define BOOST_MULTI_INDEX_HPP
18 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
20 #include <boost/core/addressof.hpp>
21 #include <boost/core/no_exceptions_support.hpp>
22 #include <boost/detail/workaround.hpp>
23 #include <boost/move/core.hpp>
24 #include <boost/move/utility_core.hpp>
25 #include <boost/mpl/at.hpp>
26 #include <boost/mpl/contains.hpp>
27 #include <boost/mpl/find_if.hpp>
28 #include <boost/mpl/identity.hpp>
29 #include <boost/mpl/int.hpp>
30 #include <boost/mpl/size.hpp>
31 #include <boost/mpl/deref.hpp>
32 #include <boost/multi_index_container_fwd.hpp>
33 #include <boost/multi_index/detail/access_specifier.hpp>
34 #include <boost/multi_index/detail/adl_swap.hpp>
35 #include <boost/multi_index/detail/allocator_traits.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/integral_constant.hpp>
47 #include <boost/type_traits/is_same.hpp>
48 #include <boost/utility/base_from_member.hpp>
50 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
51 #include <initializer_list>
54 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
55 #include <boost/multi_index/detail/archive_constructed.hpp>
56 #include <boost/multi_index/detail/serialization_version.hpp>
57 #include <boost/serialization/collection_size_type.hpp>
58 #include <boost/serialization/nvp.hpp>
59 #include <boost/serialization/split_member.hpp>
60 #include <boost/serialization/version.hpp>
61 #include <boost/throw_exception.hpp>
64 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
65 #include <boost/multi_index/detail/invariant_assert.hpp>
66 #define BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x) \
67 detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
68 detail::make_obj_guard(x,&multi_index_container::check_invariant_); \
69 BOOST_JOIN(check_invariant_,__LINE__).touch();
70 #define BOOST_MULTI_INDEX_CHECK_INVARIANT \
71 BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(*this)
73 #define BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x)
74 #define BOOST_MULTI_INDEX_CHECK_INVARIANT
79 namespace multi_index{
83 struct unequal_alloc_move_ctor_tag{};
85 } /* namespace multi_index::detail */
87 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
89 #pragma warning(disable:4522) /* spurious warning on multiple operator=()'s */
92 template<typename Value,typename IndexSpecifierList,typename Allocator>
93 class multi_index_container:
94 private ::boost::base_from_member<
95 typename detail::rebind_alloc_for<
97 typename detail::multi_index_node_type<
98 Value,IndexSpecifierList,Allocator>::type
101 BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
102 typename detail::allocator_traits<
103 typename detail::rebind_alloc_for<
105 typename detail::multi_index_node_type<
106 Value,IndexSpecifierList,Allocator>::type
109 multi_index_container<Value,IndexSpecifierList,Allocator> >,
110 public detail::multi_index_base_type<
111 Value,IndexSpecifierList,Allocator>::type
113 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
114 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
115 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
116 * lifetime of const references bound to temporaries --precisely what
120 #pragma parse_mfunc_templ off
124 BOOST_COPYABLE_AND_MOVABLE(multi_index_container)
126 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
127 template <typename,typename,typename> friend class detail::index_base;
128 template <typename,typename> friend struct detail::header_holder;
129 template <typename,typename> friend struct detail::converter;
132 typedef typename detail::multi_index_base_type<
133 Value,IndexSpecifierList,Allocator>::type super;
134 typedef typename detail::rebind_alloc_for<
136 typename super::index_node_type
137 >::type node_allocator;
138 typedef detail::allocator_traits<node_allocator> node_alloc_traits;
139 typedef typename node_alloc_traits::pointer node_pointer;
140 typedef ::boost::base_from_member<
141 node_allocator> bfm_allocator;
142 typedef detail::header_holder<
144 multi_index_container> bfm_header;
147 /* All types are inherited from super, a few are explicitly
148 * brought forward here to save us some typename's.
151 typedef typename super::ctor_args_list ctor_args_list;
152 typedef IndexSpecifierList index_specifier_type_list;
154 typedef typename super::index_type_list index_type_list;
156 typedef typename super::iterator_type_list iterator_type_list;
157 typedef typename super::const_iterator_type_list const_iterator_type_list;
158 typedef typename super::value_type value_type;
159 typedef typename super::final_allocator_type allocator_type;
160 typedef typename super::size_type size_type;
161 typedef typename super::iterator iterator;
162 typedef typename super::const_iterator const_iterator;
165 detail::no_duplicate_tags_in_index_list<index_type_list>::value);
167 /* global project() needs to see this publicly */
169 typedef typename super::final_node_type final_node_type;
171 /* construct/copy/destroy */
173 multi_index_container():
174 bfm_allocator(allocator_type()),
175 super(ctor_args_list(),bfm_allocator::member),
178 BOOST_MULTI_INDEX_CHECK_INVARIANT;
181 explicit multi_index_container(
182 const ctor_args_list& args_list,
184 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
185 /* VisualAge seems to have an ETI issue with the default value for
189 const allocator_type& al=
190 typename mpl::identity<multi_index_container>::type::
193 const allocator_type& al=allocator_type()):
197 super(args_list,bfm_allocator::member),
200 BOOST_MULTI_INDEX_CHECK_INVARIANT;
203 explicit multi_index_container(const allocator_type& al):
205 super(ctor_args_list(),bfm_allocator::member),
208 BOOST_MULTI_INDEX_CHECK_INVARIANT;
211 template<typename InputIterator>
212 multi_index_container(
213 InputIterator first,InputIterator last,
215 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
216 /* VisualAge seems to have an ETI issue with the default values
217 * for arguments args_list and al.
220 const ctor_args_list& args_list=
221 typename mpl::identity<multi_index_container>::type::
223 const allocator_type& al=
224 typename mpl::identity<multi_index_container>::type::
227 const ctor_args_list& args_list=ctor_args_list(),
228 const allocator_type& al=allocator_type()):
232 super(args_list,bfm_allocator::member),
235 BOOST_MULTI_INDEX_CHECK_INVARIANT;
237 iterator hint=super::end();
238 for(;first!=last;++first){
239 hint=super::make_iterator(
240 insert_ref_(*first,hint.get_node()).first);
251 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
252 multi_index_container(
253 std::initializer_list<Value> list,
254 const ctor_args_list& args_list=ctor_args_list(),
255 const allocator_type& al=allocator_type()):
257 super(args_list,bfm_allocator::member),
260 BOOST_MULTI_INDEX_CHECK_INVARIANT;
262 typedef const Value* init_iterator;
264 iterator hint=super::end();
265 for(init_iterator first=list.begin(),last=list.end();
266 first!=last;++first){
267 hint=super::make_iterator(insert_(*first,hint.get_node()).first);
279 multi_index_container(
280 const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
282 node_alloc_traits::select_on_container_copy_construction(
283 x.bfm_allocator::member)),
288 copy_construct_from(x);
291 multi_index_container(BOOST_RV_REF(multi_index_container) x):
292 bfm_allocator(boost::move(x.bfm_allocator::member)),
294 super(x,detail::do_not_copy_elements_tag()),
297 BOOST_MULTI_INDEX_CHECK_INVARIANT;
298 BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
302 multi_index_container(
303 const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
304 const allocator_type& al):
310 copy_construct_from(x);
313 multi_index_container(
314 BOOST_RV_REF(multi_index_container) x,const allocator_type& al):
317 super(x,detail::do_not_copy_elements_tag()),
320 BOOST_MULTI_INDEX_CHECK_INVARIANT;
321 BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
323 if(al==x.get_allocator()){
327 multi_index_container y(x,al,detail::unequal_alloc_move_ctor_tag());
332 ~multi_index_container()
337 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
338 /* As per http://www.boost.org/doc/html/move/emulation_limitations.html
339 * #move.emulation_limitations.assignment_operator
342 multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
343 const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
345 multi_index_container y(
347 node_alloc_traits::propagate_on_container_copy_assignment::value?
348 x.get_allocator():this->get_allocator());
349 swap_(y,boost::true_type() /* swap_allocators */);
354 multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
355 BOOST_COPY_ASSIGN_REF(multi_index_container) x)
357 multi_index_container y(
359 node_alloc_traits::propagate_on_container_copy_assignment::value?
360 x.get_allocator():this->get_allocator());
361 swap_(y,boost::true_type() /* swap_allocators */);
365 multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
366 BOOST_RV_REF(multi_index_container) x)
368 #include <boost/multi_index/detail/define_if_constexpr_macro.hpp>
370 BOOST_MULTI_INDEX_IF_CONSTEXPR(
371 node_alloc_traits::propagate_on_container_move_assignment::value){
372 swap_(x,boost::true_type() /* swap_allocators */);
374 else if(this->get_allocator()==x.get_allocator()){
375 swap_(x,boost::false_type() /* swap_allocators */);
378 multi_index_container y(boost::move(x),this->get_allocator());
379 swap_(y,boost::false_type() /* swap_allocators */);
383 #include <boost/multi_index/detail/undef_if_constexpr_macro.hpp>
386 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
387 multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
388 std::initializer_list<Value> list)
390 BOOST_MULTI_INDEX_CHECK_INVARIANT;
391 typedef const Value* init_iterator;
393 multi_index_container x(*this,detail::do_not_copy_elements_tag());
394 iterator hint=x.end();
395 for(init_iterator first=list.begin(),last=list.end();
396 first!=last;++first){
397 hint=x.make_iterator(x.insert_(*first,hint.get_node()).first);
400 x.swap_elements_(*this);
405 allocator_type get_allocator()const BOOST_NOEXCEPT
407 return allocator_type(bfm_allocator::member);
410 /* retrieval of indices by number */
412 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
416 BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
417 typedef typename mpl::at_c<index_type_list,N>::type type;
421 typename nth_index<N>::type& get()BOOST_NOEXCEPT
423 BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
428 const typename nth_index<N>::type& get()const BOOST_NOEXCEPT
430 BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
435 /* retrieval of indices by tag */
437 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
438 template<typename Tag>
441 typedef typename mpl::find_if<
446 BOOST_STATIC_CONSTANT(
447 bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
448 BOOST_STATIC_ASSERT(index_found);
450 typedef typename mpl::deref<iter>::type type;
453 template<typename Tag>
454 typename index<Tag>::type& get()BOOST_NOEXCEPT
459 template<typename Tag>
460 const typename index<Tag>::type& get()const BOOST_NOEXCEPT
466 /* projection of iterators by number */
468 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
470 struct nth_index_iterator
472 typedef typename nth_index<N>::type::iterator type;
476 struct nth_index_const_iterator
478 typedef typename nth_index<N>::type::const_iterator type;
481 template<int N,typename IteratorType>
482 typename nth_index_iterator<N>::type project(IteratorType it)
484 typedef typename nth_index<N>::type index_type;
486 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
488 (mpl::contains<iterator_type_list,IteratorType>::value));
491 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
492 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
493 it,static_cast<typename IteratorType::container_type&>(*this));
495 return index_type::make_iterator(
496 static_cast<final_node_type*>(it.get_node()));
499 template<int N,typename IteratorType>
500 typename nth_index_const_iterator<N>::type project(IteratorType it)const
502 typedef typename nth_index<N>::type index_type;
504 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
505 BOOST_STATIC_ASSERT((
506 mpl::contains<iterator_type_list,IteratorType>::value||
507 mpl::contains<const_iterator_type_list,IteratorType>::value));
510 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
511 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
512 it,static_cast<const typename IteratorType::container_type&>(*this));
513 return index_type::make_iterator(
514 static_cast<final_node_type*>(it.get_node()));
518 /* projection of iterators by tag */
520 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
521 template<typename Tag>
522 struct index_iterator
524 typedef typename index<Tag>::type::iterator type;
527 template<typename Tag>
528 struct index_const_iterator
530 typedef typename index<Tag>::type::const_iterator type;
533 template<typename Tag,typename IteratorType>
534 typename index_iterator<Tag>::type project(IteratorType it)
536 typedef typename index<Tag>::type index_type;
538 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
540 (mpl::contains<iterator_type_list,IteratorType>::value));
543 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
544 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
545 it,static_cast<typename IteratorType::container_type&>(*this));
546 return index_type::make_iterator(
547 static_cast<final_node_type*>(it.get_node()));
550 template<typename Tag,typename IteratorType>
551 typename index_const_iterator<Tag>::type project(IteratorType it)const
553 typedef typename index<Tag>::type index_type;
555 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
556 BOOST_STATIC_ASSERT((
557 mpl::contains<iterator_type_list,IteratorType>::value||
558 mpl::contains<const_iterator_type_list,IteratorType>::value));
561 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
562 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
563 it,static_cast<const typename IteratorType::container_type&>(*this));
564 return index_type::make_iterator(
565 static_cast<final_node_type*>(it.get_node()));
569 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
570 typedef typename super::final_node_handle_type final_node_handle_type;
571 typedef typename super::copy_map_type copy_map_type;
573 multi_index_container(
574 multi_index_container<Value,IndexSpecifierList,Allocator>& x,
575 const allocator_type& al,
576 detail::unequal_alloc_move_ctor_tag):
582 BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
584 copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
585 for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
586 map.move_clone(it.get_node());
599 /* Not until this point are the indices required to be consistent,
600 * hence the position of the invariant checker.
603 BOOST_MULTI_INDEX_CHECK_INVARIANT;
606 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
607 multi_index_container(
608 const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
609 detail::do_not_copy_elements_tag):
610 bfm_allocator(x.bfm_allocator::member),
612 super(x,detail::do_not_copy_elements_tag()),
615 BOOST_MULTI_INDEX_CHECK_INVARIANT;
619 void copy_construct_from(
620 const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
622 copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
623 for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
624 map.copy_clone(it.get_node());
630 /* Not until this point are the indices required to be consistent,
631 * hence the position of the invariant checker.
634 BOOST_MULTI_INDEX_CHECK_INVARIANT;
637 final_node_type* header()const
639 return &*bfm_header::member;
642 final_node_type* allocate_node()
644 return &*node_alloc_traits::allocate(bfm_allocator::member,1);
647 void deallocate_node(final_node_type* x)
649 node_alloc_traits::deallocate(
650 bfm_allocator::member,static_cast<node_pointer>(x),1);
653 void construct_value(final_node_type* x,const Value& v)
655 node_alloc_traits::construct(
656 bfm_allocator::member,boost::addressof(x->value()),v);
659 void construct_value(final_node_type* x,BOOST_RV_REF(Value) v)
661 node_alloc_traits::construct(
662 bfm_allocator::member,boost::addressof(x->value()),boost::move(v));
665 BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
666 void,construct_value,vartempl_construct_value_impl,final_node_type*,x)
668 void destroy_value(final_node_type* x)
670 node_alloc_traits::destroy(
671 bfm_allocator::member,boost::addressof(x->value()));
676 return node_count==0;
679 size_type size_()const
684 size_type max_size_()const
686 return static_cast<size_type>(-1);
689 template<typename Variant>
690 std::pair<final_node_type*,bool> insert_(const Value& v,Variant variant)
692 final_node_type* x=0;
693 final_node_type* res=super::insert_(v,x,variant);
696 return std::pair<final_node_type*,bool>(res,true);
699 return std::pair<final_node_type*,bool>(res,false);
703 std::pair<final_node_type*,bool> insert_(const Value& v)
705 return insert_(v,detail::lvalue_tag());
708 std::pair<final_node_type*,bool> insert_rv_(const Value& v)
710 return insert_(v,detail::rvalue_tag());
714 std::pair<final_node_type*,bool> insert_ref_(T& t)
716 final_node_type* x=allocate_node();
718 construct_value(x,t);
720 final_node_type* res=super::insert_(
721 x->value(),x,detail::emplaced_tag());
724 return std::pair<final_node_type*,bool>(res,true);
728 return std::pair<final_node_type*,bool>(res,false);
744 std::pair<final_node_type*,bool> insert_ref_(const value_type& x)
749 std::pair<final_node_type*,bool> insert_ref_(value_type& x)
754 std::pair<final_node_type*,bool> insert_nh_(final_node_handle_type& nh)
756 if(!nh)return std::pair<final_node_type*,bool>(header(),false);
758 final_node_type* x=nh.node;
759 final_node_type* res=super::insert_(
760 x->value(),x,detail::emplaced_tag());
764 return std::pair<final_node_type*,bool>(res,true);
766 else return std::pair<final_node_type*,bool>(res,false);
770 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
771 std::pair<final_node_type*,bool> emplace_(
772 BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
774 final_node_type* x=allocate_node();
776 construct_value(x,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
778 final_node_type* res=super::insert_(
779 x->value(),x,detail::emplaced_tag());
782 return std::pair<final_node_type*,bool>(res,true);
786 return std::pair<final_node_type*,bool>(res,false);
802 template<typename Variant>
803 std::pair<final_node_type*,bool> insert_(
804 const Value& v,final_node_type* position,Variant variant)
806 final_node_type* x=0;
807 final_node_type* res=super::insert_(v,position,x,variant);
810 return std::pair<final_node_type*,bool>(res,true);
813 return std::pair<final_node_type*,bool>(res,false);
817 std::pair<final_node_type*,bool> insert_(
818 const Value& v,final_node_type* position)
820 return insert_(v,position,detail::lvalue_tag());
823 std::pair<final_node_type*,bool> insert_rv_(
824 const Value& v,final_node_type* position)
826 return insert_(v,position,detail::rvalue_tag());
830 std::pair<final_node_type*,bool> insert_ref_(
831 T& t,final_node_type* position)
833 final_node_type* x=allocate_node();
835 construct_value(x,t);
837 final_node_type* res=super::insert_(
838 x->value(),position,x,detail::emplaced_tag());
841 return std::pair<final_node_type*,bool>(res,true);
845 return std::pair<final_node_type*,bool>(res,false);
861 std::pair<final_node_type*,bool> insert_ref_(
862 const value_type& x,final_node_type* position)
864 return insert_(x,position);
867 std::pair<final_node_type*,bool> insert_ref_(
868 value_type& x,final_node_type* position)
870 return insert_(x,position);
873 std::pair<final_node_type*,bool> insert_nh_(
874 final_node_handle_type& nh,final_node_type* position)
876 if(!nh)return std::pair<final_node_type*,bool>(header(),false);
878 final_node_type* x=nh.node;
879 final_node_type* res=super::insert_(
880 x->value(),position,x,detail::emplaced_tag());
884 return std::pair<final_node_type*,bool>(res,true);
886 else return std::pair<final_node_type*,bool>(res,false);
890 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
891 std::pair<final_node_type*,bool> emplace_hint_(
892 final_node_type* position,
893 BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
895 final_node_type* x=allocate_node();
897 construct_value(x,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
899 final_node_type* res=super::insert_(
900 x->value(),position,x,detail::emplaced_tag());
903 return std::pair<final_node_type*,bool>(res,true);
907 return std::pair<final_node_type*,bool>(res,false);
923 final_node_handle_type extract_(final_node_type* x)
927 return final_node_handle_type(x,get_allocator());
930 void erase_(final_node_type* x)
937 void delete_node_(final_node_type* x)
943 void delete_all_nodes_()
945 super::delete_all_nodes_();
955 void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
959 boost::integral_constant<
960 bool,node_alloc_traits::propagate_on_container_swap::value>());
964 multi_index_container<Value,IndexSpecifierList,Allocator>& x,
965 boost::true_type swap_allocators)
967 detail::adl_swap(bfm_allocator::member,x.bfm_allocator::member);
968 std::swap(bfm_header::member,x.bfm_header::member);
969 super::swap_(x,swap_allocators);
970 std::swap(node_count,x.node_count);
974 multi_index_container<Value,IndexSpecifierList,Allocator>& x,
975 boost::false_type swap_allocators)
977 std::swap(bfm_header::member,x.bfm_header::member);
978 super::swap_(x,swap_allocators);
979 std::swap(node_count,x.node_count);
983 multi_index_container<Value,IndexSpecifierList,Allocator>& x)
985 std::swap(bfm_header::member,x.bfm_header::member);
986 super::swap_elements_(x);
987 std::swap(node_count,x.node_count);
990 bool replace_(const Value& k,final_node_type* x)
992 return super::replace_(k,x,detail::lvalue_tag());
995 bool replace_rv_(const Value& k,final_node_type* x)
997 return super::replace_(k,x,detail::rvalue_tag());
1000 template<typename Modifier>
1001 bool modify_(Modifier& mod,final_node_type* x)
1004 mod(const_cast<value_type&>(x->value()));
1013 if(!super::modify_(x)){
1028 template<typename Modifier,typename Rollback>
1029 bool modify_(Modifier& mod,Rollback& back_,final_node_type* x)
1032 mod(const_cast<value_type&>(x->value()));
1042 b=super::modify_rollback_(x);
1046 back_(const_cast<value_type&>(x->value()));
1047 if(!super::check_rollback_(x))this->erase_(x);
1060 back_(const_cast<value_type&>(x->value()));
1061 if(!super::check_rollback_(x))this->erase_(x);
1073 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
1076 friend class boost::serialization::access;
1078 BOOST_SERIALIZATION_SPLIT_MEMBER()
1080 typedef typename super::index_saver_type index_saver_type;
1081 typedef typename super::index_loader_type index_loader_type;
1083 template<class Archive>
1084 void save(Archive& ar,const unsigned int version)const
1086 const serialization::collection_size_type s(size_());
1087 const detail::serialization_version<value_type> value_version;
1088 ar<<serialization::make_nvp("count",s);
1089 ar<<serialization::make_nvp("value_version",value_version);
1091 index_saver_type sm(bfm_allocator::member,s);
1093 for(iterator it=super::begin(),it_end=super::end();it!=it_end;++it){
1094 serialization::save_construct_data_adl(
1095 ar,boost::addressof(*it),value_version);
1096 ar<<serialization::make_nvp("item",*it);
1097 sm.add(it.get_node(),ar,version);
1099 sm.add_track(header(),ar,version);
1101 super::save_(ar,version,sm);
1104 template<class Archive>
1105 void load(Archive& ar,const unsigned int version)
1107 BOOST_MULTI_INDEX_CHECK_INVARIANT;
1110 serialization::collection_size_type s;
1111 detail::serialization_version<value_type> value_version;
1114 ar>>serialization::make_nvp("count",sz);
1115 s=static_cast<serialization::collection_size_type>(sz);
1118 ar>>serialization::make_nvp("count",s);
1124 ar>>serialization::make_nvp("value_version",value_version);
1127 index_loader_type lm(bfm_allocator::member,s);
1129 for(std::size_t n=0;n<s;++n){
1130 detail::archive_constructed<Value> value("item",ar,value_version);
1131 std::pair<final_node_type*,bool> p=insert_rv_(
1132 value.get(),super::end().get_node());
1133 if(!p.second)throw_exception(
1134 archive::archive_exception(
1135 archive::archive_exception::other_exception));
1136 ar.reset_object_address(
1137 boost::addressof(p.first->value()),boost::addressof(value.get()));
1138 lm.add(p.first,ar,version);
1140 lm.add_track(header(),ar,version);
1142 super::load_(ar,version,lm);
1146 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
1147 /* invariant stuff */
1149 bool invariant_()const
1151 return super::invariant_();
1154 void check_invariant_()const
1156 BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
1161 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
1162 void vartempl_construct_value_impl(
1163 final_node_type* x,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
1165 node_alloc_traits::construct(
1166 bfm_allocator::member,boost::addressof(x->value()),
1167 BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
1170 size_type node_count;
1172 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
1173 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
1174 #pragma parse_mfunc_templ reset
1178 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
1179 #pragma warning(pop) /* C4522 */
1182 /* retrieval of indices by number */
1184 template<typename MultiIndexContainer,int N>
1187 BOOST_STATIC_CONSTANT(
1189 M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
1190 BOOST_STATIC_ASSERT(N>=0&&N<M);
1191 typedef typename mpl::at_c<
1192 typename MultiIndexContainer::index_type_list,N>::type type;
1195 template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
1197 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
1199 multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
1201 typedef multi_index_container<
1202 Value,IndexSpecifierList,Allocator> multi_index_type;
1203 typedef typename nth_index<
1204 multi_index_container<
1205 Value,IndexSpecifierList,Allocator>,
1209 BOOST_STATIC_ASSERT(N>=0&&
1212 BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
1215 return detail::converter<multi_index_type,index_type>::index(m);
1218 template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
1219 const typename nth_index<
1220 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
1222 const multi_index_container<Value,IndexSpecifierList,Allocator>& m
1225 typedef multi_index_container<
1226 Value,IndexSpecifierList,Allocator> multi_index_type;
1227 typedef typename nth_index<
1228 multi_index_container<
1229 Value,IndexSpecifierList,Allocator>,
1233 BOOST_STATIC_ASSERT(N>=0&&
1236 BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
1239 return detail::converter<multi_index_type,index_type>::index(m);
1242 /* retrieval of indices by tag */
1244 template<typename MultiIndexContainer,typename Tag>
1247 typedef typename MultiIndexContainer::index_type_list index_type_list;
1249 typedef typename mpl::find_if<
1251 detail::has_tag<Tag>
1254 BOOST_STATIC_CONSTANT(
1255 bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
1256 BOOST_STATIC_ASSERT(index_found);
1258 typedef typename mpl::deref<iter>::type type;
1262 typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
1264 typename ::boost::multi_index::index<
1265 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
1267 multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
1269 typedef multi_index_container<
1270 Value,IndexSpecifierList,Allocator> multi_index_type;
1271 typedef typename ::boost::multi_index::index<
1272 multi_index_container<
1273 Value,IndexSpecifierList,Allocator>,
1277 return detail::converter<multi_index_type,index_type>::index(m);
1281 typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
1283 const typename ::boost::multi_index::index<
1284 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
1286 const multi_index_container<Value,IndexSpecifierList,Allocator>& m
1289 typedef multi_index_container<
1290 Value,IndexSpecifierList,Allocator> multi_index_type;
1291 typedef typename ::boost::multi_index::index<
1292 multi_index_container<
1293 Value,IndexSpecifierList,Allocator>,
1297 return detail::converter<multi_index_type,index_type>::index(m);
1300 /* projection of iterators by number */
1302 template<typename MultiIndexContainer,int N>
1303 struct nth_index_iterator
1305 typedef typename nth_index<MultiIndexContainer,N>::type::iterator type;
1308 template<typename MultiIndexContainer,int N>
1309 struct nth_index_const_iterator
1311 typedef typename nth_index<MultiIndexContainer,N>::type::const_iterator type;
1315 int N,typename IteratorType,
1316 typename Value,typename IndexSpecifierList,typename Allocator>
1317 typename nth_index_iterator<
1318 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
1320 multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1323 typedef multi_index_container<
1324 Value,IndexSpecifierList,Allocator> multi_index_type;
1325 typedef typename nth_index<multi_index_type,N>::type index_type;
1327 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1328 BOOST_STATIC_ASSERT((
1330 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1331 IteratorType>::value));
1334 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1336 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1337 typedef detail::converter<
1339 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1340 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1343 return detail::converter<multi_index_type,index_type>::iterator(
1344 m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
1348 int N,typename IteratorType,
1349 typename Value,typename IndexSpecifierList,typename Allocator>
1350 typename nth_index_const_iterator<
1351 multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
1353 const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1356 typedef multi_index_container<
1357 Value,IndexSpecifierList,Allocator> multi_index_type;
1358 typedef typename nth_index<multi_index_type,N>::type index_type;
1360 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1361 BOOST_STATIC_ASSERT((
1363 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1364 IteratorType>::value||
1366 BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
1367 IteratorType>::value));
1370 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1372 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1373 typedef detail::converter<
1375 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1376 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1379 return detail::converter<multi_index_type,index_type>::const_iterator(
1380 m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
1383 /* projection of iterators by tag */
1385 template<typename MultiIndexContainer,typename Tag>
1386 struct index_iterator
1388 typedef typename ::boost::multi_index::index<
1389 MultiIndexContainer,Tag>::type::iterator type;
1392 template<typename MultiIndexContainer,typename Tag>
1393 struct index_const_iterator
1395 typedef typename ::boost::multi_index::index<
1396 MultiIndexContainer,Tag>::type::const_iterator type;
1400 typename Tag,typename IteratorType,
1401 typename Value,typename IndexSpecifierList,typename Allocator>
1402 typename index_iterator<
1403 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
1405 multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1408 typedef multi_index_container<
1409 Value,IndexSpecifierList,Allocator> multi_index_type;
1410 typedef typename ::boost::multi_index::index<
1411 multi_index_type,Tag>::type index_type;
1413 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1414 BOOST_STATIC_ASSERT((
1416 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1417 IteratorType>::value));
1420 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1422 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1423 typedef detail::converter<
1425 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1426 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1429 return detail::converter<multi_index_type,index_type>::iterator(
1430 m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
1434 typename Tag,typename IteratorType,
1435 typename Value,typename IndexSpecifierList,typename Allocator>
1436 typename index_const_iterator<
1437 multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
1439 const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1442 typedef multi_index_container<
1443 Value,IndexSpecifierList,Allocator> multi_index_type;
1444 typedef typename ::boost::multi_index::index<
1445 multi_index_type,Tag>::type index_type;
1447 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1448 BOOST_STATIC_ASSERT((
1450 BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1451 IteratorType>::value||
1453 BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
1454 IteratorType>::value));
1457 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1459 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1460 typedef detail::converter<
1462 BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
1463 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
1466 return detail::converter<multi_index_type,index_type>::const_iterator(
1467 m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
1470 /* Comparison. Simple forward to first index. */
1473 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1474 typename Value2,typename IndexSpecifierList2,typename Allocator2
1477 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1478 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1480 return get<0>(x)==get<0>(y);
1484 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1485 typename Value2,typename IndexSpecifierList2,typename Allocator2
1488 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1489 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1491 return get<0>(x)<get<0>(y);
1495 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1496 typename Value2,typename IndexSpecifierList2,typename Allocator2
1499 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1500 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1502 return get<0>(x)!=get<0>(y);
1506 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1507 typename Value2,typename IndexSpecifierList2,typename Allocator2
1510 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1511 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1513 return get<0>(x)>get<0>(y);
1517 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1518 typename Value2,typename IndexSpecifierList2,typename Allocator2
1521 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1522 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1524 return get<0>(x)>=get<0>(y);
1528 typename Value1,typename IndexSpecifierList1,typename Allocator1,
1529 typename Value2,typename IndexSpecifierList2,typename Allocator2
1532 const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1533 const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1535 return get<0>(x)<=get<0>(y);
1538 /* specialized algorithms */
1540 template<typename Value,typename IndexSpecifierList,typename Allocator>
1542 multi_index_container<Value,IndexSpecifierList,Allocator>& x,
1543 multi_index_container<Value,IndexSpecifierList,Allocator>& y)
1548 } /* namespace multi_index */
1550 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
1551 /* class version = 1 : we now serialize the size through
1552 * boost::serialization::collection_size_type.
1553 * class version = 2 : proper use of {save|load}_construct_data.
1556 namespace serialization {
1557 template<typename Value,typename IndexSpecifierList,typename Allocator>
1559 boost::multi_index_container<Value,IndexSpecifierList,Allocator>
1562 BOOST_STATIC_CONSTANT(int,value=2);
1564 } /* namespace serialization */
1567 /* Associated global functions are promoted to namespace boost, except
1568 * comparison operators and swap, which are meant to be Koenig looked-up.
1571 using multi_index::get;
1572 using multi_index::project;
1574 } /* namespace boost */
1576 #undef BOOST_MULTI_INDEX_CHECK_INVARIANT
1577 #undef BOOST_MULTI_INDEX_CHECK_INVARIANT_OF