Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/multi_index_container.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* Multiply indexed container.
0002  *
0003  * Copyright 2003-2023 Joaquin M Lopez Munoz.
0004  * Distributed under the Boost Software License, Version 1.0.
0005  * (See accompanying file LICENSE_1_0.txt or copy at
0006  * http://www.boost.org/LICENSE_1_0.txt)
0007  *
0008  * See http://www.boost.org/libs/multi_index for library home page.
0009  */
0010 
0011 #ifndef BOOST_MULTI_INDEX_HPP
0012 #define BOOST_MULTI_INDEX_HPP
0013 
0014 #if defined(_MSC_VER)
0015 #pragma once
0016 #endif
0017 
0018 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0019 #include <algorithm>
0020 #include <boost/core/addressof.hpp>
0021 #include <boost/core/no_exceptions_support.hpp>
0022 #include <boost/detail/workaround.hpp>
0023 #include <boost/move/core.hpp>
0024 #include <boost/move/utility_core.hpp>
0025 #include <boost/mpl/at.hpp>
0026 #include <boost/mpl/contains.hpp>
0027 #include <boost/mpl/find_if.hpp>
0028 #include <boost/mpl/identity.hpp>
0029 #include <boost/mpl/int.hpp>
0030 #include <boost/mpl/size.hpp>
0031 #include <boost/mpl/deref.hpp>
0032 #include <boost/multi_index_container_fwd.hpp>
0033 #include <boost/multi_index/detail/access_specifier.hpp>
0034 #include <boost/multi_index/detail/adl_swap.hpp>
0035 #include <boost/multi_index/detail/allocator_traits.hpp>
0036 #include <boost/multi_index/detail/base_type.hpp>
0037 #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp>
0038 #include <boost/multi_index/detail/converter.hpp>
0039 #include <boost/multi_index/detail/header_holder.hpp>
0040 #include <boost/multi_index/detail/has_tag.hpp>
0041 #include <boost/multi_index/detail/invalidate_iterators.hpp>
0042 #include <boost/multi_index/detail/no_duplicate_tags.hpp>
0043 #include <boost/multi_index/detail/safe_mode.hpp>
0044 #include <boost/multi_index/detail/scope_guard.hpp>
0045 #include <boost/multi_index/detail/vartempl_support.hpp>
0046 #include <boost/static_assert.hpp>
0047 #include <boost/type_traits/integral_constant.hpp>
0048 #include <boost/type_traits/is_same.hpp>
0049 #include <boost/utility/base_from_member.hpp>
0050 
0051 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0052 #include <initializer_list>
0053 #endif
0054 
0055 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
0056 #include <boost/core/serialization.hpp>
0057 #include <boost/multi_index/detail/archive_constructed.hpp>
0058 #include <boost/multi_index/detail/bad_archive_exception.hpp>
0059 #include <boost/multi_index/detail/serialization_version.hpp>
0060 #include <boost/throw_exception.hpp> 
0061 
0062 #if defined(BOOST_MULTI_INDEX_ENABLE_SERIALIZATION_COMPATIBILITY_V2)
0063 #define BOOST_MULTI_INDEX_BLOCK_BOOSTDEP_HEADER \
0064   <boost/serialization/collection_size_type.hpp>
0065 #include BOOST_MULTI_INDEX_BLOCK_BOOSTDEP_HEADER
0066 #undef BOOST_MULTI_INDEX_BLOCK_BOOSTDEP_HEADER
0067 #endif
0068 #endif
0069 
0070 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
0071 #include <boost/multi_index/detail/invariant_assert.hpp>
0072 #define BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x)                              \
0073   detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
0074     detail::make_obj_guard(x,&multi_index_container::check_invariant_);      \
0075   BOOST_JOIN(check_invariant_,__LINE__).touch();
0076 #define BOOST_MULTI_INDEX_CHECK_INVARIANT                                    \
0077   BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(*this)
0078 #else
0079 #define BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x)
0080 #define BOOST_MULTI_INDEX_CHECK_INVARIANT
0081 #endif
0082 
0083 namespace boost{
0084 
0085 namespace multi_index{
0086 
0087 namespace detail{
0088 
0089 struct unequal_alloc_move_ctor_tag{};
0090 
0091 } /* namespace multi_index::detail */
0092 
0093 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
0094 #pragma warning(push)
0095 #pragma warning(disable:4522) /* spurious warning on multiple operator=()'s */
0096 #endif
0097 
0098 template<typename Value,typename IndexSpecifierList,typename Allocator>
0099 class multi_index_container:
0100   private ::boost::base_from_member<
0101     typename detail::rebind_alloc_for<
0102       Allocator,
0103       typename detail::multi_index_node_type<
0104         Value,IndexSpecifierList,Allocator>::type
0105     >::type
0106   >,
0107   BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
0108     typename detail::allocator_traits<
0109       typename detail::rebind_alloc_for<
0110         Allocator,
0111         typename detail::multi_index_node_type<
0112           Value,IndexSpecifierList,Allocator>::type
0113       >::type
0114     >::pointer,
0115     multi_index_container<Value,IndexSpecifierList,Allocator> >,
0116   public detail::multi_index_base_type<
0117     Value,IndexSpecifierList,Allocator>::type
0118 {
0119 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
0120     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
0121 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
0122  * lifetime of const references bound to temporaries --precisely what
0123  * scopeguards are.
0124  */
0125 
0126 #pragma parse_mfunc_templ off
0127 #endif
0128 
0129 private:
0130   BOOST_COPYABLE_AND_MOVABLE(multi_index_container)
0131 
0132 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
0133   template <typename,typename,typename> friend class  detail::index_base;
0134   template <typename,typename>          friend struct detail::header_holder;
0135   template <typename,typename>          friend struct detail::converter;
0136 #endif
0137 
0138   typedef typename detail::multi_index_base_type<
0139       Value,IndexSpecifierList,Allocator>::type    super;
0140   typedef typename detail::rebind_alloc_for<
0141     Allocator,
0142     typename super::index_node_type
0143   >::type                                          node_allocator;
0144   typedef detail::allocator_traits<node_allocator> node_alloc_traits;
0145   typedef typename node_alloc_traits::pointer      node_pointer;
0146   typedef ::boost::base_from_member<
0147     node_allocator>                                bfm_allocator;
0148   typedef detail::header_holder<
0149     node_pointer,
0150     multi_index_container>                         bfm_header;
0151 
0152 public:
0153   /* All types are inherited from super, a few are explicitly
0154    * brought forward here to save us some typename's.
0155    */
0156 
0157   typedef typename super::ctor_args_list           ctor_args_list;
0158   typedef IndexSpecifierList                       index_specifier_type_list;
0159  
0160   typedef typename super::index_type_list          index_type_list;
0161 
0162   typedef typename super::iterator_type_list       iterator_type_list;
0163   typedef typename super::const_iterator_type_list const_iterator_type_list;
0164   typedef typename super::value_type               value_type;
0165   typedef typename super::final_allocator_type     allocator_type;
0166   typedef typename super::size_type                size_type;
0167   typedef typename super::iterator                 iterator;
0168   typedef typename super::const_iterator           const_iterator;
0169 
0170   BOOST_STATIC_ASSERT(
0171     detail::no_duplicate_tags_in_index_list<index_type_list>::value);
0172 
0173   /* global project() needs to see this publicly */
0174 
0175   typedef typename super::final_node_type         final_node_type;
0176 
0177   /* construct/copy/destroy */
0178 
0179   multi_index_container():
0180     bfm_allocator(allocator_type()),
0181     super(ctor_args_list(),bfm_allocator::member),
0182     node_count(0)
0183   {
0184     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0185   }
0186 
0187   explicit multi_index_container(
0188     const ctor_args_list& args_list,
0189 
0190 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
0191     /* VisualAge seems to have an ETI issue with the default value for
0192      * argument al.
0193      */
0194 
0195     const allocator_type& al=
0196       typename mpl::identity<multi_index_container>::type::
0197         allocator_type()):
0198 #else
0199     const allocator_type& al=allocator_type()):
0200 #endif
0201 
0202     bfm_allocator(al),
0203     super(args_list,bfm_allocator::member),
0204     node_count(0)
0205   {
0206     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0207   }
0208 
0209   explicit multi_index_container(const allocator_type& al):
0210     bfm_allocator(al),
0211     super(ctor_args_list(),bfm_allocator::member),
0212     node_count(0)
0213   {
0214     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0215   }
0216   
0217   template<typename InputIterator>
0218   multi_index_container(
0219     InputIterator first,InputIterator last,
0220 
0221 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
0222     /* VisualAge seems to have an ETI issue with the default values
0223      * for arguments args_list and al.
0224      */
0225 
0226     const ctor_args_list& args_list=
0227       typename mpl::identity<multi_index_container>::type::
0228         ctor_args_list(),
0229     const allocator_type& al=
0230       typename mpl::identity<multi_index_container>::type::
0231         allocator_type()):
0232 #else
0233     const ctor_args_list& args_list=ctor_args_list(),
0234     const allocator_type& al=allocator_type()):
0235 #endif
0236 
0237     bfm_allocator(al),
0238     super(args_list,bfm_allocator::member),
0239     node_count(0)
0240   {
0241     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0242     BOOST_TRY{
0243       iterator hint=super::end();
0244       for(;first!=last;++first){
0245         hint=super::make_iterator(
0246           insert_ref_(*first,hint.get_node()).first);
0247         ++hint;
0248       }
0249     }
0250     BOOST_CATCH(...){
0251       clear_();
0252       BOOST_RETHROW;
0253     }
0254     BOOST_CATCH_END
0255   }
0256 
0257 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0258   multi_index_container(
0259     std::initializer_list<Value> list,
0260     const ctor_args_list& args_list=ctor_args_list(),
0261     const allocator_type& al=allocator_type()):
0262     bfm_allocator(al),
0263     super(args_list,bfm_allocator::member),
0264     node_count(0)
0265   {
0266     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0267     BOOST_TRY{
0268       typedef const Value* init_iterator;
0269 
0270       iterator hint=super::end();
0271       for(init_iterator first=list.begin(),last=list.end();
0272           first!=last;++first){
0273         hint=super::make_iterator(insert_(*first,hint.get_node()).first);
0274         ++hint;
0275       }
0276     }
0277     BOOST_CATCH(...){
0278       clear_();
0279       BOOST_RETHROW;
0280     }
0281     BOOST_CATCH_END
0282   }
0283 #endif
0284 
0285   multi_index_container(
0286     const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
0287     bfm_allocator(
0288       node_alloc_traits::select_on_container_copy_construction(
0289         x.bfm_allocator::member)),
0290     bfm_header(),
0291     super(x),
0292     node_count(0)
0293   {
0294     copy_construct_from(x);
0295   }
0296 
0297   multi_index_container(BOOST_RV_REF(multi_index_container) x):
0298     bfm_allocator(boost::move(x.bfm_allocator::member)),
0299     bfm_header(),
0300     super(x,detail::do_not_copy_elements_tag()),
0301     node_count(0)
0302   {
0303     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0304     BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
0305     swap_elements_(x);
0306   }
0307 
0308   multi_index_container(
0309     const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
0310     const allocator_type& al):
0311     bfm_allocator(al),
0312     bfm_header(),
0313     super(x),
0314     node_count(0)
0315   {
0316     copy_construct_from(x);
0317   }
0318 
0319   multi_index_container(
0320     BOOST_RV_REF(multi_index_container) x,const allocator_type& al):
0321     bfm_allocator(al),
0322     bfm_header(),
0323     super(x,detail::do_not_copy_elements_tag()),
0324     node_count(0)
0325   {
0326     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0327     BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
0328 
0329     if(al==x.get_allocator()){
0330       swap_elements_(x);
0331     }
0332     else{
0333       multi_index_container y(x,al,detail::unequal_alloc_move_ctor_tag());
0334       swap_elements_(y);
0335     }
0336   }
0337 
0338   ~multi_index_container()
0339   {
0340     delete_all_nodes_();
0341   }
0342 
0343 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0344   /* As per http://www.boost.org/doc/html/move/emulation_limitations.html
0345    * #move.emulation_limitations.assignment_operator
0346    */
0347 
0348   multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
0349     const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
0350   {
0351     multi_index_container y(
0352       x,
0353       node_alloc_traits::propagate_on_container_copy_assignment::value?
0354         x.get_allocator():this->get_allocator());
0355     swap_(y,boost::true_type() /* swap_allocators */);
0356     return *this;
0357   }
0358 #endif
0359 
0360   multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
0361     BOOST_COPY_ASSIGN_REF(multi_index_container) x)
0362   {
0363     multi_index_container y(
0364       x,
0365       node_alloc_traits::propagate_on_container_copy_assignment::value?
0366         x.get_allocator():this->get_allocator());
0367     swap_(y,boost::true_type() /* swap_allocators */);
0368     return *this;
0369   }
0370 
0371   multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
0372     BOOST_RV_REF(multi_index_container) x)
0373   {
0374 #include <boost/multi_index/detail/define_if_constexpr_macro.hpp>
0375 
0376     BOOST_MULTI_INDEX_IF_CONSTEXPR(
0377       node_alloc_traits::propagate_on_container_move_assignment::value){
0378       swap_(x,boost::true_type() /* swap_allocators */);
0379     }
0380     else if(this->get_allocator()==x.get_allocator()){
0381       swap_(x,boost::false_type() /* swap_allocators */);
0382     }
0383     else{
0384       multi_index_container y(boost::move(x),this->get_allocator());
0385       swap_(y,boost::false_type() /* swap_allocators */);
0386     }
0387     return *this;
0388 
0389 #include <boost/multi_index/detail/undef_if_constexpr_macro.hpp>
0390   }
0391 
0392 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0393   multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
0394     std::initializer_list<Value> list)
0395   {
0396     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0397     typedef const Value* init_iterator;
0398 
0399     multi_index_container x(*this,detail::do_not_copy_elements_tag());    
0400     iterator hint=x.end();
0401     for(init_iterator first=list.begin(),last=list.end();
0402         first!=last;++first){
0403       hint=x.make_iterator(x.insert_(*first,hint.get_node()).first);
0404       ++hint;
0405     }
0406     x.swap_elements_(*this);
0407     return*this;
0408   }
0409 #endif
0410 
0411   allocator_type get_allocator()const BOOST_NOEXCEPT
0412   {
0413     return allocator_type(bfm_allocator::member);
0414   }
0415 
0416   /* retrieval of indices by number */
0417 
0418 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
0419   template<int N>
0420   struct nth_index
0421   {
0422     BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
0423     typedef typename mpl::at_c<index_type_list,N>::type type;
0424   };
0425 
0426   template<int N>
0427   typename nth_index<N>::type& get()BOOST_NOEXCEPT
0428   {
0429     BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
0430     return *this;
0431   }
0432 
0433   template<int N>
0434   const typename nth_index<N>::type& get()const BOOST_NOEXCEPT
0435   {
0436     BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
0437     return *this;
0438   }
0439 #endif
0440 
0441   /* retrieval of indices by tag */
0442 
0443 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
0444   template<typename Tag>
0445   struct index
0446   {
0447     typedef typename mpl::find_if<
0448       index_type_list,
0449       detail::has_tag<Tag>
0450     >::type                                    iter;
0451 
0452     BOOST_STATIC_CONSTANT(
0453       bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
0454     BOOST_STATIC_ASSERT(index_found);
0455 
0456     typedef typename mpl::deref<iter>::type    type;
0457   };
0458 
0459   template<typename Tag>
0460   typename index<Tag>::type& get()BOOST_NOEXCEPT
0461   {
0462     return *this;
0463   }
0464 
0465   template<typename Tag>
0466   const typename index<Tag>::type& get()const BOOST_NOEXCEPT
0467   {
0468     return *this;
0469   }
0470 #endif
0471 
0472   /* projection of iterators by number */
0473 
0474 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
0475   template<int N>
0476   struct nth_index_iterator
0477   {
0478     typedef typename nth_index<N>::type::iterator type;
0479   };
0480 
0481   template<int N>
0482   struct nth_index_const_iterator
0483   {
0484     typedef typename nth_index<N>::type::const_iterator type;
0485   };
0486 
0487   template<int N,typename IteratorType>
0488   typename nth_index_iterator<N>::type project(IteratorType it)
0489   {
0490     typedef typename nth_index<N>::type index_type;
0491 
0492 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
0493     BOOST_STATIC_ASSERT(
0494       (mpl::contains<iterator_type_list,IteratorType>::value));
0495 #endif
0496 
0497     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
0498     BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,*this);
0499     return index_type::make_iterator(
0500       static_cast<final_node_type*>(it.get_node()));
0501   }
0502 
0503   template<int N,typename IteratorType>
0504   typename nth_index_const_iterator<N>::type project(IteratorType it)const
0505   {
0506     typedef typename nth_index<N>::type index_type;
0507 
0508 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
0509     BOOST_STATIC_ASSERT((
0510       mpl::contains<iterator_type_list,IteratorType>::value||
0511       mpl::contains<const_iterator_type_list,IteratorType>::value));
0512 #endif
0513 
0514     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
0515     BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,*this);
0516     return index_type::make_iterator(
0517       static_cast<final_node_type*>(it.get_node()));
0518   }
0519 #endif
0520 
0521   /* projection of iterators by tag */
0522 
0523 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
0524   template<typename Tag>
0525   struct index_iterator
0526   {
0527     typedef typename index<Tag>::type::iterator type;
0528   };
0529 
0530   template<typename Tag>
0531   struct index_const_iterator
0532   {
0533     typedef typename index<Tag>::type::const_iterator type;
0534   };
0535 
0536   template<typename Tag,typename IteratorType>
0537   typename index_iterator<Tag>::type project(IteratorType it)
0538   {
0539     typedef typename index<Tag>::type index_type;
0540 
0541 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
0542     BOOST_STATIC_ASSERT(
0543       (mpl::contains<iterator_type_list,IteratorType>::value));
0544 #endif
0545 
0546     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
0547     BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,*this);
0548     return index_type::make_iterator(
0549       static_cast<final_node_type*>(it.get_node()));
0550   }
0551 
0552   template<typename Tag,typename IteratorType>
0553   typename index_const_iterator<Tag>::type project(IteratorType it)const
0554   {
0555     typedef typename index<Tag>::type index_type;
0556 
0557 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
0558     BOOST_STATIC_ASSERT((
0559       mpl::contains<iterator_type_list,IteratorType>::value||
0560       mpl::contains<const_iterator_type_list,IteratorType>::value));
0561 #endif
0562 
0563     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
0564     BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,*this);
0565     return index_type::make_iterator(
0566       static_cast<final_node_type*>(it.get_node()));
0567   }
0568 #endif
0569 
0570 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
0571   typedef typename super::final_node_handle_type final_node_handle_type;
0572   typedef typename super::copy_map_type          copy_map_type;
0573 
0574   multi_index_container(
0575     multi_index_container<Value,IndexSpecifierList,Allocator>& x,
0576     const allocator_type& al,
0577     detail::unequal_alloc_move_ctor_tag):
0578     bfm_allocator(al),
0579     bfm_header(),
0580     super(x),
0581     node_count(0)
0582   {
0583     BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
0584     BOOST_TRY{
0585       copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
0586       for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
0587         map.move_clone(it.get_node());
0588       }
0589       super::copy_(x,map);
0590       map.release();
0591       node_count=x.size();
0592       x.clear();
0593     }
0594     BOOST_CATCH(...){
0595       x.clear();
0596       BOOST_RETHROW;
0597     }
0598     BOOST_CATCH_END
0599 
0600     /* Not until this point are the indices required to be consistent,
0601      * hence the position of the invariant checker.
0602      */
0603 
0604     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0605   }
0606 
0607 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0608   multi_index_container(
0609     const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
0610     detail::do_not_copy_elements_tag):
0611     bfm_allocator(x.bfm_allocator::member),
0612     bfm_header(),
0613     super(x,detail::do_not_copy_elements_tag()),
0614     node_count(0)
0615   {
0616     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0617   }
0618 #endif
0619 
0620   void copy_construct_from(
0621     const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
0622   {
0623     copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
0624     for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
0625       map.copy_clone(it.get_node());
0626     }
0627     super::copy_(x,map);
0628     map.release();
0629     node_count=x.size();
0630 
0631     /* Not until this point are the indices required to be consistent,
0632      * hence the position of the invariant checker.
0633      */
0634 
0635     BOOST_MULTI_INDEX_CHECK_INVARIANT;
0636   }
0637 
0638   final_node_type* header()const
0639   {
0640     return &*bfm_header::member;
0641   }
0642 
0643   final_node_type* allocate_node()
0644   {
0645     return &*node_alloc_traits::allocate(bfm_allocator::member,1);
0646   }
0647 
0648   void deallocate_node(final_node_type* x)
0649   {
0650     node_alloc_traits::deallocate(
0651       bfm_allocator::member,static_cast<node_pointer>(x),1);
0652   }
0653 
0654   void construct_value(final_node_type* x,const Value& v)
0655   {
0656     node_alloc_traits::construct(
0657       bfm_allocator::member,boost::addressof(x->value()),v);
0658   }
0659 
0660   void construct_value(final_node_type* x,BOOST_RV_REF(Value) v)
0661   {
0662     node_alloc_traits::construct(
0663       bfm_allocator::member,boost::addressof(x->value()),boost::move(v));
0664   }
0665 
0666   BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
0667     void,construct_value,vartempl_construct_value_impl,final_node_type*,x)
0668 
0669   void destroy_value(final_node_type* x)
0670   {
0671     node_alloc_traits::destroy(
0672       bfm_allocator::member,boost::addressof(x->value()));
0673   }
0674 
0675   bool empty_()const
0676   {
0677     return node_count==0;
0678   }
0679 
0680   size_type size_()const
0681   {
0682     return node_count;
0683   }
0684 
0685   size_type max_size_()const
0686   {
0687     return static_cast<size_type>(-1);
0688   }
0689 
0690   template<typename Variant>
0691   std::pair<final_node_type*,bool> insert_(const Value& v,Variant variant)
0692   {
0693     final_node_type* x=0;
0694     final_node_type* res=super::insert_(v,x,variant);
0695     if(res==x){
0696       ++node_count;
0697       return std::pair<final_node_type*,bool>(res,true);
0698     }
0699     else{
0700       return std::pair<final_node_type*,bool>(res,false);
0701     }
0702   }
0703 
0704   std::pair<final_node_type*,bool> insert_(const Value& v)
0705   {
0706     return insert_(v,detail::lvalue_tag());
0707   }
0708 
0709   std::pair<final_node_type*,bool> insert_rv_(const Value& v)
0710   {
0711     return insert_(v,detail::rvalue_tag());
0712   }
0713 
0714   template<typename T>
0715   std::pair<final_node_type*,bool> insert_ref_(T& t)
0716   {
0717     final_node_type* x=allocate_node();
0718     BOOST_TRY{
0719       construct_value(x,t);
0720       BOOST_TRY{
0721         final_node_type* res=super::insert_(
0722           x->value(),x,detail::emplaced_tag());
0723         if(res==x){
0724           ++node_count;
0725           return std::pair<final_node_type*,bool>(res,true);
0726         }
0727         else{
0728           delete_node_(x);
0729           return std::pair<final_node_type*,bool>(res,false);
0730         }
0731       }
0732       BOOST_CATCH(...){
0733         destroy_value(x);
0734         BOOST_RETHROW;
0735       }
0736       BOOST_CATCH_END
0737     }
0738     BOOST_CATCH(...){
0739       deallocate_node(x);
0740       BOOST_RETHROW;
0741     }
0742     BOOST_CATCH_END
0743   }
0744 
0745   std::pair<final_node_type*,bool> insert_ref_(const value_type& x)
0746   {
0747     return insert_(x);
0748   }
0749 
0750   std::pair<final_node_type*,bool> insert_ref_(value_type& x)
0751   {
0752     return insert_(x);
0753   }
0754 
0755   std::pair<final_node_type*,bool> insert_nh_(final_node_handle_type& nh)
0756   {
0757     if(!nh)return std::pair<final_node_type*,bool>(header(),false);
0758     else{
0759       final_node_type* x=nh.node;
0760       final_node_type* res=super::insert_(
0761         x->value(),x,detail::emplaced_tag());
0762       if(res==x){
0763         nh.release_node();
0764         ++node_count;
0765         return std::pair<final_node_type*,bool>(res,true);
0766       }
0767       else return std::pair<final_node_type*,bool>(res,false);
0768     }
0769   }
0770 
0771   template<typename Index>
0772   std::pair<final_node_type*,bool> transfer_(Index& x,final_node_type* n)
0773   {
0774     final_node_type* res=super::insert_(n->value(),n,&super::final(x));
0775     if(res==n){
0776       ++node_count;
0777       return std::pair<final_node_type*,bool>(res,true);
0778     }
0779     else{
0780       return std::pair<final_node_type*,bool>(res,false);
0781     }
0782   }
0783 
0784   template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
0785   std::pair<final_node_type*,bool> emplace_(
0786     BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
0787   {
0788     final_node_type* x=allocate_node();
0789     BOOST_TRY{
0790       construct_value(x,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
0791       BOOST_TRY{
0792         final_node_type* res=super::insert_(
0793           x->value(),x,detail::emplaced_tag());
0794         if(res==x){
0795           ++node_count;
0796           return std::pair<final_node_type*,bool>(res,true);
0797         }
0798         else{
0799           delete_node_(x);
0800           return std::pair<final_node_type*,bool>(res,false);
0801         }
0802       }
0803       BOOST_CATCH(...){
0804         destroy_value(x);
0805         BOOST_RETHROW;
0806       }
0807       BOOST_CATCH_END
0808     }
0809     BOOST_CATCH(...){
0810       deallocate_node(x);
0811       BOOST_RETHROW;
0812     }
0813     BOOST_CATCH_END
0814   }
0815 
0816   template<typename Variant>
0817   std::pair<final_node_type*,bool> insert_(
0818     const Value& v,final_node_type* position,Variant variant)
0819   {
0820     final_node_type* x=0;
0821     final_node_type* res=super::insert_(v,position,x,variant);
0822     if(res==x){
0823       ++node_count;
0824       return std::pair<final_node_type*,bool>(res,true);
0825     }
0826     else{
0827       return std::pair<final_node_type*,bool>(res,false);
0828     }
0829   }
0830 
0831   std::pair<final_node_type*,bool> insert_(
0832     const Value& v,final_node_type* position)
0833   {
0834     return insert_(v,position,detail::lvalue_tag());
0835   }
0836 
0837   std::pair<final_node_type*,bool> insert_rv_(
0838     const Value& v,final_node_type* position)
0839   {
0840     return insert_(v,position,detail::rvalue_tag());
0841   }
0842 
0843   template<typename T>
0844   std::pair<final_node_type*,bool> insert_ref_(
0845     T& t,final_node_type* position)
0846   {
0847     final_node_type* x=allocate_node();
0848     BOOST_TRY{
0849       construct_value(x,t);
0850       BOOST_TRY{
0851         final_node_type* res=super::insert_(
0852           x->value(),position,x,detail::emplaced_tag());
0853         if(res==x){
0854           ++node_count;
0855           return std::pair<final_node_type*,bool>(res,true);
0856         }
0857         else{
0858           delete_node_(x);
0859           return std::pair<final_node_type*,bool>(res,false);
0860         }
0861       }
0862       BOOST_CATCH(...){
0863         destroy_value(x);
0864         BOOST_RETHROW;
0865       }
0866       BOOST_CATCH_END
0867     }
0868     BOOST_CATCH(...){
0869       deallocate_node(x);
0870       BOOST_RETHROW;
0871     }
0872     BOOST_CATCH_END
0873   }
0874 
0875   std::pair<final_node_type*,bool> insert_ref_(
0876     const value_type& x,final_node_type* position)
0877   {
0878     return insert_(x,position);
0879   }
0880 
0881   std::pair<final_node_type*,bool> insert_ref_(
0882     value_type& x,final_node_type* position)
0883   {
0884     return insert_(x,position);
0885   }
0886 
0887   std::pair<final_node_type*,bool> insert_nh_(
0888     final_node_handle_type& nh,final_node_type* position)
0889   {
0890     if(!nh)return std::pair<final_node_type*,bool>(header(),false);
0891     else{
0892       final_node_type* x=nh.node;
0893       final_node_type* res=super::insert_(
0894         x->value(),position,x,detail::emplaced_tag());
0895       if(res==x){
0896         nh.release_node();
0897         ++node_count;
0898         return std::pair<final_node_type*,bool>(res,true);
0899       }
0900       else return std::pair<final_node_type*,bool>(res,false);
0901     }
0902   }
0903 
0904   template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
0905   std::pair<final_node_type*,bool> emplace_hint_(
0906     final_node_type* position,
0907     BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
0908   {
0909     final_node_type* x=allocate_node();
0910     BOOST_TRY{
0911       construct_value(x,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
0912       BOOST_TRY{
0913         final_node_type* res=super::insert_(
0914           x->value(),position,x,detail::emplaced_tag());
0915         if(res==x){
0916           ++node_count;
0917           return std::pair<final_node_type*,bool>(res,true);
0918         }
0919         else{
0920           delete_node_(x);
0921           return std::pair<final_node_type*,bool>(res,false);
0922         }
0923       }
0924       BOOST_CATCH(...){
0925         destroy_value(x);
0926         BOOST_RETHROW;
0927       }
0928       BOOST_CATCH_END
0929     }
0930     BOOST_CATCH(...){
0931       deallocate_node(x);
0932       BOOST_RETHROW;
0933     }
0934     BOOST_CATCH_END
0935   }
0936 
0937   final_node_handle_type extract_(final_node_type* x)
0938   {
0939     --node_count;
0940     super::extract_(x,detail::invalidate_iterators());
0941     return final_node_handle_type(x,get_allocator());
0942   }
0943 
0944   template<typename Dst>
0945   void extract_for_transfer_(final_node_type* x,Dst dst)
0946   {
0947     --node_count;
0948     super::extract_(x,dst);
0949   }
0950 
0951   void erase_(final_node_type* x)
0952   {
0953     --node_count;
0954     super::extract_(x,detail::invalidate_iterators());
0955     delete_node_(x);
0956   }
0957 
0958   void delete_node_(final_node_type* x)
0959   {
0960     destroy_value(x);
0961     deallocate_node(x);
0962   }
0963 
0964   void delete_all_nodes_()
0965   {
0966     super::delete_all_nodes_();
0967   }
0968 
0969   void clear_()
0970   {
0971     delete_all_nodes_();
0972     super::clear_();
0973     node_count=0;
0974   }
0975 
0976   template<typename Index>
0977   void transfer_range_(
0978     Index& x,
0979     BOOST_DEDUCED_TYPENAME Index::iterator first,
0980     BOOST_DEDUCED_TYPENAME Index::iterator last)
0981   {
0982     while(first!=last){
0983       transfer_(x,static_cast<final_node_type*>((first++).get_node()));
0984     }
0985   }
0986 
0987   void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
0988   {
0989     swap_(
0990       x,
0991       boost::integral_constant<
0992         bool,node_alloc_traits::propagate_on_container_swap::value>());
0993   }
0994 
0995   void swap_(
0996     multi_index_container<Value,IndexSpecifierList,Allocator>& x,
0997     boost::true_type swap_allocators)
0998   {
0999     detail::adl_swap(bfm_allocator::member,x.bfm_allocator::member);
1000     std::swap(bfm_header::member,x.bfm_header::member);
1001     super::swap_(x,swap_allocators);
1002     std::swap(node_count,x.node_count);
1003   }
1004 
1005   void swap_(
1006     multi_index_container<Value,IndexSpecifierList,Allocator>& x,
1007     boost::false_type swap_allocators)
1008   {
1009     std::swap(bfm_header::member,x.bfm_header::member);
1010     super::swap_(x,swap_allocators);
1011     std::swap(node_count,x.node_count);
1012   }
1013 
1014   void swap_elements_(
1015     multi_index_container<Value,IndexSpecifierList,Allocator>& x)
1016   {
1017     std::swap(bfm_header::member,x.bfm_header::member);
1018     super::swap_elements_(x);
1019     std::swap(node_count,x.node_count);
1020   }
1021 
1022   bool replace_(const Value& k,final_node_type* x)
1023   {
1024     return super::replace_(k,x,detail::lvalue_tag());
1025   }
1026 
1027   bool replace_rv_(const Value& k,final_node_type* x)
1028   {
1029     return super::replace_(k,x,detail::rvalue_tag());
1030   }
1031 
1032   template<typename Modifier>
1033   bool modify_(Modifier& mod,final_node_type* x)
1034   {
1035     BOOST_TRY{
1036       mod(const_cast<value_type&>(x->value()));
1037     }
1038     BOOST_CATCH(...){
1039       this->erase_(x);
1040       BOOST_RETHROW;
1041     }
1042     BOOST_CATCH_END
1043 
1044     BOOST_TRY{
1045       if(!super::modify_(x)){
1046         delete_node_(x);
1047         --node_count;
1048         return false;
1049       }
1050       else return true;
1051     }
1052     BOOST_CATCH(...){
1053       delete_node_(x);
1054       --node_count;
1055       BOOST_RETHROW;
1056     }
1057     BOOST_CATCH_END
1058   }
1059 
1060   template<typename Modifier,typename Rollback>
1061   bool modify_(Modifier& mod,Rollback& back_,final_node_type* x)
1062   {
1063     BOOST_TRY{
1064       mod(const_cast<value_type&>(x->value()));
1065     }
1066     BOOST_CATCH(...){
1067       this->erase_(x);
1068       BOOST_RETHROW;
1069     }
1070     BOOST_CATCH_END
1071 
1072     bool b;
1073     BOOST_TRY{
1074       b=super::modify_rollback_(x);
1075     }
1076     BOOST_CATCH(...){
1077       BOOST_TRY{
1078         back_(const_cast<value_type&>(x->value()));
1079         if(!super::check_rollback_(x))this->erase_(x);
1080         BOOST_RETHROW;
1081       }
1082       BOOST_CATCH(...){
1083         this->erase_(x);
1084         BOOST_RETHROW;
1085       }
1086       BOOST_CATCH_END
1087     }
1088     BOOST_CATCH_END
1089 
1090     BOOST_TRY{
1091       if(!b){
1092         back_(const_cast<value_type&>(x->value()));
1093         if(!super::check_rollback_(x))this->erase_(x);
1094         return false;
1095       }
1096       else return true;
1097     }
1098     BOOST_CATCH(...){
1099       this->erase_(x);
1100       BOOST_RETHROW;
1101     }
1102     BOOST_CATCH_END
1103   }
1104 
1105 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
1106   /* serialization */
1107 
1108   friend class boost::serialization::access;
1109 
1110   template<class Archive>
1111   void serialize(Archive& ar,const unsigned int version)
1112   {
1113     core::split_member(ar,*this,version);
1114   }
1115 
1116   typedef typename super::index_saver_type        index_saver_type;
1117   typedef typename super::index_loader_type       index_loader_type;
1118 
1119   template<class Archive>
1120   void save(Archive& ar,const unsigned int version)const
1121   {
1122     const std::size_t                               s(size_());
1123     const detail::serialization_version<value_type> value_version;
1124     ar<<core::make_nvp("count",s);
1125     ar<<core::make_nvp("value_version",value_version);
1126 
1127     index_saver_type sm(bfm_allocator::member,s);
1128 
1129     for(iterator it=super::begin(),it_end=super::end();it!=it_end;++it){
1130       core::save_construct_data_adl(
1131         ar,boost::addressof(*it),value_version);
1132       ar<<serialization::make_nvp("item",*it);
1133       sm.add(it.get_node(),ar,version);
1134     }
1135     sm.add_track(header(),ar,version);
1136 
1137     super::save_(ar,version,sm);
1138   }
1139 
1140   template<class Archive>
1141   void load(Archive& ar,const unsigned int version)
1142   {
1143     BOOST_MULTI_INDEX_CHECK_INVARIANT;
1144 
1145     clear_(); 
1146     std::size_t                               s;
1147     detail::serialization_version<value_type> value_version;
1148     if(version<1){
1149       std::size_t sz;
1150       ar>>core::make_nvp("count",sz);
1151       s=static_cast<std::size_t>(sz);
1152     }
1153     else if(version<3){
1154 #if defined(BOOST_MULTI_INDEX_ENABLE_SERIALIZATION_COMPATIBILITY_V2)
1155       serialization::collection_size_type csz;
1156       ar>>core::make_nvp("count",csz);
1157       s=static_cast<std::size_t>(csz);
1158 #else
1159       ar>>core::make_nvp("count",s);
1160 #endif
1161     }
1162     else if(version<4){
1163       unsigned long ul;
1164       ar>>core::make_nvp("count",ul);
1165       s=static_cast<std::size_t>(ul);
1166     }
1167     else{
1168       ar>>core::make_nvp("count",s);
1169     }
1170 
1171     if(version<2){
1172       value_version=0;
1173     }
1174     else{
1175       ar>>core::make_nvp("value_version",value_version);
1176     }
1177 
1178     index_loader_type lm(bfm_allocator::member,s);
1179 
1180     for(std::size_t n=0;n<s;++n){
1181       detail::archive_constructed<Value> value("item",ar,value_version);
1182       std::pair<final_node_type*,bool> p=insert_rv_(
1183         value.get(),super::end().get_node());
1184       if(!p.second)throw_exception(detail::bad_archive_exception());
1185       ar.reset_object_address(
1186         boost::addressof(p.first->value()),boost::addressof(value.get()));
1187       lm.add(p.first,ar,version);
1188     }
1189     lm.add_track(header(),ar,version);
1190 
1191     super::load_(ar,version,lm);
1192   }
1193 #endif
1194 
1195 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
1196   /* invariant stuff */
1197 
1198   bool invariant_()const
1199   {
1200     return super::invariant_();
1201   }
1202 
1203   void check_invariant_()const
1204   {
1205     BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
1206   }
1207 #endif
1208 
1209 private:
1210   template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
1211   void vartempl_construct_value_impl(
1212     final_node_type* x,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
1213   {
1214     node_alloc_traits::construct(
1215       bfm_allocator::member,boost::addressof(x->value()),
1216       BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
1217   }
1218 
1219   size_type node_count;
1220 
1221 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
1222     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
1223 #pragma parse_mfunc_templ reset
1224 #endif
1225 };
1226 
1227 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
1228 #pragma warning(pop) /* C4522 */
1229 #endif
1230 
1231 /* retrieval of indices by number */
1232 
1233 template<typename MultiIndexContainer,int N>
1234 struct nth_index
1235 {
1236   BOOST_STATIC_CONSTANT(
1237     int,
1238     M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
1239   BOOST_STATIC_ASSERT(N>=0&&N<M);
1240   typedef typename mpl::at_c<
1241     typename MultiIndexContainer::index_type_list,N>::type type;
1242 };
1243 
1244 template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
1245 typename nth_index<
1246   multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
1247 get(
1248   multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
1249 {
1250   typedef multi_index_container<
1251     Value,IndexSpecifierList,Allocator>    multi_index_type;
1252   typedef typename nth_index<
1253     multi_index_container<
1254       Value,IndexSpecifierList,Allocator>,
1255     N
1256   >::type                                  index_type;
1257 
1258   BOOST_STATIC_ASSERT(N>=0&&
1259     N<
1260     mpl::size<
1261       BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
1262     >::type::value);
1263 
1264   return detail::converter<multi_index_type,index_type>::index(m);
1265 }
1266 
1267 template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
1268 const typename nth_index<
1269   multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
1270 get(
1271   const multi_index_container<Value,IndexSpecifierList,Allocator>& m
1272 )BOOST_NOEXCEPT
1273 {
1274   typedef multi_index_container<
1275     Value,IndexSpecifierList,Allocator>    multi_index_type;
1276   typedef typename nth_index<
1277     multi_index_container<
1278       Value,IndexSpecifierList,Allocator>,
1279     N
1280   >::type                                  index_type;
1281 
1282   BOOST_STATIC_ASSERT(N>=0&&
1283     N<
1284     mpl::size<
1285       BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
1286     >::type::value);
1287 
1288   return detail::converter<multi_index_type,index_type>::index(m);
1289 }
1290 
1291 /* retrieval of indices by tag */
1292 
1293 template<typename MultiIndexContainer,typename Tag>
1294 struct index
1295 {
1296   typedef typename MultiIndexContainer::index_type_list index_type_list;
1297 
1298   typedef typename mpl::find_if<
1299     index_type_list,
1300     detail::has_tag<Tag>
1301   >::type                                      iter;
1302 
1303   BOOST_STATIC_CONSTANT(
1304     bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
1305   BOOST_STATIC_ASSERT(index_found);
1306 
1307   typedef typename mpl::deref<iter>::type       type;
1308 };
1309 
1310 template<
1311   typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
1312 >
1313 typename ::boost::multi_index::index<
1314   multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
1315 get(
1316   multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
1317 {
1318   typedef multi_index_container<
1319     Value,IndexSpecifierList,Allocator>         multi_index_type;
1320   typedef typename ::boost::multi_index::index<
1321     multi_index_container<
1322       Value,IndexSpecifierList,Allocator>,
1323     Tag
1324   >::type                                       index_type;
1325 
1326   return detail::converter<multi_index_type,index_type>::index(m);
1327 }
1328 
1329 template<
1330   typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
1331 >
1332 const typename ::boost::multi_index::index<
1333   multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
1334 get(
1335   const multi_index_container<Value,IndexSpecifierList,Allocator>& m
1336 )BOOST_NOEXCEPT
1337 {
1338   typedef multi_index_container<
1339     Value,IndexSpecifierList,Allocator>         multi_index_type;
1340   typedef typename ::boost::multi_index::index<
1341     multi_index_container<
1342       Value,IndexSpecifierList,Allocator>,
1343     Tag
1344   >::type                                       index_type;
1345 
1346   return detail::converter<multi_index_type,index_type>::index(m);
1347 }
1348 
1349 /* projection of iterators by number */
1350 
1351 template<typename MultiIndexContainer,int N>
1352 struct nth_index_iterator
1353 {
1354   typedef typename nth_index<MultiIndexContainer,N>::type::iterator type;
1355 };
1356 
1357 template<typename MultiIndexContainer,int N>
1358 struct nth_index_const_iterator
1359 {
1360   typedef typename nth_index<MultiIndexContainer,N>::type::const_iterator type;
1361 };
1362 
1363 template<
1364   int N,typename IteratorType,
1365   typename Value,typename IndexSpecifierList,typename Allocator>
1366 typename nth_index_iterator<
1367   multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
1368 project(
1369   multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1370   IteratorType it)
1371 {
1372   typedef multi_index_container<
1373     Value,IndexSpecifierList,Allocator>                multi_index_type;
1374   typedef typename nth_index<multi_index_type,N>::type index_type;
1375 
1376 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1377   BOOST_STATIC_ASSERT((
1378     mpl::contains<
1379       BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1380       IteratorType>::value));
1381 #endif
1382 
1383   BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1384   BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
1385   return detail::converter<multi_index_type,index_type>::iterator(
1386     m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
1387 }
1388 
1389 template<
1390   int N,typename IteratorType,
1391   typename Value,typename IndexSpecifierList,typename Allocator>
1392 typename nth_index_const_iterator<
1393   multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
1394 project(
1395   const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1396   IteratorType it)
1397 {
1398   typedef multi_index_container<
1399     Value,IndexSpecifierList,Allocator>                multi_index_type;
1400   typedef typename nth_index<multi_index_type,N>::type index_type;
1401 
1402 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1403   BOOST_STATIC_ASSERT((
1404     mpl::contains<
1405       BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1406       IteratorType>::value||
1407     mpl::contains<
1408       BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
1409       IteratorType>::value));
1410 #endif
1411 
1412   BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1413   BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
1414   return detail::converter<multi_index_type,index_type>::const_iterator(
1415     m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
1416 }
1417 
1418 /* projection of iterators by tag */
1419 
1420 template<typename MultiIndexContainer,typename Tag>
1421 struct index_iterator
1422 {
1423   typedef typename ::boost::multi_index::index<
1424     MultiIndexContainer,Tag>::type::iterator    type;
1425 };
1426 
1427 template<typename MultiIndexContainer,typename Tag>
1428 struct index_const_iterator
1429 {
1430   typedef typename ::boost::multi_index::index<
1431     MultiIndexContainer,Tag>::type::const_iterator type;
1432 };
1433 
1434 template<
1435   typename Tag,typename IteratorType,
1436   typename Value,typename IndexSpecifierList,typename Allocator>
1437 typename index_iterator<
1438   multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
1439 project(
1440   multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1441   IteratorType it)
1442 {
1443   typedef multi_index_container<
1444     Value,IndexSpecifierList,Allocator>         multi_index_type;
1445   typedef typename ::boost::multi_index::index<
1446     multi_index_type,Tag>::type                 index_type;
1447 
1448 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1449   BOOST_STATIC_ASSERT((
1450     mpl::contains<
1451       BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1452       IteratorType>::value));
1453 #endif
1454 
1455   BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1456   BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
1457   return detail::converter<multi_index_type,index_type>::iterator(
1458     m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
1459 }
1460 
1461 template<
1462   typename Tag,typename IteratorType,
1463   typename Value,typename IndexSpecifierList,typename Allocator>
1464 typename index_const_iterator<
1465   multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
1466 project(
1467   const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
1468   IteratorType it)
1469 {
1470   typedef multi_index_container<
1471     Value,IndexSpecifierList,Allocator>         multi_index_type;
1472   typedef typename ::boost::multi_index::index<
1473     multi_index_type,Tag>::type                 index_type;
1474 
1475 #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
1476   BOOST_STATIC_ASSERT((
1477     mpl::contains<
1478       BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
1479       IteratorType>::value||
1480     mpl::contains<
1481       BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
1482       IteratorType>::value));
1483 #endif
1484 
1485   BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
1486   BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
1487   return detail::converter<multi_index_type,index_type>::const_iterator(
1488     m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
1489 }
1490 
1491 /* Comparison. Simple forward to first index. */
1492 
1493 template<
1494   typename Value1,typename IndexSpecifierList1,typename Allocator1,
1495   typename Value2,typename IndexSpecifierList2,typename Allocator2
1496 >
1497 bool operator==(
1498   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1499   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1500 {
1501   return get<0>(x)==get<0>(y);
1502 }
1503 
1504 template<
1505   typename Value1,typename IndexSpecifierList1,typename Allocator1,
1506   typename Value2,typename IndexSpecifierList2,typename Allocator2
1507 >
1508 bool operator<(
1509   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1510   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1511 {
1512   return get<0>(x)<get<0>(y);
1513 }
1514 
1515 template<
1516   typename Value1,typename IndexSpecifierList1,typename Allocator1,
1517   typename Value2,typename IndexSpecifierList2,typename Allocator2
1518 >
1519 bool operator!=(
1520   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1521   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1522 {
1523   return get<0>(x)!=get<0>(y);
1524 }
1525 
1526 template<
1527   typename Value1,typename IndexSpecifierList1,typename Allocator1,
1528   typename Value2,typename IndexSpecifierList2,typename Allocator2
1529 >
1530 bool operator>(
1531   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1532   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1533 {
1534   return get<0>(x)>get<0>(y);
1535 }
1536 
1537 template<
1538   typename Value1,typename IndexSpecifierList1,typename Allocator1,
1539   typename Value2,typename IndexSpecifierList2,typename Allocator2
1540 >
1541 bool operator>=(
1542   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1543   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1544 {
1545   return get<0>(x)>=get<0>(y);
1546 }
1547 
1548 template<
1549   typename Value1,typename IndexSpecifierList1,typename Allocator1,
1550   typename Value2,typename IndexSpecifierList2,typename Allocator2
1551 >
1552 bool operator<=(
1553   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
1554   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
1555 {
1556   return get<0>(x)<=get<0>(y);
1557 }
1558 
1559 /*  specialized algorithms */
1560 
1561 template<typename Value,typename IndexSpecifierList,typename Allocator>
1562 void swap(
1563   multi_index_container<Value,IndexSpecifierList,Allocator>& x,
1564   multi_index_container<Value,IndexSpecifierList,Allocator>& y)
1565 {
1566   x.swap(y);
1567 }
1568 
1569 } /* namespace multi_index */
1570 
1571 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
1572 /* class version = 1 : we now serialize the size through
1573  * boost::serialization::collection_size_type.
1574  * class version = 2 : proper use of {save|load}_construct_data.
1575  * class version = 3 : dropped boost::serialization::collection_size_type
1576  * in favor of unsigned long --this allows us to provide serialization
1577  * support without including any header from Boost.Serialization.
1578  * class version = 4 : uses std::size_t rather than unsigned long (which
1579  * is smaller in LLP64 data models).
1580  */
1581 
1582 namespace serialization {
1583 template<typename Value,typename IndexSpecifierList,typename Allocator>
1584 struct version<
1585   boost::multi_index_container<Value,IndexSpecifierList,Allocator>
1586 >
1587 {
1588   BOOST_STATIC_CONSTANT(int,value=4);
1589 };
1590 } /* namespace serialization */
1591 #endif
1592 
1593 /* Associated global functions are promoted to namespace boost, except
1594  * comparison operators and swap, which are meant to be Koenig looked-up.
1595  */
1596 
1597 using multi_index::get;
1598 using multi_index::project;
1599 
1600 } /* namespace boost */
1601 
1602 #undef BOOST_MULTI_INDEX_CHECK_INVARIANT
1603 #undef BOOST_MULTI_INDEX_CHECK_INVARIANT_OF
1604 
1605 #endif