epoc32/include/stdapis/boost/multi_index/ordered_index.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
williamr@2
     1
/* Copyright 2003-2007 Joaquín M López Muñoz.
williamr@2
     2
 * Distributed under the Boost Software License, Version 1.0.
williamr@2
     3
 * (See accompanying file LICENSE_1_0.txt or copy at
williamr@2
     4
 * http://www.boost.org/LICENSE_1_0.txt)
williamr@2
     5
 *
williamr@2
     6
 * See http://www.boost.org/libs/multi_index for library home page.
williamr@2
     7
 *
williamr@2
     8
 * The internal implementation of red-black trees is based on that of SGI STL
williamr@2
     9
 * stl_tree.h file: 
williamr@2
    10
 *
williamr@2
    11
 * Copyright (c) 1996,1997
williamr@2
    12
 * Silicon Graphics Computer Systems, Inc.
williamr@2
    13
 *
williamr@2
    14
 * Permission to use, copy, modify, distribute and sell this software
williamr@2
    15
 * and its documentation for any purpose is hereby granted without fee,
williamr@2
    16
 * provided that the above copyright notice appear in all copies and
williamr@2
    17
 * that both that copyright notice and this permission notice appear
williamr@2
    18
 * in supporting documentation.  Silicon Graphics makes no
williamr@2
    19
 * representations about the suitability of this software for any
williamr@2
    20
 * purpose.  It is provided "as is" without express or implied warranty.
williamr@2
    21
 *
williamr@2
    22
 *
williamr@2
    23
 * Copyright (c) 1994
williamr@2
    24
 * Hewlett-Packard Company
williamr@2
    25
 *
williamr@2
    26
 * Permission to use, copy, modify, distribute and sell this software
williamr@2
    27
 * and its documentation for any purpose is hereby granted without fee,
williamr@2
    28
 * provided that the above copyright notice appear in all copies and
williamr@2
    29
 * that both that copyright notice and this permission notice appear
williamr@2
    30
 * in supporting documentation.  Hewlett-Packard Company makes no
williamr@2
    31
 * representations about the suitability of this software for any
williamr@2
    32
 * purpose.  It is provided "as is" without express or implied warranty.
williamr@2
    33
 *
williamr@2
    34
 */
williamr@2
    35
williamr@2
    36
#ifndef BOOST_MULTI_INDEX_ORDERED_INDEX_HPP
williamr@2
    37
#define BOOST_MULTI_INDEX_ORDERED_INDEX_HPP
williamr@2
    38
williamr@2
    39
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
williamr@2
    40
#pragma once
williamr@2
    41
#endif
williamr@2
    42
williamr@2
    43
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
williamr@2
    44
#include <algorithm>
williamr@2
    45
#include <boost/call_traits.hpp>
williamr@2
    46
#include <boost/detail/no_exceptions_support.hpp>
williamr@2
    47
#include <boost/detail/workaround.hpp>
williamr@2
    48
#include <boost/iterator/reverse_iterator.hpp>
williamr@2
    49
#include <boost/mpl/push_front.hpp>
williamr@2
    50
#include <boost/multi_index/detail/access_specifier.hpp>
williamr@2
    51
#include <boost/multi_index/detail/bidir_node_iterator.hpp>
williamr@2
    52
#include <boost/multi_index/detail/modify_key_adaptor.hpp>
williamr@2
    53
#include <boost/multi_index/detail/ord_index_node.hpp>
williamr@2
    54
#include <boost/multi_index/detail/ord_index_ops.hpp>
williamr@2
    55
#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
williamr@2
    56
#include <boost/multi_index/detail/safe_mode.hpp>
williamr@2
    57
#include <boost/multi_index/detail/scope_guard.hpp>
williamr@2
    58
#include <boost/multi_index/detail/unbounded.hpp>
williamr@2
    59
#include <boost/multi_index/detail/value_compare.hpp>
williamr@2
    60
#include <boost/multi_index/ordered_index_fwd.hpp>
williamr@2
    61
#include <boost/ref.hpp>
williamr@2
    62
#include <boost/tuple/tuple.hpp>
williamr@2
    63
#include <utility>
williamr@2
    64
williamr@2
    65
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
williamr@2
    66
#include <boost/archive/archive_exception.hpp>
williamr@2
    67
#include <boost/bind.hpp>
williamr@2
    68
#include <boost/multi_index/detail/duplicates_iterator.hpp>
williamr@2
    69
#include <boost/throw_exception.hpp> 
williamr@2
    70
#endif
williamr@2
    71
williamr@2
    72
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
williamr@2
    73
#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT                          \
williamr@2
    74
  detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
williamr@2
    75
    detail::make_obj_guard(*this,&ordered_index::check_invariant_);          \
williamr@2
    76
  BOOST_JOIN(check_invariant_,__LINE__).touch();
williamr@2
    77
#else
williamr@2
    78
#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
williamr@2
    79
#endif
williamr@2
    80
williamr@2
    81
namespace boost{
williamr@2
    82
williamr@2
    83
namespace multi_index{
williamr@2
    84
williamr@2
    85
namespace detail{
williamr@2
    86
williamr@2
    87
/* ordered_index adds a layer of ordered indexing to a given Super */
williamr@2
    88
williamr@2
    89
/* Most of the implementation of unique and non-unique indices is
williamr@2
    90
 * shared. We tell from one another on instantiation time by using
williamr@2
    91
 * these tags.
williamr@2
    92
 */
williamr@2
    93
williamr@2
    94
struct ordered_unique_tag{};
williamr@2
    95
struct ordered_non_unique_tag{};
williamr@2
    96
williamr@2
    97
template<
williamr@2
    98
  typename KeyFromValue,typename Compare,
williamr@2
    99
  typename SuperMeta,typename TagList,typename Category
williamr@2
   100
>
williamr@2
   101
class ordered_index:
williamr@2
   102
  BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
williamr@2
   103
williamr@2
   104
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   105
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
williamr@2
   106
  ,public safe_ctr_proxy_impl<
williamr@2
   107
    bidir_node_iterator<
williamr@2
   108
      ordered_index_node<typename SuperMeta::type::node_type> >,
williamr@2
   109
    ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category> >
williamr@2
   110
#else
williamr@2
   111
  ,public safe_mode::safe_container<
williamr@2
   112
    ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category> >
williamr@2
   113
#endif
williamr@2
   114
#endif
williamr@2
   115
williamr@2
   116
{ 
williamr@2
   117
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
williamr@2
   118
    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
williamr@2
   119
/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
williamr@2
   120
 * lifetime of const references bound to temporaries --precisely what
williamr@2
   121
 * scopeguards are.
williamr@2
   122
 */
williamr@2
   123
williamr@2
   124
#pragma parse_mfunc_templ off
williamr@2
   125
#endif
williamr@2
   126
williamr@2
   127
  typedef typename SuperMeta::type                   super;
williamr@2
   128
williamr@2
   129
protected:
williamr@2
   130
  typedef ordered_index_node<
williamr@2
   131
    typename super::node_type>                       node_type;
williamr@2
   132
williamr@2
   133
public:
williamr@2
   134
  /* types */
williamr@2
   135
williamr@2
   136
  typedef typename KeyFromValue::result_type         key_type;
williamr@2
   137
  typedef typename node_type::value_type             value_type;
williamr@2
   138
  typedef KeyFromValue                               key_from_value;
williamr@2
   139
  typedef Compare                                    key_compare;
williamr@2
   140
  typedef value_comparison<
williamr@2
   141
    value_type,KeyFromValue,Compare>                 value_compare;
williamr@2
   142
  typedef tuple<key_from_value,key_compare>          ctor_args;
williamr@2
   143
  typedef typename super::final_allocator_type       allocator_type;
williamr@2
   144
  typedef typename allocator_type::reference         reference;
williamr@2
   145
  typedef typename allocator_type::const_reference   const_reference;
williamr@2
   146
williamr@2
   147
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   148
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
williamr@2
   149
  typedef safe_mode::safe_iterator<
williamr@2
   150
    bidir_node_iterator<node_type>,
williamr@2
   151
    safe_ctr_proxy<
williamr@2
   152
      bidir_node_iterator<node_type> > >             iterator;
williamr@2
   153
#else
williamr@2
   154
  typedef safe_mode::safe_iterator<
williamr@2
   155
    bidir_node_iterator<node_type>,
williamr@2
   156
    ordered_index>                                   iterator;
williamr@2
   157
#endif
williamr@2
   158
#else
williamr@2
   159
  typedef bidir_node_iterator<node_type>             iterator;
williamr@2
   160
#endif
williamr@2
   161
williamr@2
   162
  typedef iterator                                   const_iterator;
williamr@2
   163
williamr@2
   164
  typedef std::size_t                                size_type;      
williamr@2
   165
  typedef std::ptrdiff_t                             difference_type;
williamr@2
   166
  typedef typename allocator_type::pointer           pointer;
williamr@2
   167
  typedef typename allocator_type::const_pointer     const_pointer;
williamr@2
   168
  typedef typename
williamr@2
   169
    boost::reverse_iterator<iterator>                reverse_iterator;
williamr@2
   170
  typedef typename
williamr@2
   171
    boost::reverse_iterator<const_iterator>          const_reverse_iterator;
williamr@2
   172
  typedef TagList                                    tag_list;
williamr@2
   173
williamr@2
   174
protected:
williamr@2
   175
  typedef typename super::final_node_type            final_node_type;
williamr@2
   176
  typedef tuples::cons<
williamr@2
   177
    ctor_args, 
williamr@2
   178
    typename super::ctor_args_list>                  ctor_args_list;
williamr@2
   179
  typedef typename mpl::push_front<
williamr@2
   180
    typename super::index_type_list,
williamr@2
   181
    ordered_index>::type                             index_type_list;
williamr@2
   182
  typedef typename mpl::push_front<
williamr@2
   183
    typename super::iterator_type_list,
williamr@2
   184
    iterator>::type    iterator_type_list;
williamr@2
   185
  typedef typename mpl::push_front<
williamr@2
   186
    typename super::const_iterator_type_list,
williamr@2
   187
    const_iterator>::type                            const_iterator_type_list;
williamr@2
   188
  typedef typename super::copy_map_type              copy_map_type;
williamr@2
   189
williamr@2
   190
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
williamr@2
   191
  typedef typename super::index_saver_type           index_saver_type;
williamr@2
   192
  typedef typename super::index_loader_type          index_loader_type;
williamr@2
   193
#endif
williamr@2
   194
williamr@2
   195
private:
williamr@2
   196
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   197
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
williamr@2
   198
  typedef safe_ctr_proxy_impl<
williamr@2
   199
    bidir_node_iterator<node_type>,
williamr@2
   200
    ordered_index>                                   safe_super;
williamr@2
   201
#else
williamr@2
   202
  typedef safe_mode::safe_container<ordered_index>   safe_super;
williamr@2
   203
#endif
williamr@2
   204
#endif
williamr@2
   205
williamr@2
   206
  typedef typename call_traits<
williamr@2
   207
    value_type>::param_type                          value_param_type;
williamr@2
   208
  typedef typename call_traits<
williamr@2
   209
    key_type>::param_type                            key_param_type;
williamr@2
   210
williamr@2
   211
public:
williamr@2
   212
williamr@2
   213
  /* construct/copy/destroy
williamr@2
   214
   * Default and copy ctors are in the protected section as indices are
williamr@2
   215
   * not supposed to be created on their own. No range ctor either.
williamr@2
   216
   */
williamr@2
   217
williamr@2
   218
  ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& operator=(
williamr@2
   219
    const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
williamr@2
   220
  {
williamr@2
   221
    this->final()=x.final();
williamr@2
   222
    return *this;
williamr@2
   223
  }
williamr@2
   224
williamr@2
   225
  allocator_type get_allocator()const
williamr@2
   226
  {
williamr@2
   227
    return this->final().get_allocator();
williamr@2
   228
  }
williamr@2
   229
williamr@2
   230
  /* iterators */
williamr@2
   231
williamr@2
   232
  iterator               begin(){return make_iterator(leftmost());}
williamr@2
   233
  const_iterator         begin()const{return make_iterator(leftmost());}
williamr@2
   234
  iterator               end(){return make_iterator(header());}
williamr@2
   235
  const_iterator         end()const{return make_iterator(header());}
williamr@2
   236
  reverse_iterator       rbegin(){return make_reverse_iterator(end());}
williamr@2
   237
  const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
williamr@2
   238
  reverse_iterator       rend(){return make_reverse_iterator(begin());}
williamr@2
   239
  const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
williamr@2
   240
 
williamr@2
   241
  /* capacity */
williamr@2
   242
williamr@2
   243
  bool      empty()const{return this->final_empty_();}
williamr@2
   244
  size_type size()const{return this->final_size_();}
williamr@2
   245
  size_type max_size()const{return this->final_max_size_();}
williamr@2
   246
williamr@2
   247
  /* modifiers */
williamr@2
   248
williamr@2
   249
  std::pair<iterator,bool> insert(value_param_type x)
williamr@2
   250
  {
williamr@2
   251
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   252
    std::pair<final_node_type*,bool> p=this->final_insert_(x);
williamr@2
   253
    return std::pair<iterator,bool>(make_iterator(p.first),p.second);
williamr@2
   254
  }
williamr@2
   255
williamr@2
   256
  iterator insert(iterator position,value_param_type x)
williamr@2
   257
  {
williamr@2
   258
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   259
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   260
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   261
    std::pair<final_node_type*,bool> p=this->final_insert_(
williamr@2
   262
      x,static_cast<final_node_type*>(position.get_node()));
williamr@2
   263
    return make_iterator(p.first);
williamr@2
   264
  }
williamr@2
   265
    
williamr@2
   266
  template<typename InputIterator>
williamr@2
   267
  void insert(InputIterator first,InputIterator last)
williamr@2
   268
  {
williamr@2
   269
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   270
    iterator hint=end();
williamr@2
   271
    for(;first!=last;++first)hint=insert(hint,*first);
williamr@2
   272
  }
williamr@2
   273
williamr@2
   274
  iterator erase(iterator position)
williamr@2
   275
  {
williamr@2
   276
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   277
    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
williamr@2
   278
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   279
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   280
    this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
williamr@2
   281
    return position;
williamr@2
   282
  }
williamr@2
   283
  
williamr@2
   284
  size_type erase(key_param_type x)
williamr@2
   285
  {
williamr@2
   286
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   287
    std::pair<iterator,iterator> p=equal_range(x);
williamr@2
   288
    size_type s=0;
williamr@2
   289
    while(p.first!=p.second){
williamr@2
   290
      p.first=erase(p.first);
williamr@2
   291
      ++s;
williamr@2
   292
    }
williamr@2
   293
    return s;
williamr@2
   294
  }
williamr@2
   295
williamr@2
   296
  iterator erase(iterator first,iterator last)
williamr@2
   297
  {
williamr@2
   298
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
williamr@2
   299
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
williamr@2
   300
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
williamr@2
   301
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
williamr@2
   302
    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
williamr@2
   303
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   304
    while(first!=last){
williamr@2
   305
      first=erase(first);
williamr@2
   306
    }
williamr@2
   307
    return first;
williamr@2
   308
  }
williamr@2
   309
williamr@2
   310
  bool replace(iterator position,value_param_type x)
williamr@2
   311
  {
williamr@2
   312
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   313
    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
williamr@2
   314
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   315
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   316
    return this->final_replace_(
williamr@2
   317
      x,static_cast<final_node_type*>(position.get_node()));
williamr@2
   318
  }
williamr@2
   319
williamr@2
   320
  template<typename Modifier>
williamr@2
   321
  bool modify(iterator position,Modifier mod)
williamr@2
   322
  {
williamr@2
   323
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   324
    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
williamr@2
   325
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   326
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   327
williamr@2
   328
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   329
    /* MSVC++ 6.0 optimizer on safe mode code chokes if this
williamr@2
   330
     * this is not added. Left it for all compilers as it does no
williamr@2
   331
     * harm.
williamr@2
   332
     */
williamr@2
   333
williamr@2
   334
    position.detach();
williamr@2
   335
#endif
williamr@2
   336
williamr@2
   337
    return this->final_modify_(
williamr@2
   338
      mod,static_cast<final_node_type*>(position.get_node()));
williamr@2
   339
  }
williamr@2
   340
williamr@2
   341
  template<typename Modifier>
williamr@2
   342
  bool modify_key(iterator position,Modifier mod)
williamr@2
   343
  {
williamr@2
   344
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   345
    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
williamr@2
   346
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   347
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   348
    return modify(
williamr@2
   349
      position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
williamr@2
   350
  }
williamr@2
   351
williamr@2
   352
  void swap(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
williamr@2
   353
  {
williamr@2
   354
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   355
    this->final_swap_(x.final());
williamr@2
   356
  }
williamr@2
   357
williamr@2
   358
  void clear()
williamr@2
   359
  {
williamr@2
   360
    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
williamr@2
   361
    this->final_clear_();
williamr@2
   362
  }
williamr@2
   363
williamr@2
   364
  /* observers */
williamr@2
   365
williamr@2
   366
  key_from_value key_extractor()const{return key;}
williamr@2
   367
  key_compare    key_comp()const{return comp;}
williamr@2
   368
  value_compare  value_comp()const{return value_compare(key,comp);}
williamr@2
   369
williamr@2
   370
  /* set operations */
williamr@2
   371
williamr@2
   372
  /* Internally, these ops rely on const_iterator being the same
williamr@2
   373
   * type as iterator.
williamr@2
   374
   */
williamr@2
   375
williamr@2
   376
  template<typename CompatibleKey>
williamr@2
   377
  iterator find(const CompatibleKey& x)const
williamr@2
   378
  {
williamr@2
   379
    return make_iterator(ordered_index_find(header(),key,x,comp));
williamr@2
   380
  }
williamr@2
   381
williamr@2
   382
  template<typename CompatibleKey,typename CompatibleCompare>
williamr@2
   383
  iterator find(
williamr@2
   384
    const CompatibleKey& x,const CompatibleCompare& comp)const
williamr@2
   385
  {
williamr@2
   386
    return make_iterator(ordered_index_find(header(),key,x,comp));
williamr@2
   387
  }
williamr@2
   388
williamr@2
   389
  template<typename CompatibleKey>
williamr@2
   390
  size_type count(const CompatibleKey& x)const
williamr@2
   391
  {
williamr@2
   392
    return count(x,comp);
williamr@2
   393
  }
williamr@2
   394
williamr@2
   395
  template<typename CompatibleKey,typename CompatibleCompare>
williamr@2
   396
  size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const
williamr@2
   397
  {
williamr@2
   398
    std::pair<iterator,iterator> p=equal_range(x,comp);
williamr@2
   399
    size_type n=std::distance(p.first,p.second);
williamr@2
   400
    return n;
williamr@2
   401
  }
williamr@2
   402
williamr@2
   403
  template<typename CompatibleKey>
williamr@2
   404
  iterator lower_bound(const CompatibleKey& x)const
williamr@2
   405
  {
williamr@2
   406
    return make_iterator(ordered_index_lower_bound(header(),key,x,comp));
williamr@2
   407
  }
williamr@2
   408
williamr@2
   409
  template<typename CompatibleKey,typename CompatibleCompare>
williamr@2
   410
  iterator lower_bound(
williamr@2
   411
    const CompatibleKey& x,const CompatibleCompare& comp)const
williamr@2
   412
  {
williamr@2
   413
    return make_iterator(ordered_index_lower_bound(header(),key,x,comp));
williamr@2
   414
  }
williamr@2
   415
williamr@2
   416
  template<typename CompatibleKey>
williamr@2
   417
  iterator upper_bound(const CompatibleKey& x)const
williamr@2
   418
  {
williamr@2
   419
    return make_iterator(ordered_index_upper_bound(header(),key,x,comp));
williamr@2
   420
  }
williamr@2
   421
williamr@2
   422
  template<typename CompatibleKey,typename CompatibleCompare>
williamr@2
   423
  iterator upper_bound(
williamr@2
   424
    const CompatibleKey& x,const CompatibleCompare& comp)const
williamr@2
   425
  {
williamr@2
   426
    return make_iterator(ordered_index_upper_bound(header(),key,x,comp));
williamr@2
   427
  }
williamr@2
   428
williamr@2
   429
  template<typename CompatibleKey>
williamr@2
   430
  std::pair<iterator,iterator> equal_range(
williamr@2
   431
    const CompatibleKey& x)const
williamr@2
   432
  {
williamr@2
   433
    return equal_range(x,comp);
williamr@2
   434
  }
williamr@2
   435
williamr@2
   436
  template<typename CompatibleKey,typename CompatibleCompare>
williamr@2
   437
  std::pair<iterator,iterator> equal_range(
williamr@2
   438
    const CompatibleKey& x,const CompatibleCompare& comp)const
williamr@2
   439
  {
williamr@2
   440
    return std::pair<iterator,iterator>(
williamr@2
   441
      lower_bound(x,comp),upper_bound(x,comp));
williamr@2
   442
  }
williamr@2
   443
williamr@2
   444
  /* range */
williamr@2
   445
williamr@2
   446
  template<typename LowerBounder,typename UpperBounder>
williamr@2
   447
  std::pair<iterator,iterator>
williamr@2
   448
  range(LowerBounder lower,UpperBounder upper)const
williamr@2
   449
  {
williamr@2
   450
    std::pair<iterator,iterator> p(
williamr@2
   451
      lower_range(lower),upper_range(upper));
williamr@2
   452
    if(p.second!=end()&&(p.first==end()||comp(key(*p.second),key(*p.first)))){
williamr@2
   453
      p.second=p.first;
williamr@2
   454
    }
williamr@2
   455
    return p;
williamr@2
   456
  }
williamr@2
   457
williamr@2
   458
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
williamr@2
   459
  ordered_index(const ctor_args_list& args_list,const allocator_type& al):
williamr@2
   460
    super(args_list.get_tail(),al),
williamr@2
   461
    key(tuples::get<0>(args_list.get_head())),
williamr@2
   462
    comp(tuples::get<1>(args_list.get_head()))
williamr@2
   463
  {
williamr@2
   464
    empty_initialize();
williamr@2
   465
  }
williamr@2
   466
williamr@2
   467
  ordered_index(
williamr@2
   468
    const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x):
williamr@2
   469
    super(x),
williamr@2
   470
williamr@2
   471
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   472
    safe_super(),
williamr@2
   473
#endif
williamr@2
   474
williamr@2
   475
    key(x.key),
williamr@2
   476
    comp(x.comp)
williamr@2
   477
  {
williamr@2
   478
    /* Copy ctor just takes the key and compare objects from x. The rest is
williamr@2
   479
     * done in subsequent call to copy_().
williamr@2
   480
     */
williamr@2
   481
  }
williamr@2
   482
williamr@2
   483
  ~ordered_index()
williamr@2
   484
  {
williamr@2
   485
    /* the container is guaranteed to be empty by now */
williamr@2
   486
  }
williamr@2
   487
williamr@2
   488
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   489
  iterator       make_iterator(node_type* node){return iterator(node,this);}
williamr@2
   490
  const_iterator make_iterator(node_type* node)const
williamr@2
   491
    {return const_iterator(node,const_cast<ordered_index*>(this));}
williamr@2
   492
#else
williamr@2
   493
  iterator       make_iterator(node_type* node){return iterator(node);}
williamr@2
   494
  const_iterator make_iterator(node_type* node)const
williamr@2
   495
                   {return const_iterator(node);}
williamr@2
   496
#endif
williamr@2
   497
williamr@2
   498
  void copy_(
williamr@2
   499
    const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x,
williamr@2
   500
    const copy_map_type& map)
williamr@2
   501
  {
williamr@2
   502
    if(!x.root()){
williamr@2
   503
      empty_initialize();
williamr@2
   504
    }
williamr@2
   505
    else{
williamr@2
   506
      header()->color()=x.header()->color();
williamr@2
   507
williamr@2
   508
      node_type* root_cpy=map.find(static_cast<final_node_type*>(x.root()));
williamr@2
   509
      header()->parent()=root_cpy->impl();
williamr@2
   510
williamr@2
   511
      node_type* leftmost_cpy=map.find(
williamr@2
   512
        static_cast<final_node_type*>(x.leftmost()));
williamr@2
   513
      header()->left()=leftmost_cpy->impl();
williamr@2
   514
williamr@2
   515
      node_type* rightmost_cpy=map.find(
williamr@2
   516
        static_cast<final_node_type*>(x.rightmost()));
williamr@2
   517
      header()->right()=rightmost_cpy->impl();
williamr@2
   518
williamr@2
   519
      typedef typename copy_map_type::const_iterator copy_map_iterator;
williamr@2
   520
      for(copy_map_iterator it=map.begin(),it_end=map.end();it!=it_end;++it){
williamr@2
   521
        node_type* org=it->first;
williamr@2
   522
        node_type* cpy=it->second;
williamr@2
   523
williamr@2
   524
        cpy->color()=org->color();
williamr@2
   525
williamr@2
   526
        ordered_index_node_impl* parent_org=org->parent();
williamr@2
   527
        if(!parent_org)cpy->parent()=0;
williamr@2
   528
        else{
williamr@2
   529
          node_type* parent_cpy=map.find(
williamr@2
   530
            static_cast<final_node_type*>(node_type::from_impl(parent_org)));
williamr@2
   531
          cpy->parent()=parent_cpy->impl();
williamr@2
   532
          if(parent_org->left()==org->impl()){
williamr@2
   533
            parent_cpy->left()=cpy->impl();
williamr@2
   534
          }
williamr@2
   535
          else if(parent_org->right()==org->impl()){
williamr@2
   536
            /* header() does not satisfy this nor the previous check */
williamr@2
   537
            parent_cpy->right()=cpy->impl();
williamr@2
   538
          }
williamr@2
   539
        }
williamr@2
   540
williamr@2
   541
        if(!org->left())cpy->left()=0;
williamr@2
   542
        if(!org->right())cpy->right()=0;
williamr@2
   543
      }
williamr@2
   544
    }
williamr@2
   545
    
williamr@2
   546
    super::copy_(x,map);
williamr@2
   547
  }
williamr@2
   548
williamr@2
   549
  node_type* insert_(value_param_type v,node_type* x)
williamr@2
   550
  {
williamr@2
   551
    link_info inf;
williamr@2
   552
    if(!link_point(key(v),inf,Category())){
williamr@2
   553
      return node_type::from_impl(inf.pos);
williamr@2
   554
    }
williamr@2
   555
williamr@2
   556
    node_type* res=static_cast<node_type*>(super::insert_(v,x));
williamr@2
   557
    if(res==x){
williamr@2
   558
      ordered_index_node_impl::link(
williamr@2
   559
        x->impl(),inf.side,inf.pos,header()->impl());
williamr@2
   560
    }
williamr@2
   561
    return res;
williamr@2
   562
  }
williamr@2
   563
williamr@2
   564
  node_type* insert_(value_param_type v,node_type* position,node_type* x)
williamr@2
   565
  {
williamr@2
   566
    link_info inf;
williamr@2
   567
    if(!hinted_link_point(key(v),position,inf,Category())){
williamr@2
   568
      return node_type::from_impl(inf.pos);
williamr@2
   569
    }
williamr@2
   570
williamr@2
   571
    node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
williamr@2
   572
    if(res==x){
williamr@2
   573
      ordered_index_node_impl::link(
williamr@2
   574
        x->impl(),inf.side,inf.pos,header()->impl());
williamr@2
   575
    }
williamr@2
   576
    return res;
williamr@2
   577
  }
williamr@2
   578
williamr@2
   579
  void erase_(node_type* x)
williamr@2
   580
  {
williamr@2
   581
    ordered_index_node_impl::rebalance_for_erase(
williamr@2
   582
      x->impl(),header()->parent(),header()->left(),header()->right());
williamr@2
   583
    super::erase_(x);
williamr@2
   584
williamr@2
   585
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   586
    detach_iterators(x);
williamr@2
   587
#endif
williamr@2
   588
  }
williamr@2
   589
williamr@2
   590
  void delete_all_nodes_()
williamr@2
   591
  {
williamr@2
   592
    delete_all_nodes(root());
williamr@2
   593
  }
williamr@2
   594
williamr@2
   595
  void clear_()
williamr@2
   596
  {
williamr@2
   597
    super::clear_();
williamr@2
   598
    empty_initialize();
williamr@2
   599
williamr@2
   600
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   601
    safe_super::detach_dereferenceable_iterators();
williamr@2
   602
#endif
williamr@2
   603
  }
williamr@2
   604
williamr@2
   605
  void swap_(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
williamr@2
   606
  {
williamr@2
   607
    std::swap(key,x.key);
williamr@2
   608
    std::swap(comp,x.comp);
williamr@2
   609
williamr@2
   610
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   611
    safe_super::swap(x);
williamr@2
   612
#endif
williamr@2
   613
williamr@2
   614
    super::swap_(x);
williamr@2
   615
  }
williamr@2
   616
williamr@2
   617
  bool replace_(value_param_type v,node_type* x)
williamr@2
   618
  {
williamr@2
   619
    if(in_place(v,x,Category())){
williamr@2
   620
      return super::replace_(v,x);
williamr@2
   621
    }
williamr@2
   622
williamr@2
   623
    node_type* next=x;
williamr@2
   624
    node_type::increment(next);
williamr@2
   625
williamr@2
   626
    ordered_index_node_impl::rebalance_for_erase(
williamr@2
   627
      x->impl(),header()->parent(),header()->left(),header()->right());
williamr@2
   628
williamr@2
   629
    BOOST_TRY{
williamr@2
   630
      link_info inf;
williamr@2
   631
      if(link_point(key(v),inf,Category())&&super::replace_(v,x)){
williamr@2
   632
        ordered_index_node_impl::link(
williamr@2
   633
          x->impl(),inf.side,inf.pos,header()->impl());
williamr@2
   634
        return true;
williamr@2
   635
      }
williamr@2
   636
      ordered_index_node_impl::restore(
williamr@2
   637
        x->impl(),next->impl(),header()->impl());
williamr@2
   638
      return false;
williamr@2
   639
    }
williamr@2
   640
    BOOST_CATCH(...){
williamr@2
   641
      ordered_index_node_impl::restore(
williamr@2
   642
        x->impl(),next->impl(),header()->impl());
williamr@2
   643
      BOOST_RETHROW;
williamr@2
   644
    }
williamr@2
   645
    BOOST_CATCH_END
williamr@2
   646
  }
williamr@2
   647
williamr@2
   648
  bool modify_(node_type* x)
williamr@2
   649
  {
williamr@2
   650
    bool b;
williamr@2
   651
    BOOST_TRY{
williamr@2
   652
      b=in_place(x->value(),x,Category());
williamr@2
   653
    }
williamr@2
   654
    BOOST_CATCH(...){
williamr@2
   655
      erase_(x);
williamr@2
   656
      BOOST_RETHROW;
williamr@2
   657
    }
williamr@2
   658
    BOOST_CATCH_END
williamr@2
   659
    if(!b){
williamr@2
   660
      ordered_index_node_impl::rebalance_for_erase(
williamr@2
   661
        x->impl(),header()->parent(),header()->left(),header()->right());
williamr@2
   662
      BOOST_TRY{
williamr@2
   663
        link_info inf;
williamr@2
   664
        if(!link_point(key(x->value()),inf,Category())){
williamr@2
   665
          super::erase_(x);
williamr@2
   666
williamr@2
   667
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   668
          detach_iterators(x);
williamr@2
   669
#endif
williamr@2
   670
          return false;
williamr@2
   671
        }
williamr@2
   672
        ordered_index_node_impl::link(
williamr@2
   673
          x->impl(),inf.side,inf.pos,header()->impl());
williamr@2
   674
      }
williamr@2
   675
      BOOST_CATCH(...){
williamr@2
   676
        super::erase_(x);
williamr@2
   677
williamr@2
   678
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   679
        detach_iterators(x);
williamr@2
   680
#endif
williamr@2
   681
williamr@2
   682
        BOOST_RETHROW;
williamr@2
   683
      }
williamr@2
   684
      BOOST_CATCH_END
williamr@2
   685
    }
williamr@2
   686
williamr@2
   687
    BOOST_TRY{
williamr@2
   688
      if(!super::modify_(x)){
williamr@2
   689
        ordered_index_node_impl::rebalance_for_erase(
williamr@2
   690
          x->impl(),header()->parent(),header()->left(),header()->right());
williamr@2
   691
williamr@2
   692
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   693
        detach_iterators(x);
williamr@2
   694
#endif
williamr@2
   695
williamr@2
   696
        return false;
williamr@2
   697
      }
williamr@2
   698
      else return true;
williamr@2
   699
    }
williamr@2
   700
    BOOST_CATCH(...){
williamr@2
   701
      ordered_index_node_impl::rebalance_for_erase(
williamr@2
   702
        x->impl(),header()->parent(),header()->left(),header()->right());
williamr@2
   703
williamr@2
   704
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   705
      detach_iterators(x);
williamr@2
   706
#endif
williamr@2
   707
williamr@2
   708
      BOOST_RETHROW;
williamr@2
   709
    }
williamr@2
   710
    BOOST_CATCH_END
williamr@2
   711
  }
williamr@2
   712
williamr@2
   713
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
williamr@2
   714
  /* serialization */
williamr@2
   715
williamr@2
   716
  template<typename Archive>
williamr@2
   717
  void save_(
williamr@2
   718
    Archive& ar,const unsigned int version,const index_saver_type& sm)const
williamr@2
   719
  {
williamr@2
   720
    save_(ar,version,sm,Category());
williamr@2
   721
  }
williamr@2
   722
williamr@2
   723
  template<typename Archive>
williamr@2
   724
  void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
williamr@2
   725
  {
williamr@2
   726
    load_(ar,version,lm,Category());
williamr@2
   727
  }
williamr@2
   728
#endif
williamr@2
   729
williamr@2
   730
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
williamr@2
   731
  /* invariant stuff */
williamr@2
   732
williamr@2
   733
  bool invariant_()const
williamr@2
   734
  {
williamr@2
   735
    if(size()==0||begin()==end()){
williamr@2
   736
      if(size()!=0||begin()!=end()||
williamr@2
   737
         header()->left()!=header()->impl()||
williamr@2
   738
         header()->right()!=header()->impl())return false;
williamr@2
   739
    }
williamr@2
   740
    else{
williamr@2
   741
      if((size_type)std::distance(begin(),end())!=size())return false;
williamr@2
   742
williamr@2
   743
      std::size_t len=ordered_index_node_impl::black_count(
williamr@2
   744
        leftmost()->impl(),root()->impl());
williamr@2
   745
      for(const_iterator it=begin(),it_end=end();it!=it_end;++it){
williamr@2
   746
        node_type* x=it.get_node();
williamr@2
   747
        node_type* left_x=node_type::from_impl(x->left());
williamr@2
   748
        node_type* right_x=node_type::from_impl(x->right());
williamr@2
   749
williamr@2
   750
        if(x->color()==red){
williamr@2
   751
          if((left_x&&left_x->color()==red)||
williamr@2
   752
             (right_x&&right_x->color()==red))return false;
williamr@2
   753
        }
williamr@2
   754
        if(left_x&&comp(key(x->value()),key(left_x->value())))return false;
williamr@2
   755
        if(right_x&&comp(key(right_x->value()),key(x->value())))return false;
williamr@2
   756
        if(!left_x&&!right_x&&
williamr@2
   757
           ordered_index_node_impl::black_count(
williamr@2
   758
             x->impl(),root()->impl())!=len)
williamr@2
   759
          return false;
williamr@2
   760
      }
williamr@2
   761
    
williamr@2
   762
      if(leftmost()->impl()!=
williamr@2
   763
         ordered_index_node_impl::minimum(root()->impl()))
williamr@2
   764
        return false;
williamr@2
   765
      if(rightmost()->impl()!=
williamr@2
   766
         ordered_index_node_impl::maximum(root()->impl()))
williamr@2
   767
        return false;
williamr@2
   768
    }
williamr@2
   769
williamr@2
   770
    return super::invariant_();
williamr@2
   771
  }
williamr@2
   772
williamr@2
   773
  
williamr@2
   774
  /* This forwarding function eases things for the boost::mem_fn construct
williamr@2
   775
   * in BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT. Actually,
williamr@2
   776
   * final_check_invariant is already an inherited member function of
williamr@2
   777
   * ordered_index.
williamr@2
   778
   */
williamr@2
   779
  void check_invariant_()const{this->final_check_invariant_();}
williamr@2
   780
#endif
williamr@2
   781
williamr@2
   782
private:
williamr@2
   783
  node_type* header()const{return this->final_header();}
williamr@2
   784
  node_type* root()const{return node_type::from_impl(header()->parent());}
williamr@2
   785
  node_type* leftmost()const{return node_type::from_impl(header()->left());}
williamr@2
   786
  node_type* rightmost()const{return node_type::from_impl(header()->right());}
williamr@2
   787
williamr@2
   788
  void empty_initialize()
williamr@2
   789
  {
williamr@2
   790
    header()->color()=red;
williamr@2
   791
    /* used to distinguish header() from root, in iterator.operator++ */
williamr@2
   792
    
williamr@2
   793
    header()->parent()=0;
williamr@2
   794
    header()->left()=header()->impl();
williamr@2
   795
    header()->right()=header()->impl();
williamr@2
   796
  }
williamr@2
   797
williamr@2
   798
  struct link_info
williamr@2
   799
  {
williamr@2
   800
    ordered_index_side       side;
williamr@2
   801
    ordered_index_node_impl* pos;
williamr@2
   802
  };
williamr@2
   803
williamr@2
   804
  bool link_point(key_param_type k,link_info& inf,ordered_unique_tag)
williamr@2
   805
  {
williamr@2
   806
    node_type* y=header();
williamr@2
   807
    node_type* x=root();
williamr@2
   808
    bool c=true;
williamr@2
   809
    while(x){
williamr@2
   810
      y=x;
williamr@2
   811
      c=comp(k,key(x->value()));
williamr@2
   812
      x=node_type::from_impl(c?x->left():x->right());
williamr@2
   813
    }
williamr@2
   814
    node_type* yy=y;
williamr@2
   815
    if(c){
williamr@2
   816
      if(yy==leftmost()){
williamr@2
   817
        inf.side=to_left;
williamr@2
   818
        inf.pos=y->impl();
williamr@2
   819
        return true;
williamr@2
   820
      }
williamr@2
   821
      else node_type::decrement(yy);
williamr@2
   822
    }
williamr@2
   823
williamr@2
   824
    if(comp(key(yy->value()),k)){
williamr@2
   825
      inf.side=c?to_left:to_right;
williamr@2
   826
      inf.pos=y->impl();
williamr@2
   827
      return true;
williamr@2
   828
    }
williamr@2
   829
    else{
williamr@2
   830
      inf.pos=yy->impl();
williamr@2
   831
      return false;
williamr@2
   832
    }
williamr@2
   833
  }
williamr@2
   834
williamr@2
   835
  bool link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
williamr@2
   836
  {
williamr@2
   837
    node_type* y=header();
williamr@2
   838
    node_type* x=root();
williamr@2
   839
    bool c=true;
williamr@2
   840
    while (x){
williamr@2
   841
     y=x;
williamr@2
   842
     c=comp(k,key(x->value()));
williamr@2
   843
     x=node_type::from_impl(c?x->left():x->right());
williamr@2
   844
    }
williamr@2
   845
    inf.side=c?to_left:to_right;
williamr@2
   846
    inf.pos=y->impl();
williamr@2
   847
    return true;
williamr@2
   848
  }
williamr@2
   849
williamr@2
   850
  bool hinted_link_point(
williamr@2
   851
    key_param_type k,node_type* position,link_info& inf,ordered_unique_tag)
williamr@2
   852
  {
williamr@2
   853
    if(position->impl()==header()->left()){ 
williamr@2
   854
      if(size()>0&&comp(k,key(position->value()))){
williamr@2
   855
        inf.side=to_left;
williamr@2
   856
        inf.pos=position->impl();
williamr@2
   857
        return true;
williamr@2
   858
      }
williamr@2
   859
      else return link_point(k,inf,ordered_unique_tag());
williamr@2
   860
    } 
williamr@2
   861
    else if(position==header()){ 
williamr@2
   862
      if(comp(key(rightmost()->value()),k)){
williamr@2
   863
        inf.side=to_right;
williamr@2
   864
        inf.pos=rightmost()->impl();
williamr@2
   865
        return true;
williamr@2
   866
      }
williamr@2
   867
      else return link_point(k,inf,ordered_unique_tag());
williamr@2
   868
    } 
williamr@2
   869
    else{
williamr@2
   870
      node_type* before=position;
williamr@2
   871
      node_type::decrement(before);
williamr@2
   872
      if(comp(key(before->value()),k)&&comp(k,key(position->value()))){
williamr@2
   873
        if(before->right()==0){
williamr@2
   874
          inf.side=to_right;
williamr@2
   875
          inf.pos=before->impl();
williamr@2
   876
          return true;
williamr@2
   877
        }
williamr@2
   878
        else{
williamr@2
   879
          inf.side=to_left;
williamr@2
   880
          inf.pos=position->impl();
williamr@2
   881
          return true;
williamr@2
   882
        }
williamr@2
   883
      } 
williamr@2
   884
      else return link_point(k,inf,ordered_unique_tag());
williamr@2
   885
    }
williamr@2
   886
  }
williamr@2
   887
williamr@2
   888
  bool hinted_link_point(
williamr@2
   889
    key_param_type k,node_type* position,link_info& inf,ordered_non_unique_tag)
williamr@2
   890
  {
williamr@2
   891
    if(position->impl()==header()->left()){ 
williamr@2
   892
      if(size()>0&&!comp(key(position->value()),k)){
williamr@2
   893
        inf.side=to_left;
williamr@2
   894
        inf.pos=position->impl();
williamr@2
   895
        return true;
williamr@2
   896
      }
williamr@2
   897
      else return link_point(k,inf,ordered_non_unique_tag());
williamr@2
   898
    } 
williamr@2
   899
    else if(position==header()){
williamr@2
   900
      if(!comp(k,key(rightmost()->value()))){
williamr@2
   901
        inf.side=to_right;
williamr@2
   902
        inf.pos=rightmost()->impl();
williamr@2
   903
        return true;
williamr@2
   904
      }
williamr@2
   905
      else return link_point(k,inf,ordered_non_unique_tag());
williamr@2
   906
    } 
williamr@2
   907
    else{
williamr@2
   908
      node_type* before=position;
williamr@2
   909
      node_type::decrement(before);
williamr@2
   910
      if (!comp(k,key(before->value()))&&!comp(key(position->value()),k)){
williamr@2
   911
        if(before->right()==0){
williamr@2
   912
          inf.side=to_right;
williamr@2
   913
          inf.pos=before->impl();
williamr@2
   914
          return true;
williamr@2
   915
        }
williamr@2
   916
        else{
williamr@2
   917
          inf.side=to_left;
williamr@2
   918
          inf.pos=position->impl();
williamr@2
   919
          return true;
williamr@2
   920
        }
williamr@2
   921
      } 
williamr@2
   922
      else return link_point(k,inf,ordered_non_unique_tag());
williamr@2
   923
    }
williamr@2
   924
  }
williamr@2
   925
williamr@2
   926
  void delete_all_nodes(node_type* x)
williamr@2
   927
  {
williamr@2
   928
    if(!x)return;
williamr@2
   929
williamr@2
   930
    delete_all_nodes(node_type::from_impl(x->left()));
williamr@2
   931
    delete_all_nodes(node_type::from_impl(x->right()));
williamr@2
   932
    this->final_delete_node_(static_cast<final_node_type*>(x));
williamr@2
   933
  }
williamr@2
   934
williamr@2
   935
  bool in_place(value_param_type v,node_type* x,ordered_unique_tag)
williamr@2
   936
  {
williamr@2
   937
    node_type* y;
williamr@2
   938
    if(x!=leftmost()){
williamr@2
   939
      y=x;
williamr@2
   940
      node_type::decrement(y);
williamr@2
   941
      if(!comp(key(y->value()),key(v)))return false;
williamr@2
   942
    }
williamr@2
   943
williamr@2
   944
    y=x;
williamr@2
   945
    node_type::increment(y);
williamr@2
   946
    return y==header()||comp(key(v),key(y->value()));
williamr@2
   947
  }
williamr@2
   948
williamr@2
   949
  bool in_place(value_param_type v,node_type* x,ordered_non_unique_tag)
williamr@2
   950
  {
williamr@2
   951
    node_type* y;
williamr@2
   952
    if(x!=leftmost()){
williamr@2
   953
      y=x;
williamr@2
   954
      node_type::decrement(y);
williamr@2
   955
      if(comp(key(v),key(y->value())))return false;
williamr@2
   956
    }
williamr@2
   957
williamr@2
   958
    y=x;
williamr@2
   959
    node_type::increment(y);
williamr@2
   960
    return y==header()||!comp(key(y->value()),key(v));
williamr@2
   961
  }
williamr@2
   962
williamr@2
   963
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   964
  void detach_iterators(node_type* x)
williamr@2
   965
  {
williamr@2
   966
    iterator it=make_iterator(x);
williamr@2
   967
    safe_mode::detach_equivalent_iterators(it);
williamr@2
   968
  }
williamr@2
   969
#endif
williamr@2
   970
williamr@2
   971
  template<typename LowerBounder>
williamr@2
   972
  iterator lower_range(LowerBounder lower)const
williamr@2
   973
  {
williamr@2
   974
    node_type* y=header();
williamr@2
   975
    node_type* z=root();
williamr@2
   976
williamr@2
   977
    while(z){
williamr@2
   978
      if(lower(key(z->value()))){
williamr@2
   979
        y=z;
williamr@2
   980
        z=node_type::from_impl(z->left());
williamr@2
   981
      }
williamr@2
   982
      else z=node_type::from_impl(z->right());
williamr@2
   983
    }
williamr@2
   984
williamr@2
   985
    return make_iterator(y);
williamr@2
   986
  }
williamr@2
   987
williamr@2
   988
  iterator lower_range(unbounded_type)const
williamr@2
   989
  {
williamr@2
   990
    return begin();
williamr@2
   991
  }
williamr@2
   992
williamr@2
   993
  template<typename UpperBounder>
williamr@2
   994
  iterator upper_range(UpperBounder upper)const
williamr@2
   995
  {
williamr@2
   996
    node_type* y=header();
williamr@2
   997
    node_type* z=root();
williamr@2
   998
williamr@2
   999
    while(z){
williamr@2
  1000
      if(!upper(key(z->value()))){
williamr@2
  1001
        y=z;
williamr@2
  1002
        z=node_type::from_impl(z->left());
williamr@2
  1003
      }
williamr@2
  1004
      else z=node_type::from_impl(z->right());
williamr@2
  1005
    }
williamr@2
  1006
williamr@2
  1007
    return make_iterator(y);
williamr@2
  1008
  }
williamr@2
  1009
williamr@2
  1010
  iterator upper_range(unbounded_type)const
williamr@2
  1011
  {
williamr@2
  1012
    return end();
williamr@2
  1013
  }
williamr@2
  1014
williamr@2
  1015
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
williamr@2
  1016
  template<typename Archive>
williamr@2
  1017
  void save_(
williamr@2
  1018
    Archive& ar,const unsigned int version,const index_saver_type& sm,
williamr@2
  1019
    ordered_unique_tag)const
williamr@2
  1020
  {
williamr@2
  1021
    super::save_(ar,version,sm);
williamr@2
  1022
  }
williamr@2
  1023
williamr@2
  1024
  template<typename Archive>
williamr@2
  1025
  void load_(
williamr@2
  1026
    Archive& ar,const unsigned int version,const index_loader_type& lm,
williamr@2
  1027
    ordered_unique_tag)
williamr@2
  1028
  {
williamr@2
  1029
    super::load_(ar,version,lm);
williamr@2
  1030
  }
williamr@2
  1031
williamr@2
  1032
  template<typename Archive>
williamr@2
  1033
  void save_(
williamr@2
  1034
    Archive& ar,const unsigned int version,const index_saver_type& sm,
williamr@2
  1035
    ordered_non_unique_tag)const
williamr@2
  1036
  {
williamr@2
  1037
    typedef duplicates_iterator<node_type,value_compare> dup_iterator;
williamr@2
  1038
williamr@2
  1039
    sm.save(
williamr@2
  1040
      dup_iterator(begin().get_node(),end().get_node(),value_comp()),
williamr@2
  1041
      dup_iterator(end().get_node(),value_comp()),
williamr@2
  1042
      ar,version);
williamr@2
  1043
    super::save_(ar,version,sm);
williamr@2
  1044
  }
williamr@2
  1045
williamr@2
  1046
  template<typename Archive>
williamr@2
  1047
  void load_(
williamr@2
  1048
    Archive& ar,const unsigned int version,const index_loader_type& lm,
williamr@2
  1049
    ordered_non_unique_tag)
williamr@2
  1050
  {
williamr@2
  1051
    lm.load(
williamr@2
  1052
      ::boost::bind(&ordered_index::rearranger,this,_1,_2),
williamr@2
  1053
      ar,version);
williamr@2
  1054
    super::load_(ar,version,lm);
williamr@2
  1055
  }
williamr@2
  1056
williamr@2
  1057
  void rearranger(node_type* position,node_type *x)
williamr@2
  1058
  {
williamr@2
  1059
    if(!position||comp(key(position->value()),key(x->value()))){
williamr@2
  1060
      position=lower_bound(key(x->value())).get_node();
williamr@2
  1061
    }
williamr@2
  1062
    else if(comp(key(x->value()),key(position->value()))){
williamr@2
  1063
      /* inconsistent rearrangement */
williamr@2
  1064
      throw_exception(
williamr@2
  1065
        archive::archive_exception(
williamr@2
  1066
          archive::archive_exception::other_exception));
williamr@2
  1067
    }
williamr@2
  1068
    else node_type::increment(position);
williamr@2
  1069
williamr@2
  1070
    if(position!=x){
williamr@2
  1071
      ordered_index_node_impl::rebalance_for_erase(
williamr@2
  1072
        x->impl(),header()->parent(),header()->left(),header()->right());
williamr@2
  1073
      ordered_index_node_impl::restore(
williamr@2
  1074
        x->impl(),position->impl(),header()->impl());
williamr@2
  1075
    }
williamr@2
  1076
  }
williamr@2
  1077
#endif /* serialization */
williamr@2
  1078
williamr@2
  1079
  key_from_value key;
williamr@2
  1080
  key_compare    comp;
williamr@2
  1081
williamr@2
  1082
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
williamr@2
  1083
    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
williamr@2
  1084
#pragma parse_mfunc_templ reset
williamr@2
  1085
#endif
williamr@2
  1086
};
williamr@2
  1087
williamr@2
  1088
/* comparison */
williamr@2
  1089
williamr@2
  1090
template<
williamr@2
  1091
  typename KeyFromValue1,typename Compare1,
williamr@2
  1092
  typename SuperMeta1,typename TagList1,typename Category1,
williamr@2
  1093
  typename KeyFromValue2,typename Compare2,
williamr@2
  1094
  typename SuperMeta2,typename TagList2,typename Category2
williamr@2
  1095
>
williamr@2
  1096
bool operator==(
williamr@2
  1097
  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
williamr@2
  1098
  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
williamr@2
  1099
{
williamr@2
  1100
  return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
williamr@2
  1101
}
williamr@2
  1102
williamr@2
  1103
template<
williamr@2
  1104
  typename KeyFromValue1,typename Compare1,
williamr@2
  1105
  typename SuperMeta1,typename TagList1,typename Category1,
williamr@2
  1106
  typename KeyFromValue2,typename Compare2,
williamr@2
  1107
  typename SuperMeta2,typename TagList2,typename Category2
williamr@2
  1108
>
williamr@2
  1109
bool operator<(
williamr@2
  1110
  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
williamr@2
  1111
  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
williamr@2
  1112
{
williamr@2
  1113
  return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
williamr@2
  1114
}
williamr@2
  1115
williamr@2
  1116
template<
williamr@2
  1117
  typename KeyFromValue1,typename Compare1,
williamr@2
  1118
  typename SuperMeta1,typename TagList1,typename Category1,
williamr@2
  1119
  typename KeyFromValue2,typename Compare2,
williamr@2
  1120
  typename SuperMeta2,typename TagList2,typename Category2
williamr@2
  1121
>
williamr@2
  1122
bool operator!=(
williamr@2
  1123
  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
williamr@2
  1124
  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
williamr@2
  1125
{
williamr@2
  1126
  return !(x==y);
williamr@2
  1127
}
williamr@2
  1128
williamr@2
  1129
template<
williamr@2
  1130
  typename KeyFromValue1,typename Compare1,
williamr@2
  1131
  typename SuperMeta1,typename TagList1,typename Category1,
williamr@2
  1132
  typename KeyFromValue2,typename Compare2,
williamr@2
  1133
  typename SuperMeta2,typename TagList2,typename Category2
williamr@2
  1134
>
williamr@2
  1135
bool operator>(
williamr@2
  1136
  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
williamr@2
  1137
  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
williamr@2
  1138
{
williamr@2
  1139
  return y<x;
williamr@2
  1140
}
williamr@2
  1141
williamr@2
  1142
template<
williamr@2
  1143
  typename KeyFromValue1,typename Compare1,
williamr@2
  1144
  typename SuperMeta1,typename TagList1,typename Category1,
williamr@2
  1145
  typename KeyFromValue2,typename Compare2,
williamr@2
  1146
  typename SuperMeta2,typename TagList2,typename Category2
williamr@2
  1147
>
williamr@2
  1148
bool operator>=(
williamr@2
  1149
  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
williamr@2
  1150
  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
williamr@2
  1151
{
williamr@2
  1152
  return !(x<y);
williamr@2
  1153
}
williamr@2
  1154
williamr@2
  1155
template<
williamr@2
  1156
  typename KeyFromValue1,typename Compare1,
williamr@2
  1157
  typename SuperMeta1,typename TagList1,typename Category1,
williamr@2
  1158
  typename KeyFromValue2,typename Compare2,
williamr@2
  1159
  typename SuperMeta2,typename TagList2,typename Category2
williamr@2
  1160
>
williamr@2
  1161
bool operator<=(
williamr@2
  1162
  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
williamr@2
  1163
  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
williamr@2
  1164
{
williamr@2
  1165
  return !(x>y);
williamr@2
  1166
}
williamr@2
  1167
williamr@2
  1168
/*  specialized algorithms */
williamr@2
  1169
williamr@2
  1170
template<
williamr@2
  1171
  typename KeyFromValue,typename Compare,
williamr@2
  1172
  typename SuperMeta,typename TagList,typename Category
williamr@2
  1173
>
williamr@2
  1174
void swap(
williamr@2
  1175
  ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x,
williamr@2
  1176
  ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& y)
williamr@2
  1177
{
williamr@2
  1178
  x.swap(y);
williamr@2
  1179
}
williamr@2
  1180
williamr@2
  1181
} /* namespace multi_index::detail */
williamr@2
  1182
williamr@2
  1183
/* ordered_index specifiers */
williamr@2
  1184
williamr@2
  1185
template<typename Arg1,typename Arg2,typename Arg3>
williamr@2
  1186
struct ordered_unique
williamr@2
  1187
{
williamr@2
  1188
  typedef typename detail::ordered_index_args<
williamr@2
  1189
    Arg1,Arg2,Arg3>                                index_args;
williamr@2
  1190
  typedef typename index_args::tag_list_type::type tag_list_type;
williamr@2
  1191
  typedef typename index_args::key_from_value_type key_from_value_type;
williamr@2
  1192
  typedef typename index_args::compare_type        compare_type;
williamr@2
  1193
williamr@2
  1194
  template<typename Super>
williamr@2
  1195
  struct node_class
williamr@2
  1196
  {
williamr@2
  1197
    typedef detail::ordered_index_node<Super> type;
williamr@2
  1198
  };
williamr@2
  1199
williamr@2
  1200
  template<typename SuperMeta>
williamr@2
  1201
  struct index_class
williamr@2
  1202
  {
williamr@2
  1203
    typedef detail::ordered_index<
williamr@2
  1204
      key_from_value_type,compare_type,
williamr@2
  1205
      SuperMeta,tag_list_type,detail::ordered_unique_tag> type;
williamr@2
  1206
  };
williamr@2
  1207
};
williamr@2
  1208
williamr@2
  1209
template<typename Arg1,typename Arg2,typename Arg3>
williamr@2
  1210
struct ordered_non_unique
williamr@2
  1211
{
williamr@2
  1212
  typedef detail::ordered_index_args<
williamr@2
  1213
    Arg1,Arg2,Arg3>                                index_args;
williamr@2
  1214
  typedef typename index_args::tag_list_type::type tag_list_type;
williamr@2
  1215
  typedef typename index_args::key_from_value_type key_from_value_type;
williamr@2
  1216
  typedef typename index_args::compare_type        compare_type;
williamr@2
  1217
williamr@2
  1218
  template<typename Super>
williamr@2
  1219
  struct node_class
williamr@2
  1220
  {
williamr@2
  1221
    typedef detail::ordered_index_node<Super> type;
williamr@2
  1222
  };
williamr@2
  1223
williamr@2
  1224
  template<typename SuperMeta>
williamr@2
  1225
  struct index_class
williamr@2
  1226
  {
williamr@2
  1227
    typedef detail::ordered_index<
williamr@2
  1228
      key_from_value_type,compare_type,
williamr@2
  1229
      SuperMeta,tag_list_type,detail::ordered_non_unique_tag> type;
williamr@2
  1230
  };
williamr@2
  1231
};
williamr@2
  1232
williamr@2
  1233
} /* namespace multi_index */
williamr@2
  1234
williamr@2
  1235
} /* namespace boost */
williamr@2
  1236
williamr@2
  1237
#undef BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
williamr@2
  1238
williamr@2
  1239
#endif