epoc32/include/stdapis/boost/multi_index_container.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:27:01 +0100
branchSymbian2
changeset 3 e1b950c65cb4
permissions -rw-r--r--
Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
     1 /* Multiply indexed container.
     2  *
     3  * Copyright 2003-2007 Joaquín M López Muñoz.
     4  * Distributed under the Boost Software License, Version 1.0.
     5  * (See accompanying file LICENSE_1_0.txt or copy at
     6  * http://www.boost.org/LICENSE_1_0.txt)
     7  *
     8  * See http://www.boost.org/libs/multi_index for library home page.
     9  */
    10 
    11 #ifndef BOOST_MULTI_INDEX_HPP
    12 #define BOOST_MULTI_INDEX_HPP
    13 
    14 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
    15 #pragma once
    16 #endif
    17 
    18 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
    19 #include <algorithm>
    20 #include <boost/detail/allocator_utilities.hpp>
    21 #include <boost/detail/no_exceptions_support.hpp>
    22 #include <boost/detail/workaround.hpp>
    23 #include <boost/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/base_type.hpp>
    33 #include <boost/multi_index/detail/converter.hpp>
    34 #include <boost/multi_index/detail/def_ctor_tuple_cons.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>
    44 
    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> 
    50 #endif
    51 
    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();
    58 #else
    59 #define BOOST_MULTI_INDEX_CHECK_INVARIANT
    60 #endif
    61 
    62 namespace boost{
    63 
    64 namespace multi_index{
    65 
    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<
    70       Allocator,
    71       typename detail::multi_index_node_type<
    72         Value,IndexSpecifierList,Allocator>::type
    73     >::type>,
    74   BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
    75     typename detail::multi_index_node_type<
    76       Value,IndexSpecifierList,Allocator>::type,
    77     multi_index_container<Value,IndexSpecifierList,Allocator> >,
    78   public detail::multi_index_base_type<
    79     Value,IndexSpecifierList,Allocator>::type
    80 {
    81 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
    82     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
    83 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
    84  * lifetime of const references bound to temporaries --precisely what
    85  * scopeguards are.
    86  */
    87 
    88 #pragma parse_mfunc_templ off
    89 #endif
    90 
    91 private:
    92 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
    93   template <typename,typename,typename> friend class  detail::index_base;
    94   template <typename,typename>          friend class  detail::header_holder;
    95   template <typename,typename>          friend class  detail::converter;
    96 #endif
    97 
    98   typedef typename detail::multi_index_base_type<
    99       Value,IndexSpecifierList,Allocator>::type   super;
   100   typedef ::boost::base_from_member<
   101     typename boost::detail::allocator::rebind_to<
   102       Allocator,
   103       typename super::node_type
   104     >::type>                                      bfm_allocator;
   105   typedef detail::header_holder<
   106     typename super::node_type,
   107     multi_index_container>                        bfm_header;
   108 
   109 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
   110   /* see definition of index_type_list below */
   111   typedef typename super::index_type_list         super_index_type_list;
   112 #endif
   113 
   114 public:
   115   /* All types are inherited from super, a few are explicitly
   116    * brought forward here to save us some typename's.
   117    */
   118 
   119 #if defined(BOOST_MSVC)
   120   typedef 
   121     detail::default_constructible_tuple_cons<
   122       typename super::ctor_args_list>              ctor_args_list;
   123 #else
   124   typedef typename super::ctor_args_list           ctor_args_list;
   125 #endif
   126 
   127   typedef IndexSpecifierList                       index_specifier_type_list;
   128  
   129 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
   130   /* MSVC++ 6.0 chokes on moderately long index lists (around 6 indices
   131    * or more), with errors ranging from corrupt exes to duplicate
   132    * comdats. The following type hiding hack alleviates this condition;
   133    * best results combined with type hiding of the indexed_by construct
   134    * itself, as explained in the "Compiler specifics" section of
   135    * the documentation.
   136    */
   137 
   138   struct index_type_list:super_index_type_list
   139   {
   140     typedef index_type_list                      type;
   141     typedef typename super_index_type_list::back back;
   142     typedef mpl::v_iter<type,0>                  begin;
   143     typedef mpl::v_iter<
   144       type,
   145       mpl::size<super_index_type_list>::value>   end;
   146   };
   147 #else
   148   typedef typename super::index_type_list          index_type_list;
   149 #endif
   150 
   151   typedef typename super::iterator_type_list       iterator_type_list;
   152   typedef typename super::const_iterator_type_list const_iterator_type_list;
   153   typedef typename super::value_type               value_type;
   154   typedef typename super::final_allocator_type     allocator_type;
   155   typedef typename super::iterator                 iterator;
   156   typedef typename super::const_iterator           const_iterator;
   157 
   158   BOOST_STATIC_ASSERT(
   159     detail::no_duplicate_tags_in_index_list<index_type_list>::value);
   160 
   161   /* global project() needs to see this publicly */
   162 
   163   typedef typename super::node_type node_type;
   164 
   165   /* construct/copy/destroy */
   166 
   167   explicit multi_index_container(
   168 
   169 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
   170     /* VisualAge seems to have an ETI issue with the default values
   171      * for arguments args_list and al.
   172      */
   173 
   174     const ctor_args_list& args_list=
   175       typename mpl::identity<multi_index_container>::type::
   176         ctor_args_list(),
   177     const allocator_type& al=
   178       typename mpl::identity<multi_index_container>::type::
   179         allocator_type()):
   180 #else
   181     const ctor_args_list& args_list=ctor_args_list(),
   182     const allocator_type& al=allocator_type()):
   183 #endif
   184 
   185     bfm_allocator(al),
   186     super(args_list,bfm_allocator::member),
   187     node_count(0)
   188   {
   189     BOOST_MULTI_INDEX_CHECK_INVARIANT;
   190   }    
   191 
   192   template<typename InputIterator>
   193   multi_index_container(
   194     InputIterator first,InputIterator last,
   195 
   196 #if BOOST_WORKAROUND(__IBMCPP__,<=600)
   197     /* VisualAge seems to have an ETI issue with the default values
   198      * for arguments args_list and al.
   199      */
   200 
   201     const ctor_args_list& args_list=
   202       typename mpl::identity<multi_index_container>::type::
   203         ctor_args_list(),
   204     const allocator_type& al=
   205       typename mpl::identity<multi_index_container>::type::
   206         allocator_type()):
   207 #else
   208     const ctor_args_list& args_list=ctor_args_list(),
   209     const allocator_type& al=allocator_type()):
   210 #endif
   211 
   212     bfm_allocator(al),
   213     super(args_list,bfm_allocator::member),
   214     node_count(0)
   215   {
   216     BOOST_MULTI_INDEX_CHECK_INVARIANT;
   217     BOOST_TRY{
   218       iterator hint=super::end();
   219       for(;first!=last;++first){
   220         hint=super::make_iterator(insert_(*first,hint.get_node()).first);
   221       }
   222     }
   223     BOOST_CATCH(...){
   224       clear_();
   225       BOOST_RETHROW;
   226     }
   227     BOOST_CATCH_END
   228   }
   229 
   230   multi_index_container(
   231     const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
   232     bfm_allocator(x.bfm_allocator::member),
   233     bfm_header(),
   234     super(x),
   235     node_count(0)
   236   {
   237     copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
   238     for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
   239       map.clone(it.get_node());
   240     }
   241     super::copy_(x,map);
   242     map.release();
   243     node_count=x.size();
   244 
   245     /* Not until this point are the indices required to be consistent,
   246      * hence the position of the invariant checker.
   247      */
   248 
   249     BOOST_MULTI_INDEX_CHECK_INVARIANT;
   250   }
   251 
   252   ~multi_index_container()
   253   {
   254     delete_all_nodes_();
   255   }
   256 
   257   multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
   258     const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
   259   {
   260     BOOST_MULTI_INDEX_CHECK_INVARIANT;
   261     multi_index_container<Value,IndexSpecifierList,Allocator> tmp(x);
   262     this->swap(tmp);
   263     return *this;
   264   }
   265 
   266   allocator_type get_allocator()const
   267   {
   268     return allocator_type(bfm_allocator::member);
   269   }
   270 
   271   /* retrieval of indices by number */
   272 
   273 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
   274   template<int N>
   275   struct nth_index
   276   {
   277     BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
   278     typedef typename mpl::at_c<index_type_list,N>::type type;
   279   };
   280 
   281   template<int N>
   282   typename nth_index<N>::type& get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
   283   {
   284     BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
   285     return *this;
   286   }
   287 
   288   template<int N>
   289   const typename nth_index<N>::type& get(
   290     BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
   291   {
   292     BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
   293     return *this;
   294   }
   295 #endif
   296 
   297   /* retrieval of indices by tag */
   298 
   299 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
   300   template<typename Tag>
   301   struct index
   302   {
   303     typedef typename mpl::find_if<
   304       index_type_list,
   305       detail::has_tag<Tag>
   306     >::type                                    iter;
   307 
   308     BOOST_STATIC_CONSTANT(
   309       bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
   310     BOOST_STATIC_ASSERT(index_found);
   311 
   312     typedef typename mpl::deref<iter>::type    type;
   313   };
   314 
   315   template<typename Tag>
   316   typename index<Tag>::type& get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
   317   {
   318     return *this;
   319   }
   320 
   321   template<typename Tag>
   322   const typename index<Tag>::type& get(
   323     BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))const
   324   {
   325     return *this;
   326   }
   327 #endif
   328 
   329   /* projection of iterators by number */
   330 
   331 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
   332   template<int N>
   333   struct nth_index_iterator
   334   {
   335     typedef typename nth_index<N>::type::iterator type;
   336   };
   337 
   338   template<int N>
   339   struct nth_index_const_iterator
   340   {
   341     typedef typename nth_index<N>::type::const_iterator type;
   342   };
   343 
   344   template<int N,typename IteratorType>
   345   typename nth_index_iterator<N>::type project(
   346     IteratorType it
   347     BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
   348   {
   349     typedef typename nth_index<N>::type index;
   350 
   351     BOOST_STATIC_ASSERT(
   352       (mpl::contains<iterator_type_list,IteratorType>::value));
   353 
   354     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
   355     BOOST_MULTI_INDEX_CHECK_IS_OWNER(
   356       it,static_cast<typename IteratorType::container_type&>(*this));
   357 
   358     return index::make_iterator(static_cast<node_type*>(it.get_node()));
   359   }
   360 
   361   template<int N,typename IteratorType>
   362   typename nth_index_const_iterator<N>::type project(
   363     IteratorType it
   364     BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
   365   {
   366     typedef typename nth_index<N>::type index;
   367 
   368     BOOST_STATIC_ASSERT((
   369       mpl::contains<iterator_type_list,IteratorType>::value||
   370       mpl::contains<const_iterator_type_list,IteratorType>::value));
   371 
   372     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
   373     BOOST_MULTI_INDEX_CHECK_IS_OWNER(
   374       it,static_cast<const typename IteratorType::container_type&>(*this));
   375     return index::make_iterator(static_cast<node_type*>(it.get_node()));
   376   }
   377 #endif
   378 
   379   /* projection of iterators by tag */
   380 
   381 #if !defined(BOOST_NO_MEMBER_TEMPLATES)
   382   template<typename Tag>
   383   struct index_iterator
   384   {
   385     typedef typename index<Tag>::type::iterator type;
   386   };
   387 
   388   template<typename Tag>
   389   struct index_const_iterator
   390   {
   391     typedef typename index<Tag>::type::const_iterator type;
   392   };
   393 
   394   template<typename Tag,typename IteratorType>
   395   typename index_iterator<Tag>::type project(
   396     IteratorType it
   397     BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
   398   {
   399     typedef typename index<Tag>::type index;
   400 
   401     BOOST_STATIC_ASSERT(
   402       (mpl::contains<iterator_type_list,IteratorType>::value));
   403 
   404     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
   405     BOOST_MULTI_INDEX_CHECK_IS_OWNER(
   406       it,static_cast<typename IteratorType::container_type&>(*this));
   407     return index::make_iterator(static_cast<node_type*>(it.get_node()));
   408   }
   409 
   410   template<typename Tag,typename IteratorType>
   411   typename index_const_iterator<Tag>::type project(
   412     IteratorType it
   413     BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))const
   414   {
   415     typedef typename index<Tag>::type index;
   416 
   417     BOOST_STATIC_ASSERT((
   418       mpl::contains<iterator_type_list,IteratorType>::value||
   419       mpl::contains<const_iterator_type_list,IteratorType>::value));
   420 
   421     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
   422     BOOST_MULTI_INDEX_CHECK_IS_OWNER(
   423       it,static_cast<const typename IteratorType::container_type&>(*this));
   424     return index::make_iterator(static_cast<node_type*>(it.get_node()));
   425   }
   426 #endif
   427 
   428 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
   429   typedef typename super::copy_map_type copy_map_type;
   430 
   431   node_type* header()const
   432   {
   433     return bfm_header::member;
   434   }
   435 
   436   node_type* allocate_node()
   437   {
   438     return bfm_allocator::member.allocate(1);
   439   }
   440 
   441   void deallocate_node(node_type* x)
   442   {
   443     bfm_allocator::member.deallocate(x,1);
   444   }
   445 
   446   bool empty_()const
   447   {
   448     return node_count==0;
   449   }
   450 
   451   std::size_t size_()const
   452   {
   453     return node_count;
   454   }
   455 
   456   std::size_t max_size_()const
   457   {
   458     return static_cast<std::size_t >(-1);
   459   }
   460 
   461   std::pair<node_type*,bool> insert_(const Value& v)
   462   {
   463     node_type* x=allocate_node();
   464     BOOST_TRY{
   465       node_type* res=super::insert_(v,x);
   466       if(res==x){
   467         ++node_count;
   468         return std::pair<node_type*,bool>(res,true);
   469       }
   470       else{
   471         deallocate_node(x);
   472         return std::pair<node_type*,bool>(res,false);
   473       }
   474     }
   475     BOOST_CATCH(...){
   476       deallocate_node(x);
   477       BOOST_RETHROW;
   478     }
   479     BOOST_CATCH_END
   480   }
   481 
   482   std::pair<node_type*,bool> insert_(const Value& v,node_type* position)
   483   {
   484     node_type* x=allocate_node();
   485     BOOST_TRY{
   486       node_type* res=super::insert_(v,position,x);
   487       if(res==x){
   488         ++node_count;
   489         return std::pair<node_type*,bool>(res,true);
   490       }
   491       else{
   492         deallocate_node(x);
   493         return std::pair<node_type*,bool>(res,false);
   494       }
   495     }
   496     BOOST_CATCH(...){
   497       deallocate_node(x);
   498       BOOST_RETHROW;
   499     }
   500     BOOST_CATCH_END
   501   }
   502 
   503   void erase_(node_type* x)
   504   {
   505     super::erase_(x);
   506     deallocate_node(x);
   507     --node_count;
   508   }
   509 
   510   void delete_node_(node_type* x)
   511   {
   512     super::delete_node_(x);
   513     deallocate_node(x);
   514   }
   515 
   516   void delete_all_nodes_()
   517   {
   518     super::delete_all_nodes_();
   519   }
   520 
   521   void clear_()
   522   {
   523     delete_all_nodes_();
   524     super::clear_();
   525     node_count=0;
   526   }
   527 
   528   void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
   529   {
   530     std::swap(bfm_header::member,x.bfm_header::member);
   531     super::swap_(x);
   532     std::swap(node_count,x.node_count);
   533   }
   534 
   535   bool replace_(const Value& k,node_type* x)
   536   {
   537     return super::replace_(k,x);
   538   }
   539 
   540   template<typename Modifier>
   541   bool modify_(Modifier mod,node_type* x)
   542   {
   543     mod(const_cast<value_type&>(x->value()));
   544 
   545     BOOST_TRY{
   546       if(!super::modify_(x)){
   547         deallocate_node(x);
   548         --node_count;
   549         return false;
   550       }
   551       else return true;
   552     }
   553     BOOST_CATCH(...){
   554       deallocate_node(x);
   555       --node_count;
   556       BOOST_RETHROW;
   557     }
   558     BOOST_CATCH_END
   559   }
   560 
   561 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   562   /* serialization */
   563 
   564   friend class boost::serialization::access;
   565 
   566   BOOST_SERIALIZATION_SPLIT_MEMBER()
   567 
   568   typedef typename super::index_saver_type        index_saver_type;
   569   typedef typename super::index_loader_type       index_loader_type;
   570 
   571   template<class Archive>
   572   void save(Archive& ar,const unsigned int version)const
   573   {
   574     const std::size_t s=size_();
   575     ar<<serialization::make_nvp("count",s);
   576     index_saver_type sm(bfm_allocator::member,s);
   577 
   578     for(iterator it=super::begin(),it_end=super::end();it!=it_end;++it){
   579       ar<<serialization::make_nvp("item",*it);
   580       sm.add(it.get_node(),ar,version);
   581     }
   582     sm.add_track(header(),ar,version);
   583 
   584     super::save_(ar,version,sm);
   585   }
   586 
   587   template<class Archive>
   588   void load(Archive& ar,const unsigned int version)
   589   {
   590     BOOST_MULTI_INDEX_CHECK_INVARIANT;
   591 
   592     clear_(); 
   593 
   594     std::size_t s;
   595     ar>>serialization::make_nvp("count",s);
   596     index_loader_type lm(bfm_allocator::member,s);
   597 
   598     for(std::size_t n=0;n<s;++n){
   599       detail::archive_constructed<Value> value("item",ar,version);
   600       std::pair<node_type*,bool> p=insert_(
   601         value.get(),super::end().get_node());
   602       if(!p.second)throw_exception(
   603         archive::archive_exception(
   604           archive::archive_exception::other_exception));
   605       ar.reset_object_address(&p.first->value(),&value.get());
   606       lm.add(p.first,ar,version);
   607     }
   608     lm.add_track(header(),ar,version);
   609 
   610     super::load_(ar,version,lm);
   611   }
   612 #endif
   613 
   614 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
   615   /* invariant stuff */
   616 
   617   bool invariant_()const
   618   {
   619     return super::invariant_();
   620   }
   621 
   622   void check_invariant_()const
   623   {
   624     BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
   625   }
   626 #endif
   627 
   628 private:
   629   std::size_t node_count;
   630 
   631 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
   632     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
   633 #pragma parse_mfunc_templ reset
   634 #endif
   635 };
   636 
   637 /* retrieval of indices by number */
   638 
   639 template<typename MultiIndexContainer,int N>
   640 struct nth_index
   641 {
   642   BOOST_STATIC_CONSTANT(
   643     int,
   644     M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
   645   BOOST_STATIC_ASSERT(N>=0&&N<M);
   646   typedef typename mpl::at_c<
   647     typename MultiIndexContainer::index_type_list,N>::type type;
   648 };
   649 
   650 template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
   651 typename nth_index<
   652   multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
   653 get(
   654   multi_index_container<Value,IndexSpecifierList,Allocator>& m
   655   BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
   656 {
   657   typedef multi_index_container<
   658     Value,IndexSpecifierList,Allocator>    multi_index_type;
   659   typedef typename nth_index<
   660     multi_index_container<
   661       Value,IndexSpecifierList,Allocator>,
   662     N
   663   >::type                                  index;
   664 
   665   BOOST_STATIC_ASSERT(N>=0&&
   666     N<
   667     mpl::size<
   668       BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
   669     >::type::value);
   670 
   671   return detail::converter<multi_index_type,index>::index(m);
   672 }
   673 
   674 template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
   675 const typename nth_index<
   676   multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
   677 get(
   678   const multi_index_container<Value,IndexSpecifierList,Allocator>& m
   679   BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
   680 {
   681   typedef multi_index_container<
   682     Value,IndexSpecifierList,Allocator>    multi_index_type;
   683   typedef typename nth_index<
   684     multi_index_container<
   685       Value,IndexSpecifierList,Allocator>,
   686     N
   687   >::type                                  index;
   688 
   689   BOOST_STATIC_ASSERT(N>=0&&
   690     N<
   691     mpl::size<
   692       BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
   693     >::type::value);
   694 
   695   return detail::converter<multi_index_type,index>::index(m);
   696 }
   697 
   698 /* retrieval of indices by tag */
   699 
   700 template<typename MultiIndexContainer,typename Tag>
   701 struct index
   702 {
   703   typedef typename MultiIndexContainer::index_type_list index_type_list;
   704 
   705   typedef typename mpl::find_if<
   706     index_type_list,
   707     detail::has_tag<Tag>
   708   >::type                                      iter;
   709 
   710   BOOST_STATIC_CONSTANT(
   711     bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
   712   BOOST_STATIC_ASSERT(index_found);
   713 
   714   typedef typename mpl::deref<iter>::type       type;
   715 };
   716 
   717 template<
   718   typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
   719 >
   720 typename ::boost::multi_index::index<
   721   multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
   722 get(
   723   multi_index_container<Value,IndexSpecifierList,Allocator>& m
   724   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
   725 {
   726   typedef multi_index_container<
   727     Value,IndexSpecifierList,Allocator>         multi_index_type;
   728   typedef typename ::boost::multi_index::index<
   729     multi_index_container<
   730       Value,IndexSpecifierList,Allocator>,
   731     Tag
   732   >::type                                       index;
   733 
   734   return detail::converter<multi_index_type,index>::index(m);
   735 }
   736 
   737 template<
   738   typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
   739 >
   740 const typename ::boost::multi_index::index<
   741   multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
   742 get(
   743   const multi_index_container<Value,IndexSpecifierList,Allocator>& m
   744   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
   745 {
   746   typedef multi_index_container<
   747     Value,IndexSpecifierList,Allocator>         multi_index_type;
   748   typedef typename ::boost::multi_index::index<
   749     multi_index_container<
   750       Value,IndexSpecifierList,Allocator>,
   751     Tag
   752   >::type                                       index;
   753 
   754   return detail::converter<multi_index_type,index>::index(m);
   755 }
   756 
   757 /* projection of iterators by number */
   758 
   759 template<typename MultiIndexContainer,int N>
   760 struct nth_index_iterator
   761 {
   762   typedef typename detail::prevent_eti<
   763     nth_index<MultiIndexContainer,N>,
   764     typename nth_index<MultiIndexContainer,N>::type>::type::iterator type;
   765 };
   766 
   767 template<typename MultiIndexContainer,int N>
   768 struct nth_index_const_iterator
   769 {
   770   typedef typename detail::prevent_eti<
   771     nth_index<MultiIndexContainer,N>,
   772     typename nth_index<MultiIndexContainer,N>::type
   773   >::type::const_iterator type;
   774 };
   775 
   776 template<
   777   int N,typename IteratorType,
   778   typename Value,typename IndexSpecifierList,typename Allocator>
   779 typename nth_index_iterator<
   780   multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
   781 project(
   782   multi_index_container<Value,IndexSpecifierList,Allocator>& m,
   783   IteratorType it
   784   BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
   785 {
   786   typedef multi_index_container<
   787     Value,IndexSpecifierList,Allocator>                multi_index_type;
   788   typedef typename nth_index<multi_index_type,N>::type index;
   789 
   790 #if !defined(BOOST_MSVC)||!(BOOST_MSVC<1310) /* ain't work in MSVC++ 6.0/7.0 */
   791   BOOST_STATIC_ASSERT((
   792     mpl::contains<
   793       BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
   794       IteratorType>::value));
   795 #endif
   796 
   797   BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
   798 
   799 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   800   typedef detail::converter<
   801     multi_index_type,
   802     BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
   803   BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
   804 #endif
   805 
   806   return detail::converter<multi_index_type,index>::iterator(
   807     m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
   808 }
   809 
   810 template<
   811   int N,typename IteratorType,
   812   typename Value,typename IndexSpecifierList,typename Allocator>
   813 typename nth_index_const_iterator<
   814   multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
   815 project(
   816   const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
   817   IteratorType it
   818   BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
   819 {
   820   typedef multi_index_container<
   821     Value,IndexSpecifierList,Allocator>                multi_index_type;
   822   typedef typename nth_index<multi_index_type,N>::type index;
   823 
   824 #if !defined(BOOST_MSVC)||!(BOOST_MSVC<1310) /* ain't work in MSVC++ 6.0/7.0 */
   825   BOOST_STATIC_ASSERT((
   826     mpl::contains<
   827       BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
   828       IteratorType>::value||
   829     mpl::contains<
   830       BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
   831       IteratorType>::value));
   832 #endif
   833 
   834   BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
   835 
   836 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   837   typedef detail::converter<
   838     multi_index_type,
   839     BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
   840   BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
   841 #endif
   842 
   843   return detail::converter<multi_index_type,index>::const_iterator(
   844     m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
   845 }
   846 
   847 /* projection of iterators by tag */
   848 
   849 template<typename MultiIndexContainer,typename Tag>
   850 struct index_iterator
   851 {
   852   typedef typename ::boost::multi_index::index<
   853     MultiIndexContainer,Tag>::type::iterator    type;
   854 };
   855 
   856 template<typename MultiIndexContainer,typename Tag>
   857 struct index_const_iterator
   858 {
   859   typedef typename ::boost::multi_index::index<
   860     MultiIndexContainer,Tag>::type::const_iterator type;
   861 };
   862 
   863 template<
   864   typename Tag,typename IteratorType,
   865   typename Value,typename IndexSpecifierList,typename Allocator>
   866 typename index_iterator<
   867   multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
   868 project(
   869   multi_index_container<Value,IndexSpecifierList,Allocator>& m,
   870   IteratorType it
   871   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
   872 {
   873   typedef multi_index_container<
   874     Value,IndexSpecifierList,Allocator>         multi_index_type;
   875   typedef typename ::boost::multi_index::index<
   876     multi_index_type,Tag>::type                 index;
   877 
   878 #if !defined(BOOST_MSVC)||!(BOOST_MSVC<1310) /* ain't work in MSVC++ 6.0/7.0 */
   879   BOOST_STATIC_ASSERT((
   880     mpl::contains<
   881       BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
   882       IteratorType>::value));
   883 #endif
   884 
   885   BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
   886 
   887 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   888   typedef detail::converter<
   889     multi_index_type,
   890     BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
   891   BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
   892 #endif
   893 
   894   return detail::converter<multi_index_type,index>::iterator(
   895     m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
   896 }
   897 
   898 template<
   899   typename Tag,typename IteratorType,
   900   typename Value,typename IndexSpecifierList,typename Allocator>
   901 typename index_const_iterator<
   902   multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
   903 project(
   904   const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
   905   IteratorType it
   906   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
   907 {
   908   typedef multi_index_container<
   909     Value,IndexSpecifierList,Allocator>         multi_index_type;
   910   typedef typename ::boost::multi_index::index<
   911     multi_index_type,Tag>::type                 index;
   912 
   913 #if !defined(BOOST_MSVC)||!(BOOST_MSVC<1310) /* ain't work in MSVC++ 6.0/7.0 */
   914   BOOST_STATIC_ASSERT((
   915     mpl::contains<
   916       BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
   917       IteratorType>::value||
   918     mpl::contains<
   919       BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
   920       IteratorType>::value));
   921 #endif
   922 
   923   BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
   924 
   925 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
   926   typedef detail::converter<
   927     multi_index_type,
   928     BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
   929   BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
   930 #endif
   931 
   932   return detail::converter<multi_index_type,index>::const_iterator(
   933     m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
   934 }
   935 
   936 /* Comparison. Simple forward to first index. */
   937 
   938 template<
   939   typename Value1,typename IndexSpecifierList1,typename Allocator1,
   940   typename Value2,typename IndexSpecifierList2,typename Allocator2
   941 >
   942 bool operator==(
   943   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
   944   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
   945 {
   946   return get<0>(x)==get<0>(y);
   947 }
   948 
   949 template<
   950   typename Value1,typename IndexSpecifierList1,typename Allocator1,
   951   typename Value2,typename IndexSpecifierList2,typename Allocator2
   952 >
   953 bool operator<(
   954   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
   955   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
   956 {
   957   return get<0>(x)<get<0>(y);
   958 }
   959 
   960 template<
   961   typename Value1,typename IndexSpecifierList1,typename Allocator1,
   962   typename Value2,typename IndexSpecifierList2,typename Allocator2
   963 >
   964 bool operator!=(
   965   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
   966   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
   967 {
   968   return get<0>(x)!=get<0>(y);
   969 }
   970 
   971 template<
   972   typename Value1,typename IndexSpecifierList1,typename Allocator1,
   973   typename Value2,typename IndexSpecifierList2,typename Allocator2
   974 >
   975 bool operator>(
   976   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
   977   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
   978 {
   979   return get<0>(x)>get<0>(y);
   980 }
   981 
   982 template<
   983   typename Value1,typename IndexSpecifierList1,typename Allocator1,
   984   typename Value2,typename IndexSpecifierList2,typename Allocator2
   985 >
   986 bool operator>=(
   987   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
   988   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
   989 {
   990   return get<0>(x)>=get<0>(y);
   991 }
   992 
   993 template<
   994   typename Value1,typename IndexSpecifierList1,typename Allocator1,
   995   typename Value2,typename IndexSpecifierList2,typename Allocator2
   996 >
   997 bool operator<=(
   998   const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
   999   const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1000 {
  1001   return get<0>(x)<=get<0>(y);
  1002 }
  1003 
  1004 /*  specialized algorithms */
  1005 
  1006 template<typename Value,typename IndexSpecifierList,typename Allocator>
  1007 void swap(
  1008   multi_index_container<Value,IndexSpecifierList,Allocator>& x,
  1009   multi_index_container<Value,IndexSpecifierList,Allocator>& y)
  1010 {
  1011   x.swap(y);
  1012 }
  1013 
  1014 } /* namespace multi_index */
  1015 
  1016 /* Associated global functions are promoted to namespace boost, except
  1017  * comparison operators and swap, which are meant to be Koenig looked-up.
  1018  */
  1019 
  1020 using multi_index::get;
  1021 using multi_index::project;
  1022 
  1023 } /* namespace boost */
  1024 
  1025 #undef BOOST_MULTI_INDEX_CHECK_INVARIANT
  1026 
  1027 #endif