Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/multi_index_container.hpp @ 66

Last change on this file since 66 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 29.3 KB
Line 
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
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
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
114public:
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
428BOOST_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
628private:
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
639template<typename MultiIndexContainer,int N>
640struct 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
650template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
651typename nth_index<
652  multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
653get(
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
674template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
675const typename nth_index<
676  multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
677get(
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
700template<typename MultiIndexContainer,typename Tag>
701struct 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
717template<
718  typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
719>
720typename ::boost::multi_index::index<
721  multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
722get(
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
737template<
738  typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
739>
740const typename ::boost::multi_index::index<
741  multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
742get(
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
759template<typename MultiIndexContainer,int N>
760struct 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
767template<typename MultiIndexContainer,int N>
768struct 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
776template<
777  int N,typename IteratorType,
778  typename Value,typename IndexSpecifierList,typename Allocator>
779typename nth_index_iterator<
780  multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
781project(
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
810template<
811  int N,typename IteratorType,
812  typename Value,typename IndexSpecifierList,typename Allocator>
813typename nth_index_const_iterator<
814  multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
815project(
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
849template<typename MultiIndexContainer,typename Tag>
850struct index_iterator
851{
852  typedef typename ::boost::multi_index::index<
853    MultiIndexContainer,Tag>::type::iterator    type;
854};
855
856template<typename MultiIndexContainer,typename Tag>
857struct index_const_iterator
858{
859  typedef typename ::boost::multi_index::index<
860    MultiIndexContainer,Tag>::type::const_iterator type;
861};
862
863template<
864  typename Tag,typename IteratorType,
865  typename Value,typename IndexSpecifierList,typename Allocator>
866typename index_iterator<
867  multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
868project(
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
898template<
899  typename Tag,typename IteratorType,
900  typename Value,typename IndexSpecifierList,typename Allocator>
901typename index_const_iterator<
902  multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
903project(
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
938template<
939  typename Value1,typename IndexSpecifierList1,typename Allocator1,
940  typename Value2,typename IndexSpecifierList2,typename Allocator2
941>
942bool 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
949template<
950  typename Value1,typename IndexSpecifierList1,typename Allocator1,
951  typename Value2,typename IndexSpecifierList2,typename Allocator2
952>
953bool 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
960template<
961  typename Value1,typename IndexSpecifierList1,typename Allocator1,
962  typename Value2,typename IndexSpecifierList2,typename Allocator2
963>
964bool 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
971template<
972  typename Value1,typename IndexSpecifierList1,typename Allocator1,
973  typename Value2,typename IndexSpecifierList2,typename Allocator2
974>
975bool 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
982template<
983  typename Value1,typename IndexSpecifierList1,typename Allocator1,
984  typename Value2,typename IndexSpecifierList2,typename Allocator2
985>
986bool 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
993template<
994  typename Value1,typename IndexSpecifierList1,typename Allocator1,
995  typename Value2,typename IndexSpecifierList2,typename Allocator2
996>
997bool 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
1006template<typename Value,typename IndexSpecifierList,typename Allocator>
1007void 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
1020using multi_index::get;
1021using multi_index::project;
1022
1023} /* namespace boost */
1024
1025#undef BOOST_MULTI_INDEX_CHECK_INVARIANT
1026
1027#endif
Note: See TracBrowser for help on using the repository browser.