epoc32/include/stdapis/boost/multi_index_container.hpp
branchSymbian2
changeset 2 2fe1408b6811
equal deleted inserted replaced
1:666f914201fb 2:2fe1408b6811
       
     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