source: NonGTP/Boost/boost/multi_index_container.hpp @ 857

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