~tsarev/boostdc/cmake

« back to all changes in this revision

Viewing changes to boost/boost/multi_index_container.hpp

  • Committer: bigmuscle
  • Date: 2010-05-08 08:47:15 UTC
  • Revision ID: svn-v4:5fb55d53-692c-0410-a46a-e90ab66e00ee:trunk:497
removed old boost version

Show diffs side-by-side

added added

removed removed

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