1 /* Multiply indexed container.
3 * Copyright 2003-2008 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
14 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
18 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
20 #include <boost/detail/allocator_utilities.hpp>
21 #include <boost/detail/no_exceptions_support.hpp>
22 #include <boost/detail/workaround.hpp>
23 #include <boost/mpl/at.hpp>
24 #include <boost/mpl/contains.hpp>
25 #include <boost/mpl/find_if.hpp>
26 #include <boost/mpl/identity.hpp>
27 #include <boost/mpl/int.hpp>
28 #include <boost/mpl/size.hpp>
29 #include <boost/mpl/deref.hpp>
30 #include <boost/multi_index_container_fwd.hpp>
31 #include <boost/multi_index/detail/access_specifier.hpp>
32 #include <boost/multi_index/detail/adl_swap.hpp>
33 #include <boost/multi_index/detail/base_type.hpp>
34 #include <boost/multi_index/detail/converter.hpp>
35 #include <boost/multi_index/detail/header_holder.hpp>
36 #include <boost/multi_index/detail/has_tag.hpp>
37 #include <boost/multi_index/detail/no_duplicate_tags.hpp>
38 #include <boost/multi_index/detail/prevent_eti.hpp>
39 #include <boost/multi_index/detail/safe_mode.hpp>
40 #include <boost/multi_index/detail/scope_guard.hpp>
41 #include <boost/static_assert.hpp>
42 #include <boost/type_traits/is_same.hpp>
43 #include <boost/utility/base_from_member.hpp>
45 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
46 #include <boost/multi_index/detail/archive_constructed.hpp>
47 #include <boost/serialization/nvp.hpp>
48 #include <boost/serialization/split_member.hpp>
49 #include <boost/throw_exception.hpp>
52 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
53 #include <boost/multi_index/detail/invariant_assert.hpp>
54 #define BOOST_MULTI_INDEX_CHECK_INVARIANT \
55 detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
56 detail::make_obj_guard(*this,&multi_index_container::check_invariant_); \
57 BOOST_JOIN(check_invariant_,__LINE__).touch();
59 #define BOOST_MULTI_INDEX_CHECK_INVARIANT
64 namespace multi_index
{
66 template<typename Value
,typename IndexSpecifierList
,typename Allocator
>
67 class multi_index_container
:
68 private ::boost::base_from_member
<
69 typename
boost::detail::allocator::rebind_to
<
71 typename
detail::multi_index_node_type
<
72 Value
,IndexSpecifierList
,Allocator
>::type
74 BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS
detail::header_holder
<
75 typename
detail::prevent_eti
<
77 typename
boost::detail::allocator::rebind_to
<
79 typename
detail::multi_index_node_type
<
80 Value
,IndexSpecifierList
,Allocator
>::type
83 multi_index_container
<Value
,IndexSpecifierList
,Allocator
> >,
84 public detail::multi_index_base_type
<
85 Value
,IndexSpecifierList
,Allocator
>::type
87 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
88 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
89 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
90 * lifetime of const references bound to temporaries --precisely what
94 #pragma parse_mfunc_templ off
98 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
99 template <typename
,typename
,typename
> friend class detail::index_base
;
100 template <typename
,typename
> friend struct detail::header_holder
;
101 template <typename
,typename
> friend struct detail::converter
;
104 typedef typename
detail::multi_index_base_type
<
105 Value
,IndexSpecifierList
,Allocator
>::type super
;
107 boost::detail::allocator::rebind_to
<
109 typename
super::node_type
110 >::type node_allocator
;
111 typedef ::boost::base_from_member
<
112 node_allocator
> bfm_allocator
;
113 typedef detail::header_holder
<
114 typename
detail::prevent_eti
<
118 multi_index_container
> bfm_header
;
120 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
121 /* see definition of index_type_list below */
122 typedef typename
super::index_type_list super_index_type_list
;
126 /* All types are inherited from super, a few are explicitly
127 * brought forward here to save us some typename's.
130 typedef typename
super::ctor_args_list ctor_args_list
;
131 typedef IndexSpecifierList index_specifier_type_list
;
133 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
134 /* MSVC++ 6.0 chokes on moderately long index lists (around 6 indices
135 * or more), with errors ranging from corrupt exes to duplicate
136 * comdats. The following type hiding hack alleviates this condition;
137 * best results combined with type hiding of the indexed_by construct
138 * itself, as explained in the "Compiler specifics" section of
142 struct index_type_list
:super_index_type_list
144 typedef index_type_list type
;
145 typedef typename
super_index_type_list::back back
;
146 typedef mpl::v_iter
<type
,0> begin
;
149 mpl::size
<super_index_type_list
>::value
> end
;
152 typedef typename
super::index_type_list index_type_list
;
155 typedef typename
super::iterator_type_list iterator_type_list
;
156 typedef typename
super::const_iterator_type_list const_iterator_type_list
;
157 typedef typename
super::value_type value_type
;
158 typedef typename
super::final_allocator_type allocator_type
;
159 typedef typename
super::iterator iterator
;
160 typedef typename
super::const_iterator const_iterator
;
163 detail::no_duplicate_tags_in_index_list
<index_type_list
>::value
);
165 /* global project() needs to see this publicly */
167 typedef typename
super::node_type node_type
;
169 /* construct/copy/destroy */
171 explicit multi_index_container(
173 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
174 /* VisualAge seems to have an ETI issue with the default values
175 * for arguments args_list and al.
178 const ctor_args_list
& args_list
=
179 typename
mpl::identity
<multi_index_container
>::type::
181 const allocator_type
& al
=
182 typename
mpl::identity
<multi_index_container
>::type::
185 const ctor_args_list
& args_list
=ctor_args_list(),
186 const allocator_type
& al
=allocator_type()):
190 super(args_list
,bfm_allocator::member
),
193 BOOST_MULTI_INDEX_CHECK_INVARIANT
;
196 explicit multi_index_container(const allocator_type
& al
):
198 super(ctor_args_list(),bfm_allocator::member
),
201 BOOST_MULTI_INDEX_CHECK_INVARIANT
;
204 template<typename InputIterator
>
205 multi_index_container(
206 InputIterator first
,InputIterator last
,
208 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
209 /* VisualAge seems to have an ETI issue with the default values
210 * for arguments args_list and al.
213 const ctor_args_list
& args_list
=
214 typename
mpl::identity
<multi_index_container
>::type::
216 const allocator_type
& al
=
217 typename
mpl::identity
<multi_index_container
>::type::
220 const ctor_args_list
& args_list
=ctor_args_list(),
221 const allocator_type
& al
=allocator_type()):
225 super(args_list
,bfm_allocator::member
),
228 BOOST_MULTI_INDEX_CHECK_INVARIANT
;
230 iterator hint
=super::end();
231 for(;first
!=last
;++first
){
232 hint
=super::make_iterator(insert_(*first
,hint
.get_node()).first
);
242 multi_index_container(
243 const multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& x
):
244 bfm_allocator(x
.bfm_allocator::member
),
249 copy_map_type
map(bfm_allocator::member
,x
.size(),x
.header(),header());
250 for(const_iterator it
=x
.begin(),it_end
=x
.end();it
!=it_end
;++it
){
251 map
.clone(it
.get_node());
257 /* Not until this point are the indices required to be consistent,
258 * hence the position of the invariant checker.
261 BOOST_MULTI_INDEX_CHECK_INVARIANT
;
264 ~multi_index_container()
269 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& operator=(
270 multi_index_container
<Value
,IndexSpecifierList
,Allocator
> x
)
272 BOOST_MULTI_INDEX_CHECK_INVARIANT
;
277 allocator_type
get_allocator()const
279 return allocator_type(bfm_allocator::member
);
282 /* retrieval of indices by number */
284 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
288 BOOST_STATIC_ASSERT(N
>=0&&N
<mpl::size
<index_type_list
>::type::value
);
289 typedef typename
mpl::at_c
<index_type_list
,N
>::type type
;
293 typename nth_index
<N
>::type
& get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N
))
295 BOOST_STATIC_ASSERT(N
>=0&&N
<mpl::size
<index_type_list
>::type::value
);
300 const typename nth_index
<N
>::type
& get(
301 BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N
))const
303 BOOST_STATIC_ASSERT(N
>=0&&N
<mpl::size
<index_type_list
>::type::value
);
308 /* retrieval of indices by tag */
310 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
311 template<typename Tag
>
314 typedef typename
mpl::find_if
<
319 BOOST_STATIC_CONSTANT(
320 bool,index_found
=!(is_same
<iter
,typename
mpl::end
<index_type_list
>::type
>::value
));
321 BOOST_STATIC_ASSERT(index_found
);
323 typedef typename
mpl::deref
<iter
>::type type
;
326 template<typename Tag
>
327 typename index
<Tag
>::type
& get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag
))
332 template<typename Tag
>
333 const typename index
<Tag
>::type
& get(
334 BOOST_EXPLICIT_TEMPLATE_TYPE(Tag
))const
340 /* projection of iterators by number */
342 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
344 struct nth_index_iterator
346 typedef typename nth_index
<N
>::type::iterator type
;
350 struct nth_index_const_iterator
352 typedef typename nth_index
<N
>::type::const_iterator type
;
355 template<int N
,typename IteratorType
>
356 typename nth_index_iterator
<N
>::type
project(
358 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N
))
360 typedef typename nth_index
<N
>::type index
;
362 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
364 (mpl::contains
<iterator_type_list
,IteratorType
>::value
));
367 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it
);
368 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
369 it
,static_cast<typename
IteratorType::container_type
&>(*this));
371 return index::make_iterator(static_cast<node_type
*>(it
.get_node()));
374 template<int N
,typename IteratorType
>
375 typename nth_index_const_iterator
<N
>::type
project(
377 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N
))const
379 typedef typename nth_index
<N
>::type index
;
381 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
382 BOOST_STATIC_ASSERT((
383 mpl::contains
<iterator_type_list
,IteratorType
>::value
||
384 mpl::contains
<const_iterator_type_list
,IteratorType
>::value
));
387 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it
);
388 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
389 it
,static_cast<const typename
IteratorType::container_type
&>(*this));
390 return index::make_iterator(static_cast<node_type
*>(it
.get_node()));
394 /* projection of iterators by tag */
396 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
397 template<typename Tag
>
398 struct index_iterator
400 typedef typename index
<Tag
>::type::iterator type
;
403 template<typename Tag
>
404 struct index_const_iterator
406 typedef typename index
<Tag
>::type::const_iterator type
;
409 template<typename Tag
,typename IteratorType
>
410 typename index_iterator
<Tag
>::type
project(
412 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag
))
414 typedef typename index
<Tag
>::type index
;
416 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
418 (mpl::contains
<iterator_type_list
,IteratorType
>::value
));
421 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it
);
422 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
423 it
,static_cast<typename
IteratorType::container_type
&>(*this));
424 return index::make_iterator(static_cast<node_type
*>(it
.get_node()));
427 template<typename Tag
,typename IteratorType
>
428 typename index_const_iterator
<Tag
>::type
project(
430 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag
))const
432 typedef typename index
<Tag
>::type index
;
434 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
435 BOOST_STATIC_ASSERT((
436 mpl::contains
<iterator_type_list
,IteratorType
>::value
||
437 mpl::contains
<const_iterator_type_list
,IteratorType
>::value
));
440 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it
);
441 BOOST_MULTI_INDEX_CHECK_IS_OWNER(
442 it
,static_cast<const typename
IteratorType::container_type
&>(*this));
443 return index::make_iterator(static_cast<node_type
*>(it
.get_node()));
447 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS
:
448 typedef typename
super::copy_map_type copy_map_type
;
450 node_type
* header()const
452 return &*bfm_header::member
;
455 node_type
* allocate_node()
457 return &*bfm_allocator::member
.allocate(1);
460 void deallocate_node(node_type
* x
)
462 typedef typename
node_allocator::pointer node_pointer
;
463 bfm_allocator::member
.deallocate(static_cast<node_pointer
>(x
),1);
468 return node_count
==0;
471 std::size_t size_()const
476 std::size_t max_size_()const
478 return static_cast<std::size_t >(-1);
481 std::pair
<node_type
*,bool> insert_(const Value
& v
)
483 node_type
* x
=allocate_node();
485 node_type
* res
=super::insert_(v
,x
);
488 return std::pair
<node_type
*,bool>(res
,true);
492 return std::pair
<node_type
*,bool>(res
,false);
502 std::pair
<node_type
*,bool> insert_(const Value
& v
,node_type
* position
)
504 node_type
* x
=allocate_node();
506 node_type
* res
=super::insert_(v
,position
,x
);
509 return std::pair
<node_type
*,bool>(res
,true);
513 return std::pair
<node_type
*,bool>(res
,false);
523 void erase_(node_type
* x
)
530 void delete_node_(node_type
* x
)
532 super::delete_node_(x
);
536 void delete_all_nodes_()
538 super::delete_all_nodes_();
548 void swap_(multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& x
)
550 if(bfm_allocator::member
!=x
.bfm_allocator::member
){
551 detail::adl_swap(bfm_allocator::member
,x
.bfm_allocator::member
);
553 std::swap(bfm_header::member
,x
.bfm_header::member
);
555 std::swap(node_count
,x
.node_count
);
558 bool replace_(const Value
& k
,node_type
* x
)
560 return super::replace_(k
,x
);
563 template<typename Modifier
>
564 bool modify_(Modifier
& mod
,node_type
* x
)
566 mod(const_cast<value_type
&>(x
->value()));
569 if(!super::modify_(x
)){
584 template<typename Modifier
,typename Rollback
>
585 bool modify_(Modifier
& mod
,Rollback
& back
,node_type
* x
)
587 mod(const_cast<value_type
&>(x
->value()));
591 b
=super::modify_rollback_(x
);
595 back(const_cast<value_type
&>(x
->value()));
608 back(const_cast<value_type
&>(x
->value()));
620 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
623 friend class boost::serialization::access
;
625 BOOST_SERIALIZATION_SPLIT_MEMBER()
627 typedef typename
super::index_saver_type index_saver_type
;
628 typedef typename
super::index_loader_type index_loader_type
;
630 template<class Archive
>
631 void save(Archive
& ar
,const unsigned int version
)const
633 const std::size_t s
=size_();
634 ar
<<serialization::make_nvp("count",s
);
635 index_saver_type
sm(bfm_allocator::member
,s
);
637 for(iterator it
=super::begin(),it_end
=super::end();it
!=it_end
;++it
){
638 ar
<<serialization::make_nvp("item",*it
);
639 sm
.add(it
.get_node(),ar
,version
);
641 sm
.add_track(header(),ar
,version
);
643 super::save_(ar
,version
,sm
);
646 template<class Archive
>
647 void load(Archive
& ar
,const unsigned int version
)
649 BOOST_MULTI_INDEX_CHECK_INVARIANT
;
654 ar
>>serialization::make_nvp("count",s
);
655 index_loader_type
lm(bfm_allocator::member
,s
);
657 for(std::size_t n
=0;n
<s
;++n
){
658 detail::archive_constructed
<Value
> value("item",ar
,version
);
659 std::pair
<node_type
*,bool> p
=insert_(
660 value
.get(),super::end().get_node());
661 if(!p
.second
)throw_exception(
662 archive::archive_exception(
663 archive::archive_exception::other_exception
));
664 ar
.reset_object_address(&p
.first
->value(),&value
.get());
665 lm
.add(p
.first
,ar
,version
);
667 lm
.add_track(header(),ar
,version
);
669 super::load_(ar
,version
,lm
);
673 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
674 /* invariant stuff */
676 bool invariant_()const
678 return super::invariant_();
681 void check_invariant_()const
683 BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
688 std::size_t node_count
;
690 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
691 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
692 #pragma parse_mfunc_templ reset
696 /* retrieval of indices by number */
698 template<typename MultiIndexContainer
,int N
>
701 BOOST_STATIC_CONSTANT(
703 M
=mpl::size
<typename
MultiIndexContainer::index_type_list
>::type::value
);
704 BOOST_STATIC_ASSERT(N
>=0&&N
<M
);
705 typedef typename
mpl::at_c
<
706 typename
MultiIndexContainer::index_type_list
,N
>::type type
;
709 template<int N
,typename Value
,typename IndexSpecifierList
,typename Allocator
>
711 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>,N
>::type
&
713 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& m
714 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N
))
716 typedef multi_index_container
<
717 Value
,IndexSpecifierList
,Allocator
> multi_index_type
;
718 typedef typename nth_index
<
719 multi_index_container
<
720 Value
,IndexSpecifierList
,Allocator
>,
724 BOOST_STATIC_ASSERT(N
>=0&&
727 BOOST_DEDUCED_TYPENAME
multi_index_type::index_type_list
730 return detail::converter
<multi_index_type
,index
>::index(m
);
733 template<int N
,typename Value
,typename IndexSpecifierList
,typename Allocator
>
734 const typename nth_index
<
735 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>,N
>::type
&
737 const multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& m
738 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N
))
740 typedef multi_index_container
<
741 Value
,IndexSpecifierList
,Allocator
> multi_index_type
;
742 typedef typename nth_index
<
743 multi_index_container
<
744 Value
,IndexSpecifierList
,Allocator
>,
748 BOOST_STATIC_ASSERT(N
>=0&&
751 BOOST_DEDUCED_TYPENAME
multi_index_type::index_type_list
754 return detail::converter
<multi_index_type
,index
>::index(m
);
757 /* retrieval of indices by tag */
759 template<typename MultiIndexContainer
,typename Tag
>
762 typedef typename
MultiIndexContainer::index_type_list index_type_list
;
764 typedef typename
mpl::find_if
<
769 BOOST_STATIC_CONSTANT(
770 bool,index_found
=!(is_same
<iter
,typename
mpl::end
<index_type_list
>::type
>::value
));
771 BOOST_STATIC_ASSERT(index_found
);
773 typedef typename
mpl::deref
<iter
>::type type
;
777 typename Tag
,typename Value
,typename IndexSpecifierList
,typename Allocator
779 typename ::boost::multi_index::index
<
780 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>,Tag
>::type
&
782 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& m
783 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag
))
785 typedef multi_index_container
<
786 Value
,IndexSpecifierList
,Allocator
> multi_index_type
;
787 typedef typename ::boost::multi_index::index
<
788 multi_index_container
<
789 Value
,IndexSpecifierList
,Allocator
>,
793 return detail::converter
<multi_index_type
,index
>::index(m
);
797 typename Tag
,typename Value
,typename IndexSpecifierList
,typename Allocator
799 const typename ::boost::multi_index::index
<
800 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>,Tag
>::type
&
802 const multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& m
803 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag
))
805 typedef multi_index_container
<
806 Value
,IndexSpecifierList
,Allocator
> multi_index_type
;
807 typedef typename ::boost::multi_index::index
<
808 multi_index_container
<
809 Value
,IndexSpecifierList
,Allocator
>,
813 return detail::converter
<multi_index_type
,index
>::index(m
);
816 /* projection of iterators by number */
818 template<typename MultiIndexContainer
,int N
>
819 struct nth_index_iterator
821 typedef typename
detail::prevent_eti
<
822 nth_index
<MultiIndexContainer
,N
>,
823 typename nth_index
<MultiIndexContainer
,N
>::type
>::type::iterator type
;
826 template<typename MultiIndexContainer
,int N
>
827 struct nth_index_const_iterator
829 typedef typename
detail::prevent_eti
<
830 nth_index
<MultiIndexContainer
,N
>,
831 typename nth_index
<MultiIndexContainer
,N
>::type
832 >::type::const_iterator type
;
836 int N
,typename IteratorType
,
837 typename Value
,typename IndexSpecifierList
,typename Allocator
>
838 typename nth_index_iterator
<
839 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>,N
>::type
841 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& m
,
843 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N
))
845 typedef multi_index_container
<
846 Value
,IndexSpecifierList
,Allocator
> multi_index_type
;
847 typedef typename nth_index
<multi_index_type
,N
>::type index
;
849 #if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
850 (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
851 BOOST_STATIC_ASSERT((
853 BOOST_DEDUCED_TYPENAME
multi_index_type::iterator_type_list
,
854 IteratorType
>::value
));
857 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it
);
859 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
860 typedef detail::converter
<
862 BOOST_DEDUCED_TYPENAME
IteratorType::container_type
> converter
;
863 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it
,converter::index(m
));
866 return detail::converter
<multi_index_type
,index
>::iterator(
867 m
,static_cast<typename
multi_index_type::node_type
*>(it
.get_node()));
871 int N
,typename IteratorType
,
872 typename Value
,typename IndexSpecifierList
,typename Allocator
>
873 typename nth_index_const_iterator
<
874 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>,N
>::type
876 const multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& m
,
878 BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N
))
880 typedef multi_index_container
<
881 Value
,IndexSpecifierList
,Allocator
> multi_index_type
;
882 typedef typename nth_index
<multi_index_type
,N
>::type index
;
884 #if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
885 (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
886 BOOST_STATIC_ASSERT((
888 BOOST_DEDUCED_TYPENAME
multi_index_type::iterator_type_list
,
889 IteratorType
>::value
||
891 BOOST_DEDUCED_TYPENAME
multi_index_type::const_iterator_type_list
,
892 IteratorType
>::value
));
895 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it
);
897 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
898 typedef detail::converter
<
900 BOOST_DEDUCED_TYPENAME
IteratorType::container_type
> converter
;
901 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it
,converter::index(m
));
904 return detail::converter
<multi_index_type
,index
>::const_iterator(
905 m
,static_cast<typename
multi_index_type::node_type
*>(it
.get_node()));
908 /* projection of iterators by tag */
910 template<typename MultiIndexContainer
,typename Tag
>
911 struct index_iterator
913 typedef typename ::boost::multi_index::index
<
914 MultiIndexContainer
,Tag
>::type::iterator type
;
917 template<typename MultiIndexContainer
,typename Tag
>
918 struct index_const_iterator
920 typedef typename ::boost::multi_index::index
<
921 MultiIndexContainer
,Tag
>::type::const_iterator type
;
925 typename Tag
,typename IteratorType
,
926 typename Value
,typename IndexSpecifierList
,typename Allocator
>
927 typename index_iterator
<
928 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>,Tag
>::type
930 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& m
,
932 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag
))
934 typedef multi_index_container
<
935 Value
,IndexSpecifierList
,Allocator
> multi_index_type
;
936 typedef typename ::boost::multi_index::index
<
937 multi_index_type
,Tag
>::type index
;
939 #if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
940 (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
941 BOOST_STATIC_ASSERT((
943 BOOST_DEDUCED_TYPENAME
multi_index_type::iterator_type_list
,
944 IteratorType
>::value
));
947 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it
);
949 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
950 typedef detail::converter
<
952 BOOST_DEDUCED_TYPENAME
IteratorType::container_type
> converter
;
953 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it
,converter::index(m
));
956 return detail::converter
<multi_index_type
,index
>::iterator(
957 m
,static_cast<typename
multi_index_type::node_type
*>(it
.get_node()));
961 typename Tag
,typename IteratorType
,
962 typename Value
,typename IndexSpecifierList
,typename Allocator
>
963 typename index_const_iterator
<
964 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>,Tag
>::type
966 const multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& m
,
968 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag
))
970 typedef multi_index_container
<
971 Value
,IndexSpecifierList
,Allocator
> multi_index_type
;
972 typedef typename ::boost::multi_index::index
<
973 multi_index_type
,Tag
>::type index
;
975 #if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
976 (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
977 BOOST_STATIC_ASSERT((
979 BOOST_DEDUCED_TYPENAME
multi_index_type::iterator_type_list
,
980 IteratorType
>::value
||
982 BOOST_DEDUCED_TYPENAME
multi_index_type::const_iterator_type_list
,
983 IteratorType
>::value
));
986 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it
);
988 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
989 typedef detail::converter
<
991 BOOST_DEDUCED_TYPENAME
IteratorType::container_type
> converter
;
992 BOOST_MULTI_INDEX_CHECK_IS_OWNER(it
,converter::index(m
));
995 return detail::converter
<multi_index_type
,index
>::const_iterator(
996 m
,static_cast<typename
multi_index_type::node_type
*>(it
.get_node()));
999 /* Comparison. Simple forward to first index. */
1002 typename Value1
,typename IndexSpecifierList1
,typename Allocator1
,
1003 typename Value2
,typename IndexSpecifierList2
,typename Allocator2
1006 const multi_index_container
<Value1
,IndexSpecifierList1
,Allocator1
>& x
,
1007 const multi_index_container
<Value2
,IndexSpecifierList2
,Allocator2
>& y
)
1009 return get
<0>(x
)==get
<0>(y
);
1013 typename Value1
,typename IndexSpecifierList1
,typename Allocator1
,
1014 typename Value2
,typename IndexSpecifierList2
,typename Allocator2
1017 const multi_index_container
<Value1
,IndexSpecifierList1
,Allocator1
>& x
,
1018 const multi_index_container
<Value2
,IndexSpecifierList2
,Allocator2
>& y
)
1020 return get
<0>(x
)<get
<0>(y
);
1024 typename Value1
,typename IndexSpecifierList1
,typename Allocator1
,
1025 typename Value2
,typename IndexSpecifierList2
,typename Allocator2
1028 const multi_index_container
<Value1
,IndexSpecifierList1
,Allocator1
>& x
,
1029 const multi_index_container
<Value2
,IndexSpecifierList2
,Allocator2
>& y
)
1031 return get
<0>(x
)!=get
<0>(y
);
1035 typename Value1
,typename IndexSpecifierList1
,typename Allocator1
,
1036 typename Value2
,typename IndexSpecifierList2
,typename Allocator2
1039 const multi_index_container
<Value1
,IndexSpecifierList1
,Allocator1
>& x
,
1040 const multi_index_container
<Value2
,IndexSpecifierList2
,Allocator2
>& y
)
1042 return get
<0>(x
)>get
<0>(y
);
1046 typename Value1
,typename IndexSpecifierList1
,typename Allocator1
,
1047 typename Value2
,typename IndexSpecifierList2
,typename Allocator2
1050 const multi_index_container
<Value1
,IndexSpecifierList1
,Allocator1
>& x
,
1051 const multi_index_container
<Value2
,IndexSpecifierList2
,Allocator2
>& y
)
1053 return get
<0>(x
)>=get
<0>(y
);
1057 typename Value1
,typename IndexSpecifierList1
,typename Allocator1
,
1058 typename Value2
,typename IndexSpecifierList2
,typename Allocator2
1061 const multi_index_container
<Value1
,IndexSpecifierList1
,Allocator1
>& x
,
1062 const multi_index_container
<Value2
,IndexSpecifierList2
,Allocator2
>& y
)
1064 return get
<0>(x
)<=get
<0>(y
);
1067 /* specialized algorithms */
1069 template<typename Value
,typename IndexSpecifierList
,typename Allocator
>
1071 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& x
,
1072 multi_index_container
<Value
,IndexSpecifierList
,Allocator
>& y
)
1077 } /* namespace multi_index */
1079 /* Associated global functions are promoted to namespace boost, except
1080 * comparison operators and swap, which are meant to be Koenig looked-up.
1083 using multi_index::get
;
1084 using multi_index::project
;
1086 } /* namespace boost */
1088 #undef BOOST_MULTI_INDEX_CHECK_INVARIANT