Boost logo

Boost-Commit :

From: joaquin_at_[hidden]
Date: 2007-10-11 06:57:37


Author: joaquin
Date: 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
New Revision: 39922
URL: http://svn.boost.org/trac/boost/changeset/39922

Log:
Boost 1.35 version of Boost.MultiIndex
allocator_utilities.hpp: added partial_std_allocator_wrapper::value_type
composite_key.hpp: used hash_fwd.hpp
auto_space.hpp: added support for non-standard allocators
bidir_node_iterator.hpp: moved friend-injected operators out of class
copy_map.hpp: added support for non-standard allocators
hash_index_args.hpp: removed deprecated use of <boost/functional/hash/hash.hpp>
hash_index_iterator.hpp: moved friend-injected operators our of class
hash_index_node.hpp: added support for non-standard allocators
header_holder.hpp:added support for non-standard allocators
index_base.hpp: added support for non-standard allocators, added modify_rollback, added small improvement to modify
index_loader.hpp: added support for non-standard allocators
index_matcher.hpp: added support for non-standard allocators
index_node_base.hpp: added support for non-standard allocators
iter_adaptor.hpp: added some out-of-class operators to alleviate a MSVC++ 6.0 problem
modify_key_adaptor.hpp: renamed some vars to accomudate broader usage scope
node_type.hpp: added support for non-standard allocators
ord_index_node.hpp: added support for non-standard allocators
ord_index_ops.hpp: implemented a more efficient equal_range
rnd_index_loader.hpp: added support for non-standard allocators
rnd_index_node.hpp: added support for non-standard allocators
rnd_index_ops.hpp: added support for non-standard allocators
rnd_index_ptr_array.hpp: added support for non-standard allocators
rnd_node_iterator.hpp: moved friend-injected operators out of class
seq_index_node.hpp: added support for non-standard allocators
seq_index_ops.hpp: added support for non-standard allocators
uintptr_type.hpp: added support for __int64
unbounded.hpp: fixed ODR problem
value_compare.hpp: fixed a small unefficiency
global_fun: initial commit
hashed_index.hpp: added support for non-standard allocators, added c[r]{begin|end}, [local_]iterator_to, rollback modify
identity_fwd.hpp: fixed wrong include guard name
key_extractors.hpp: added global_fun
mem_fun.hpp: removed superfluous =0's
ordered_index.hpp: added support for non-standard allocators, added c[r]{begin|end}, iterator_to, rollback modify, improved equal_range and range, added conformance to DR 233
random_access_index.hpp: added support for non-standard allocators, added c[r]{begin|end}, iterator_to, rollback modify, added conformance to 23.1.1/9
sequenced_index.hpp: added support for non-standard allocators, added c[r]{begin|end}, iterator_to, rollback modify, added conformance to 23.1.1/9, improved resize
multi_index_container.hpp: added support for non-standard allocators, improved ctor_args_list, rollback modify
acknowledgements.html: added entry for Boost 1.35
examples.html: renamed example 2, added B.IP example/composite_keys.cpp
future_work.html: removed entry on bimap
hash_indices.html: added c[r]{begin|end}, [local_]iterator_to, rollback modify
reference/index.html: added global_fun
reference/key_extraction.html: added global_fun, added technical correction
multi_index_container.html: added support for non-standard allocators
ord_indices.html: added c[r]{begin|end}, iterator_to, rollback modify
rnd_indices.html: added c[r]{begin|end}, iterator_to, rollback modify
seq_indices.html: added c[r]{begin|end}, iterator_to, rollback modify
release_notes.html: added entry for Boost 1.35
tests.html: added new serialization test file
basics.html: added rollback modify
creation.html: added support for non-standard allocators
tutorial/indices.html: added iterator_to
tutorial/key_extraction.html: added global_fun
composite_keys.cpp: fixed technicality
fun_key.cpp: was memfun_key.cpp, added global_fun
ip_allocator.cpp: initial commit
example/Jamfile.v2: renamed memfun_key, added ip_allocator
test_perf.cpp: fixed technicality
employee.hpp: used a non-standard allocator
test/Jamfile.v2: added new test file
non_std_allocator.hpp: initial commit
pair_of_ints.hpp: added decrement facilities
test_capacity.cpp: added extra check on resize
test_copy_assignment.cpp: added test for 23.1.1/9
test_iterators.cpp: added tests for c[r]{begin|end} and [local_]iterator_to, fixed technicality
test_key_extractors.cpp: added tests for global_fun
test_modifiers.cpp: added tests dor DR 233, fixed technicality
test_range.cpp: added extra checks to secure range refactoring
test_rearrange.cpp: fixed technicality
test_serialization.cpp: added new test file
test_serialization1.cpp: corrected include, used a non-standard allocator
test_serialization2.cpp: corrected include, used a non-standard allocator, split some stuff ro test_serialization3.cpp
test_serialization3.cpp: initial commit
test_serialization3.hpp: initial commit
test_serialization_template.hpp: removed some reliance on ADL
test_update.cpp: addes tests for rollback modify, fixed technicality
Added:
   trunk/boost/multi_index/global_fun.hpp (contents, props changed)
   trunk/libs/multi_index/example/fun_key.cpp (contents, props changed)
   trunk/libs/multi_index/example/ip_allocator.cpp (contents, props changed)
   trunk/libs/multi_index/test/non_std_allocator.hpp (contents, props changed)
   trunk/libs/multi_index/test/test_serialization3.cpp (contents, props changed)
   trunk/libs/multi_index/test/test_serialization3.hpp (contents, props changed)
Text files modified:
   trunk/boost/detail/allocator_utilities.hpp | 12 +
   trunk/boost/multi_index/composite_key.hpp | 4
   trunk/boost/multi_index/detail/auto_space.hpp | 26 ++
   trunk/boost/multi_index/detail/bidir_node_iterator.hpp | 16 +
   trunk/boost/multi_index/detail/bucket_array.hpp | 33 ++-
   trunk/boost/multi_index/detail/copy_map.hpp | 45 +++--
   trunk/boost/multi_index/detail/hash_index_args.hpp | 6
   trunk/boost/multi_index/detail/hash_index_iterator.hpp | 16 +
   trunk/boost/multi_index/detail/hash_index_node.hpp | 112 +++++++++---
   trunk/boost/multi_index/detail/header_holder.hpp | 8
   trunk/boost/multi_index/detail/index_base.hpp | 12 +
   trunk/boost/multi_index/detail/index_loader.hpp | 4
   trunk/boost/multi_index/detail/index_matcher.hpp | 4
   trunk/boost/multi_index/detail/index_node_base.hpp | 13
   trunk/boost/multi_index/detail/iter_adaptor.hpp | 54 ++++++
   trunk/boost/multi_index/detail/modify_key_adaptor.hpp | 10
   trunk/boost/multi_index/detail/node_type.hpp | 4
   trunk/boost/multi_index/detail/ord_index_node.hpp | 340 ++++++++++++++++++++++++---------------
   trunk/boost/multi_index/detail/ord_index_ops.hpp | 80 ++++++---
   trunk/boost/multi_index/detail/rnd_index_loader.hpp | 63 ++++--
   trunk/boost/multi_index/detail/rnd_index_node.hpp | 159 +++++++++++------
   trunk/boost/multi_index/detail/rnd_index_ops.hpp | 64 ++++---
   trunk/boost/multi_index/detail/rnd_index_ptr_array.hpp | 34 +++
   trunk/boost/multi_index/detail/rnd_node_iterator.hpp | 44 ++--
   trunk/boost/multi_index/detail/seq_index_node.hpp | 138 ++++++++++-----
   trunk/boost/multi_index/detail/seq_index_ops.hpp | 81 +++++---
   trunk/boost/multi_index/detail/uintptr_type.hpp | 11 +
   trunk/boost/multi_index/detail/unbounded.hpp | 59 +++++-
   trunk/boost/multi_index/detail/value_compare.hpp | 5
   trunk/boost/multi_index/hashed_index.hpp | 217 ++++++++++++++++++-------
   trunk/boost/multi_index/identity_fwd.hpp | 6
   trunk/boost/multi_index/key_extractors.hpp | 3
   trunk/boost/multi_index/mem_fun.hpp | 24 --
   trunk/boost/multi_index/ordered_index.hpp | 306 ++++++++++++++++++++++++++---------
   trunk/boost/multi_index/random_access_index.hpp | 144 +++++++++++++---
   trunk/boost/multi_index/sequenced_index.hpp | 143 +++++++++++++---
   trunk/boost/multi_index_container.hpp | 90 ++++++++--
   trunk/libs/multi_index/doc/acknowledgements.html | 16 +
   trunk/libs/multi_index/doc/examples.html | 40 +++
   trunk/libs/multi_index/doc/future_work.html | 18 -
   trunk/libs/multi_index/doc/reference/hash_indices.html | 126 ++++++++++++--
   trunk/libs/multi_index/doc/reference/index.html | 8
   trunk/libs/multi_index/doc/reference/key_extraction.html | 180 ++++++++++++++++++++-
   trunk/libs/multi_index/doc/reference/multi_index_container.html | 30 ++
   trunk/libs/multi_index/doc/reference/ord_indices.html | 108 ++++++++++--
   trunk/libs/multi_index/doc/reference/rnd_indices.html | 63 ++++++
   trunk/libs/multi_index/doc/reference/seq_indices.html | 59 ++++++
   trunk/libs/multi_index/doc/release_notes.html | 69 +++++++
   trunk/libs/multi_index/doc/tests.html | 7
   trunk/libs/multi_index/doc/tutorial/basics.html | 74 +++++++-
   trunk/libs/multi_index/doc/tutorial/creation.html | 57 ++++++
   trunk/libs/multi_index/doc/tutorial/indices.html | 60 ++++++
   trunk/libs/multi_index/doc/tutorial/key_extraction.html | 155 ++++++++++++++++-
   trunk/libs/multi_index/example/Jamfile.v2 | 13 +
   trunk/libs/multi_index/example/composite_keys.cpp | 5
   trunk/libs/multi_index/perf/test_perf.cpp | 5
   trunk/libs/multi_index/test/Jamfile.v2 | 5
   trunk/libs/multi_index/test/employee.hpp | 6
   trunk/libs/multi_index/test/pair_of_ints.hpp | 17 +
   trunk/libs/multi_index/test/test_capacity.cpp | 5
   trunk/libs/multi_index/test/test_copy_assignment.cpp | 27 +++
   trunk/libs/multi_index/test/test_iterators.cpp | 34 +++
   trunk/libs/multi_index/test/test_key_extractors.cpp | 104 ++++++++++++
   trunk/libs/multi_index/test/test_modifiers.cpp | 32 +++
   trunk/libs/multi_index/test/test_range.cpp | 4
   trunk/libs/multi_index/test/test_rearrange.cpp | 3
   trunk/libs/multi_index/test/test_serialization.cpp | 4
   trunk/libs/multi_index/test/test_serialization1.cpp | 8
   trunk/libs/multi_index/test/test_serialization2.cpp | 89 ---------
   trunk/libs/multi_index/test/test_serialization_template.hpp | 12
   trunk/libs/multi_index/test/test_update.cpp | 57 ++++--
   71 files changed, 2870 insertions(+), 1020 deletions(-)

Modified: trunk/boost/detail/allocator_utilities.hpp
==============================================================================
--- trunk/boost/detail/allocator_utilities.hpp (original)
+++ trunk/boost/detail/allocator_utilities.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -30,13 +30,21 @@
 namespace allocator{
 
 /* partial_std_allocator_wrapper inherits the functionality of a std
- * allocator while providing a templatized ctor.
+ * allocator while providing a templatized ctor and other bits missing
+ * in some stdlib implementation or another.
  */
 
 template<typename Type>
 class partial_std_allocator_wrapper:public std::allocator<Type>
 {
 public:
+ /* Oddly enough, STLport does not define std::allocator<void>::value_type
+ * when configured to work without partial template specialization.
+ * No harm in supplying the definition here unconditionally.
+ */
+
+ typedef Type value_type;
+
   partial_std_allocator_wrapper(){};
 
   template<typename Other>

Modified: trunk/boost/multi_index/composite_key.hpp
==============================================================================
--- trunk/boost/multi_index/composite_key.hpp (original)
+++ trunk/boost/multi_index/composite_key.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -14,6 +14,7 @@
 #endif
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <boost/functional/hash_fwd.hpp>
 #include <boost/multi_index/detail/access_specifier.hpp>
 #include <boost/multi_index/detail/prevent_eti.hpp>
 #include <boost/mpl/eval_if.hpp>
@@ -106,7 +107,6 @@
 namespace boost{
 
 template<class T> class reference_wrapper; /* fwd decl. */
-template<class T> struct hash; /* fwd decl. */
 
 namespace multi_index{
 

Modified: trunk/boost/multi_index/detail/auto_space.hpp
==============================================================================
--- trunk/boost/multi_index/detail/auto_space.hpp (original)
+++ trunk/boost/multi_index/detail/auto_space.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -16,6 +16,7 @@
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 #include <algorithm>
 #include <boost/detail/allocator_utilities.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
 #include <boost/noncopyable.hpp>
 #include <memory>
 
@@ -44,8 +45,15 @@
 template<typename T,typename Allocator=std::allocator<T> >
 struct auto_space:private noncopyable
 {
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,T
+ >::type
+ >::type::pointer pointer;
+
   explicit auto_space(const Allocator& al=Allocator(),std::size_t n=1):
- al_(al),n_(n),data_(n_?al_.allocate(n_):0)
+ al_(al),n_(n),data_(n_?al_.allocate(n_):pointer(0))
   {}
 
   ~auto_space()
@@ -55,10 +63,20 @@
 
   Allocator get_allocator()const{return al_;}
 
- T* data()const{return data_;}
+ pointer data()const{return data_;}
 
   void swap(auto_space& x)
   {
+ if(al_!=x.al_){
+
+#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)
+ std::swap(al_,x.al_);
+#else
+ using std::swap;
+ swap(al_,x.al_);
+#endif
+
+ }
     std::swap(n_,x.n_);
     std::swap(data_,x.data_);
   }
@@ -67,7 +85,7 @@
   typename boost::detail::allocator::rebind_to<
     Allocator,T>::type al_;
   std::size_t n_;
- T* data_;
+ pointer data_;
 };
 
 template<typename T,typename Allocator>

Modified: trunk/boost/multi_index/detail/bidir_node_iterator.hpp
==============================================================================
--- trunk/boost/multi_index/detail/bidir_node_iterator.hpp (original)
+++ trunk/boost/multi_index/detail/bidir_node_iterator.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -49,12 +49,6 @@
     return node->value();
   }
 
- friend bool operator==(
- const bidir_node_iterator& x,const bidir_node_iterator& y)
- {
- return x.node==y.node;
- }
-
   bidir_node_iterator& operator++()
   {
     Node::increment(node);
@@ -102,6 +96,14 @@
   Node* node;
 };
 
+template<typename Node,typename Derived>
+bool operator==(
+ const bidir_node_iterator<Node,Derived>& x,
+ const bidir_node_iterator<Node,Derived>& y)
+{
+ return x.get_node()==y.get_node();
+}
+
 } /* namespace multi_index::detail */
 
 } /* namespace multi_index */

Modified: trunk/boost/multi_index/detail/bucket_array.hpp
==============================================================================
--- trunk/boost/multi_index/detail/bucket_array.hpp (original)
+++ trunk/boost/multi_index/detail/bucket_array.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -17,6 +17,7 @@
 #include <algorithm>
 #include <boost/multi_index/detail/auto_space.hpp>
 #include <boost/multi_index/detail/hash_index_node.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
 #include <boost/noncopyable.hpp>
 #include <cstddef>
 #include <limits.h>
@@ -84,8 +85,20 @@
 template<typename Allocator>
 class bucket_array:public bucket_array_base
 {
+ typedef typename prevent_eti<
+ Allocator,
+ hashed_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ Allocator,
+ void
+ >::type
+ >
+ >::type node_impl_type;
+
 public:
- bucket_array(const Allocator& al,hashed_index_node_impl* end_,std::size_t size):
+ typedef typename node_impl_type::pointer pointer;
+
+ bucket_array(const Allocator& al,pointer end_,std::size_t size):
     size_(bucket_array_base::next_prime(size)),
     spc(al,size_+1)
   {
@@ -104,21 +117,21 @@
     return hash%size_;
   }
 
- hashed_index_node_impl* begin()const{return &buckets()[0];}
- hashed_index_node_impl* end()const{return &buckets()[size_];}
- hashed_index_node_impl* at(std::size_t n)const{return &buckets()[n];}
+ pointer begin()const{return buckets();}
+ pointer end()const{return buckets()+size_;}
+ pointer at(std::size_t n)const{return buckets()+n;}
 
   std::size_t first_nonempty(std::size_t n)const
   {
     for(;;++n){
- hashed_index_node_impl* x=at(n);
+ pointer x=at(n);
       if(x->next()!=x)return n;
     }
   }
 
   void clear()
   {
- for(hashed_index_node_impl* x=begin(),*y=end();x!=y;++x)x->next()=x;
+ for(pointer x=begin(),y=end();x!=y;++x)x->next()=x;
   }
 
   void swap(bucket_array& x)
@@ -128,10 +141,10 @@
   }
 
 private:
- std::size_t size_;
- auto_space<hashed_index_node_impl,Allocator> spc;
+ std::size_t size_;
+ auto_space<node_impl_type,Allocator> spc;
 
- hashed_index_node_impl* buckets()const
+ pointer buckets()const
   {
     return spc.data();
   }

Modified: trunk/boost/multi_index/detail/copy_map.hpp
==============================================================================
--- trunk/boost/multi_index/detail/copy_map.hpp (original)
+++ trunk/boost/multi_index/detail/copy_map.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -17,6 +17,7 @@
 #include <algorithm>
 #include <boost/detail/no_exceptions_support.hpp>
 #include <boost/multi_index/detail/auto_space.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
 #include <boost/noncopyable.hpp>
 #include <cstddef>
 #include <functional>
@@ -69,31 +70,31 @@
   {
     if(!released){
       for(std::size_t i=0;i<n;++i){
- boost::detail::allocator::destroy(&spc.data()[i].second->value());
- deallocate(spc.data()[i].second);
+ boost::detail::allocator::destroy(&(spc.data()+i)->second->value());
+ deallocate((spc.data()+i)->second);
       }
     }
   }
 
- const_iterator begin()const{return spc.data();}
- const_iterator end()const{return spc.data()+n;}
+ const_iterator begin()const{return &*spc.data();}
+ const_iterator end()const{return &*(spc.data()+n);}
 
   void clone(Node* node)
   {
- spc.data()[n].first=node;
- spc.data()[n].second=al_.allocate(1);
+ (spc.data()+n)->first=node;
+ (spc.data()+n)->second=&*al_.allocate(1);
     BOOST_TRY{
       boost::detail::allocator::construct(
- &spc.data()[n].second->value(),node->value());
+ &(spc.data()+n)->second->value(),node->value());
     }
     BOOST_CATCH(...){
- deallocate(spc.data()[n].second);
+ deallocate((spc.data()+n)->second);
       BOOST_RETHROW;
     }
     BOOST_CATCH_END
     ++n;
 
- if(n==size_)std::sort(spc.data(),spc.data()+size_);
+ if(n==size_)std::sort(&*spc.data(),&*spc.data()+size_);
   }
 
   Node* find(Node* node)const
@@ -109,18 +110,24 @@
   }
 
 private:
- typename boost::detail::allocator::rebind_to<
- Allocator,Node>::type al_;
- std::size_t size_;
- auto_space<copy_map_entry<Node>,Allocator> spc;
- std::size_t n;
- Node* header_org_;
- Node* header_cpy_;
- bool released;
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,Node>::type
+ >::type allocator_type;
+ typedef typename allocator_type::pointer allocator_pointer;
+
+ allocator_type al_;
+ std::size_t size_;
+ auto_space<copy_map_entry<Node>,Allocator> spc;
+ std::size_t n;
+ Node* header_org_;
+ Node* header_cpy_;
+ bool released;
 
   void deallocate(Node* node)
   {
- al_.deallocate(node,1);
+ al_.deallocate(static_cast<allocator_pointer>(node),1);
   }
 };
 

Modified: trunk/boost/multi_index/detail/hash_index_args.hpp
==============================================================================
--- trunk/boost/multi_index/detail/hash_index_args.hpp (original)
+++ trunk/boost/multi_index/detail/hash_index_args.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -14,7 +14,7 @@
 #endif
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
-#include <boost/functional/hash/hash.hpp>
+#include <boost/functional/hash.hpp>
 #include <boost/mpl/aux_/na.hpp>
 #include <boost/mpl/eval_if.hpp>
 #include <boost/mpl/identity.hpp>
@@ -26,8 +26,6 @@
 
 namespace boost{
 
-template<class T> struct hash; /* fwd decl. */
-
 namespace multi_index{
 
 namespace detail{

Modified: trunk/boost/multi_index/detail/hash_index_iterator.hpp
==============================================================================
--- trunk/boost/multi_index/detail/hash_index_iterator.hpp (original)
+++ trunk/boost/multi_index/detail/hash_index_iterator.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -50,12 +50,6 @@
     return node->value();
   }
 
- friend bool operator==(
- const hashed_index_iterator& x,const hashed_index_iterator& y)
- {
- return x.node==y.node;
- }
-
   hashed_index_iterator& operator++()
   {
     Node::increment(node,buckets->begin(),buckets->end());
@@ -100,6 +94,14 @@
   BucketArray* buckets;
 };
 
+template<typename Node,typename BucketArray,typename Derived>
+bool operator==(
+ const hashed_index_iterator<Node,BucketArray,Derived>& x,
+ const hashed_index_iterator<Node,BucketArray,Derived>& y)
+{
+ return x.get_node()==y.get_node();
+}
+
 } /* namespace multi_index::detail */
 
 } /* namespace multi_index */

Modified: trunk/boost/multi_index/detail/hash_index_node.hpp
==============================================================================
--- trunk/boost/multi_index/detail/hash_index_node.hpp (original)
+++ trunk/boost/multi_index/detail/hash_index_node.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -14,6 +14,8 @@
 #endif
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <boost/detail/allocator_utilities.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
 #include <functional>
 
 namespace boost{
@@ -24,18 +26,30 @@
 
 /* singly-linked node for use by hashed_index */
 
+template<typename Allocator>
 struct hashed_index_node_impl
 {
- hashed_index_node_impl*& next(){return next_;}
- hashed_index_node_impl* next()const{return next_;}
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,hashed_index_node_impl
+ >::type
+ >::type::pointer pointer;
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,hashed_index_node_impl
+ >::type
+ >::type::const_pointer const_pointer;
+
+ pointer& next(){return next_;}
+ pointer next()const{return next_;}
 
   /* algorithmic stuff */
 
- static void increment(
- hashed_index_node_impl*& x,
- hashed_index_node_impl* bbegin,hashed_index_node_impl* bbend)
+ static void increment(pointer& x,pointer bbegin,pointer bbend)
   {
- std::less_equal<hashed_index_node_impl*> leq;
+ std::less_equal<pointer> leq;
 
     x=x->next();
     if(leq(bbegin,x)&&leq(x,bbend)){ /* bucket node */
@@ -46,66 +60,100 @@
     }
   }
 
- static void link(
- hashed_index_node_impl* x,hashed_index_node_impl* pos)
+ static void link(pointer x,pointer pos)
   {
     x->next()=pos->next();
     pos->next()=x;
   };
 
- static void unlink(hashed_index_node_impl* x)
+ static void unlink(pointer x)
   {
- hashed_index_node_impl* y=x->next();
+ pointer y=x->next();
     while(y->next()!=x){y=y->next();}
     y->next()=x->next();
   }
 
- static hashed_index_node_impl* prev(hashed_index_node_impl* x)
+ static pointer prev(pointer x)
   {
- hashed_index_node_impl* y=x->next();
+ pointer y=x->next();
     while(y->next()!=x){y=y->next();}
     return y;
   }
 
- static void unlink_next(hashed_index_node_impl* x)
+ static void unlink_next(pointer x)
   {
     x->next()=x->next()->next();
   }
 
 private:
- hashed_index_node_impl* next_;
+ pointer next_;
 };
 
 template<typename Super>
-struct hashed_index_node_trampoline:hashed_index_node_impl{};
+struct hashed_index_node_trampoline:
+ prevent_eti<
+ Super,
+ hashed_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ typename Super::allocator_type,
+ void
+ >::type
+ >
+ >::type
+{
+ typedef typename prevent_eti<
+ Super,
+ hashed_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ typename Super::allocator_type,
+ void
+ >::type
+ >
+ >::type impl_type;
+};
 
 template<typename Super>
 struct hashed_index_node:Super,hashed_index_node_trampoline<Super>
 {
- hashed_index_node_impl* impl()
- {return static_cast<impl_type*>(this);}
- const hashed_index_node_impl* impl()const
- {return static_cast<const impl_type*>(this);}
-
- static hashed_index_node* from_impl(hashed_index_node_impl *x)
- {return static_cast<hashed_index_node*>(static_cast<impl_type*>(x));}
- static const hashed_index_node* from_impl(const hashed_index_node_impl* x)
+private:
+ typedef hashed_index_node_trampoline<Super> trampoline;
+
+public:
+ typedef typename trampoline::impl_type impl_type;
+ typedef typename trampoline::pointer impl_pointer;
+ typedef typename trampoline::const_pointer const_impl_pointer;
+
+ impl_pointer impl()
+ {
+ return static_cast<impl_pointer>(
+ static_cast<impl_type*>(static_cast<trampoline*>(this)));
+ }
+
+ const_impl_pointer impl()const
+ {
+ return static_cast<const_impl_pointer>(
+ static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
+ }
+
+ static hashed_index_node* from_impl(impl_pointer x)
+ {
+ return static_cast<hashed_index_node*>(
+ static_cast<trampoline*>(&*x));
+ }
+
+ static const hashed_index_node* from_impl(const_impl_pointer x)
   {
     return static_cast<const hashed_index_node*>(
- static_cast<const impl_type*>(x));
+ static_cast<const trampoline*>(&*x));
   }
 
   static void increment(
- hashed_index_node*& x,
- hashed_index_node_impl* bbegin,hashed_index_node_impl* bend)
+ hashed_index_node*& x,impl_pointer bbegin,impl_pointer bend)
   {
- hashed_index_node_impl* xi=x->impl();
- impl_type::increment(xi,bbegin,bend);
+ impl_pointer xi=x->impl();
+ trampoline::increment(xi,bbegin,bend);
     x=from_impl(xi);
   }
-
-private:
- typedef hashed_index_node_trampoline<Super> impl_type;
 };
 
 } /* namespace multi_index::detail */

Modified: trunk/boost/multi_index/detail/header_holder.hpp
==============================================================================
--- trunk/boost/multi_index/detail/header_holder.hpp (original)
+++ trunk/boost/multi_index/detail/header_holder.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -29,13 +29,13 @@
  * to the base from member trick.
  */
 
-template<typename NodeType,typename Final>
+template<typename NodeTypePtr,typename Final>
 struct header_holder:private noncopyable
 {
   header_holder():member(final().allocate_node()){}
- ~header_holder(){final().deallocate_node(member);}
+ ~header_holder(){final().deallocate_node(&*member);}
 
- NodeType* member;
+ NodeTypePtr member;
 
 private:
   Final& final(){return *static_cast<Final*>(this);}

Modified: trunk/boost/multi_index/detail/index_base.hpp
==============================================================================
--- trunk/boost/multi_index/detail/index_base.hpp (original)
+++ trunk/boost/multi_index/detail/index_base.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -46,7 +46,7 @@
 class index_base
 {
 protected:
- typedef index_node_base<Value> node_type;
+ typedef index_node_base<Value,Allocator> node_type;
   typedef typename multi_index_node_type<
     Value,IndexSpecifierList,Allocator>::type final_node_type;
   typedef multi_index_container<
@@ -117,6 +117,8 @@
 
   bool modify_(node_type*){return true;}
 
+ bool modify_rollback_(node_type*){return true;}
+
 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   /* serialization */
 
@@ -162,9 +164,13 @@
     {return final().replace_(k,x);}
 
   template<typename Modifier>
- bool final_modify_(Modifier mod,final_node_type* x)
+ bool final_modify_(Modifier& mod,final_node_type* x)
     {return final().modify_(mod,x);}
 
+ template<typename Modifier,typename Rollback>
+ bool final_modify_(Modifier& mod,Rollback& back,final_node_type* x)
+ {return final().modify_(mod,back,x);}
+
 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
   void final_check_invariant_()const{final().check_invariant_();}
 #endif

Modified: trunk/boost/multi_index/detail/index_loader.hpp
==============================================================================
--- trunk/boost/multi_index/detail/index_loader.hpp (original)
+++ trunk/boost/multi_index/detail/index_loader.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -91,7 +91,7 @@
   }
 
 private:
- Node** entries()const{return spc.data();}
+ Node** entries()const{return &*spc.data();}
 
   /* We try to delay sorting as much as possible just in case it
    * is not necessary, hence this version of load_node.

Modified: trunk/boost/multi_index/detail/index_matcher.hpp
==============================================================================
--- trunk/boost/multi_index/detail/index_matcher.hpp (original)
+++ trunk/boost/multi_index/detail/index_matcher.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -179,7 +179,7 @@
   }
 
 private:
- entry* entries()const{return spc.data();}
+ entry* entries()const{return &*spc.data();}
 
   auto_space<entry,Allocator> spc;
   std::size_t size_;

Modified: trunk/boost/multi_index/detail/index_node_base.hpp
==============================================================================
--- trunk/boost/multi_index/detail/index_node_base.hpp (original)
+++ trunk/boost/multi_index/detail/index_node_base.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -42,11 +42,12 @@
>::type space;
 };
 
-template<typename Value>
+template<typename Value,typename Allocator>
 struct index_node_base:private pod_value_holder<Value>
 {
   typedef index_node_base base_type; /* used for serialization purposes */
   typedef Value value_type;
+ typedef Allocator allocator_type;
 
   value_type& value()
   {
@@ -88,7 +89,9 @@
   const Value* p
   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
 {
- return static_cast<Node*>(index_node_base<Value>::from_value(p));
+ typedef typename Node::allocator_type allocator_type;
+ return static_cast<Node*>(
+ index_node_base<Value,allocator_type>::from_value(p));
 }
 
 } /* namespace multi_index::detail */
@@ -109,9 +112,9 @@
 namespace detail{
 #endif
 
-template<class Archive,typename Value>
+template<class Archive,typename Value,typename Allocator>
 inline void load_construct_data(
- Archive&,boost::multi_index::detail::index_node_base<Value>*,
+ Archive&,boost::multi_index::detail::index_node_base<Value,Allocator>*,
   const unsigned int)
 {
   throw_exception(

Modified: trunk/boost/multi_index/detail/iter_adaptor.hpp
==============================================================================
--- trunk/boost/multi_index/detail/iter_adaptor.hpp (original)
+++ trunk/boost/multi_index/detail/iter_adaptor.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -30,6 +30,12 @@
  * for internal consumption.
  */
 
+/* NB. The purpose of the (non-inclass) global operators ==, < and - defined
+ * above is to partially alleviate a problem of MSVC++ 6.0 by * which
+ * friend-injected operators on T are not visible if T is instantiated only
+ * in template code where T is a dependent type.
+ */
+
 class iter_adaptor_access
 {
 public:
@@ -107,6 +113,15 @@
   const Derived& final()const{return *static_cast<const Derived*>(this);}
 };
 
+template<class Derived,class Base>
+bool operator==(
+ const forward_iter_adaptor_base<Derived,Base>& x,
+ const forward_iter_adaptor_base<Derived,Base>& y)
+{
+ return iter_adaptor_access::equal(
+ static_cast<const Derived&>(x),static_cast<const Derived&>(y));
+}
+
 template<>
 struct iter_adaptor_selector<std::forward_iterator_tag>
 {
@@ -156,6 +171,15 @@
   const Derived& final()const{return *static_cast<const Derived*>(this);}
 };
 
+template<class Derived,class Base>
+bool operator==(
+ const bidirectional_iter_adaptor_base<Derived,Base>& x,
+ const bidirectional_iter_adaptor_base<Derived,Base>& y)
+{
+ return iter_adaptor_access::equal(
+ static_cast<const Derived&>(x),static_cast<const Derived&>(y));
+}
+
 template<>
 struct iter_adaptor_selector<std::bidirectional_iterator_tag>
 {
@@ -228,6 +252,34 @@
   const Derived& final()const{return *static_cast<const Derived*>(this);}
 };
 
+template<class Derived,class Base>
+bool operator==(
+ const random_access_iter_adaptor_base<Derived,Base>& x,
+ const random_access_iter_adaptor_base<Derived,Base>& y)
+{
+ return iter_adaptor_access::equal(
+ static_cast<const Derived&>(x),static_cast<const Derived&>(y));
+}
+
+template<class Derived,class Base>
+bool operator<(
+ const random_access_iter_adaptor_base<Derived,Base>& x,
+ const random_access_iter_adaptor_base<Derived,Base>& y)
+{
+ return iter_adaptor_access::distance_to(
+ static_cast<const Derived&>(x),static_cast<const Derived&>(y))>0;
+}
+
+template<class Derived,class Base>
+typename random_access_iter_adaptor_base<Derived,Base>::difference_type
+operator-(
+ const random_access_iter_adaptor_base<Derived,Base>& x,
+ const random_access_iter_adaptor_base<Derived,Base>& y)
+{
+ return iter_adaptor_access::distance_to(
+ static_cast<const Derived&>(y),static_cast<const Derived&>(x));
+}
+
 template<>
 struct iter_adaptor_selector<std::random_access_iterator_tag>
 {

Modified: trunk/boost/multi_index/detail/modify_key_adaptor.hpp
==============================================================================
--- trunk/boost/multi_index/detail/modify_key_adaptor.hpp (original)
+++ trunk/boost/multi_index/detail/modify_key_adaptor.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -24,19 +24,19 @@
  * with references to references, dealing with function pointers, etc.
  */
 
-template<typename Modifier,typename Value,typename KeyFromValue>
+template<typename Fun,typename Value,typename KeyFromValue>
 struct modify_key_adaptor
 {
 
- modify_key_adaptor(Modifier mod_,KeyFromValue kfv_):mod(mod_),kfv(kfv_){}
+ modify_key_adaptor(Fun f_,KeyFromValue kfv_):f(f_),kfv(kfv_){}
 
   void operator()(Value& x)
   {
- mod(kfv(x));
+ f(kfv(x));
   }
 
 private:
- Modifier mod;
+ Fun f;
   KeyFromValue kfv;
 };
 

Modified: trunk/boost/multi_index/detail/node_type.hpp
==============================================================================
--- trunk/boost/multi_index/detail/node_type.hpp (original)
+++ trunk/boost/multi_index/detail/node_type.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -65,7 +65,7 @@
 
   typedef typename mpl::reverse_iter_fold<
     IndexSpecifierList,
- index_node_base<Value>,
+ index_node_base<Value,Allocator>,
     mpl::bind2<index_node_applier,mpl::_2,mpl::_1>
>::type type;
 };

Modified: trunk/boost/multi_index/detail/ord_index_node.hpp
==============================================================================
--- trunk/boost/multi_index/detail/ord_index_node.hpp (original)
+++ trunk/boost/multi_index/detail/ord_index_node.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -42,12 +42,15 @@
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 #include <cstddef>
+#include <boost/detail/allocator_utilities.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
 
 #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
 #include <boost/mpl/and.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/multi_index/detail/uintptr_type.hpp>
 #include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/is_same.hpp>
 #endif
 
 namespace boost{
@@ -61,27 +64,43 @@
 enum ordered_index_color{red=false,black=true};
 enum ordered_index_side{to_left=false,to_right=true};
 
+template<typename Allocator>
 struct ordered_index_node_impl; /* fwd decl. */
 
+template<typename Allocator>
 struct ordered_index_node_std_base
 {
- typedef ordered_index_color& color_ref;
- typedef ordered_index_node_impl*& parent_ref;
-
- ordered_index_color& color(){return color_;}
- ordered_index_color color()const{return color_;}
- ordered_index_node_impl*& parent(){return parent_;}
- ordered_index_node_impl* parent()const{return parent_;}
- ordered_index_node_impl*& left(){return left_;}
- ordered_index_node_impl* left()const{return left_;}
- ordered_index_node_impl*& right(){return right_;}
- ordered_index_node_impl* right()const{return right_;}
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,
+ ordered_index_node_impl<Allocator>
+ >::type
+ >::type::pointer pointer;
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,
+ ordered_index_node_impl<Allocator>
+ >::type
+ >::type::const_pointer const_pointer;
+ typedef ordered_index_color& color_ref;
+ typedef pointer& parent_ref;
+
+ ordered_index_color& color(){return color_;}
+ ordered_index_color color()const{return color_;}
+ pointer& parent(){return parent_;}
+ pointer parent()const{return parent_;}
+ pointer& left(){return left_;}
+ pointer left()const{return left_;}
+ pointer& right(){return right_;}
+ pointer right()const{return right_;}
 
 private:
- ordered_index_color color_;
- ordered_index_node_impl* parent_;
- ordered_index_node_impl* left_;
- ordered_index_node_impl* right_;
+ ordered_index_color color_;
+ pointer parent_;
+ pointer left_;
+ pointer right_;
 };
 
 #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
@@ -102,8 +121,12 @@
 #pragma warning(disable:4312 4311)
 #endif
 
+template<typename Allocator>
 struct ordered_index_node_compressed_base
 {
+ typedef ordered_index_node_impl<Allocator>* pointer;
+ typedef const ordered_index_node_impl<Allocator>* const_pointer;
+
   struct color_ref
   {
     color_ref(uintptr_type* r_):r(r_){}
@@ -133,12 +156,12 @@
   {
     parent_ref(uintptr_type* r_):r(r_){}
     
- operator ordered_index_node_impl*()const
+ operator pointer()const
     {
- return (ordered_index_node_impl*)(void*)(*r&~uintptr_type(1));
+ return (pointer)(void*)(*r&~uintptr_type(1));
     }
     
- parent_ref& operator=(ordered_index_node_impl* p)
+ parent_ref& operator=(pointer p)
     {
       *r=((uintptr_type)(void*)p)|(*r&uintptr_type(1));
       return *this;
@@ -146,69 +169,92 @@
     
     parent_ref& operator=(const parent_ref& x)
     {
- return operator=(x.operator ordered_index_node_impl*());
+ return operator=(x.operator pointer());
     }
 
- ordered_index_node_impl* operator->()const
+ pointer operator->()const
     {
- return operator ordered_index_node_impl*();
+ return operator pointer();
     }
 
   private:
     uintptr_type* r;
   };
   
- color_ref color(){return color_ref(&parentcolor_);}
- ordered_index_color color()const
+ color_ref color(){return color_ref(&parentcolor_);}
+ ordered_index_color color()const
   {
     return ordered_index_color(parentcolor_&std::size_t(1ul));
   }
 
- parent_ref parent(){return parent_ref(&parentcolor_);}
- ordered_index_node_impl* parent()const
+ parent_ref parent(){return parent_ref(&parentcolor_);}
+ pointer parent()const
   {
- return (ordered_index_node_impl*)(void*)(parentcolor_&~uintptr_type(1));
+ return (pointer)(void*)(parentcolor_&~uintptr_type(1));
   }
 
- ordered_index_node_impl*& left(){return left_;}
- ordered_index_node_impl* left()const{return left_;}
- ordered_index_node_impl*& right(){return right_;}
- ordered_index_node_impl* right()const{return right_;}
+ pointer& left(){return left_;}
+ pointer left()const{return left_;}
+ pointer& right(){return right_;}
+ pointer right()const{return right_;}
 
 private:
- uintptr_type parentcolor_;
- ordered_index_node_impl* left_;
- ordered_index_node_impl* right_;
+ uintptr_type parentcolor_;
+ pointer left_;
+ pointer right_;
 };
 #if defined(BOOST_MSVC)
 #pragma warning(pop)
 #endif
 #endif
 
-struct ordered_index_node_impl:
+template<typename Allocator>
+struct ordered_index_node_impl_base:
 
 #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
   mpl::if_c<
     !(has_uintptr_type::value)||
- (alignment_of<ordered_index_node_compressed_base>::value%2),
- ordered_index_node_std_base,
- ordered_index_node_compressed_base
+ (alignment_of<ordered_index_node_compressed_base<Allocator> >::value%2)||
+ !(is_same<
+ typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,
+ ordered_index_node_impl<Allocator>
+ >::type
+ >::type::pointer,
+ ordered_index_node_impl<Allocator>*>::value),
+ ordered_index_node_std_base<Allocator>,
+ ordered_index_node_compressed_base<Allocator>
>::type
 #else
- ordered_index_node_std_base
+ ordered_index_node_std_base<Allocator>
 #endif
 
+{};
+
+template<typename Allocator>
+struct ordered_index_node_impl:ordered_index_node_impl_base<Allocator>
 {
+private:
+ typedef ordered_index_node_impl_base<Allocator> super;
+
+public:
+ typedef typename super::color_ref color_ref;
+ typedef typename super::parent_ref parent_ref;
+ typedef typename super::pointer pointer;
+ typedef typename super::const_pointer const_pointer;
+
   /* interoperability with bidir_node_iterator */
 
- static void increment(ordered_index_node_impl*& x)
+ static void increment(pointer& x)
   {
- if(x->right()){
+ if(x->right()!=pointer(0)){
       x=x->right();
- while(x->left())x=x->left();
+ while(x->left()!=pointer(0))x=x->left();
     }
     else{
- ordered_index_node_impl* y=x->parent();
+ pointer y=x->parent();
       while(x==y->right()){
         x=y;
         y=y->parent();
@@ -217,17 +263,17 @@
     }
   }
 
- static void decrement(ordered_index_node_impl*& x)
+ static void decrement(pointer& x)
   {
     if(x->color()==red&&x->parent()->parent()==x){
       x=x->right();
     }
- else if(x->left()){
- ordered_index_node_impl* y=x->left();
- while(y->right())y=y->right();
+ else if(x->left()!=pointer(0)){
+ pointer y=x->left();
+ while(y->right()!=pointer(0))y=y->right();
       x=y;
     }else{
- ordered_index_node_impl* y=x->parent();
+ pointer y=x->parent();
       while(x==y->left()){
         x=y;
         y=y->parent();
@@ -238,12 +284,11 @@
 
   /* algorithmic stuff */
 
- static void rotate_left(
- ordered_index_node_impl* x,parent_ref root)
+ static void rotate_left(pointer x,parent_ref root)
   {
- ordered_index_node_impl* y=x->right();
+ pointer y=x->right();
     x->right()=y->left();
- if(y->left())y->left()->parent()=x;
+ if(y->left()!=pointer(0))y->left()->parent()=x;
     y->parent()=x->parent();
     
     if(x==root) root=y;
@@ -253,24 +298,23 @@
     x->parent()=y;
   }
 
- static ordered_index_node_impl* minimum(ordered_index_node_impl* x)
+ static pointer minimum(pointer x)
   {
- while(x->left())x=x->left();
+ while(x->left()!=pointer(0))x=x->left();
     return x;
   }
 
- static ordered_index_node_impl* maximum(ordered_index_node_impl* x)
+ static pointer maximum(pointer x)
   {
- while(x->right())x=x->right();
+ while(x->right()!=pointer(0))x=x->right();
     return x;
   }
 
- static void rotate_right(
- ordered_index_node_impl* x,parent_ref root)
+ static void rotate_right(pointer x,parent_ref root)
   {
- ordered_index_node_impl* y=x->left();
+ pointer y=x->left();
     x->left()=y->right();
- if(y->right())y->right()->parent()=x;
+ if(y->right()!=pointer(0))y->right()->parent()=x;
     y->parent()=x->parent();
 
     if(x==root) root=y;
@@ -280,14 +324,13 @@
     x->parent()=y;
   }
 
- static void rebalance(
- ordered_index_node_impl* x,parent_ref root)
+ static void rebalance(pointer x,parent_ref root)
   {
     x->color()=red;
     while(x!=root&&x->parent()->color()==red){
       if(x->parent()==x->parent()->parent()->left()){
- ordered_index_node_impl* y=x->parent()->parent()->right();
- if(y&&y->color()==red){
+ pointer y=x->parent()->parent()->right();
+ if(y!=pointer(0)&&y->color()==red){
           x->parent()->color()=black;
           y->color()=black;
           x->parent()->parent()->color()=red;
@@ -304,8 +347,8 @@
         }
       }
       else{
- ordered_index_node_impl* y=x->parent()->parent()->left();
- if(y&&y->color()==red){
+ pointer y=x->parent()->parent()->left();
+ if(y!=pointer(0)&&y->color()==red){
           x->parent()->color()=black;
           y->color()=black;
           x->parent()->parent()->color()=red;
@@ -326,9 +369,7 @@
   }
 
   static void link(
- ordered_index_node_impl* x,
- ordered_index_side side,ordered_index_node_impl* position,
- ordered_index_node_impl* header)
+ pointer x,ordered_index_side side,pointer position,pointer header)
   {
     if(side==to_left){
       position->left()=x; /* also makes leftmost=x when parent==header */
@@ -347,28 +388,27 @@
       }
     }
     x->parent()=position;
- x->left()=0;
- x->right()=0;
+ x->left()=pointer(0);
+ x->right()=pointer(0);
     ordered_index_node_impl::rebalance(x,header->parent());
   }
 
- static ordered_index_node_impl* rebalance_for_erase(
- ordered_index_node_impl* z,parent_ref root,
- ordered_index_node_impl*& leftmost,ordered_index_node_impl*& rightmost)
- {
- ordered_index_node_impl* y=z;
- ordered_index_node_impl* x=0;
- ordered_index_node_impl* x_parent=0;
- if(y->left()==0){ /* z has at most one non-null child. y==z. */
- x=y->right(); /* x might be null */
+ static pointer rebalance_for_erase(
+ pointer z,parent_ref root,pointer& leftmost,pointer& rightmost)
+ {
+ pointer y=z;
+ pointer x=pointer(0);
+ pointer x_parent=pointer(0);
+ if(y->left()==pointer(0)){ /* z has at most one non-null child. y==z. */
+ x=y->right(); /* x might be null */
     }
     else{
- if(y->right()==0) { /* z has exactly one non-null child. y==z. */
- x=y->left(); /* x is not null */
+ if(y->right()==pointer(0)){ /* z has exactly one non-null child. y==z. */
+ x=y->left(); /* x is not null */
       }
- else{ /* z has two non-null children. Set y to */
- y=y->right(); /* z's successor. x might be null. */
- while(y->left())y=y->left();
+ else{ /* z has two non-null children. Set y to */
+ y=y->right(); /* z's successor. x might be null. */
+ while(y->left()!=pointer(0))y=y->left();
         x=y->right();
       }
     }
@@ -377,7 +417,7 @@
       y->left()=z->left();
       if(y!=z->right()){
         x_parent=y->parent();
- if(x) x->parent()=y->parent();
+ if(x!=pointer(0))x->parent()=y->parent();
         y->parent()->left()=x; /* y must be a child of left */
         y->right()=z->right();
         z->right()->parent()=y;
@@ -397,7 +437,7 @@
     }
     else{ /* y==z */
       x_parent=y->parent();
- if(x)x->parent()=y->parent();
+ if(x!=pointer(0))x->parent()=y->parent();
       if(root==z){
         root=x;
       }
@@ -406,15 +446,15 @@
         else z->parent()->right()=x;
       }
       if(leftmost==z){
- if(z->right()==0){ /* z->left() must be null also */
+ if(z->right()==pointer(0)){ /* z->left() must be null also */
           leftmost=z->parent();
         }
         else{
- leftmost=minimum(x); /* makes leftmost==header if z==root */
+ leftmost=minimum(x); /* makes leftmost==header if z==root */
         }
       }
       if(rightmost==z){
- if(z->left()==0){ /* z->right() must be null also */
+ if(z->left()==pointer(0)){ /* z->right() must be null also */
           rightmost=z->parent();
         }
         else{ /* x==z->left() */
@@ -423,75 +463,73 @@
       }
     }
     if(y->color()!=red){
- while(x!=root&&(x==0 || x->color()==black)){
+ while(x!=root&&(x==pointer(0)|| x->color()==black)){
         if(x==x_parent->left()){
- ordered_index_node_impl* w=x_parent->right();
+ pointer w=x_parent->right();
           if(w->color()==red){
             w->color()=black;
             x_parent->color()=red;
             rotate_left(x_parent,root);
             w=x_parent->right();
           }
- if((w->left()==0||w->left()->color()==black) &&
- (w->right()==0||w->right()->color()==black)){
+ if((w->left()==pointer(0)||w->left()->color()==black) &&
+ (w->right()==pointer(0)||w->right()->color()==black)){
             w->color()=red;
             x=x_parent;
             x_parent=x_parent->parent();
           }
           else{
- if(w->right()==0
+ if(w->right()==pointer(0 )
                 || w->right()->color()==black){
- if(w->left()) w->left()->color()=black;
+ if(w->left()!=pointer(0)) w->left()->color()=black;
               w->color()=red;
               rotate_right(w,root);
               w=x_parent->right();
             }
             w->color()=x_parent->color();
             x_parent->color()=black;
- if(w->right())w->right()->color()=black;
+ if(w->right()!=pointer(0))w->right()->color()=black;
             rotate_left(x_parent,root);
             break;
           }
         }
         else{ /* same as above,with right <-> left */
- ordered_index_node_impl* w=x_parent->left();
+ pointer w=x_parent->left();
           if(w->color()==red){
             w->color()=black;
             x_parent->color()=red;
             rotate_right(x_parent,root);
             w=x_parent->left();
           }
- if((w->right()==0||w->right()->color()==black) &&
- (w->left()==0||w->left()->color()==black)){
+ if((w->right()==pointer(0)||w->right()->color()==black) &&
+ (w->left()==pointer(0)||w->left()->color()==black)){
             w->color()=red;
             x=x_parent;
             x_parent=x_parent->parent();
           }
           else{
- if(w->left()==0||w->left()->color()==black){
- if(w->right())w->right()->color()=black;
+ if(w->left()==pointer(0)||w->left()->color()==black){
+ if(w->right()!=pointer(0))w->right()->color()=black;
               w->color()=red;
               rotate_left(w,root);
               w=x_parent->left();
             }
             w->color()=x_parent->color();
             x_parent->color()=black;
- if(w->left())w->left()->color()=black;
+ if(w->left()!=pointer(0))w->left()->color()=black;
             rotate_right(x_parent,root);
             break;
           }
         }
       }
- if(x)x->color()=black;
+ if(x!=pointer(0))x->color()=black;
     }
     return y;
   }
 
- static void restore(
- ordered_index_node_impl* x,ordered_index_node_impl* position,
- ordered_index_node_impl* header)
+ static void restore(pointer x,pointer position,pointer header)
   {
- if(position->left()==0||position->left()==header){
+ if(position->left()==pointer(0)||position->left()==header){
       link(x,to_left,position,header);
     }
     else{
@@ -503,10 +541,9 @@
 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
   /* invariant stuff */
 
- static std::size_t black_count(
- ordered_index_node_impl* node,ordered_index_node_impl* root)
+ static std::size_t black_count(pointer node,pointer root)
   {
- if(!node)return 0;
+ if(node==pointer(0))return 0;
     std::size_t sum=0;
     for(;;){
       if(node->color()==black)++sum;
@@ -519,54 +556,87 @@
 };
 
 template<typename Super>
-struct ordered_index_node_trampoline:ordered_index_node_impl{};
+struct ordered_index_node_trampoline:
+ prevent_eti<
+ Super,
+ ordered_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ typename Super::allocator_type,
+ void
+ >::type
+ >
+ >::type
+{
+ typedef typename prevent_eti<
+ Super,
+ ordered_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ typename Super::allocator_type,
+ void
+ >::type
+ >
+ >::type impl_type;
+};
 
 template<typename Super>
 struct ordered_index_node:Super,ordered_index_node_trampoline<Super>
 {
 private:
- typedef ordered_index_node_trampoline<Super> impl_type;
- typedef typename impl_type::color_ref color_ref;
- typedef typename impl_type::parent_ref parent_ref;
+ typedef ordered_index_node_trampoline<Super> trampoline;
 
 public:
- color_ref color(){return impl_type::color();}
- ordered_index_color color()const{return impl_type::color();}
- parent_ref parent(){return impl_type::parent();}
- ordered_index_node_impl* parent()const{return impl_type::parent();}
- ordered_index_node_impl*& left(){return impl_type::left();}
- ordered_index_node_impl* left()const{return impl_type::left();}
- ordered_index_node_impl*& right(){return impl_type::right();}
- ordered_index_node_impl* right()const{return impl_type::right();}
-
- ordered_index_node_impl* impl(){return static_cast<impl_type*>(this);}
- const ordered_index_node_impl* impl()const
- {return static_cast<const impl_type*>(this);}
+ typedef typename trampoline::impl_type impl_type;
+ typedef typename trampoline::color_ref impl_color_ref;
+ typedef typename trampoline::parent_ref impl_parent_ref;
+ typedef typename trampoline::pointer impl_pointer;
+ typedef typename trampoline::const_pointer const_impl_pointer;
+
+ impl_color_ref color(){return trampoline::color();}
+ ordered_index_color color()const{return trampoline::color();}
+ impl_parent_ref parent(){return trampoline::parent();}
+ impl_pointer parent()const{return trampoline::parent();}
+ impl_pointer& left(){return trampoline::left();}
+ impl_pointer left()const{return trampoline::left();}
+ impl_pointer& right(){return trampoline::right();}
+ impl_pointer right()const{return trampoline::right();}
 
- static ordered_index_node* from_impl(ordered_index_node_impl *x)
+ impl_pointer impl()
   {
- return static_cast<ordered_index_node*>(static_cast<impl_type*>(x));
+ return static_cast<impl_pointer>(
+ static_cast<impl_type*>(static_cast<trampoline*>(this)));
   }
-
- static const ordered_index_node* from_impl(const ordered_index_node_impl* x)
+
+ const_impl_pointer impl()const
+ {
+ return static_cast<const_impl_pointer>(
+ static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
+ }
+
+ static ordered_index_node* from_impl(impl_pointer x)
+ {
+ return static_cast<ordered_index_node*>(
+ static_cast<trampoline*>(&*x));
+ }
+
+ static const ordered_index_node* from_impl(const_impl_pointer x)
   {
     return static_cast<const ordered_index_node*>(
- static_cast<const impl_type*>(x));
+ static_cast<const trampoline*>(&*x));
   }
 
   /* interoperability with bidir_node_iterator */
 
   static void increment(ordered_index_node*& x)
   {
- ordered_index_node_impl* xi=x->impl();
- impl_type::increment(xi);
+ impl_pointer xi=x->impl();
+ trampoline::increment(xi);
     x=from_impl(xi);
   }
 
   static void decrement(ordered_index_node*& x)
   {
- ordered_index_node_impl* xi=x->impl();
- impl_type::decrement(xi);
+ impl_pointer xi=x->impl();
+ trampoline::decrement(xi);
     x=from_impl(xi);
   }
 };

Modified: trunk/boost/multi_index/detail/ord_index_ops.hpp
==============================================================================
--- trunk/boost/multi_index/detail/ord_index_ops.hpp (original)
+++ trunk/boost/multi_index/detail/ord_index_ops.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -40,6 +40,9 @@
 #pragma once
 #endif
 
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <utility>
+
 namespace boost{
 
 namespace multi_index{
@@ -55,21 +58,20 @@
   typename CompatibleKey,typename CompatibleCompare
>
 inline Node* ordered_index_find(
- Node* header,const KeyFromValue& key,const CompatibleKey& x,
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
   const CompatibleCompare& comp)
 {
- Node* y=header;
- Node* z=Node::from_impl(header->parent());
-
- while (z){
- if(!comp(key(z->value()),x)){
- y=z;
- z=Node::from_impl(z->left());
+ Node* y0=y;
+
+ while (top){
+ if(!comp(key(top->value()),x)){
+ y=top;
+ top=Node::from_impl(top->left());
     }
- else z=Node::from_impl(z->right());
+ else top=Node::from_impl(top->right());
   }
     
- return (y==header||comp(x,key(y->value())))?header:y;
+ return (y==y0||comp(x,key(y->value())))?y0:y;
 }
 
 template<
@@ -77,18 +79,15 @@
   typename CompatibleKey,typename CompatibleCompare
>
 inline Node* ordered_index_lower_bound(
- Node* header,const KeyFromValue& key,const CompatibleKey& x,
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
   const CompatibleCompare& comp)
 {
- Node* y=header;
- Node* z=Node::from_impl(header->parent());
-
- while(z){
- if(!comp(key(z->value()),x)){
- y=z;
- z=Node::from_impl(z->left());
+ while(top){
+ if(!comp(key(top->value()),x)){
+ y=top;
+ top=Node::from_impl(top->left());
     }
- else z=Node::from_impl(z->right());
+ else top=Node::from_impl(top->right());
   }
 
   return y;
@@ -99,23 +98,46 @@
   typename CompatibleKey,typename CompatibleCompare
>
 inline Node* ordered_index_upper_bound(
- Node* header,const KeyFromValue& key,const CompatibleKey& x,
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
   const CompatibleCompare& comp)
 {
- Node* y=header;
- Node* z=Node::from_impl(header->parent());
-
- while(z){
- if(comp(x,key(z->value()))){
- y=z;
- z=Node::from_impl(z->left());
+ while(top){
+ if(comp(x,key(top->value()))){
+ y=top;
+ top=Node::from_impl(top->left());
     }
- else z=Node::from_impl(z->right());
+ else top=Node::from_impl(top->right());
   }
 
   return y;
 }
 
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleKey,typename CompatibleCompare
+>
+inline std::pair<Node*,Node*> ordered_index_equal_range(
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+ const CompatibleCompare& comp)
+{
+ while(top){
+ if(comp(key(top->value()),x)){
+ top=Node::from_impl(top->right());
+ }
+ else if(comp(x,key(top->value()))){
+ y=top;
+ top=Node::from_impl(top->left());
+ }
+ else{
+ return std::pair<Node*,Node*>(
+ ordered_index_lower_bound(Node::from_impl(top->left()),top,key,x,comp),
+ ordered_index_upper_bound(Node::from_impl(top->right()),y,key,x,comp));
+ }
+ }
+
+ return std::pair<Node*,Node*>(y,y);
+}
+
 } /* namespace multi_index::detail */
 
 } /* namespace multi_index */

Modified: trunk/boost/multi_index/detail/rnd_index_loader.hpp
==============================================================================
--- trunk/boost/multi_index/detail/rnd_index_loader.hpp (original)
+++ trunk/boost/multi_index/detail/rnd_index_loader.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -15,7 +15,9 @@
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 #include <algorithm>
+#include <boost/detail/allocator_utilities.hpp>
 #include <boost/multi_index/detail/auto_space.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
 #include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
 #include <boost/noncopyable.hpp>
 #include <cstddef>
@@ -43,10 +45,19 @@
 class random_access_index_loader_base:private noncopyable
 {
 protected:
- typedef random_access_index_node_impl node_type;
- typedef random_access_index_ptr_array<Allocator> ptr_array_type;
+ typedef typename prevent_eti<
+ Allocator,
+ random_access_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ Allocator,
+ void
+ >::type
+ >
+ >::type node_impl_type;
+ typedef typename node_impl_type::pointer node_impl_pointer;
+ typedef random_access_index_ptr_array<Allocator> ptr_array;
 
- random_access_index_loader_base(const Allocator& al_,ptr_array_type& ptrs_):
+ random_access_index_loader_base(const Allocator& al_,ptr_array& ptrs_):
     al(al_),
     ptrs(ptrs_),
     header(*ptrs.end()),
@@ -58,14 +69,14 @@
   {
     if(preprocessed)
     {
- node_type* n=header;
+ node_impl_pointer n=header;
       next(n)=n;
 
       for(std::size_t i=ptrs.size();i--;){
         n=prev(n);
         std::size_t d=position(n);
         if(d!=i){
- node_type* m=prev(next_at(i));
+ node_impl_pointer m=prev(next_at(i));
           std::swap(m->up(),n->up());
           next_at(d)=next_at(i);
           std::swap(prev_at(d),prev_at(i));
@@ -75,10 +86,10 @@
     }
   }
 
- void rearrange(node_type* position,node_type *x)
+ void rearrange(node_impl_pointer position,node_impl_pointer x)
   {
     preprocess(); /* only incur this penalty if rearrange() is ever called */
- if(!position)position=header;
+ if(position==node_impl_pointer(0))position=header;
     next(prev(x))=next(x);
     prev(next(x))=prev(x);
     prev(x)=position;
@@ -91,49 +102,50 @@
   {
     if(!preprocessed){
       /* get space for the auxiliary prev array */
- auto_space<node_type*,Allocator> tmp(al,ptrs.size()+1);
+ auto_space<node_impl_pointer,Allocator> tmp(al,ptrs.size()+1);
       prev_spc.swap(tmp);
 
       /* prev_spc elements point to the prev nodes */
- std::rotate_copy(ptrs.begin(),ptrs.end(),ptrs.end()+1,prev_spc.data());
+ std::rotate_copy(
+ &*ptrs.begin(),&*ptrs.end(),&*ptrs.end()+1,&*prev_spc.data());
 
       /* ptrs elements point to the next nodes */
- std::rotate(ptrs.begin(),ptrs.begin()+1,ptrs.end()+1);
+ std::rotate(&*ptrs.begin(),&*ptrs.begin()+1,&*ptrs.end()+1);
 
       preprocessed=true;
     }
   }
 
- std::size_t position(node_type* x)const
+ std::size_t position(node_impl_pointer x)const
   {
     return (std::size_t)(x->up()-ptrs.begin());
   }
 
- node_type*& next_at(std::size_t n)const
+ node_impl_pointer& next_at(std::size_t n)const
   {
     return *ptrs.at(n);
   }
 
- node_type*& prev_at(std::size_t n)const
+ node_impl_pointer& prev_at(std::size_t n)const
   {
- return prev_spc.data()[n];
+ return *(prev_spc.data()+n);
   }
 
- node_type*& next(node_type* x)const
+ node_impl_pointer& next(node_impl_pointer x)const
   {
     return *(x->up());
   }
 
- node_type*& prev(node_type* x)const
+ node_impl_pointer& prev(node_impl_pointer x)const
   {
     return prev_at(position(x));
   }
 
- Allocator al;
- ptr_array_type& ptrs;
- node_type* header;
- auto_space<node_type*,Allocator> prev_spc;
- bool preprocessed;
+ Allocator al;
+ ptr_array& ptrs;
+ node_impl_pointer header;
+ auto_space<node_impl_pointer,Allocator> prev_spc;
+ bool preprocessed;
 };
 
 template<typename Node,typename Allocator>
@@ -141,16 +153,17 @@
   private random_access_index_loader_base<Allocator>
 {
   typedef random_access_index_loader_base<Allocator> super;
- typedef typename super::ptr_array_type ptr_array_type;
+ typedef typename super::node_impl_pointer node_impl_pointer;
+ typedef typename super::ptr_array ptr_array;
 
 public:
- random_access_index_loader(const Allocator& al_,ptr_array_type& ptrs_):
+ random_access_index_loader(const Allocator& al_,ptr_array& ptrs_):
     super(al_,ptrs_)
   {}
 
   void rearrange(Node* position,Node *x)
   {
- super::rearrange(position?position->impl():0,x->impl());
+ super::rearrange(position?position->impl():node_impl_pointer(0),x->impl());
   }
 };
 

Modified: trunk/boost/multi_index/detail/rnd_index_node.hpp
==============================================================================
--- trunk/boost/multi_index/detail/rnd_index_node.hpp (original)
+++ trunk/boost/multi_index/detail/rnd_index_node.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -15,7 +15,9 @@
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 #include <algorithm>
+#include <boost/detail/allocator_utilities.hpp>
 #include <boost/math/common_factor_rt.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
 #include <cstddef>
 #include <functional>
 
@@ -25,42 +27,58 @@
 
 namespace detail{
 
+template<typename Allocator>
 struct random_access_index_node_impl
 {
- random_access_index_node_impl**& up(){return up_;}
- random_access_index_node_impl** up()const{return up_;}
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,random_access_index_node_impl
+ >::type
+ >::type::pointer pointer;
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,random_access_index_node_impl
+ >::type
+ >::type::const_pointer const_pointer;
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,pointer
+ >::type
+ >::type::pointer ptr_pointer;
+
+ ptr_pointer& up(){return up_;}
+ ptr_pointer up()const{return up_;}
 
   /* interoperability with rnd_node_iterator */
 
- static void increment(random_access_index_node_impl*& x)
+ static void increment(pointer& x)
   {
     x=*(x->up()+1);
   }
 
- static void decrement(random_access_index_node_impl*& x)
+ static void decrement(pointer& x)
   {
     x=*(x->up()-1);
   }
 
- static void advance(
- random_access_index_node_impl*& x,std::ptrdiff_t n)
+ static void advance(pointer& x,std::ptrdiff_t n)
   {
     x=*(x->up()+n);
   }
 
- static std::ptrdiff_t distance(
- random_access_index_node_impl* x,random_access_index_node_impl* y)
+ static std::ptrdiff_t distance(pointer x,pointer y)
   {
     return y->up()-x->up();
   }
 
   /* algorithmic stuff */
 
- static void relocate(
- random_access_index_node_impl** pos,
- random_access_index_node_impl** x)
+ static void relocate(ptr_pointer pos,ptr_pointer x)
   {
- random_access_index_node_impl* n=*x;
+ pointer n=*x;
     if(x<pos){
       extract(x,pos);
       *(pos-1)=n;
@@ -77,12 +95,9 @@
     }
   };
 
- static void relocate(
- random_access_index_node_impl** pos,
- random_access_index_node_impl** first,
- random_access_index_node_impl** last)
+ static void relocate(ptr_pointer pos,ptr_pointer first,ptr_pointer last)
   {
- random_access_index_node_impl** begin,**middle,**end;
+ ptr_pointer begin,middle,end;
     if(pos<first){
       begin=pos;
       middle=first;
@@ -100,38 +115,36 @@
     std::ptrdiff_t p=math::gcd(n,m);
 
     for(std::ptrdiff_t i=0;i<p;++i){
- random_access_index_node_impl* tmp=begin[i];
+ pointer tmp=begin[i];
       for(std::ptrdiff_t j=i,k;;){
         if(j<n_m)k=j+m;
         else k=j-n_m;
         if(k==i){
- begin[j]=tmp;
- begin[j]->up()=&begin[j];
+ *(begin+j)=tmp;
+ (*(begin+j))->up()=begin+j;
           break;
         }
         else{
- begin[j]=begin[k];
- begin[j]->up()=&begin[j];
+ *(begin+j)=*(begin+k);
+ (*(begin+j))->up()=begin+j;
         }
 
         if(k<n_m)j=k+m;
         else j=k-n_m;
         if(j==i){
- begin[k]=tmp;
- begin[k]->up()=&begin[k];
+ *(begin+k)=tmp;
+ (*(begin+k))->up()=begin+k;
           break;
         }
         else{
- begin[k]=begin[j];
- begin[k]->up()=&begin[k];
+ *(begin+k)=*(begin+j);
+ (*(begin+k))->up()=begin+k;
         }
       }
     }
   };
 
- static void extract(
- random_access_index_node_impl** x,
- random_access_index_node_impl** pend)
+ static void extract(ptr_pointer x,ptr_pointer pend)
   {
     --pend;
     while(x!=pend){
@@ -142,9 +155,7 @@
   }
 
   static void transfer(
- random_access_index_node_impl** pbegin0,
- random_access_index_node_impl** pend0,
- random_access_index_node_impl** pbegin1)
+ ptr_pointer pbegin0,ptr_pointer pend0,ptr_pointer pbegin1)
   {
     while(pbegin0!=pend0){
       *pbegin1=*pbegin0++;
@@ -153,9 +164,7 @@
     }
   }
 
- static void reverse(
- random_access_index_node_impl** pbegin,
- random_access_index_node_impl** pend)
+ static void reverse(ptr_pointer pbegin,ptr_pointer pend)
   {
     std::ptrdiff_t d=(pend-pbegin)/2;
     for(std::ptrdiff_t i=0;i<d;++i){
@@ -167,68 +176,100 @@
   }
 
 private:
- random_access_index_node_impl** up_;
+ ptr_pointer up_;
 };
 
 template<typename Super>
-struct random_access_index_node_trampoline:random_access_index_node_impl{};
+struct random_access_index_node_trampoline:
+ prevent_eti<
+ Super,
+ random_access_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ typename Super::allocator_type,
+ void
+ >::type
+ >
+ >::type
+{
+ typedef typename prevent_eti<
+ Super,
+ random_access_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ typename Super::allocator_type,
+ void
+ >::type
+ >
+ >::type impl_type;
+};
 
 template<typename Super>
 struct random_access_index_node:
   Super,random_access_index_node_trampoline<Super>
 {
- random_access_index_node_impl**& up(){return impl_type::up();}
- random_access_index_node_impl** up()const{return impl_type::up();}
+private:
+ typedef random_access_index_node_trampoline<Super> trampoline;
+
+public:
+ typedef typename trampoline::impl_type impl_type;
+ typedef typename trampoline::pointer impl_pointer;
+ typedef typename trampoline::const_pointer const_impl_pointer;
+ typedef typename trampoline::ptr_pointer impl_ptr_pointer;
+
+ impl_ptr_pointer& up(){return trampoline::up();}
+ impl_ptr_pointer up()const{return trampoline::up();}
 
- random_access_index_node_impl* impl()
- {return static_cast<impl_type*>(this);}
- const random_access_index_node_impl* impl()const
- {return static_cast<const impl_type*>(this);}
+ impl_pointer impl()
+ {
+ return static_cast<impl_pointer>(
+ static_cast<impl_type*>(static_cast<trampoline*>(this)));
+ }
 
- static random_access_index_node* from_impl(random_access_index_node_impl *x)
+ const_impl_pointer impl()const
+ {
+ return static_cast<const_impl_pointer>(
+ static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
+ }
+
+ static random_access_index_node* from_impl(impl_pointer x)
   {
     return static_cast<random_access_index_node*>(
- static_cast<impl_type*>(x));
+ static_cast<trampoline*>(&*x));
   }
 
- static const random_access_index_node* from_impl(
- const random_access_index_node_impl* x)
+ static const random_access_index_node* from_impl(const_impl_pointer x)
   {
     return static_cast<const random_access_index_node*>(
- static_cast<const impl_type*>(x));
+ static_cast<const trampoline*>(&*x));
   }
 
   /* interoperability with rnd_node_iterator */
 
   static void increment(random_access_index_node*& x)
   {
- random_access_index_node_impl* xi=x->impl();
- impl_type::increment(xi);
+ impl_pointer xi=x->impl();
+ trampoline::increment(xi);
     x=from_impl(xi);
   }
 
   static void decrement(random_access_index_node*& x)
   {
- random_access_index_node_impl* xi=x->impl();
- impl_type::decrement(xi);
+ impl_pointer xi=x->impl();
+ trampoline::decrement(xi);
     x=from_impl(xi);
   }
 
   static void advance(random_access_index_node*& x,std::ptrdiff_t n)
   {
- random_access_index_node_impl* xi=x->impl();
- impl_type::advance(xi,n);
+ impl_pointer xi=x->impl();
+ trampoline::advance(xi,n);
     x=from_impl(xi);
   }
 
   static std::ptrdiff_t distance(
     random_access_index_node* x,random_access_index_node* y)
   {
- return impl_type::distance(x->impl(),y->impl());
+ return trampoline::distance(x->impl(),y->impl());
   }
-
-private:
- typedef random_access_index_node_trampoline<Super> impl_type;
 };
 
 } /* namespace multi_index::detail */

Modified: trunk/boost/multi_index/detail/rnd_index_ops.hpp
==============================================================================
--- trunk/boost/multi_index/detail/rnd_index_ops.hpp (original)
+++ trunk/boost/multi_index/detail/rnd_index_ops.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -34,10 +34,11 @@
   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
 {
   typedef typename Node::value_type value_type;
+ typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
 
- random_access_index_node_impl** first=ptrs.begin(),
- ** res=first,
- ** last=ptrs.end();
+ impl_ptr_pointer first=ptrs.begin(),
+ res=first,
+ last=ptrs.end();
   for(;first!=last;++first){
     if(!pred(
         const_cast<const value_type&>(Node::from_impl(*first)->value()))){
@@ -57,11 +58,12 @@
   random_access_index_ptr_array<Allocator>& ptrs,BinaryPredicate binary_pred
   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
 {
- typedef typename Node::value_type value_type;
+ typedef typename Node::value_type value_type;
+ typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
 
- random_access_index_node_impl** first=ptrs.begin(),
- ** res=first,
- ** last=ptrs.end();
+ impl_ptr_pointer first=ptrs.begin(),
+ res=first,
+ last=ptrs.end();
   if(first!=last){
     for(;++first!=last;){
       if(!binary_pred(
@@ -84,17 +86,19 @@
 void random_access_index_inplace_merge(
   const Allocator& al,
   random_access_index_ptr_array<Allocator>& ptrs,
- random_access_index_node_impl** first1,Compare comp
+ BOOST_DEDUCED_TYPENAME Node::impl_ptr_pointer first1,Compare comp
   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
 {
- typedef typename Node::value_type value_type;
-
- auto_space<random_access_index_node_impl*,Allocator> spc(al,ptrs.size());
-
- random_access_index_node_impl** first0=ptrs.begin(),
- ** last0=first1,
- ** last1=ptrs.end(),
- ** out=spc.data();
+ typedef typename Node::value_type value_type;
+ typedef typename Node::impl_pointer impl_pointer;
+ typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
+
+ auto_space<impl_pointer,Allocator> spc(al,ptrs.size());
+
+ impl_ptr_pointer first0=ptrs.begin(),
+ last0=first1,
+ last1=ptrs.end(),
+ out=spc.data();
   while(first0!=last0&&first1!=last1){
     if(comp(
         const_cast<const value_type&>(Node::from_impl(*first1)->value()),
@@ -105,8 +109,8 @@
       *out++=*first0++;
     }
   }
- std::copy(first0,last0,out);
- std::copy(first1,last1,out);
+ std::copy(&*first0,&*last0,&*out);
+ std::copy(&*first1,&*last1,&*out);
 
   first1=ptrs.begin();
   out=spc.data();
@@ -124,13 +128,13 @@
 template<typename Node,typename Compare>
 struct random_access_index_sort_compare:
   std::binary_function<
- const typename Node::value_type*,const typename Node::value_type*,bool>
+ typename Node::impl_pointer,
+ typename Node::impl_pointer,bool>
 {
   random_access_index_sort_compare(Compare comp_=Compare()):comp(comp_){}
 
   bool operator()(
- random_access_index_node_impl* x,
- random_access_index_node_impl* y)const
+ typename Node::impl_pointer x,typename Node::impl_pointer y)const
   {
     typedef typename Node::value_type value_type;
 
@@ -171,18 +175,20 @@
    */
 
   typedef typename Node::value_type value_type;
+ typedef typename Node::impl_pointer impl_pointer;
+ typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
   typedef random_access_index_sort_compare<
     Node,Compare> ptr_compare;
   
- random_access_index_node_impl** first=ptrs.begin();
- random_access_index_node_impl** last=ptrs.end();
+ impl_ptr_pointer first=ptrs.begin();
+ impl_ptr_pointer last=ptrs.end();
   auto_space<
- random_access_index_node_impl*,
- Allocator> spc(al,ptrs.size());
- random_access_index_node_impl** buf=spc.data();
+ impl_pointer,
+ Allocator> spc(al,ptrs.size());
+ impl_ptr_pointer buf=spc.data();
 
- std::copy(first,last,buf);
- std::stable_sort(buf,buf+ptrs.size(),ptr_compare(comp));
+ std::copy(&*first,&*last,&*buf);
+ std::stable_sort(&*buf,&*buf+ptrs.size(),ptr_compare(comp));
 
   while(first!=last){
     *first=*buf++;

Modified: trunk/boost/multi_index/detail/rnd_index_ptr_array.hpp
==============================================================================
--- trunk/boost/multi_index/detail/rnd_index_ptr_array.hpp (original)
+++ trunk/boost/multi_index/detail/rnd_index_ptr_array.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -15,7 +15,9 @@
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 #include <algorithm>
+#include <boost/detail/allocator_utilities.hpp>
 #include <boost/multi_index/detail/auto_space.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
 #include <boost/multi_index/detail/rnd_index_node.hpp>
 #include <boost/noncopyable.hpp>
 #include <cstddef>
@@ -31,8 +33,24 @@
 template<typename Allocator>
 class random_access_index_ptr_array:private noncopyable
 {
+ typedef typename prevent_eti<
+ Allocator,
+ random_access_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ Allocator,
+ void
+ >::type
+ >
+ >::type node_impl_type;
+
 public:
- typedef random_access_index_node_impl* value_type;
+ typedef typename node_impl_type::pointer value_type;
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,value_type
+ >::type
+ >::type::pointer pointer;
 
   random_access_index_ptr_array(
     const Allocator& al,value_type end_,std::size_t size):
@@ -58,15 +76,15 @@
   {
     if(c>capacity_){
       auto_space<value_type,Allocator> spc1(spc.get_allocator(),c+1);
- random_access_index_node_impl::transfer(begin(),end()+1,spc1.data());
+ node_impl_type::transfer(begin(),end()+1,spc1.data());
       spc.swap(spc1);
       capacity_=c;
     }
   }
 
- value_type* begin()const{return &ptrs()[0];}
- value_type* end()const{return &ptrs()[size_];}
- value_type* at(std::size_t n)const{return &ptrs()[n];}
+ pointer begin()const{return ptrs();}
+ pointer end()const{return ptrs()+size_;}
+ pointer at(std::size_t n)const{return ptrs()+n;}
 
   void push_back(value_type x)
   {
@@ -79,7 +97,7 @@
 
   void erase(value_type x)
   {
- random_access_index_node_impl::extract(x->up(),end()+1);
+ node_impl_type::extract(x->up(),end()+1);
     --size_;
   }
 
@@ -102,7 +120,7 @@
   std::size_t capacity_;
   auto_space<value_type,Allocator> spc;
 
- value_type* ptrs()const
+ pointer ptrs()const
   {
     return spc.data();
   }

Modified: trunk/boost/multi_index/detail/rnd_node_iterator.hpp
==============================================================================
--- trunk/boost/multi_index/detail/rnd_node_iterator.hpp (original)
+++ trunk/boost/multi_index/detail/rnd_node_iterator.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -47,18 +47,6 @@
     return node->value();
   }
 
- friend bool operator==(
- const rnd_node_iterator& x,const rnd_node_iterator& y)
- {
- return x.node==y.node;
- }
-
- friend bool operator<(
- const rnd_node_iterator& x,const rnd_node_iterator& y)
- {
- return Node::distance(x.node,y.node)>0;
- }
-
   rnd_node_iterator& operator++()
   {
     Node::increment(node);
@@ -83,12 +71,6 @@
     return *this;
   }
 
- friend std::ptrdiff_t operator-(
- const rnd_node_iterator& x,const rnd_node_iterator& y)
- {
- return Node::distance(y.node,x.node);
- }
-
 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   /* Serialization. As for why the following is public,
    * see explanation in safe_mode_iterator notes in safe_mode.hpp.
@@ -124,6 +106,30 @@
   Node* node;
 };
 
+template<typename Node,typename Derived>
+bool operator==(
+ const rnd_node_iterator<Node,Derived>& x,
+ const rnd_node_iterator<Node,Derived>& y)
+{
+ return x.get_node()==y.get_node();
+}
+
+template<typename Node,typename Derived>
+bool operator<(
+ const rnd_node_iterator<Node,Derived>& x,
+ const rnd_node_iterator<Node,Derived>& y)
+{
+ return Node::distance(x.get_node(),y.get_node())>0;
+}
+
+template<typename Node,typename Derived>
+std::ptrdiff_t operator-(
+ const rnd_node_iterator<Node,Derived>& x,
+ const rnd_node_iterator<Node,Derived>& y)
+{
+ return Node::distance(y.get_node(),x.get_node());
+}
+
 } /* namespace multi_index::detail */
 
 } /* namespace multi_index */

Modified: trunk/boost/multi_index/detail/seq_index_node.hpp
==============================================================================
--- trunk/boost/multi_index/detail/seq_index_node.hpp (original)
+++ trunk/boost/multi_index/detail/seq_index_node.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -13,7 +13,10 @@
 #pragma once
 #endif
 
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 #include <algorithm>
+#include <boost/detail/allocator_utilities.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
 
 namespace boost{
 
@@ -23,36 +26,48 @@
 
 /* doubly-linked node for use by sequenced_index */
 
+template<typename Allocator>
 struct sequenced_index_node_impl
 {
- sequenced_index_node_impl*& prior(){return prior_;}
- sequenced_index_node_impl* prior()const{return prior_;}
- sequenced_index_node_impl*& next(){return next_;}
- sequenced_index_node_impl* next()const{return next_;}
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,sequenced_index_node_impl
+ >::type
+ >::type::pointer pointer;
+ typedef typename prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,sequenced_index_node_impl
+ >::type
+ >::type::const_pointer const_pointer;
+
+ pointer& prior(){return prior_;}
+ pointer prior()const{return prior_;}
+ pointer& next(){return next_;}
+ pointer next()const{return next_;}
 
   /* interoperability with bidir_node_iterator */
 
- static void increment(sequenced_index_node_impl*& x){x=x->next();}
- static void decrement(sequenced_index_node_impl*& x){x=x->prior();}
+ static void increment(pointer& x){x=x->next();}
+ static void decrement(pointer& x){x=x->prior();}
 
   /* algorithmic stuff */
 
- static void link(
- sequenced_index_node_impl* x,sequenced_index_node_impl* header)
+ static void link(pointer x,pointer header)
   {
     x->prior()=header->prior();
     x->next()=header;
     x->prior()->next()=x->next()->prior()=x;
   };
 
- static void unlink(sequenced_index_node_impl* x)
+ static void unlink(pointer x)
   {
     x->prior()->next()=x->next();
     x->next()->prior()=x->prior();
   }
 
- static void relink(
- sequenced_index_node_impl* position,sequenced_index_node_impl* x)
+ static void relink(pointer position,pointer x)
   {
     unlink(x);
     x->prior()=position->prior();
@@ -60,14 +75,12 @@
     x->prior()->next()=x->next()->prior()=x;
   }
 
- static void relink(
- sequenced_index_node_impl* position,
- sequenced_index_node_impl* x,sequenced_index_node_impl* y)
+ static void relink(pointer position,pointer x,pointer y)
   {
     /* position is assumed not to be in [x,y) */
 
     if(x!=y){
- sequenced_index_node_impl* z=y->prior();
+ pointer z=y->prior();
       x->prior()->next()=y;
       y->prior()=x->prior();
       x->prior()=position->prior();
@@ -77,17 +90,17 @@
     }
   }
 
- static void reverse(sequenced_index_node_impl* header)
+ static void reverse(pointer header)
   {
- sequenced_index_node_impl* x=header;
+ pointer x=header;
     do{
- sequenced_index_node_impl* y=x->next();
+ pointer y=x->next();
       std::swap(x->prior(),x->next());
       x=y;
     }while(x!=header);
   }
 
- static void swap(sequenced_index_node_impl* x,sequenced_index_node_impl* y)
+ static void swap(pointer x,pointer y)
   {
     /* This swap function does not exchange the header nodes,
      * but rather their pointers. This is *not* used for implementing
@@ -117,53 +130,88 @@
   }
 
 private:
- sequenced_index_node_impl* prior_;
- sequenced_index_node_impl* next_;
+ pointer prior_;
+ pointer next_;
 };
 
 template<typename Super>
-struct sequenced_index_node_trampoline:sequenced_index_node_impl{};
+struct sequenced_index_node_trampoline:
+ prevent_eti<
+ Super,
+ sequenced_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ typename Super::allocator_type,
+ void
+ >::type
+ >
+ >::type
+{
+ typedef typename prevent_eti<
+ Super,
+ sequenced_index_node_impl<
+ typename boost::detail::allocator::rebind_to<
+ typename Super::allocator_type,
+ void
+ >::type
+ >
+ >::type impl_type;
+};
 
 template<typename Super>
 struct sequenced_index_node:Super,sequenced_index_node_trampoline<Super>
 {
- sequenced_index_node_impl*& prior(){return impl_type::prior();}
- sequenced_index_node_impl* prior()const{return impl_type::prior();}
- sequenced_index_node_impl*& next(){return impl_type::next();}
- sequenced_index_node_impl* next()const{return impl_type::next();}
-
- sequenced_index_node_impl* impl()
- {return static_cast<impl_type*>(this);}
- const sequenced_index_node_impl* impl()const
- {return static_cast<const impl_type*>(this);}
-
- static sequenced_index_node* from_impl(sequenced_index_node_impl *x)
- {return static_cast<sequenced_index_node*>(static_cast<impl_type*>(x));}
- static const sequenced_index_node* from_impl(
- const sequenced_index_node_impl* x)
+private:
+ typedef sequenced_index_node_trampoline<Super> trampoline;
+
+public:
+ typedef typename trampoline::impl_type impl_type;
+ typedef typename trampoline::pointer impl_pointer;
+ typedef typename trampoline::const_pointer const_impl_pointer;
+
+ impl_pointer& prior(){return trampoline::prior();}
+ impl_pointer prior()const{return trampoline::prior();}
+ impl_pointer& next(){return trampoline::next();}
+ impl_pointer next()const{return trampoline::next();}
+
+ impl_pointer impl()
+ {
+ return static_cast<impl_pointer>(
+ static_cast<impl_type*>(static_cast<trampoline*>(this)));
+ }
+
+ const_impl_pointer impl()const
+ {
+ return static_cast<const_impl_pointer>(
+ static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
+ }
+
+ static sequenced_index_node* from_impl(impl_pointer x)
+ {
+ return static_cast<sequenced_index_node*>(
+ static_cast<trampoline*>(&*x));
+ }
+
+ static const sequenced_index_node* from_impl(const_impl_pointer x)
   {
     return static_cast<const sequenced_index_node*>(
- static_cast<const impl_type*>(x));
+ static_cast<const trampoline*>(&*x));
   }
 
   /* interoperability with bidir_node_iterator */
 
   static void increment(sequenced_index_node*& x)
   {
- sequenced_index_node_impl* xi=x->impl();
- impl_type::increment(xi);
+ impl_pointer xi=x->impl();
+ trampoline::increment(xi);
     x=from_impl(xi);
   }
 
   static void decrement(sequenced_index_node*& x)
   {
- sequenced_index_node_impl* xi=x->impl();
- impl_type::decrement(xi);
+ impl_pointer xi=x->impl();
+ trampoline::decrement(xi);
     x=from_impl(xi);
   }
-
-private:
- typedef sequenced_index_node_trampoline<Super> impl_type;
 };
 
 } /* namespace multi_index::detail */

Modified: trunk/boost/multi_index/detail/seq_index_ops.hpp
==============================================================================
--- trunk/boost/multi_index/detail/seq_index_ops.hpp (original)
+++ trunk/boost/multi_index/detail/seq_index_ops.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -77,23 +77,28 @@
 
 template<typename Node,typename Compare>
 void sequenced_index_collate(
- sequenced_index_node_impl* x,sequenced_index_node_impl* y,Compare comp
+ BOOST_DEDUCED_TYPENAME Node::impl_type* x,
+ BOOST_DEDUCED_TYPENAME Node::impl_type* y,
+ Compare comp
   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
 {
- sequenced_index_node_impl* first0=x->next();
- sequenced_index_node_impl* last0=x;
- sequenced_index_node_impl* first1=y->next();
- sequenced_index_node_impl* last1=y;
+ typedef typename Node::impl_type impl_type;
+ typedef typename Node::impl_pointer impl_pointer;
+
+ impl_pointer first0=x->next();
+ impl_pointer last0=x;
+ impl_pointer first1=y->next();
+ impl_pointer last1=y;
   while(first0!=last0&&first1!=last1){
     if(comp(
         Node::from_impl(first1)->value(),Node::from_impl(first0)->value())){
- sequenced_index_node_impl* tmp=first1->next();
- sequenced_index_node_impl::relink(first0,first1);
+ impl_pointer tmp=first1->next();
+ impl_type::relink(first0,first1);
       first1=tmp;
     }
     else first0=first0->next();
   }
- sequenced_index_node_impl::relink(last0,first1,last1);
+ impl_type::relink(last0,first1,last1);
 }
 
 /* Some versions of CGG require a bogus typename in counter_spc
@@ -122,54 +127,64 @@
   if(header->next()==header->impl()||
      header->next()->next()==header->impl())return;
 
- aligned_storage<
- sizeof(sequenced_index_node_impl),
- alignment_of<
- sequenced_index_node_impl>::value
- >::type carry_spc;
- sequenced_index_node_impl& carry=
- *static_cast<sequenced_index_node_impl*>(static_cast<void*>(&carry_spc));
- aligned_storage<
+ typedef typename Node::impl_type impl_type;
+ typedef typename Node::impl_pointer impl_pointer;
+
+ typedef typename aligned_storage<
+ sizeof(impl_type),
+ alignment_of<impl_type>::value
+ >::type carry_spc_type;
+ carry_spc_type carry_spc;
+ impl_type& carry=
+ *static_cast<impl_type*>(static_cast<void*>(&carry_spc));
+ typedef typename aligned_storage<
     sizeof(
- sequenced_index_node_impl
+ impl_type
         [sequenced_index_sort_max_fill]),
     alignment_of<
- sequenced_index_node_impl
+ impl_type
         [sequenced_index_sort_max_fill]
>::value
- >::type counter_spc;
- sequenced_index_node_impl* counter=
- static_cast<sequenced_index_node_impl*>(static_cast<void*>(&counter_spc));
- std::size_t fill=0;
+ >::type counter_spc_type;
+ counter_spc_type counter_spc;
+ impl_type* counter=
+ static_cast<impl_type*>(static_cast<void*>(&counter_spc));
+ std::size_t fill=0;
 
- carry.prior()=carry.next()=&carry;
- counter[0].prior()=counter[0].next()=&counter[0];
+ carry.prior()=carry.next()=static_cast<impl_pointer>(&carry);
+ counter[0].prior()=counter[0].next()=static_cast<impl_pointer>(&counter[0]);
 
   BOOST_TRY{
     while(header->next()!=header->impl()){
- sequenced_index_node_impl::relink(carry.next(),header->next());
+ impl_type::relink(carry.next(),header->next());
       std::size_t i=0;
- while(i<fill&&counter[i].next()!=&counter[i]){
+ while(i<fill&&counter[i].next()!=static_cast<impl_pointer>(&counter[i])){
         sequenced_index_collate<Node>(&carry,&counter[i++],comp);
       }
- sequenced_index_node_impl::swap(&carry,&counter[i]);
+ impl_type::swap(
+ static_cast<impl_pointer>(&carry),
+ static_cast<impl_pointer>(&counter[i]));
       if(i==fill){
         ++fill;
- counter[fill].prior()=counter[fill].next()=&counter[fill];
+ counter[fill].prior()=counter[fill].next()=
+ static_cast<impl_pointer>(&counter[fill]);
       }
     }
 
     for(std::size_t i=1;i<fill;++i){
       sequenced_index_collate<Node>(&counter[i],&counter[i-1],comp);
     }
- sequenced_index_node_impl::swap(header->impl(),&counter[fill-1]);
+ impl_type::swap(
+ header->impl(),static_cast<impl_pointer>(&counter[fill-1]));
   }
   BOOST_CATCH(...)
   {
- sequenced_index_node_impl::relink(header->impl(),carry.next(),&carry);
+ impl_type::relink(
+ header->impl(),carry.next(),static_cast<impl_pointer>(&carry));
     for(std::size_t i=0;i<=fill;++i){
- sequenced_index_node_impl::relink(
- header->impl(),counter[i].next(),&counter[i]);
+ impl_type::relink(
+ header->impl(),counter[i].next(),
+ static_cast<impl_pointer>(&counter[i]));
     }
     BOOST_RETHROW;
   }

Modified: trunk/boost/multi_index/detail/uintptr_type.hpp
==============================================================================
--- trunk/boost/multi_index/detail/uintptr_type.hpp (original)
+++ trunk/boost/multi_index/detail/uintptr_type.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -44,13 +44,20 @@
 template<>struct uintptr_candidates<3> {typedef unsigned int type;};
 #endif
 
+#if defined(BOOST_HAS_MS_INT64)
+template<>struct uintptr_candidates<4> {typedef unsigned __int64 type;};
+#else
+template<>struct uintptr_candidates<4> {typedef unsigned int type;};
+#endif
+
 struct uintptr_aux
 {
   BOOST_STATIC_CONSTANT(int,index=
     sizeof(void*)==sizeof(uintptr_candidates<0>::type)?0:
     sizeof(void*)==sizeof(uintptr_candidates<1>::type)?1:
     sizeof(void*)==sizeof(uintptr_candidates<2>::type)?2:
- sizeof(void*)==sizeof(uintptr_candidates<3>::type)?3:-1);
+ sizeof(void*)==sizeof(uintptr_candidates<3>::type)?3:
+ sizeof(void*)==sizeof(uintptr_candidates<4>::type)?4:-1);
 
   BOOST_STATIC_CONSTANT(bool,has_uintptr_type=(index>=0));
 

Modified: trunk/boost/multi_index/detail/unbounded.hpp
==============================================================================
--- trunk/boost/multi_index/detail/unbounded.hpp (original)
+++ trunk/boost/multi_index/detail/unbounded.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -22,28 +22,59 @@
 
 /* dummy type and variable for use in ordered_index::range() */
 
-namespace detail{
-
-struct unbounded_type{};
-
-} /* namespace multi_index::detail */
-
-namespace{
-
 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
 /* The default branch actually works for MSVC 6.0, but seems like
- * the const qualifier reduces the performance of ordered indices! This
- * behavior is hard to explain and probably a test artifact, but it
- * does not hurt to have the workaround anyway.
+ * this implementation of unbounded improves the performance of ordered
+ * indices! This behavior is hard to explain and probably a test artifact,
+ * but it does not hurt to have the workaround anyway.
  */
 
+namespace detail{struct unbounded_type{};}
+
+namespace{
+
 static detail::unbounded_type unbounded_obj=detail::unbounded_type();
 static detail::unbounded_type& unbounded=unbounded_obj;
+
+} /* unnamed */
 #else
-const detail::unbounded_type unbounded=detail::unbounded_type();
+/* ODR-abiding technique shown at the example attached to
+ * http://lists.boost.org/Archives/boost/2006/07/108355.php
+ */
+
+namespace detail{class unbounded_helper;}
+
+detail::unbounded_helper unbounded(detail::unbounded_helper);
+
+namespace detail{
+
+class unbounded_helper
+{
+ unbounded_helper(){}
+ unbounded_helper(const unbounded_helper&){}
+ friend unbounded_helper multi_index::unbounded(unbounded_helper);
+};
+
+typedef unbounded_helper (*unbounded_type)(unbounded_helper);
+
+} /* namespace multi_index::detail */
+
+inline detail::unbounded_helper unbounded(detail::unbounded_helper)
+{
+ return detail::unbounded_helper();
+}
 #endif
 
-} /* unnamed */
+/* tags used in the implementation of range */
+
+namespace detail{
+
+struct none_unbounded_tag{};
+struct lower_unbounded_tag{};
+struct upper_unbounded_tag{};
+struct both_unbounded_tag{};
+
+} /* namespace multi_index::detail */
 
 } /* namespace multi_index */
 

Modified: trunk/boost/multi_index/detail/value_compare.hpp
==============================================================================
--- trunk/boost/multi_index/detail/value_compare.hpp (original)
+++ trunk/boost/multi_index/detail/value_compare.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -26,7 +26,8 @@
 template<typename Value,typename KeyFromValue,typename Compare>
 struct value_comparison:std::binary_function<Value,Value,bool>
 {
- value_comparison(KeyFromValue key_=KeyFromValue(),Compare comp_=Compare()):
+ value_comparison(
+ const KeyFromValue& key_=KeyFromValue(),const Compare& comp_=Compare()):
     key(key_),comp(comp_)
   {
   }

Added: trunk/boost/multi_index/global_fun.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/multi_index/global_fun.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -0,0 +1,188 @@
+/* Copyright 2003-2007 Joaquín M López Muñoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/multi_index for library home page.
+ */
+
+#ifndef BOOST_MULTI_INDEX_GLOBAL_FUN_HPP
+#define BOOST_MULTI_INDEX_GLOBAL_FUN_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#if !defined(BOOST_NO_SFINAE)
+#include <boost/type_traits/is_convertible.hpp>
+#endif
+
+namespace boost{
+
+template<class T> class reference_wrapper; /* fwd decl. */
+
+namespace multi_index{
+
+namespace detail{
+
+/* global_fun is a read-only key extractor from Value based on a given global
+ * (or static member) function with signature:
+ *
+ * Type f([const] Value [&]);
+ *
+ * Additionally, global_fun and const_global_fun are overloaded to support
+ * referece_wrappers of Value and "chained pointers" to Value's. By chained
+ * pointer to T we mean a type P such that, given a p of Type P
+ * *...n...*x is convertible to T&, for some n>=1.
+ * Examples of chained pointers are raw and smart pointers, iterators and
+ * arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
+ */
+
+/* NB. Some overloads of operator() have an extra dummy parameter int=0.
+ * This disambiguator serves several purposes:
+ * - Without it, MSVC++ 6.0 incorrectly regards some overloads as
+ * specializations of a previous member function template.
+ * - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
+ * as if they have the same signature.
+ * - If remove_const is broken due to lack of PTS, int=0 avoids the
+ * declaration of memfuns with identical signature.
+ */
+
+template<class Value,typename Type,Type (*PtrToFunction)(Value)>
+struct const_ref_global_fun_base
+{
+ typedef typename remove_reference<Type>::type result_type;
+
+ template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+ typename disable_if<
+ is_convertible<const ChainedPtr&,Value>,Type>::type
+#else
+ Type
+#endif
+
+ operator()(const ChainedPtr& x)const
+ {
+ return operator()(*x);
+ }
+
+ Type operator()(Value x)const
+ {
+ return PtrToFunction(x);
+ }
+
+ Type operator()(
+ const reference_wrapper<
+ typename remove_reference<Value>::type>& x)const
+ {
+ return operator()(x.get());
+ }
+
+ Type operator()(
+ const reference_wrapper<
+ typename remove_const<
+ typename remove_reference<Value>::type>::type>& x,int=0)const
+ {
+ return operator()(x.get());
+ }
+};
+
+template<class Value,typename Type,Type (*PtrToFunction)(Value)>
+struct non_const_ref_global_fun_base
+{
+ typedef typename remove_reference<Type>::type result_type;
+
+ template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+ typename disable_if<
+ is_convertible<ChainedPtr&,Value>,Type>::type
+#else
+ Type
+#endif
+
+ operator()(const ChainedPtr& x)const
+ {
+ return operator()(*x);
+ }
+
+ Type operator()(Value x)const
+ {
+ return PtrToFunction(x);
+ }
+
+ Type operator()(
+ const reference_wrapper<
+ typename remove_reference<Value>::type>& x)const
+ {
+ return operator()(x.get());
+ }
+};
+
+template<class Value,typename Type,Type (*PtrToFunction)(Value)>
+struct non_ref_global_fun_base
+{
+ typedef typename remove_reference<Type>::type result_type;
+
+ template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+ typename disable_if<
+ is_convertible<const ChainedPtr&,const Value&>,Type>::type
+#else
+ Type
+#endif
+
+ operator()(const ChainedPtr& x)const
+ {
+ return operator()(*x);
+ }
+
+ Type operator()(const Value& x)const
+ {
+ return PtrToFunction(x);
+ }
+
+ Type operator()(const reference_wrapper<const Value>& x)const
+ {
+ return operator()(x.get());
+ }
+
+ Type operator()(
+ const reference_wrapper<
+ typename remove_const<Value>::type>& x,int=0)const
+ {
+ return operator()(x.get());
+ }
+};
+
+} /* namespace multi_index::detail */
+
+template<class Value,typename Type,Type (*PtrToFunction)(Value)>
+struct global_fun:
+ mpl::if_c<
+ is_reference<Value>::value,
+ typename mpl::if_c<
+ is_const<typename remove_reference<Value>::type>::value,
+ detail::const_ref_global_fun_base<Value,Type,PtrToFunction>,
+ detail::non_const_ref_global_fun_base<Value,Type,PtrToFunction>
+ >::type,
+ detail::non_ref_global_fun_base<Value,Type,PtrToFunction>
+ >::type
+{
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif

Modified: trunk/boost/multi_index/hashed_index.hpp
==============================================================================
--- trunk/boost/multi_index/hashed_index.hpp (original)
+++ trunk/boost/multi_index/hashed_index.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -100,6 +100,10 @@
 protected:
   typedef hashed_index_node<
     typename super::node_type> node_type;
+
+private:
+ typedef typename node_type::impl_type node_impl_type;
+ typedef typename node_impl_type::pointer node_impl_pointer;
   typedef bucket_array<
     typename super::final_allocator_type> bucket_array_type;
 
@@ -172,8 +176,7 @@
 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
   typedef safe_ctr_proxy_impl<
     hashed_index_iterator<
- node_type,
- bucket_array_type>,
+ node_type,bucket_array_type>,
     hashed_index> safe_super;
 #else
   typedef safe_mode::safe_container<
@@ -227,6 +230,19 @@
   iterator end(){return make_iterator(header());}
   const_iterator end()const{return make_iterator(header());}
 
+ const_iterator cbegin()const{return begin();}
+ const_iterator cend()const{return end();}
+
+ iterator iterator_to(const value_type& x)
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
+
+ const_iterator iterator_to(const value_type& x)const
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
+
   /* modifiers */
 
   std::pair<iterator,bool> insert(value_param_type x)
@@ -268,15 +284,15 @@
   {
     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
 
- size_type s=0;
- std::size_t buc=buckets.position(hash(k));
- hashed_index_node_impl* x=buckets.at(buc);
- hashed_index_node_impl* y=x->next();
+ size_type s=0;
+ std::size_t buc=buckets.position(hash(k));
+ node_impl_pointer x=buckets.at(buc);
+ node_impl_pointer y=x->next();
     while(y!=x){
       if(eq(k,key(node_type::from_impl(y)->value()))){
         bool b;
         do{
- hashed_index_node_impl* z=y->next();
+ node_impl_pointer z=y->next();
           b=z!=x&&eq(
             key(node_type::from_impl(y)->value()),
             key(node_type::from_impl(z)->value()));
@@ -337,6 +353,27 @@
       mod,static_cast<final_node_type*>(position.get_node()));
   }
 
+ template<typename Modifier,typename Rollback>
+ bool modify(iterator position,Modifier mod,Rollback back)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ /* MSVC++ 6.0 optimizer on safe mode code chokes if this
+ * this is not added. Left it for all compilers as it does no
+ * harm.
+ */
+
+ position.detach();
+#endif
+
+ return this->final_modify_(
+ mod,back,static_cast<final_node_type*>(position.get_node()));
+ }
+
   template<typename Modifier>
   bool modify_key(iterator position,Modifier mod)
   {
@@ -348,6 +385,19 @@
       position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
   }
 
+ template<typename Modifier,typename Rollback>
+ bool modify_key(iterator position,Modifier mod,Rollback back)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+ return modify(
+ position,
+ modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
+ modify_key_adaptor<Modifier,value_type,KeyFromValue>(back,key));
+ }
+
   void clear()
   {
     BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
@@ -385,9 +435,9 @@
     const CompatibleKey& k,
     const CompatibleHash& hash,const CompatiblePred& eq)const
   {
- std::size_t buc=buckets.position(hash(k));
- hashed_index_node_impl* x=buckets.at(buc);
- hashed_index_node_impl* y=x->next();
+ std::size_t buc=buckets.position(hash(k));
+ node_impl_pointer x=buckets.at(buc);
+ node_impl_pointer y=x->next();
     while(y!=x){
       if(eq(k,key(node_type::from_impl(y)->value()))){
         return make_iterator(node_type::from_impl(y));
@@ -410,10 +460,10 @@
     const CompatibleKey& k,
     const CompatibleHash& hash,const CompatiblePred& eq)const
   {
- size_type res=0;
- std::size_t buc=buckets.position(hash(k));
- hashed_index_node_impl* x=buckets.at(buc);
- hashed_index_node_impl* y=x->next();
+ size_type res=0;
+ std::size_t buc=buckets.position(hash(k));
+ node_impl_pointer x=buckets.at(buc);
+ node_impl_pointer y=x->next();
     while(y!=x){
       if(eq(k,key(node_type::from_impl(y)->value()))){
         do{
@@ -440,12 +490,12 @@
     const CompatibleKey& k,
     const CompatibleHash& hash,const CompatiblePred& eq)const
   {
- std::size_t buc=buckets.position(hash(k));
- hashed_index_node_impl* x=buckets.at(buc);
- hashed_index_node_impl* y=x->next();
+ std::size_t buc=buckets.position(hash(k));
+ node_impl_pointer x=buckets.at(buc);
+ node_impl_pointer y=x->next();
     while(y!=x){
       if(eq(k,key(node_type::from_impl(y)->value()))){
- hashed_index_node_impl* y0=y;
+ node_impl_pointer y0=y;
         do{
           y=y->next();
         }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
@@ -471,9 +521,9 @@
 
   size_type bucket_size(size_type n)const
   {
- size_type res=0;
- hashed_index_node_impl* x=buckets.at(n);
- hashed_index_node_impl* y=x->next();
+ size_type res=0;
+ node_impl_pointer x=buckets.at(n);
+ node_impl_pointer y=x->next();
     while(y!=x){
       ++res;
       y=y->next();
@@ -493,8 +543,8 @@
 
   const_local_iterator begin(size_type n)const
   {
- hashed_index_node_impl* x=buckets.at(n);
- hashed_index_node_impl* y=x->next();
+ node_impl_pointer x=buckets.at(n);
+ node_impl_pointer y=x->next();
     if(y==x)return end();
     return make_iterator(node_type::from_impl(y));
   }
@@ -506,7 +556,7 @@
 
   const_local_iterator end(size_type n)const
   {
- hashed_index_node_impl* x=buckets.at(n);
+ node_impl_pointer x=buckets.at(n);
     if(x==x->next())return end();
     do{
       ++x;
@@ -514,6 +564,19 @@
     return make_iterator(node_type::from_impl(x->next()));
   }
 
+ const_local_iterator cbegin(size_type n)const{return begin(n);}
+ const_local_iterator cend(size_type n)const{return end(n);}
+
+ local_iterator local_iterator_to(const value_type& x)
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
+
+ const_local_iterator local_iterator_to(const value_type& x)const
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
+
   /* hash policy */
 
   float load_factor()const{return static_cast<float>(size())/bucket_count();}
@@ -602,13 +665,13 @@
     const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
     const copy_map_type& map)
   {
- for(hashed_index_node_impl* begin_org=x.buckets.begin(),
- * begin_cpy=buckets.begin(),
- * end_org=x.buckets.end();
+ for(node_impl_pointer begin_org=x.buckets.begin(),
+ begin_cpy=buckets.begin(),
+ end_org=x.buckets.end();
         begin_org!=end_org;++begin_org,++begin_cpy){
 
- hashed_index_node_impl* next_org=begin_org->next();
- hashed_index_node_impl* cpy=begin_cpy;
+ node_impl_pointer next_org=begin_org->next();
+ node_impl_pointer cpy=begin_cpy;
       while(next_org!=begin_org){
         cpy->next()=
           static_cast<node_type*>(
@@ -628,8 +691,8 @@
   {
     reserve(size()+1);
 
- std::size_t buc=find_bucket(v);
- hashed_index_node_impl* pos=buckets.at(buc);
+ std::size_t buc=find_bucket(v);
+ node_impl_pointer pos=buckets.at(buc);
     if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
 
     node_type* res=static_cast<node_type*>(super::insert_(v,x));
@@ -644,8 +707,8 @@
   {
     reserve(size()+1);
 
- std::size_t buc=find_bucket(v);
- hashed_index_node_impl* pos=buckets.at(buc);
+ std::size_t buc=find_bucket(v);
+ node_impl_pointer pos=buckets.at(buc);
     if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
 
     node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
@@ -669,11 +732,11 @@
 
   void delete_all_nodes_()
   {
- for(hashed_index_node_impl* x=buckets.begin(),*x_end=buckets.end();
+ for(node_impl_pointer x=buckets.begin(),x_end=buckets.end();
         x!=x_end;++x){
- hashed_index_node_impl* y=x->next();
+ node_impl_pointer y=x->next();
       while(y!=x){
- hashed_index_node_impl* z=y->next();
+ node_impl_pointer z=y->next();
         this->final_delete_node_(
           static_cast<final_node_type*>(node_type::from_impl(y)));
         y=z;
@@ -716,12 +779,12 @@
       return super::replace_(v,x);
     }
 
- hashed_index_node_impl* y=prev(x);
+ node_impl_pointer y=prev(x);
     unlink_next(y);
 
     BOOST_TRY{
- std::size_t buc=find_bucket(v);
- hashed_index_node_impl* pos=buckets.at(buc);
+ std::size_t buc=find_bucket(v);
+ node_impl_pointer pos=buckets.at(buc);
       if(link_point(v,pos,Category())&&super::replace_(v,x)){
         link(x,pos);
         if(first_bucket>buc){
@@ -746,8 +809,8 @@
   {
     unlink(x);
 
- std::size_t buc;
- hashed_index_node_impl* pos;
+ std::size_t buc;
+ node_impl_pointer pos;
     BOOST_TRY
     {
       buc=find_bucket(x->value());
@@ -806,6 +869,34 @@
     BOOST_CATCH_END
   }
 
+ bool modify_rollback_(node_type* x)
+ {
+ node_impl_pointer y=prev(x);
+ unlink_next(y);
+
+ BOOST_TRY{
+ std::size_t buc=find_bucket(x->value());
+ node_impl_pointer pos=buckets.at(buc);
+ if(link_point(x->value(),pos,Category())&&super::modify_rollback_(x)){
+ link(x,pos);
+ if(first_bucket>buc){
+ first_bucket=buc;
+ }
+ else if(first_bucket<buc){
+ first_bucket=buckets.first_nonempty(first_bucket);
+ }
+ return true;
+ }
+ link(x,y);
+ return false;
+ }
+ BOOST_CATCH(...){
+ link(x,y);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+
 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   /* serialization */
 
@@ -872,9 +963,9 @@
   }
 
   bool link_point(
- value_param_type v,hashed_index_node_impl*& pos,hashed_unique_tag)
+ value_param_type v,node_impl_pointer& pos,hashed_unique_tag)
   {
- hashed_index_node_impl* x=pos->next();
+ node_impl_pointer x=pos->next();
     while(x!=pos){
       if(eq(key(v),key(node_type::from_impl(x)->value()))){
         pos=x;
@@ -886,10 +977,10 @@
   }
 
   bool link_point(
- value_param_type v,hashed_index_node_impl*& pos,hashed_non_unique_tag)
+ value_param_type v,node_impl_pointer& pos,hashed_non_unique_tag)
   {
- hashed_index_node_impl* prev=pos;
- hashed_index_node_impl* x=pos->next();
+ node_impl_pointer prev=pos;
+ node_impl_pointer x=pos->next();
     while(x!=pos){
       if(eq(key(v),key(node_type::from_impl(x)->value()))){
         pos=prev;
@@ -901,29 +992,29 @@
     return true;
   }
   
- void link(node_type* x,hashed_index_node_impl* pos)
+ void link(node_type* x,node_impl_pointer pos)
   {
- hashed_index_node_impl::link(x->impl(),pos);
+ node_impl_type::link(x->impl(),pos);
   };
 
- void link(hashed_index_node_impl* x,hashed_index_node_impl* pos)
+ void link(node_impl_pointer x,node_impl_pointer pos)
   {
- hashed_index_node_impl::link(x,pos);
+ node_impl_type::link(x,pos);
   };
 
   void unlink(node_type* x)
   {
- hashed_index_node_impl::unlink(x->impl());
+ node_impl_type::unlink(x->impl());
   };
 
- static hashed_index_node_impl* prev(node_type* x)
+ static node_impl_pointer prev(node_type* x)
   {
- return hashed_index_node_impl::prev(x->impl());
+ return node_impl_type::prev(x->impl());
   }
 
- static void unlink_next(hashed_index_node_impl* x)
+ static void unlink_next(node_impl_pointer x)
   {
- hashed_index_node_impl::unlink_next(x);
+ node_impl_type::unlink_next(x);
   }
 
   void calculate_max_load()
@@ -949,10 +1040,10 @@
     auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
 
     std::size_t i=0;
- hashed_index_node_impl* x=buckets.begin();
- hashed_index_node_impl* x_end=buckets.end();
+ node_impl_pointer x=buckets.begin();
+ node_impl_pointer x_end=buckets.end();
     for(;x!=x_end;++x){
- hashed_index_node_impl* y=x->next();
+ node_impl_pointer y=x->next();
       while(y!=x){
         hashes.data()[i++]=hash(key(node_type::from_impl(y)->value()));
         y=y->next();
@@ -962,11 +1053,11 @@
     i=0;
     x=buckets.begin();
     for(;x!=x_end;++x){
- hashed_index_node_impl* y=x->next();
+ node_impl_pointer y=x->next();
       while(y!=x){
- hashed_index_node_impl* z=y->next();
- std::size_t buc1=buckets1.position(hashes.data()[i++]);
- hashed_index_node_impl* x1=buckets1.at(buc1);
+ node_impl_pointer z=y->next();
+ std::size_t buc1=buckets1.position(hashes.data()[i++]);
+ node_impl_pointer x1=buckets1.at(buc1);
         link(y,x1);
         y=z;
       }
@@ -1014,7 +1105,7 @@
 
 } /* namespace multi_index::detail */
 
-/* sequenced index specifiers */
+/* hashed index specifiers */
 
 template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
 struct hashed_unique

Modified: trunk/boost/multi_index/identity_fwd.hpp
==============================================================================
--- trunk/boost/multi_index/identity_fwd.hpp (original)
+++ trunk/boost/multi_index/identity_fwd.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -6,8 +6,8 @@
  * See http://www.boost.org/libs/multi_index for library home page.
  */
 
-#ifndef BOOST_MULTI_INDEX_IDENTITY_HPP
-#define BOOST_MULTI_INDEX_IDENTITY_HPP
+#ifndef BOOST_MULTI_INDEX_IDENTITY_FWD_HPP
+#define BOOST_MULTI_INDEX_IDENTITY_FWD_HPP
 
 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
 #pragma once

Modified: trunk/boost/multi_index/key_extractors.hpp
==============================================================================
--- trunk/boost/multi_index/key_extractors.hpp (original)
+++ trunk/boost/multi_index/key_extractors.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2005 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -15,6 +15,7 @@
 
 #include <boost/multi_index/composite_key.hpp>
 #include <boost/multi_index/identity.hpp>
+#include <boost/multi_index/global_fun.hpp>
 #include <boost/multi_index/member.hpp>
 #include <boost/multi_index/mem_fun.hpp>
 

Modified: trunk/boost/multi_index/mem_fun.hpp
==============================================================================
--- trunk/boost/multi_index/mem_fun.hpp (original)
+++ trunk/boost/multi_index/mem_fun.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,4 +1,4 @@
-/* Copyright 2003-2006 Joaquín M López Muñoz.
+/* Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -39,16 +39,6 @@
  * arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
  */
 
-/* NB. Some overloads of operator() have an extra dummy parameter int=0.
- * This disambiguator serves several purposes:
- * - Without it, MSVC++ 6.0 incorrectly regards some overloads as
- * specializations of a previous member function template.
- * - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
- * as if they have the same signature.
- * - If remove_const is broken due to lack of PTS, int=0 avoids the
- * declaration of memfuns with identical signature.
- */
-
 template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const>
 struct const_mem_fun
 {
@@ -78,7 +68,7 @@
     return operator()(x.get());
   }
 
- Type operator()(const reference_wrapper<Class>& x,int=0)const
+ Type operator()(const reference_wrapper<Class>& x)const
   {
     return operator()(x.get());
   }
@@ -115,9 +105,9 @@
 };
 
 /* MSVC++ 6.0 has problems with const member functions as non-type template
- * parameters, somehow it takes them as non-const. mem_fun_explicit workarounds
- * this defficiency by accepting an extra type parameter that specifies the
- * signature of he member function. The workaround was found at:
+ * parameters, somehow it takes them as non-const. const_mem_fun_explicit
+ * workarounds this deficiency by accepting an extra type parameter that
+ * specifies the signature of the member function. The workaround was found at:
  * Daniel, C.:"Re: weird typedef problem in VC",
  * news:microsoft.public.vc.language, 21st nov 2002,
  * http://groups.google.com/groups?
@@ -155,7 +145,7 @@
     return operator()(x.get());
   }
 
- Type operator()(const reference_wrapper<Class>& x,int=0)const
+ Type operator()(const reference_wrapper<Class>& x)const
   {
     return operator()(x.get());
   }
@@ -194,7 +184,7 @@
 };
 
 /* BOOST_MULTI_INDEX_CONST_MEM_FUN and BOOST_MULTI_INDEX_MEM_FUN resolve to
- * mem_fun_explicit for MSVC++ 6.0 and to [const_]mem_fun otherwise.
+ * [const_]mem_fun_explicit for MSVC++ 6.0 and to [const_]mem_fun otherwise.
  */
 
 #if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)

Modified: trunk/boost/multi_index/ordered_index.hpp
==============================================================================
--- trunk/boost/multi_index/ordered_index.hpp (original)
+++ trunk/boost/multi_index/ordered_index.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -46,6 +46,7 @@
 #include <boost/detail/no_exceptions_support.hpp>
 #include <boost/detail/workaround.hpp>
 #include <boost/iterator/reverse_iterator.hpp>
+#include <boost/mpl/if.hpp>
 #include <boost/mpl/push_front.hpp>
 #include <boost/multi_index/detail/access_specifier.hpp>
 #include <boost/multi_index/detail/bidir_node_iterator.hpp>
@@ -60,6 +61,7 @@
 #include <boost/multi_index/ordered_index_fwd.hpp>
 #include <boost/ref.hpp>
 #include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/is_same.hpp>
 #include <utility>
 
 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
@@ -130,6 +132,10 @@
   typedef ordered_index_node<
     typename super::node_type> node_type;
 
+private:
+ typedef typename node_type::impl_type node_impl_type;
+ typedef typename node_impl_type::pointer node_impl_pointer;
+
 public:
   /* types */
 
@@ -237,7 +243,21 @@
   const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
   reverse_iterator rend(){return make_reverse_iterator(begin());}
   const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
+ const_iterator cbegin()const{return begin();}
+ const_iterator cend()const{return end();}
+ const_reverse_iterator crbegin()const{return rbegin();}
+ const_reverse_iterator crend()const{return rend();}
  
+ iterator iterator_to(const value_type& x)
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
+
+ const_iterator iterator_to(const value_type& x)const
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
+
   /* capacity */
 
   bool empty()const{return this->final_empty_();}
@@ -338,6 +358,27 @@
       mod,static_cast<final_node_type*>(position.get_node()));
   }
 
+ template<typename Modifier,typename Rollback>
+ bool modify(iterator position,Modifier mod,Rollback back)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ /* MSVC++ 6.0 optimizer on safe mode code chokes if this
+ * this is not added. Left it for all compilers as it does no
+ * harm.
+ */
+
+ position.detach();
+#endif
+
+ return this->final_modify_(
+ mod,back,static_cast<final_node_type*>(position.get_node()));
+ }
+
   template<typename Modifier>
   bool modify_key(iterator position,Modifier mod)
   {
@@ -349,6 +390,19 @@
       position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
   }
 
+ template<typename Modifier,typename Rollback>
+ bool modify_key(iterator position,Modifier mod,Rollback back)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ return modify(
+ position,
+ modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
+ modify_key_adaptor<Modifier,value_type,KeyFromValue>(back,key));
+ }
+
   void swap(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
   {
     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
@@ -376,14 +430,14 @@
   template<typename CompatibleKey>
   iterator find(const CompatibleKey& x)const
   {
- return make_iterator(ordered_index_find(header(),key,x,comp));
+ return make_iterator(ordered_index_find(root(),header(),key,x,comp));
   }
 
   template<typename CompatibleKey,typename CompatibleCompare>
   iterator find(
     const CompatibleKey& x,const CompatibleCompare& comp)const
   {
- return make_iterator(ordered_index_find(header(),key,x,comp));
+ return make_iterator(ordered_index_find(root(),header(),key,x,comp));
   }
 
   template<typename CompatibleKey>
@@ -403,42 +457,51 @@
   template<typename CompatibleKey>
   iterator lower_bound(const CompatibleKey& x)const
   {
- return make_iterator(ordered_index_lower_bound(header(),key,x,comp));
+ return make_iterator(
+ ordered_index_lower_bound(root(),header(),key,x,comp));
   }
 
   template<typename CompatibleKey,typename CompatibleCompare>
   iterator lower_bound(
     const CompatibleKey& x,const CompatibleCompare& comp)const
   {
- return make_iterator(ordered_index_lower_bound(header(),key,x,comp));
+ return make_iterator(
+ ordered_index_lower_bound(root(),header(),key,x,comp));
   }
 
   template<typename CompatibleKey>
   iterator upper_bound(const CompatibleKey& x)const
   {
- return make_iterator(ordered_index_upper_bound(header(),key,x,comp));
+ return make_iterator(
+ ordered_index_upper_bound(root(),header(),key,x,comp));
   }
 
   template<typename CompatibleKey,typename CompatibleCompare>
   iterator upper_bound(
     const CompatibleKey& x,const CompatibleCompare& comp)const
   {
- return make_iterator(ordered_index_upper_bound(header(),key,x,comp));
+ return make_iterator(
+ ordered_index_upper_bound(root(),header(),key,x,comp));
   }
 
   template<typename CompatibleKey>
   std::pair<iterator,iterator> equal_range(
     const CompatibleKey& x)const
   {
- return equal_range(x,comp);
+ std::pair<node_type*,node_type*> p=
+ ordered_index_equal_range(root(),header(),key,x,comp);
+ return std::pair<iterator,iterator>(
+ make_iterator(p.first),make_iterator(p.second));
   }
 
   template<typename CompatibleKey,typename CompatibleCompare>
   std::pair<iterator,iterator> equal_range(
     const CompatibleKey& x,const CompatibleCompare& comp)const
   {
+ std::pair<node_type*,node_type*> p=
+ ordered_index_equal_range(root(),header(),key,x,comp);
     return std::pair<iterator,iterator>(
- lower_bound(x,comp),upper_bound(x,comp));
+ make_iterator(p.first),make_iterator(p.second));
   }
 
   /* range */
@@ -447,12 +510,21 @@
   std::pair<iterator,iterator>
   range(LowerBounder lower,UpperBounder upper)const
   {
- std::pair<iterator,iterator> p(
- lower_range(lower),upper_range(upper));
- if(p.second!=end()&&(p.first==end()||comp(key(*p.second),key(*p.first)))){
- p.second=p.first;
- }
- return p;
+ typedef typename mpl::if_<
+ is_same<LowerBounder,unbounded_type>,
+ BOOST_DEDUCED_TYPENAME mpl::if_<
+ is_same<UpperBounder,unbounded_type>,
+ both_unbounded_tag,
+ lower_unbounded_tag
+ >::type,
+ BOOST_DEDUCED_TYPENAME mpl::if_<
+ is_same<UpperBounder,unbounded_type>,
+ upper_unbounded_tag,
+ none_unbounded_tag
+ >::type
+ >::type dispatch;
+
+ return range(lower,upper,dispatch());
   }
 
 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
@@ -523,8 +595,8 @@
 
         cpy->color()=org->color();
 
- ordered_index_node_impl* parent_org=org->parent();
- if(!parent_org)cpy->parent()=0;
+ node_impl_pointer parent_org=org->parent();
+ if(parent_org==node_impl_pointer(0))cpy->parent()=node_impl_pointer(0);
         else{
           node_type* parent_cpy=map.find(
             static_cast<final_node_type*>(node_type::from_impl(parent_org)));
@@ -538,8 +610,10 @@
           }
         }
 
- if(!org->left())cpy->left()=0;
- if(!org->right())cpy->right()=0;
+ if(org->left()==node_impl_pointer(0))
+ cpy->left()=node_impl_pointer(0);
+ if(org->right()==node_impl_pointer(0))
+ cpy->right()=node_impl_pointer(0);
       }
     }
     
@@ -555,8 +629,7 @@
 
     node_type* res=static_cast<node_type*>(super::insert_(v,x));
     if(res==x){
- ordered_index_node_impl::link(
- x->impl(),inf.side,inf.pos,header()->impl());
+ node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
     }
     return res;
   }
@@ -570,15 +643,14 @@
 
     node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
     if(res==x){
- ordered_index_node_impl::link(
- x->impl(),inf.side,inf.pos,header()->impl());
+ node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
     }
     return res;
   }
 
   void erase_(node_type* x)
   {
- ordered_index_node_impl::rebalance_for_erase(
+ node_impl_type::rebalance_for_erase(
       x->impl(),header()->parent(),header()->left(),header()->right());
     super::erase_(x);
 
@@ -623,23 +695,20 @@
     node_type* next=x;
     node_type::increment(next);
 
- ordered_index_node_impl::rebalance_for_erase(
+ node_impl_type::rebalance_for_erase(
       x->impl(),header()->parent(),header()->left(),header()->right());
 
     BOOST_TRY{
       link_info inf;
       if(link_point(key(v),inf,Category())&&super::replace_(v,x)){
- ordered_index_node_impl::link(
- x->impl(),inf.side,inf.pos,header()->impl());
+ node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
         return true;
       }
- ordered_index_node_impl::restore(
- x->impl(),next->impl(),header()->impl());
+ node_impl_type::restore(x->impl(),next->impl(),header()->impl());
       return false;
     }
     BOOST_CATCH(...){
- ordered_index_node_impl::restore(
- x->impl(),next->impl(),header()->impl());
+ node_impl_type::restore(x->impl(),next->impl(),header()->impl());
       BOOST_RETHROW;
     }
     BOOST_CATCH_END
@@ -657,7 +726,7 @@
     }
     BOOST_CATCH_END
     if(!b){
- ordered_index_node_impl::rebalance_for_erase(
+ node_impl_type::rebalance_for_erase(
         x->impl(),header()->parent(),header()->left(),header()->right());
       BOOST_TRY{
         link_info inf;
@@ -669,8 +738,7 @@
 #endif
           return false;
         }
- ordered_index_node_impl::link(
- x->impl(),inf.side,inf.pos,header()->impl());
+ node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
       }
       BOOST_CATCH(...){
         super::erase_(x);
@@ -686,7 +754,7 @@
 
     BOOST_TRY{
       if(!super::modify_(x)){
- ordered_index_node_impl::rebalance_for_erase(
+ node_impl_type::rebalance_for_erase(
           x->impl(),header()->parent(),header()->left(),header()->right());
 
 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
@@ -698,7 +766,7 @@
       else return true;
     }
     BOOST_CATCH(...){
- ordered_index_node_impl::rebalance_for_erase(
+ node_impl_type::rebalance_for_erase(
         x->impl(),header()->parent(),header()->left(),header()->right());
 
 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
@@ -710,6 +778,35 @@
     BOOST_CATCH_END
   }
 
+ bool modify_rollback_(node_type* x)
+ {
+ if(in_place(x->value(),x,Category())){
+ return super::modify_rollback_(x);
+ }
+
+ node_type* next=x;
+ node_type::increment(next);
+
+ node_impl_type::rebalance_for_erase(
+ x->impl(),header()->parent(),header()->left(),header()->right());
+
+ BOOST_TRY{
+ link_info inf;
+ if(link_point(key(x->value()),inf,Category())&&
+ super::modify_rollback_(x)){
+ node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
+ return true;
+ }
+ node_impl_type::restore(x->impl(),next->impl(),header()->impl());
+ return false;
+ }
+ BOOST_CATCH(...){
+ node_impl_type::restore(x->impl(),next->impl(),header()->impl());
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+
 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   /* serialization */
 
@@ -740,7 +837,7 @@
     else{
       if((size_type)std::distance(begin(),end())!=size())return false;
 
- std::size_t len=ordered_index_node_impl::black_count(
+ std::size_t len=node_impl_type::black_count(
         leftmost()->impl(),root()->impl());
       for(const_iterator it=begin(),it_end=end();it!=it_end;++it){
         node_type* x=it.get_node();
@@ -754,16 +851,13 @@
         if(left_x&&comp(key(x->value()),key(left_x->value())))return false;
         if(right_x&&comp(key(right_x->value()),key(x->value())))return false;
         if(!left_x&&!right_x&&
- ordered_index_node_impl::black_count(
- x->impl(),root()->impl())!=len)
+ node_impl_type::black_count(x->impl(),root()->impl())!=len)
           return false;
       }
     
- if(leftmost()->impl()!=
- ordered_index_node_impl::minimum(root()->impl()))
+ if(leftmost()->impl()!=node_impl_type::minimum(root()->impl()))
         return false;
- if(rightmost()->impl()!=
- ordered_index_node_impl::maximum(root()->impl()))
+ if(rightmost()->impl()!=node_impl_type::maximum(root()->impl()))
         return false;
     }
 
@@ -790,15 +884,17 @@
     header()->color()=red;
     /* used to distinguish header() from root, in iterator.operator++ */
     
- header()->parent()=0;
+ header()->parent()=node_impl_pointer(0);
     header()->left()=header()->impl();
     header()->right()=header()->impl();
   }
 
   struct link_info
   {
- ordered_index_side side;
- ordered_index_node_impl* pos;
+ link_info():side(to_left){}
+
+ ordered_index_side side;
+ node_impl_pointer pos;
   };
 
   bool link_point(key_param_type k,link_info& inf,ordered_unique_tag)
@@ -847,6 +943,21 @@
     return true;
   }
 
+ bool lower_link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
+ {
+ node_type* y=header();
+ node_type* x=root();
+ bool c=false;
+ while (x){
+ y=x;
+ c=comp(key(x->value()),k);
+ x=node_type::from_impl(c?x->right():x->left());
+ }
+ inf.side=c?to_right:to_left;
+ inf.pos=y->impl();
+ return true;
+ }
+
   bool hinted_link_point(
     key_param_type k,node_type* position,link_info& inf,ordered_unique_tag)
   {
@@ -870,7 +981,7 @@
       node_type* before=position;
       node_type::decrement(before);
       if(comp(key(before->value()),k)&&comp(k,key(position->value()))){
- if(before->right()==0){
+ if(before->right()==node_impl_pointer(0)){
           inf.side=to_right;
           inf.pos=before->impl();
           return true;
@@ -894,7 +1005,7 @@
         inf.pos=position->impl();
         return true;
       }
- else return link_point(k,inf,ordered_non_unique_tag());
+ else return lower_link_point(k,inf,ordered_non_unique_tag());
     }
     else if(position==header()){
       if(!comp(k,key(rightmost()->value()))){
@@ -907,17 +1018,20 @@
     else{
       node_type* before=position;
       node_type::decrement(before);
- if (!comp(k,key(before->value()))&&!comp(key(position->value()),k)){
- if(before->right()==0){
- inf.side=to_right;
- inf.pos=before->impl();
- return true;
- }
- else{
- inf.side=to_left;
- inf.pos=position->impl();
- return true;
+ if(!comp(k,key(before->value()))){
+ if(!comp(key(position->value()),k)){
+ if(before->right()==node_impl_pointer(0)){
+ inf.side=to_right;
+ inf.pos=before->impl();
+ return true;
+ }
+ else{
+ inf.side=to_left;
+ inf.pos=position->impl();
+ return true;
+ }
         }
+ else return lower_link_point(k,inf,ordered_non_unique_tag());
       }
       else return link_point(k,inf,ordered_non_unique_tag());
     }
@@ -968,48 +1082,84 @@
   }
 #endif
 
- template<typename LowerBounder>
- iterator lower_range(LowerBounder lower)const
+ template<typename LowerBounder,typename UpperBounder>
+ std::pair<iterator,iterator>
+ range(LowerBounder lower,UpperBounder upper,none_unbounded_tag)const
   {
     node_type* y=header();
     node_type* z=root();
 
     while(z){
- if(lower(key(z->value()))){
+ if(!lower(key(z->value()))){
+ z=node_type::from_impl(z->right());
+ }
+ else if(!upper(key(z->value()))){
         y=z;
         z=node_type::from_impl(z->left());
       }
- else z=node_type::from_impl(z->right());
+ else{
+ return std::pair<iterator,iterator>(
+ make_iterator(
+ lower_range(node_type::from_impl(z->left()),z,lower)),
+ make_iterator(
+ upper_range(node_type::from_impl(z->right()),y,upper)));
+ }
     }
 
- return make_iterator(y);
+ return std::pair<iterator,iterator>(make_iterator(y),make_iterator(y));
   }
 
- iterator lower_range(unbounded_type)const
+ template<typename LowerBounder,typename UpperBounder>
+ std::pair<iterator,iterator>
+ range(LowerBounder,UpperBounder upper,lower_unbounded_tag)const
   {
- return begin();
+ return std::pair<iterator,iterator>(
+ begin(),
+ make_iterator(upper_range(root(),header(),upper)));
   }
 
- template<typename UpperBounder>
- iterator upper_range(UpperBounder upper)const
+ template<typename LowerBounder,typename UpperBounder>
+ std::pair<iterator,iterator>
+ range(LowerBounder lower,UpperBounder,upper_unbounded_tag)const
   {
- node_type* y=header();
- node_type* z=root();
+ return std::pair<iterator,iterator>(
+ make_iterator(lower_range(root(),header(),lower)),
+ end());
+ }
 
- while(z){
- if(!upper(key(z->value()))){
- y=z;
- z=node_type::from_impl(z->left());
+ template<typename LowerBounder,typename UpperBounder>
+ std::pair<iterator,iterator>
+ range(LowerBounder,UpperBounder,both_unbounded_tag)const
+ {
+ return std::pair<iterator,iterator>(begin(),end());
+ }
+
+ template<typename LowerBounder>
+ node_type * lower_range(node_type* top,node_type* y,LowerBounder lower)const
+ {
+ while(top){
+ if(lower(key(top->value()))){
+ y=top;
+ top=node_type::from_impl(top->left());
       }
- else z=node_type::from_impl(z->right());
+ else top=node_type::from_impl(top->right());
     }
 
- return make_iterator(y);
+ return y;
   }
 
- iterator upper_range(unbounded_type)const
+ template<typename UpperBounder>
+ node_type * upper_range(node_type* top,node_type* y,UpperBounder upper)const
   {
- return end();
+ while(top){
+ if(!upper(key(top->value()))){
+ y=top;
+ top=node_type::from_impl(top->left());
+ }
+ else top=node_type::from_impl(top->right());
+ }
+
+ return y;
   }
 
 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
@@ -1068,9 +1218,9 @@
     else node_type::increment(position);
 
     if(position!=x){
- ordered_index_node_impl::rebalance_for_erase(
+ node_impl_type::rebalance_for_erase(
         x->impl(),header()->parent(),header()->left(),header()->right());
- ordered_index_node_impl::restore(
+ node_impl_type::restore(
         x->impl(),position->impl(),header()->impl());
     }
   }

Modified: trunk/boost/multi_index/random_access_index.hpp
==============================================================================
--- trunk/boost/multi_index/random_access_index.hpp (original)
+++ trunk/boost/multi_index/random_access_index.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -19,6 +19,8 @@
 #include <boost/detail/no_exceptions_support.hpp>
 #include <boost/detail/workaround.hpp>
 #include <boost/iterator/reverse_iterator.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/not.hpp>
 #include <boost/mpl/push_front.hpp>
 #include <boost/multi_index/detail/access_specifier.hpp>
 #include <boost/multi_index/detail/index_node_base.hpp>
@@ -32,6 +34,7 @@
 #include <boost/multi_index/random_access_index_fwd.hpp>
 #include <boost/throw_exception.hpp>
 #include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/is_integral.hpp>
 #include <cstddef>
 #include <functional>
 #include <stdexcept>
@@ -94,6 +97,12 @@
   typedef random_access_index_node<
     typename super::node_type> node_type;
 
+private:
+ typedef typename node_type::impl_type node_impl_type;
+ typedef random_access_index_ptr_array<
+ typename super::final_allocator_type> ptr_array;
+ typedef typename ptr_array::pointer node_impl_ptr_pointer;
+
 public:
   /* types */
 
@@ -183,9 +192,7 @@
   template <class InputIterator>
   void assign(InputIterator first,InputIterator last)
   {
- BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
- clear();
- for(;first!=last;++first)push_back(*first);
+ assign_iter(first,last,mpl::not_<is_integral<InputIterator> >());
   }
 
   void assign(size_type n,value_param_type value)
@@ -212,6 +219,20 @@
   const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
   reverse_iterator rend(){return make_reverse_iterator(begin());}
   const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
+ const_iterator cbegin()const{return begin();}
+ const_iterator cend()const{return end();}
+ const_reverse_iterator crbegin()const{return rbegin();}
+ const_reverse_iterator crend()const{return rend();}
+
+ iterator iterator_to(const value_type& x)
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
+
+ const_iterator iterator_to(const value_type& x)const
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
 
   /* capacity */
 
@@ -290,19 +311,7 @@
   template<typename InputIterator>
   void insert(iterator position,InputIterator first,InputIterator last)
   {
- BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
- size_type s=0;
- BOOST_TRY{
- for(;first!=last;++first){
- if(push_back(*first).second)++s;
- }
- }
- BOOST_CATCH(...){
- relocate(position,end()-s,end());
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- relocate(position,end()-s,end());
+ insert_iter(position,first,last,mpl::not_<is_integral<InputIterator> >());
   }
 
   iterator erase(iterator position)
@@ -360,6 +369,27 @@
       mod,static_cast<final_node_type*>(position.get_node()));
   }
 
+ template<typename Modifier,typename Rollback>
+ bool modify(iterator position,Modifier mod,Rollback back)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ /* MSVC++ 6.0 optimizer on safe mode code chokes if this
+ * this is not added. Left it for all compilers as it does no
+ * harm.
+ */
+
+ position.detach();
+#endif
+
+ return this->final_modify_(
+ mod,back,static_cast<final_node_type*>(position.get_node()));
+ }
+
   void swap(random_access_index<SuperMeta,TagList>& x)
   {
     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
@@ -540,7 +570,7 @@
   void reverse()
   {
     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
- random_access_index_node_impl::reverse(ptrs.begin(),ptrs.end());
+ node_impl_type::reverse(ptrs.begin(),ptrs.end());
   }
 
   /* rearrange operations */
@@ -575,10 +605,10 @@
   void rearrange(InputIterator first)
   {
     BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
- for(random_access_index_node_impl** p0=ptrs.begin(),** p0_end=ptrs.end();
+ for(node_impl_ptr_pointer p0=ptrs.begin(),p0_end=ptrs.end();
         p0!=p0_end;++first,++p0){
- const value_type& v1=*first;
- random_access_index_node_impl** p1=node_from_value<node_type>(&v1)->up();
+ const value_type& v1=*first;
+ node_impl_ptr_pointer p1=node_from_value<node_type>(&v1)->up();
 
       std::swap(*p0,*p1);
       (*p0)->up()=p0;
@@ -625,9 +655,9 @@
   void copy_(
     const random_access_index<SuperMeta,TagList>& x,const copy_map_type& map)
   {
- for(random_access_index_node_impl** begin_org=x.ptrs.begin(),
- ** begin_cpy=ptrs.begin(),
- ** end_org=x.ptrs.end();
+ for(node_impl_ptr_pointer begin_org=x.ptrs.begin(),
+ begin_cpy=ptrs.begin(),
+ end_org=x.ptrs.end();
         begin_org!=end_org;++begin_org,++begin_cpy){
       *begin_cpy=
          static_cast<node_type*>(
@@ -668,8 +698,7 @@
 
   void delete_all_nodes_()
   {
- for(random_access_index_node_impl** x=ptrs.begin(),**x_end=ptrs.end();
- x!=x_end;++x){
+ for(node_impl_ptr_pointer x=ptrs.begin(),x_end=ptrs.end();x!=x_end;++x){
       this->final_delete_node_(
         static_cast<final_node_type*>(node_type::from_impl(*x)));
     }
@@ -727,6 +756,11 @@
     BOOST_CATCH_END
   }
 
+ bool modify_rollback_(node_type* x)
+ {
+ return super::modify_rollback_(x);
+ }
+
 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   /* serialization */
 
@@ -785,12 +819,12 @@
 
   static void relocate(node_type* position,node_type* x)
   {
- random_access_index_node_impl::relocate(position->up(),x->up());
+ node_impl_type::relocate(position->up(),x->up());
   }
 
   static void relocate(node_type* position,node_type* first,node_type* last)
   {
- random_access_index_node_impl::relocate(
+ node_impl_type::relocate(
       position->up(),first->up(),last->up());
   }
 
@@ -802,7 +836,61 @@
   }
 #endif
 
- random_access_index_ptr_array<typename super::final_allocator_type> ptrs;
+ template <class InputIterator>
+ void assign_iter(InputIterator first,InputIterator last,mpl::true_)
+ {
+ BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+ clear();
+ for(;first!=last;++first)push_back(*first);
+ }
+
+ void assign_iter(size_type n,value_param_type value,mpl::false_)
+ {
+ BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+ clear();
+ for(size_type i=0;i<n;++i)push_back(value);
+ }
+
+ template<typename InputIterator>
+ void insert_iter(
+ iterator position,InputIterator first,InputIterator last,mpl::true_)
+ {
+ BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+ size_type s=0;
+ BOOST_TRY{
+ for(;first!=last;++first){
+ if(push_back(*first).second)++s;
+ }
+ }
+ BOOST_CATCH(...){
+ relocate(position,end()-s,end());
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ relocate(position,end()-s,end());
+ }
+
+ void insert_iter(
+ iterator position,size_type n,value_param_type x,mpl::false_)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+ size_type s=0;
+ BOOST_TRY{
+ while(n--){
+ if(push_back(x).second)++s;
+ }
+ }
+ BOOST_CATCH(...){
+ relocate(position,end()-s,end());
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ relocate(position,end()-s,end());
+ }
+
+ ptr_array ptrs;
 
 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
     BOOST_WORKAROUND(__MWERKS__,<=0x3003)

Modified: trunk/boost/multi_index/sequenced_index.hpp
==============================================================================
--- trunk/boost/multi_index/sequenced_index.hpp (original)
+++ trunk/boost/multi_index/sequenced_index.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -15,9 +15,12 @@
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 #include <boost/call_traits.hpp>
+#include <boost/detail/allocator_utilities.hpp>
 #include <boost/detail/no_exceptions_support.hpp>
 #include <boost/detail/workaround.hpp>
 #include <boost/iterator/reverse_iterator.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/not.hpp>
 #include <boost/mpl/push_front.hpp>
 #include <boost/multi_index/detail/access_specifier.hpp>
 #include <boost/multi_index/detail/bidir_node_iterator.hpp>
@@ -29,6 +32,7 @@
 #include <boost/multi_index/detail/seq_index_ops.hpp>
 #include <boost/multi_index/sequenced_index_fwd.hpp>
 #include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/is_integral.hpp>
 #include <cstddef>
 #include <functional>
 #include <utility>
@@ -81,47 +85,50 @@
 #pragma parse_mfunc_templ off
 #endif
 
- typedef typename SuperMeta::type super;
+ typedef typename SuperMeta::type super;
 
 protected:
   typedef sequenced_index_node<
- typename super::node_type> node_type;
+ typename super::node_type> node_type;
 
+private:
+ typedef typename node_type::impl_type node_impl_type;
+
 public:
   /* types */
 
- typedef typename node_type::value_type value_type;
- typedef tuples::null_type ctor_args;
- typedef typename super::final_allocator_type allocator_type;
- typedef typename allocator_type::reference reference;
- typedef typename allocator_type::const_reference const_reference;
+ typedef typename node_type::value_type value_type;
+ typedef tuples::null_type ctor_args;
+ typedef typename super::final_allocator_type allocator_type;
+ typedef typename allocator_type::reference reference;
+ typedef typename allocator_type::const_reference const_reference;
 
 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
   typedef safe_mode::safe_iterator<
     bidir_node_iterator<node_type>,
     safe_ctr_proxy<
- bidir_node_iterator<node_type> > > iterator;
+ bidir_node_iterator<node_type> > > iterator;
 #else
   typedef safe_mode::safe_iterator<
     bidir_node_iterator<node_type>,
- sequenced_index> iterator;
+ sequenced_index> iterator;
 #endif
 #else
- typedef bidir_node_iterator<node_type> iterator;
+ typedef bidir_node_iterator<node_type> iterator;
 #endif
 
- typedef iterator const_iterator;
+ typedef iterator const_iterator;
 
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
- typedef typename allocator_type::pointer pointer;
- typedef typename allocator_type::const_pointer const_pointer;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef typename allocator_type::pointer pointer;
+ typedef typename allocator_type::const_pointer const_pointer;
   typedef typename
- boost::reverse_iterator<iterator> reverse_iterator;
+ boost::reverse_iterator<iterator> reverse_iterator;
   typedef typename
- boost::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef TagList tag_list;
+ boost::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef TagList tag_list;
 
 protected:
   typedef typename super::final_node_type final_node_type;
@@ -175,9 +182,7 @@
   template <class InputIterator>
   void assign(InputIterator first,InputIterator last)
   {
- BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
- clear();
- for(;first!=last;++first)push_back(*first);
+ assign_iter(first,last,mpl::not_<is_integral<InputIterator> >());
   }
 
   void assign(size_type n,value_param_type value)
@@ -204,6 +209,20 @@
   const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
   reverse_iterator rend(){return make_reverse_iterator(begin());}
   const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
+ const_iterator cbegin()const{return begin();}
+ const_iterator cend()const{return end();}
+ const_reverse_iterator crbegin()const{return rbegin();}
+ const_reverse_iterator crend()const{return rend();}
+
+ iterator iterator_to(const value_type& x)
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
+
+ const_iterator iterator_to(const value_type& x)const
+ {
+ return make_iterator(node_from_value<node_type>(&x));
+ }
 
   /* capacity */
 
@@ -216,8 +235,15 @@
     BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
     if(n>size())insert(end(),n-size(),x);
     else if(n<size()){
- iterator it=begin();
- std::advance(it,n);
+ iterator it;
+ if(n<=size()/2){
+ it=begin();
+ std::advance(it,n);
+ }
+ else{
+ it=end();
+ for(size_type m=size()-n;m--;--it){}
+ }
       erase(it,end());
     }
   }
@@ -261,8 +287,7 @@
   template<typename InputIterator>
   void insert(iterator position,InputIterator first,InputIterator last)
   {
- BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
- for(;first!=last;++first)insert(position,*first);
+ insert_iter(position,first,last,mpl::not_<is_integral<InputIterator> >());
   }
 
   iterator erase(iterator position)
@@ -320,6 +345,27 @@
       mod,static_cast<final_node_type*>(position.get_node()));
   }
 
+ template<typename Modifier,typename Rollback>
+ bool modify(iterator position,Modifier mod,Rollback back)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ /* MSVC++ 6.0 optimizer on safe mode code chokes if this
+ * this is not added. Left it for all compilers as it does no
+ * harm.
+ */
+
+ position.detach();
+#endif
+
+ return this->final_modify_(
+ mod,back,static_cast<final_node_type*>(position.get_node()));
+ }
+
   void swap(sequenced_index<SuperMeta,TagList>& x)
   {
     BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
@@ -451,7 +497,7 @@
   void reverse()
   {
     BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
- sequenced_index_node_impl::reverse(header()->impl());
+ node_impl_type::reverse(header()->impl());
   }
 
   /* rearrange operations */
@@ -627,6 +673,11 @@
     BOOST_CATCH_END
   }
 
+ bool modify_rollback_(node_type* x)
+ {
+ return super::modify_rollback_(x);
+ }
+
 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   /* serialization */
 
@@ -688,22 +739,22 @@
 
   void link(node_type* x)
   {
- sequenced_index_node_impl::link(x->impl(),header()->impl());
+ node_impl_type::link(x->impl(),header()->impl());
   };
 
   static void unlink(node_type* x)
   {
- sequenced_index_node_impl::unlink(x->impl());
+ node_impl_type::unlink(x->impl());
   }
 
   static void relink(node_type* position,node_type* x)
   {
- sequenced_index_node_impl::relink(position->impl(),x->impl());
+ node_impl_type::relink(position->impl(),x->impl());
   }
 
   static void relink(node_type* position,node_type* first,node_type* last)
   {
- sequenced_index_node_impl::relink(
+ node_impl_type::relink(
       position->impl(),first->impl(),last->impl());
   }
 
@@ -724,6 +775,38 @@
   }
 #endif
 
+ template <class InputIterator>
+ void assign_iter(InputIterator first,InputIterator last,mpl::true_)
+ {
+ BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+ clear();
+ for(;first!=last;++first)push_back(*first);
+ }
+
+ void assign_iter(size_type n,value_param_type value,mpl::false_)
+ {
+ BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+ clear();
+ for(size_type i=0;i<n;++i)push_back(value);
+ }
+
+ template<typename InputIterator>
+ void insert_iter(
+ iterator position,InputIterator first,InputIterator last,mpl::true_)
+ {
+ BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+ for(;first!=last;++first)insert(position,*first);
+ }
+
+ void insert_iter(
+ iterator position,size_type n,value_param_type x,mpl::false_)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+ for(size_type i=0;i<n;++i)insert(position,x);
+ }
+
 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
 #pragma parse_mfunc_templ reset

Modified: trunk/boost/multi_index_container.hpp
==============================================================================
--- trunk/boost/multi_index_container.hpp (original)
+++ trunk/boost/multi_index_container.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -31,7 +31,6 @@
 #include <boost/multi_index/detail/access_specifier.hpp>
 #include <boost/multi_index/detail/base_type.hpp>
 #include <boost/multi_index/detail/converter.hpp>
-#include <boost/multi_index/detail/def_ctor_tuple_cons.hpp>
 #include <boost/multi_index/detail/header_holder.hpp>
 #include <boost/multi_index/detail/has_tag.hpp>
 #include <boost/multi_index/detail/no_duplicate_tags.hpp>
@@ -72,8 +71,14 @@
         Value,IndexSpecifierList,Allocator>::type
>::type>,
   BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
- typename detail::multi_index_node_type<
- Value,IndexSpecifierList,Allocator>::type,
+ typename detail::prevent_eti<
+ Allocator,
+ typename boost::detail::allocator::rebind_to<
+ Allocator,
+ typename detail::multi_index_node_type<
+ Value,IndexSpecifierList,Allocator>::type
+ >::type
+ >::type::pointer,
     multi_index_container<Value,IndexSpecifierList,Allocator> >,
   public detail::multi_index_base_type<
     Value,IndexSpecifierList,Allocator>::type
@@ -97,13 +102,18 @@
 
   typedef typename detail::multi_index_base_type<
       Value,IndexSpecifierList,Allocator>::type super;
- typedef ::boost::base_from_member<
- typename boost::detail::allocator::rebind_to<
+ typedef typename
+ boost::detail::allocator::rebind_to<
       Allocator,
       typename super::node_type
- >::type> bfm_allocator;
+ >::type node_allocator;
+ typedef ::boost::base_from_member<
+ node_allocator> bfm_allocator;
   typedef detail::header_holder<
- typename super::node_type,
+ typename detail::prevent_eti<
+ Allocator,
+ node_allocator
+ >::type::pointer,
     multi_index_container> bfm_header;
 
 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
@@ -116,15 +126,8 @@
    * brought forward here to save us some typename's.
    */
 
-#if defined(BOOST_MSVC)
- typedef
- detail::default_constructible_tuple_cons<
- typename super::ctor_args_list> ctor_args_list;
-#else
- typedef typename super::ctor_args_list ctor_args_list;
-#endif
-
- typedef IndexSpecifierList index_specifier_type_list;
+ typedef typename super::ctor_args_list ctor_args_list;
+ typedef IndexSpecifierList index_specifier_type_list;
  
 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
   /* MSVC++ 6.0 chokes on moderately long index lists (around 6 indices
@@ -430,17 +433,18 @@
 
   node_type* header()const
   {
- return bfm_header::member;
+ return &*bfm_header::member;
   }
 
   node_type* allocate_node()
   {
- return bfm_allocator::member.allocate(1);
+ return &*bfm_allocator::member.allocate(1);
   }
 
   void deallocate_node(node_type* x)
   {
- bfm_allocator::member.deallocate(x,1);
+ typedef typename node_allocator::pointer node_pointer;
+ bfm_allocator::member.deallocate(static_cast<node_pointer>(x),1);
   }
 
   bool empty_()const
@@ -527,6 +531,16 @@
 
   void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
   {
+ if(bfm_allocator::member!=x.bfm_allocator::member){
+
+#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)
+ std::swap(bfm_allocator::member,x.bfm_allocator::member);
+#else
+ using std::swap;
+ swap(bfm_allocator::member,x.bfm_allocator::member);
+#endif
+
+ }
     std::swap(bfm_header::member,x.bfm_header::member);
     super::swap_(x);
     std::swap(node_count,x.node_count);
@@ -538,7 +552,7 @@
   }
 
   template<typename Modifier>
- bool modify_(Modifier mod,node_type* x)
+ bool modify_(Modifier& mod,node_type* x)
   {
     mod(const_cast<value_type&>(x->value()));
 
@@ -558,6 +572,42 @@
     BOOST_CATCH_END
   }
 
+ template<typename Modifier,typename Rollback>
+ bool modify_(Modifier& mod,Rollback& back,node_type* x)
+ {
+ mod(const_cast<value_type&>(x->value()));
+
+ bool b;
+ BOOST_TRY{
+ b=super::modify_rollback_(x);
+ }
+ BOOST_CATCH(...){
+ BOOST_TRY{
+ back(const_cast<value_type&>(x->value()));
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH(...){
+ this->erase_(x);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+ BOOST_CATCH_END
+
+ BOOST_TRY{
+ if(!b){
+ back(const_cast<value_type&>(x->value()));
+ return false;
+ }
+ else return true;
+ }
+ BOOST_CATCH(...){
+ this->erase_(x);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+
 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
   /* serialization */
 

Modified: trunk/libs/multi_index/doc/acknowledgements.html
==============================================================================
--- trunk/libs/multi_index/doc/acknowledgements.html (original)
+++ trunk/libs/multi_index/doc/acknowledgements.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -148,6 +148,18 @@
 <br style="clear:all;">
 </p>
 
+<h2><a name="boost_1_35">Boost 1.35 release</a></h2>
+
+<p>
+global_fun
+was included after a proposal by Markus Werle. Bruno Mart&iacute;nez Aguerre
+suggested the inclusion of
+iterator_to. The
+rollback versions of <code>modify</code> and <code>modify_key</code> arose
+from discussions with Mat&iacute;as Capeletto. Steven Watanabe spotted an
+include guard bug present from the first release of the library.
+</p>
+
 <hr>
 
 <div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
@@ -161,9 +173,9 @@
 
 <br>
 
-<p>Revised December 21st 2006</p>
+<p>Revised September 3rd 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/examples.html
==============================================================================
--- trunk/libs/multi_index/doc/examples.html (original)
+++ trunk/libs/multi_index/doc/examples.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -31,7 +31,7 @@
 
 <ul>
   <li>Example 1: basic usage</li>
- <li>Example 2: using member functions as keys</li>
+ <li>Example 2: using functions as keys</li>
   <li><a href="#example3">Example 3: constructing <code>multi_index_container</code>s
     with <code>ctor_args_list</code></a></li>
   <li>Example 4: bidirectional map</li>
@@ -42,6 +42,7 @@
   <li>Example 9: serialization and MRU lists</li>
   <li>Example 10: random access indices</li>
   <li>Example 11: index rearrangement</li>
+ <li>Example 12: using Boost.Interprocess allocators</li>
 </ul>
 
 <h2><a name="example1">Example 1: basic usage</a></h2>
@@ -55,23 +56,23 @@
 with an admittedly boring set of <code>employee</code> records.
 </p>
 
-<h2><a name="example2">Example 2: using member functions as keys</a></h2>
+<h2><a name="example2">Example 2: using functions as keys</a></h2>
 
 <p>
-See source code.
+See source code.
 </p>
 
 <p>
 Usually keys assigned to an index are based on a member variable of the
 element, but key extractors can be defined which take their value from
-a member function. This has some similarity with the concept of
+a member function or a global function. This has some similarity with the concept of
 <i>calculated keys</i> supported by some relational database engines.
 The example shows how to use the predefined <code>const_mem_fun</code>
-key extractor to deal with this situation.
+and <code>global_fun</code> key extractors to deal with this situation.
 </p>
 
 <p>
-Keys based on member functions usually will not be actual references,
+Keys based on functions usually will not be actual references,
 but rather the temporary values resulting from the invocation of the
 member function used. This implies that <code>modify_key</code> cannot be
 applied to this type of extractors, which is a perfectly logical
@@ -111,6 +112,12 @@
 dictionary with online query of words in both languages.
 </p>
 
+<p>
+This bidirectional map can be considered as a primitive precursor
+to the full-fledged container provided by
+Boost.Bimap.
+</p>
+
 <h2><a name="example5">Example 5: sequenced indices</a></h2>
 
 <p>
@@ -412,6 +419,23 @@
 auxiliary data structure.
 </p>
 
+<h2><a name="example12">Example 12: using Boost.Interprocess allocators</a></h2>
+
+<p>
+See source code.
+</p>
+
+<p>
+Boost.MultiIndex supports special allocators such as those provided by
+Boost.Interprocess,
+which allows for <code>multi_index_container</code>s to be placed in shared
+memory. The example features a front-end to a small book database
+implemented by means of a <code>multi_index_container</code> stored
+in a Boost.Interprocess memory mapped file. The reader can verify that several
+instances of the program correctly work simultaneously and immediately see
+the changes to the database performed by any other instance.
+</p>
+
 <hr>
 
 <div class="prev_link"><a href="performance.html"><img src="prev.gif" alt="performance" border="0"><br>
@@ -426,9 +450,9 @@
 
 <br>
 
-<p>Revised March 3rd 2006</p>
+<p>Revised July 16th 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/future_work.html
==============================================================================
--- trunk/libs/multi_index/doc/future_work.html (original)
+++ trunk/libs/multi_index/doc/future_work.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -41,7 +41,6 @@
   <li>Notifying indices</li>
   <li>Constraints</li>
   <li>User-defined indices</li>
- <li>Bidirectional map</li>
   <li>Indexed maps</li>
   <li>Move semantics</li>
 </ul>
@@ -150,19 +149,6 @@
 user can write implementations for her own indices.
 </p>
 
-<h2><a name="bimap">Bidirectional map</a></h2>
-
-<p>
-Example 4 in the examples section
-features a <i>bidirectional map</i>, implemented as a
-<code>multi_index_container</code> with two unique ordered indices. This particular
-structure is deemed important enough as to provide it as a separate
-class template, relying internally in <code>multi_index_container</code>. As
-feedback is collected from the users of Boost.MultiIndex, other singular
-instantiations of <code>multi_index_container</code> might be encapsulated
-to form a component library of ready to use containers.
-</p>
-
 <h2><a name="indexed_maps">Indexed maps</a></h2>
 
 <p>
@@ -240,9 +226,9 @@
 
 <br>
 
-<p>Revised February 6th 2006</p>
+<p>Revised July 5th 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/reference/hash_indices.html
==============================================================================
--- trunk/libs/multi_index/doc/reference/hash_indices.html (original)
+++ trunk/libs/multi_index/doc/reference/hash_indices.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -44,9 +44,11 @@
           <li>Instantiation types</li>
           <li>Nested types</li>
           <li>Constructors, copy and assignment</li>
+ <li>Iterators</li>
           <li>Modifiers</li>
           <li>Observers</li>
           <li>Lookup</li>
+ <li>Bucket interface</li>
           <li>Hash policy</li>
           <li>Serialization</li>
         </ul>
@@ -248,7 +250,12 @@
   <span class=identifier>const_iterator</span> <span class=identifier>begin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
   <span class=identifier>iterator</span> <span class=identifier>end</span><span class=special>();</span>
   <span class=identifier>const_iterator</span> <span class=identifier>end</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
  
+ <span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+
   <span class=comment>// modifiers:</span>
 
   <span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
@@ -262,7 +269,11 @@
 
   <span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
   <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
+ <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
+ <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
   <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
+ <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
+ <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
   
   <span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
   <span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
@@ -313,6 +324,11 @@
   <span class=identifier>const_local_iterator</span> <span class=identifier>begin</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
   <span class=identifier>local_iterator</span> <span class=identifier>end</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>);</span>
   <span class=identifier>const_local_iterator</span> <span class=identifier>end</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_local_iterator</span> <span class=identifier>cbegin</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_local_iterator</span> <span class=identifier>cend</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+
+ <span class=identifier>local_iterator</span> <span class=identifier>local_iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
+ <span class=identifier>const_local_iterator</span> <span class=identifier>local_iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
 
   <span class=comment>// hash policy:</span>
 
@@ -434,6 +450,18 @@
 <b>Returns:</b> <code>*this</code>.<br>
 </blockquote>
 
+<h4><a name="iterators">Iterators</a></h4>
+
+<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);</br>
+const_iterator iterator_to(const value_type&amp; x)const;</code>
+
+<blockquote>
+<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
+<b>Returns:</b> An iterator to <code>x</code>.<br>
+<b>Complexity:</b> Constant.<br>
+<b>Exception safety:</b> <code>nothrow</code>.<br>
+</blockquote>
+
 <h4><a name="modifiers">Modifiers</a></h4>
 
 <code>std::pair&lt;iterator,bool> insert(const value_type&amp; x);</code>
@@ -589,37 +617,77 @@
 the element pointed to by <code>position</code> is erased.
 </blockquote>
 
-<a name="modify_key">
-<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
+<code>template&lt;typename Modifier,typename Rollback><br>
+bool modify(iterator position,Modifier mod,Rollback back);</code>
 
 <blockquote>
-<b>Requires:</b> <code>key_from_value</code> is a read/write
-Key Extractor
-from <code>value_type</code>. <code>Modifier</code> is a model of
+<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
 <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
 <code>Unary Function</code></a> accepting arguments of type
-<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
-iterator of the index.</br>
-<b>Effects:</b> Calls <code>mod(k)</code> where <code>k</code> is the key
-obtained by the internal <code>KeyFromValue</code> object of the index from
-the element pointed to by <code>position</code>, and rearranges
-<code>*position</code> into all the indices of the <code>multi_index_container</code>.
-Rearrangement is successful if
+<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
+iterator of the index. The sequence of operations <code>mod(e)</code>,
+<code>back(e)</code>, where <code>e</code> is the element
+pointed to by <code>position</code>, restores all keys of the element
+to their original state.</br>
+<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
+pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
+all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
 <ul>
   <li>the index is non-unique OR no other element exists
     with equivalent key,</li>
   <li>AND rearrangement is allowed by all other indices of the
     <code>multi_index_container</code>.</li>
 </ul>
-If the rearrangement fails, the element is erased.<br>
-<b>Postconditions:</b>Validity of <code>position</code> is preserved if
-the operation succeeds.<br>
+If the rearrangement fails, <code>back(e)</code> is invoked and the
+element is kept at its original position in all indices.<br>
+<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
+the element is erased under the conditions described below.<br>
 <b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
 otherwise.<br>
 <b>Complexity:</b> <code>O(M(n))</code>.<br>
-<b>Exception safety:</b> Basic. If an exception is thrown by some
-user-provided operation (except possibly <code>mod</code>), then
-the element pointed to by <code>position</code> is erased.
+<b>Exception safety:</b> Strong, except if <code>back</code> throws an
+exception, in which case the modified element is erased. If <code>back</code>
+throws inside the handling code executing after some other user-provided
+operation has thrown, it is the exception generated by <code>back</code> that
+is rethrown.
+</blockquote>
+
+<a name="modify_key">
+<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
+
+<blockquote>
+<b>Requires:</b> <code>key_from_value</code> is a read/write
+Key Extractor
+from <code>value_type</code>. <code>Modifier</code> is a model of
+<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
+<code>Unary Function</code></a> accepting arguments of type
+<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
+iterator of the index.</br>
+<b>Effects:</b> Equivalent to <code>modify(position,mod')</code>,
+with <code>mod'</code> defined in such a way that
+<code>mod'(x)</code> is the same as <code>mod(key(x))</code>, where
+<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
+</blockquote>
+
+<code>template&lt;typename Modifier,typename Rollback><br>
+bool modify_key(iterator position,Modifier mod,Rollback back);</code>
+
+<blockquote>
+<b>Requires:</b> <code>key_from_value</code> is a read/write
+Key Extractor
+from <code>value_type</code>. <code>Modifier</code> and <code>Rollback</code>
+are models of <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
+<code>Unary Function</code></a> accepting arguments of type
+<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
+iterator of the index.
+The sequence of operations <code>mod(k)</code>,
+<code>back(k)</code>, where <code>k</code> is the key of the element
+pointed to by <code>position</code>, restores k to its original state.</br>
+<b>Effects:</b> Equivalent to <code>modify(position,mod',back')</code>,
+with <code>mod'</code> and <code>back</code> defined in such a way that
+<code>mod'(x)</code> is the same as <code>mod(key(x))</code> and
+<code>back'(x)</code> is the same as <code>back(key(x))</code>, where
+<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
 </blockquote>
 
 <h4><a name="observers">Observers</a></h4>
@@ -768,7 +836,8 @@
 <b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
 (<code>hasher</code>, <code>key_equal</code>).</br>
 <b>Effects:</b> Returns a range containing all elements with keys equivalent
-to <code>x</code> (and only those).<br>
+to <code>x</code> (and only those), or (<code>end()</code>,<code>end()</code>)
+if no such elements exist.<br>
 <b>Complexity:</b> Average case <code>O(count(x))</code>, worst case
 <code>O(n)</code>.<br>
 </blockquote>
@@ -786,11 +855,24 @@
 <code>CompatiblePred</code>) is a compatible extension of
 (<code>hasher</code>, <code>key_equal</code>).</br>
 <b>Effects:</b> Returns a range containing all elements with keys equivalent
-to <code>x</code> (and only those).<br>
+to <code>x</code> (and only those), or (<code>end()</code>,<code>end()</code>)
+if no such elements exist.<br>
 <b>Complexity:</b> Average case <code>O(count(x,hash,eq))</code>, worst case
 <code>O(n)</code>.<br>
 </blockquote>
 
+<h4><a name="bucket_interface">Bucket interface</a></h4>
+
+<code>local_iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local_iterator_to(const value_type&amp; x);</br>
+const_local_iterator local_iterator_to(const value_type&amp; x)const;</code>
+
+<blockquote>
+<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
+<b>Returns:</b> An iterator to <code>x</code>.<br>
+<b>Complexity:</b> Constant.<br>
+<b>Exception safety:</b> <code>nothrow</code>.<br>
+</blockquote>
+
 
 <h4><a name="hash_policy">Hash policy</a></h4>
 
@@ -895,9 +977,9 @@
 
 <br>
 
-<p>Revised July 13th 2006</p>
+<p>Revised July 2nd 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/reference/index.html
==============================================================================
--- trunk/libs/multi_index/doc/reference/index.html (original)
+++ trunk/libs/multi_index/doc/reference/index.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -88,7 +88,9 @@
       <li><a href="key_extraction.html#member_synopsis">
         <code>"boost/multi_index/member.hpp"</code></a>,</li>
           <li><a href="key_extraction.html#mem_fun_synopsis">
- <code>"boost/multi_index/mem_fun.hpp"</code></a> and</li>
+ <code>"boost/multi_index/mem_fun.hpp"</code></a>,</li>
+ <li><a href="key_extraction.html#global_fun_synopsis">
+ <code>"boost/multi_index/global_fun.hpp"</code></a> and</li>
           <li><a href="key_extraction.html#composite_key_synopsis">
         <code>"boost/multi_index/composite_key.hpp"</code></a>.</li>
     </ul>
@@ -125,9 +127,9 @@
 
 <br>
 
-<p>Revised February 6th 2005</p>
+<p>Revised June 19th 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/reference/key_extraction.html
==============================================================================
--- trunk/libs/multi_index/doc/reference/key_extraction.html (original)
+++ trunk/libs/multi_index/doc/reference/key_extraction.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -63,6 +63,12 @@
       <li>Macro BOOST_MULTI_INDEX_MEM_FUN</li>
     </ul>
   </li>
+ <li><a href="#global_fun_synopsis">Header
+ <code>"boost/multi_index/global_fun.hpp"</code> synopsis</a>
+ <ul>
+ <li>Class template global_fun</li>
+ </ul>
+ </li>
   <li><a href="#composite_key_synopsis">Header
     <code>"boost/multi_index/composite_key.hpp"</code> synopsis</a>
     <ul>
@@ -131,12 +137,13 @@
 </p>
 
 <p>
-Boost.MultiIndex provides five general-purpose key extractors:
+Boost.MultiIndex provides six general-purpose key extractors:
 <ul>
   <li>identity,</li>
   <li>member,</li>
   <li>const_mem_fun,</li>
- <li>mem_fun and</li>
+ <li>mem_fun,</li>
+ <li>global_fun and</li>
   <li>composite_key,</li>
 </ul>
 plus replacements for some of them:
@@ -178,6 +185,7 @@
 <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
 <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
 <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>mem_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
+<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>global_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
 <span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>composite_key</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
 </pre></blockquote>
 
@@ -770,6 +778,147 @@
 </p>
 
 <h2>
+<a name="global_fun_synopsis">Header
+<a href="../../../../boost/multi_index/global_fun.hpp">
+<code>"boost/multi_index/global_fun.hpp"</code></a> synopsis</a></h2>
+
+<blockquote><pre>
+<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
+
+<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
+
+<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(*</span><span class=identifier>PtrToFunction</span><span class=special>)(</span><span class=identifier>Value</span><span class=special>)&gt;</span>
+<span class=keyword>struct</span> <span class=identifier>global_fun</span><span class=special>;</span>
+
+<span class=special>}</span> <span class=comment>// namespace boost::multi_index</span>
+
+<span class=special>}</span> <span class=comment>// namespace boost</span>
+</pre></blockquote>
+
+<h3><a name="global_fun">Class template <code>global_fun</code></a></h3>
+
+<p>
+<code>global_fun</code> is a Key Extractor
+based on a given global or static member function accepting the base type as argument
+and returning the associated key.
+</p>
+
+<blockquote><pre>
+<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(*</span><span class=identifier>PtrToFunction</span><span class=special>)(</span><span class=identifier>Value</span><span class=special>)&gt;</span>
+<span class=keyword>struct</span> <span class=identifier>global_fun</span>
+<span class=special>{</span>
+ <span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Type</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
+
+ <span class=comment>// Only provided under the following circumstances:
+ // - If Value is a reference to a constant type, only provided
+ // when const ChainedPtr&amp; is not convertible to Value;
+ // - if Value is a reference to a non-const type, only provided
+ // when ChainedPtr&amp; is not convertible to Value;
+ // - else, only provided when const ChainedPtr&amp; is not
+ // convertible to const Value&amp;.</span>
+ <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+
+ <span class=comment>// only provided if Value is a reference type</span>
+ <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Value</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+
+ <span class=comment>// only provided if Value is not a reference type</span>
+ <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+
+ <span class=comment>// only provided if Value is not a reference type</span>
+ <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+
+ <span class=comment>// only provided if Value is a reference type</span>
+ <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span>
+ <span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span>
+ <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+
+ <span class=comment>// only provided if Value is not a reference type or is
+ // a reference to a constant type</span>
+ <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span>
+ <span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span>
+ <span class=keyword>typename</span> <span class=identifier>remove_const</span><span class=special>&lt;</span>
+ <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+<span class=special>};</span>
+</pre></blockquote>
+
+<p>
+<code>PtrToFunction</code> specifies the particular function used to extract
+the key of type <code>Type</code> from some <code>BaseType</code>.
+<code>global_fun</code> supports the following function signatures:
+<ul>
+ <li><code>Type f(BaseType)</code> (<code>Value</code> is <code>BaseType</code>),</li>
+ <li><code>Type f(const BaseType&amp;)</code> (<code>Value</code> is <code>const BaseType&amp;</code>),</li>
+ <li><code>Type f(BaseType&amp;)</code> (<code>Value</code> is <code>BaseType&amp;</code>).</li>
+</ul>
+<code>global_fun&lt;Type,Value,PtrToFunction&gt;</code> is a model of:
+<ul>
+ <li>Key Extractor
+ from <code>reference_wrapper&lt;BaseType></code>,</li>
+ <li>Key Extractor
+ from any chained pointer
+ to <code>BaseType</code>.</li>
+</ul>
+When <code>Value</code> is <code>BaseType</code> or
+<code>const BaseType&amp;</code>,
+<code>global_fun&lt;Type,Value,PtrToFunction&gt;</code> is also a model of:
+<ul>
+ <li>Key Extractor
+ from <code>BaseType</code>,</li>
+ <li>Key Extractor
+ from <code>reference_wrapper&lt;const BaseType></code>,</li>
+ <li>Key Extractor
+ from any chained pointer
+ to <code>const BaseType</code>.</li>
+</ul>
+</p>
+
+<h4><code>global_fun</code> members</h4>
+
+<code>template&lt;typename ChainedPtr> Type operator()(const ChainedPtr&amp; x)const;</code>
+
+<blockquote>
+<b>Requires:</b> <code>ChainedPtr</code> is a chained pointer
+type to <code>Value</code>.<br>
+<b>Returns:</b> <code>PtrToFunction)(y)</code>, where <code>y</code> is the
+object chained-pointed to by <code>x</code>.
+</blockquote>
+
+<code>Type operator()(Value x)const;</code>
+
+<blockquote>
+<b>Returns:</b> <code>PtrToFunction(x)</code>.
+</blockquote>
+
+<code>Type operator()(const Value&amp; x)const;</code>
+
+<blockquote>
+<b>Returns:</b> <code>PtrToFunction(x)</code>.
+</blockquote>
+
+<code>Type operator()(const reference_wrapper&lt;const Value&gt;&amp; x)const;</code>
+
+<blockquote>
+<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
+</blockquote>
+
+<code>
+Type operator()(<br>
+&nbsp;&nbsp;const reference_wrapper&lt;remove_reference&lt;Value&gt;::type&gt;&amp; x)const;</code>
+
+<blockquote>
+<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
+</blockquote>
+
+<code>Type operator()(<br>
+&nbsp;&nbsp;const reference_wrapper&lt;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;typename remove_const&lt;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename remove_reference&lt;Value&gt;::type&gt;::type&gt;&amp; x)const;</code>
+
+<blockquote>
+<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
+</blockquote>
+
+<h2>
 <a name="composite_key_synopsis">Header
 <a href="../../../../boost/multi_index/composite_key.hpp">
 <code>"boost/multi_index/composite_key.hpp"</code></a> synopsis</a></h2>
@@ -787,7 +936,7 @@
   
 <span class=comment>// comparison operators for composite_key_result:</span>
 
-<span class=comment>// <b>OP</b> is any of =,&lt;,!=,&gt;,&gt;=,&lt;=</span>
+<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
 
 <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey2</span><span class=special>&gt;</span>
 <span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
@@ -1005,7 +1154,7 @@
 
 <span class=comment>// comparison:</span>
   
-<span class=comment>// <b>OP</b> is any of =,&lt;,!=,&gt;,&gt;=,&lt;=</span>
+<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
 
 <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey2</span><span class=special>&gt;</span>
 <span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
@@ -2072,9 +2221,22 @@
 <code>composite_key_result&lt;composite_key&lt;K0,...,Kk> ></code>, with
 <code>Ki::result_type = Qi</code> for all <code>i = 0,...,k</code>.
 </blockquote>
-provided that each <code>Qi</code> is either <code>Ti</code> or a
-Compatible Key
-of <code>Comparei</code>. In this case, the comparison is done
+provided that
+<ul>
+ <li>for <code>i = 0,...,min(j,k)-1</code>, <code>Qi</code> is either <code>Ti</code>
+ or <i>not coarser</i> than <code>Ti</code> (<code>Qi</code> is a
+ Compatible Key
+ of <code>Comparei</code> and there are no two distinct elements of
+ <code>Ti</code> equivalent to one single element of <code>Qi</code>);
+ </li>
+ <li>
+ <code>Qm</code> (with <code>m = min(j,k)</code>) is either <code>Tm</code> or a
+ Compatible Key
+ of <code>Comparem</code>.
+ </li>
+</ul>
+
+In this case, the comparison is done
 lexicographically only on the first <code>1+min(j,k)</code> elements.
 </p>
 
@@ -2101,9 +2263,9 @@
 
 <br>
 
-<p>Revised July 13th 2006</p>
+<p>Revised August 2nd 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/reference/multi_index_container.html
==============================================================================
--- trunk/libs/multi_index/doc/reference/multi_index_container.html (original)
+++ trunk/libs/multi_index/doc/reference/multi_index_container.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -493,7 +493,8 @@
 <ol>
   <li><code>Value</code> is the
     <a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
- type of the elements contained.</li>
+ type of the elements contained.
+ </li>
   <li><code>IndexSpecifierList</code> specifies the indices that the
     <code>multi_index_container</code> is composed of. It must be a non-empty
     <a href="../../../../libs/mpl/doc/refmanual/forward-sequence.html">
@@ -503,8 +504,27 @@
     syntactic convenience, the
     <a href="indices.html#indexed_by"><code>indexed_by</code></a>
     MPL sequence can be used.
- <li><code>Allocator</code> must comply with the C++ requirements for
- allocators <b>[lib.allocator.requirements]</b>.
+ </li>
+ <li><code>Allocator</code> must be an allocator of <code>Value</code> objects
+ satisfying the associated C++ requirements at <b>[lib.allocator.requirements]</b>.
+ The following relaxations to the standard requirements are allowed:
+ <ul>
+ <li>Non-equal allocator instances are supported: swapping two non-equal
+ instances must not throw any exception.
+ </li>
+ <li>For every type <code>T</code>,
+ the type <code>Allocator::rebind&lt;T&gt;::other::pointer</code> can be any
+ kind of
+ <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"><code>Random
+ Access Iterator</code></a>, provided that it is explicitly constructible from
+ the literal <code>0</code> (standing here as the null pointer) or from any
+ <code>p</code> of type <code>T*</code> pointing into an area allocated by
+ some instance of <code>Allocator</code> or some other allocator type rebound
+ from <code>Allocator</code>. A <code>pointer</code> constructed from
+ <code>p</code> shall dereference to <code>*p</code>.
+ </li>
+ </ul>
+ </li>
 </ol>
 Indices of a given <code>multi_index_container</code> instantiation cannot have
 duplicate tags, either within a single
@@ -882,9 +902,9 @@
 
 <br>
 
-<p>Revised February 6th 2006</p>
+<p>Revised July 17th 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/reference/ord_indices.html
==============================================================================
--- trunk/libs/multi_index/doc/reference/ord_indices.html (original)
+++ trunk/libs/multi_index/doc/reference/ord_indices.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -43,6 +43,7 @@
           <li>Complexity signature</li>
           <li>Instantiation types</li>
           <li>Constructors, copy and assignment</li>
+ <li>Iterators</li>
           <li>Modifiers</li>
           <li>Observers</li>
           <li>Set operations</li>
@@ -205,7 +206,7 @@
 
 <span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
 
-<span class=keyword>namespace</span><span class=special>{</span> <b>implementation defined </b><span class=identifier>unbounded</span><span class=special>;</span> <span class=special>}</span> <span class=comment>// see range()</span>
+<b>implementation defined </b><span class=identifier>unbounded</span><span class=special>;</span> <span class=comment>// see range()</span>
 
 <span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
 
@@ -252,7 +253,14 @@
   <span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
   <span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
   <span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
  
+ <span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
+
   <span class=comment>// capacity:</span>
 
   <span class=keyword>bool</span> <span class=identifier>empty</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
@@ -272,7 +280,11 @@
 
   <span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
   <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
+ <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
+ <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
   <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
+ <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
+ <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
   
   <span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
   <span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
@@ -395,7 +407,7 @@
   <li>copying: <code>c(n)=n*log(n)</code>,</li>
   <li>insertion: <code>i(n)=log(n)</code>,</li>
   <li>hinted insertion: <code>h(n)=1</code> (constant) if the hint element
- precedes the point of insertion, <code>h(n)=log(n)</code> otherwise,</li>
+ is immediately after the point of insertion, <code>h(n)=log(n)</code> otherwise,</li>
   <li>deletion: <code>d(n)=1</code> (amortized constant),</li>
   <li>replacement: <code>r(n)=1</code> (constant) if the element position does not
     change, <code>r(n)=log(n)</code> otherwise,</li>
@@ -448,6 +460,18 @@
 <b>Returns:</b> <code>*this</code>.<br>
 </blockquote>
 
+<h4><a name="iterators">Iterators</a></h4>
+
+<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);</br>
+const_iterator iterator_to(const value_type&amp; x)const;</code>
+
+<blockquote>
+<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
+<b>Returns:</b> An iterator to <code>x</code>.<br>
+<b>Complexity:</b> Constant.<br>
+<b>Exception safety:</b> <code>nothrow</code>.<br>
+</blockquote>
+
 <h4><a name="modifiers">Modifiers</a></h4>
 
 <code>std::pair&lt;iterator,bool> insert(const value_type&amp; x);</code>
@@ -602,37 +626,77 @@
 the element pointed to by <code>position</code> is erased.
 </blockquote>
 
-<a name="modify_key">
-<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
+<code>template&lt;typename Modifier,typename Rollback><br>
+bool modify(iterator position,Modifier mod,Rollback back);</code>
 
 <blockquote>
-<b>Requires:</b> <code>key_from_value</code> is a read/write
-Key Extractor
-from <code>value_type</code>. <code>Modifier</code> is a model of
+<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
 <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
 <code>Unary Function</code></a> accepting arguments of type
-<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
-iterator of the index.</br>
-<b>Effects:</b> Calls <code>mod(k)</code> where <code>k</code> is the key
-obtained by the internal <code>KeyFromValue</code> object of the index from
-the element pointed to by <code>position</code>, and rearranges
-<code>*position</code> into all the indices of the <code>multi_index_container</code>.
-Rearrangement is successful if
+<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
+iterator of the index. The sequence of operations <code>mod(e)</code>,
+<code>back(e)</code>, where <code>e</code> is the element
+pointed to by <code>position</code>, restores all keys of the element
+to their original state.</br>
+<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
+pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
+all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
 <ul>
   <li>the index is non-unique OR no other element exists
     with equivalent key,</li>
   <li>AND rearrangement is allowed by all other indices of the
     <code>multi_index_container</code>.</li>
 </ul>
-If the rearrangement fails, the element is erased.<br>
-<b>Postconditions:</b>Validity of <code>position</code> is preserved if
-the operation succeeds.<br>
+If the rearrangement fails, <code>back(e)</code> is invoked and the
+element is kept at its original position in all indices.<br>
+<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
+the element is erased under the conditions described below.<br>
 <b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
 otherwise.<br>
 <b>Complexity:</b> <code>O(M(n))</code>.<br>
-<b>Exception safety:</b> Basic. If an exception is thrown by some
-user-provided operation (except possibly <code>mod</code>), then
-the element pointed to by <code>position</code> is erased.
+<b>Exception safety:</b> Strong, except if <code>back</code> throws an
+exception, in which case the modified element is erased. If <code>back</code>
+throws inside the handling code executing after some other user-provided
+operation has thrown, it is the exception generated by <code>back</code> that
+is rethrown.
+</blockquote>
+
+<a name="modify_key">
+<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
+
+<blockquote>
+<b>Requires:</b> <code>key_from_value</code> is a read/write
+Key Extractor
+from <code>value_type</code>. <code>Modifier</code> is a model of
+<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
+<code>Unary Function</code></a> accepting arguments of type
+<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
+iterator of the index.</br>
+<b>Effects:</b> Equivalent to <code>modify(position,mod')</code>,
+with <code>mod'</code> defined in such a way that
+<code>mod'(x)</code> is the same as <code>mod(key(x))</code>, where
+<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
+</blockquote>
+
+<code>template&lt;typename Modifier,typename Rollback><br>
+bool modify_key(iterator position,Modifier mod,Rollback back);</code>
+
+<blockquote>
+<b>Requires:</b> <code>key_from_value</code> is a read/write
+Key Extractor
+from <code>value_type</code>. <code>Modifier</code> and <code>Rollback</code>
+are models of <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
+<code>Unary Function</code></a> accepting arguments of type
+<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
+iterator of the index.
+The sequence of operations <code>mod(k)</code>,
+<code>back(k)</code>, where <code>k</code> is the key of the element
+pointed to by <code>position</code>, restores k to its original state.</br>
+<b>Effects:</b> Equivalent to <code>modify(position,mod',back')</code>,
+with <code>mod'</code> and <code>back</code> defined in such a way that
+<code>mod'(x)</code> is the same as <code>mod(key(x))</code> and
+<code>back'(x)</code> is the same as <code>back(key(x))</code>, where
+<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
 </blockquote>
 
 <h4><a name="observers">Observers</a></h4>
@@ -954,9 +1018,9 @@
 
 <br>
 
-<p>Revised March 31st 2006</p>
+<p>Revised July 2nd 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/reference/rnd_indices.html
==============================================================================
--- trunk/libs/multi_index/doc/reference/rnd_indices.html (original)
+++ trunk/libs/multi_index/doc/reference/rnd_indices.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -41,6 +41,7 @@
           <li>Complexity signature</li>
           <li>Instantiation types</li>
           <li>Constructors, copy and assignment</li>
+ <li>Iterators</li>
           <li>Capacity operations</li>
           <li>Modifiers</li>
           <li>List operations</li>
@@ -238,6 +239,13 @@
   <span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
   <span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
   <span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+
+ <span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
 
   <span class=comment>// capacity:</span>
 
@@ -273,6 +281,8 @@
 
   <span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
   <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
+ <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
+ <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
 
   <span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
 
@@ -396,7 +406,7 @@
 
 <p>
 (<code>shl</code> and <code>rel</code> stand for <i>shift left</i> and
-<i>relocate</i>, respetively.)
+<i>relocate</i>, respectively.)
 </p>
 
 <h4><a name="instantiation_types">Instantiation types</a></h4>
@@ -462,6 +472,18 @@
 </pre></blockquote>
 </blockquote>
 
+<h4><a name="iterators">Iterators</a></h4>
+
+<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);</br>
+const_iterator iterator_to(const value_type&amp; x)const;</code>
+
+<blockquote>
+<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
+<b>Returns:</b> An iterator to <code>x</code>.<br>
+<b>Complexity:</b> Constant.<br>
+<b>Exception safety:</b> <code>nothrow</code>.<br>
+</blockquote>
+
 <h4><a name="capacity">Capacity operations</a></h4>
 
 <a name="capacity_memfun"><code>size_type capacity()const;</code></a>
@@ -634,8 +656,8 @@
 <b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
 pointed to by <code>position</code> and rearranges <code>*position</code> into
 all the indices of the <code>multi_index_container</code>. Rearrangement on
-rancom access indices does not change the position of the element with respect
-to the index; rearrangement on other indices may or might not suceed. If the
+random access indices does not change the position of the element with respect
+to the index; rearrangement on other indices may or might not succeed. If the
 rearrangement fails, the element is erased.<br>
 <b>Postconditions:</b> Validity of <code>position</code> is preserved if the
 operation succeeds.<br>
@@ -647,6 +669,37 @@
 the element pointed to by <code>position</code> is erased.
 </blockquote>
 
+<code>template&lt;typename Modifier,typename Rollback><br>
+bool modify(iterator position,Modifier mod,Rollback back);</code>
+
+<blockquote>
+<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
+<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
+<code>Unary Function</code></a> accepting arguments of type
+<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
+iterator of the index. The sequence of operations <code>mod(e)</code>,
+<code>back(e)</code>, where <code>e</code> is the element
+pointed to by <code>position</code>, restores all keys of the element
+to their original state.</br>
+<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
+pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
+all the indices of the <code>multi_index_container</code>. Rearrangement on
+random access indices does not change the position of the element with respect
+to the index; rearrangement on other indices may or might not succeed. If the
+rearrangement fails, <code>back(e)</code> is invoked and the
+element is kept at its original position in all indices.<br>
+<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
+the element is erased under the conditions described below.<br>
+<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
+otherwise.<br>
+<b>Complexity:</b> <code>O(M(n))</code>.<br>
+<b>Exception safety:</b> Strong, except if <code>back</code> throws an
+exception, in which case the modified element is erased. If <code>back</code>
+throws inside the handling code executing after some other user-provided
+operation has thrown, it is the exception generated by <code>back</code> that
+is rethrown.
+</blockquote>
+
 <h4><a name="list_operations">List operations</a></h4>
 
 <p>
@@ -946,9 +999,9 @@
 
 <br>
 
-<p>Revised February 6th 2006</p>
+<p>Revised July 2nd 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/reference/seq_indices.html
==============================================================================
--- trunk/libs/multi_index/doc/reference/seq_indices.html (original)
+++ trunk/libs/multi_index/doc/reference/seq_indices.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -41,6 +41,7 @@
           <li>Complexity signature</li>
           <li>Instantiation types</li>
           <li>Constructors, copy and assignment</li>
+ <li>Iterators</li>
           <li>Capacity operations</li>
           <li>Modifiers</li>
           <li>List operations</li>
@@ -229,6 +230,13 @@
   <span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
   <span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
   <span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+
+ <span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
+ <span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
 
   <span class=comment>// capacity:</span>
 
@@ -260,6 +268,8 @@
 
   <span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
   <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
+ <span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
+ <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
 
   <span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
 
@@ -436,6 +446,18 @@
 </pre></blockquote>
 </blockquote>
 
+<h4><a name="iterators">Iterators</a></h4>
+
+<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);</br>
+const_iterator iterator_to(const value_type&amp; x)const;</code>
+
+<blockquote>
+<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
+<b>Returns:</b> An iterator to <code>x</code>.<br>
+<b>Complexity:</b> Constant.<br>
+<b>Exception safety:</b> <code>nothrow</code>.<br>
+</blockquote>
+
 <h4><a name="capacity">Capacity operations</a></h4>
 
 <code>void resize(size_type n,const value_type&amp; x=value_type());</code>
@@ -587,7 +609,7 @@
 pointed to by <code>position</code> and rearranges <code>*position</code> into
 all the indices of the <code>multi_index_container</code>. Rearrangement on sequenced
 indices does not change the position of the element with respect to the index;
-rearrangement on other indices may or might not suceed. If the rearrangement
+rearrangement on other indices may or might not succeed. If the rearrangement
 fails, the element is erased.<br>
 <b>Postconditions:</b> Validity of <code>position</code> is preserved if the
 operation succeeds.<br>
@@ -599,6 +621,37 @@
 the element pointed to by <code>position</code> is erased.
 </blockquote>
 
+<code>template&lt;typename Modifier,typename Rollback><br>
+bool modify(iterator position,Modifier mod,Rollback back);</code>
+
+<blockquote>
+<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
+<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
+<code>Unary Function</code></a> accepting arguments of type
+<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
+iterator of the index. The sequence of operations <code>mod(e)</code>,
+<code>back(e)</code>, where <code>e</code> is the element
+pointed to by <code>position</code>, restores all keys of the element
+to their original state.</br>
+<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
+pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
+all the indices of the <code>multi_index_container</code>. Rearrangement on sequenced
+indices does not change the position of the element with respect to the index;
+rearrangement on other indices may or might not succeed. If the rearrangement
+fails, <code>back(e)</code> is invoked and the
+element is kept at its original position in all indices.<br>
+<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
+the element is erased under the conditions described below.<br>
+<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
+otherwise.<br>
+<b>Complexity:</b> <code>O(M(n))</code>.<br>
+<b>Exception safety:</b> Strong, except if <code>back</code> throws an
+exception, in which case the modified element is erased. If <code>back</code>
+throws inside the handling code executing after some other user-provided
+operation has thrown, it is the exception generated by <code>back</code> that
+is rethrown.
+</blockquote>
+
 <h4><a name="list_operations">List operations</a></h4>
 
 <p>
@@ -901,9 +954,9 @@
 
 <br>
 
-<p>Revised February 6th 2006</p>
+<p>Revised July 2nd 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/release_notes.html
==============================================================================
--- trunk/libs/multi_index/doc/release_notes.html (original)
+++ trunk/libs/multi_index/doc/release_notes.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -31,11 +31,76 @@
 <h2>Contents</h2>
 
 <ul>
+ <li>Boost 1.35 release</li>
   <li>Boost 1.34 release</li>
   <li>Boost 1.33.1 release</li>
   <li>Boost 1.33 release</li>
 </ul>
 
+<h2><a name="boost_1_35">Boost 1.35 release</a></h2>
+
+<p>
+<ul>
+ <li>New global_fun
+ predefined key extractor.
+ </li>
+ <li>Added iterator_to
+ facility.
+ </li>
+ <li>Included <a href="tutorial/creation.html#special_allocator">support for
+ non-standard allocators</a> such as those of
+ Boost.Interprocess, which makes
+ <code>multi_index_container</code>s placeable in shared memory.
+ </li>
+ <li>New versions of <code>modify</code> and <code>modify_key</code> with
+ rollback, as described in the
+ tutorial.
+ </li>
+ <li>Indices provide the new <code>cbegin</code>, <code>cend</code> and,
+ when applicable, <code>crbegin</code> and <code>crend</code>
+ member functions, in accordance with the latest drafts of the next
+ revision of the C++ standard.
+ </li>
+ <li>Hinted insertion in ordered indices fully conforms to the resolutions of
+ C++ Standard Library
+ <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233">Defect
+ Report 233</a>. The new requirement that the point of insertion
+ be always as close as possible to the hint induces a different behavior than
+ exhibited in former releases of Boost.MultiIndex, which can potentially cause
+ backwards compatibility problems; in any case, the likelihood of these
+ compatibility issues arising in a real scenario is very low.
+ </li>
+ <li>Sequenced and random access indices now follow the requirements of the
+ C++ standard for sequence containers with respect to the operations
+ <code>assign(f,l)</code> and <code>insert(p,f,l)</code> (23.1.1/9): if
+ <code>f</code> and <code>l</code> are of the same integral type, the
+ iterator-based overloads of these member functions are avoided:
+<blockquote><pre>
+<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
+ <span class=keyword>int</span><span class=special>,</span><span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
+<span class=special>&gt;</span> <span class=identifier>sequenced_container</span><span class=special>;</span>
+
+<span class=identifier>std</span><span class=special>::</span><span class=identifier>list</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=identifier>l</span><span class=special>(...);</span>
+<span class=identifier>sequenced_container</span> <span class=identifier>c</span><span class=special>;</span>
+
+<span class=comment>// iterator-based overload of assign</span>
+<span class=identifier>c</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=identifier>l</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>l</span><span class=special>.</span><span class=identifier>end</span><span class=special>());</span>
+
+<span class=comment>// The following is equivalent to
+// c.assign(
+// static_cast&lt;sequenced_container::size_type&gt;(10),100);
+// that is, &quot;10&quot; and &quot;100&quot; are not taken to be iterators as
+// in the previous expression.</span>
+<span class=identifier>c</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=number>10</span><span class=special>,</span><span class=number>100</span><span class=special>);</span>
+</pre></blockquote>
+ </li>
+ <li>The performance of ordered indices <code>range</code> and
+ <code>equal_range</code> has been improved.
+ </li>
+ <li>Maintenance fixes.</li>
+</ul>
+</p>
+
 <h2><a name="boost_1_34">Boost 1.34 release</a></h2>
 
 <p>
@@ -140,9 +205,9 @@
 
 <br>
 
-<p>Revised February 6th 2006</p>
+<p>Revised October 11th 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/tests.html
==============================================================================
--- trunk/libs/multi_index/doc/tests.html (original)
+++ trunk/libs/multi_index/doc/tests.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -116,7 +116,8 @@
 </tr>
 <tr class="odd_tr">
   <td>test_serialization1.cpp<br>
- test_serialization2.cpp</td>
+ test_serialization2.cpp<br>
+ test_serialization3.cpp</td>
   <td>Serialization support.</td>
 </tr>
 <tr>
@@ -149,9 +150,9 @@
 <br>
 
 
-<p>Revised March 2nd 2006</p>
+<p>Revised July 11th 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/tutorial/basics.html
==============================================================================
--- trunk/libs/multi_index/doc/tutorial/basics.html (original)
+++ trunk/libs/multi_index/doc/tutorial/basics.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -956,15 +956,69 @@
 leaves no trace of the previous value of the element. Integrity constraints
 thus lead to the following policy: when a collision happens in the
 process of calling <code>modify</code>, the element is erased and the method returns
-<code>false</code>. This difference in behavior between <code>replace</code> and
-<code>modify</code> has to be considered by the programmer on a case-by-case basis.
+<code>false</code>. There is a further version of <code>modify</code> which
+accepts a <i>rollback</i> functor to undo the changes in case of collision:
 </p>
 
+<blockquote><pre>
+<span class=keyword>struct</span> <span class=identifier>change_id</span>
+<span class=special>{</span>
+ <span class=identifier>change_id</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>new_id</span><span class=special>):</span><span class=identifier>new_id</span><span class=special>(</span><span class=identifier>new_id</span><span class=special>){}</span>
+
+ <span class=keyword>void</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>employee</span><span class=special>&amp;</span> <span class=identifier>e</span><span class=special>)</span>
+ <span class=special>{</span>
+ <span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>=</span><span class=identifier>new_id</span><span class=special>;</span>
+ <span class=special>}</span>
+
+<span class=keyword>private</span><span class=special>:</span>
+ <span class=keyword>int</span> <span class=identifier>new_id</span><span class=special>;</span>
+<span class=special>};</span>
+<span class=special>...</span>
+<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=...</span>
+
+<span class=keyword>int</span> <span class=identifier>old_id</span><span class=special>=</span><span class=identifier>it</span><span class=special>-&gt;</span><span class=identifier>id</span><span class=special>;</span> <span class=comment>// keep the original id
+
+// try to modify the id, restore it in case of collisions</span>
+<span class=identifier>es</span><span class=special>.</span><span class=identifier>modify</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>change_id</span><span class=special>(</span><span class=number>321</span><span class=special>),</span><span class=identifier>change_id</span><span class=special>(</span><span class=identifier>old_id</span><span class=special>));</span>
+</pre></blockquote>
+
+<p>In the example, <code>change_id(old_id)</code> is invoked to restore the original
+conditions when the modification results in collisions with some other element.
+The differences in behavior between <code>replace</code>, <code>modify</code> and
+<code>modify</code> with rollback have to be considered by the programmer on a
+case-by-case basis to determine the best updating mechanism.
+</p>
+
+<p align="center">
+<table cellspacing="0">
+ <caption><b>Behavior of the different updating mechanisms.</b></caption>
+<tr>
+ <th align="center">updating function</th>
+ <th>If there is a collision...</th>
+</tr>
+<tr>
+ <td align="center"><code>replace(it,x)</code></td>
+ <td>replacement does not take place.</td>
+</tr>
+<tr class="odd_tr">
+ <td align="center"><code>modify(it,mod)</code></td>
+ <td>the element is erased.</td>
+</tr>
+<tr>
+ <td align="center"><code>modify(it,mod,back)</code></td>
+ <td><code>back</code> is used to restore the original conditions.
+ (If <code>back</code> throws, the element is erased.)
+ </td>
+</tr>
+</table>
+</p>
+
+
 <p>
-A key-based version of <code>modify</code>, named
-modify_key, is
-provided as well. In this case, the modifying functor is passed a reference to
-the <code>key_value</code> part of the element instead of the whole object.
+Key-based versions of <code>modify</code>, named
+modify_key, are
+provided as well. In this case, the modifying functors are passed a reference to
+the <code>key_type</code> part of the element instead of the whole object.
 </p>
 
 <blockquote><pre>
@@ -990,8 +1044,8 @@
 </pre></blockquote>
 
 <p>
-Just as <code>modify</code> does, <code>modify_key</code> erases the element if
-the modification results in collisions in some index. <code>modify</code> and
+Like <code>modify</code>, there are versions of <code>modify_key</code> with and
+without rollback. <code>modify</code> and
 <code>modify_key</code> are particularly well suited to use in conjunction to
 <a href="../../../../libs/lambda/index.html">Boost.Lambda</a>
 for defining the modifying functors:
@@ -1205,9 +1259,9 @@
 
 <br>
 
-<p>Revised July 13th 2006</p>
+<p>Revised July 17th 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/tutorial/creation.html
==============================================================================
--- trunk/libs/multi_index/doc/tutorial/creation.html (original)
+++ trunk/libs/multi_index/doc/tutorial/creation.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -32,6 +32,7 @@
 <ul>
   <li>Value semantics</li>
   <li>Use of ctor_args_list</li>
+ <li>Special allocator support</li>
   <li>Serialization</li>
 </ul>
 
@@ -191,6 +192,60 @@
 puts in practise these concepts.
 </p>
 
+<h2><a name="special_allocator">Special allocator support</a></h2>
+
+<p>
+Boost.MultiIndex allows for a slightly more general class of allocators
+than strictly required by the C++ standard, as explained in detail in the
+reference.
+An important type of non-standard allocators supported are those provided by the
+Boost Interprocess Library;
+this opens up the possibility of placing <code>multi_index_container</code>s
+in shared memory.
+</p>
+
+<blockquote><pre>
+<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>interprocess</span><span class=special>/</span><span class=identifier>allocators</span><span class=special>/</span><span class=identifier>allocator</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
+<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>interprocess</span><span class=special>/</span><span class=identifier>managed_shared_memory</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
+
+<span class=keyword>namespace</span> <span class=identifier>bip</span><span class=special>=</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>interprocess</span><span class=special>;</span>
+
+<span class=comment>// a shared memory compatible allocator of ints</span>
+<span class=keyword>typedef</span> <span class=identifier>bip</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span>
+ <span class=keyword>int</span><span class=special>,</span><span class=identifier>bip</span><span class=special>::</span><span class=identifier>managed_shared_memory</span><span class=special>::</span><span class=identifier>segment_manager</span>
+<span class=special>&gt;</span> <span class=identifier>shared_int_allocator</span><span class=special>;</span>
+
+<span class=comment>// define a shared memory compatible multi_index_container
+// using shared_int_allocator</span>
+<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
+ <span class=keyword>int</span><span class=special>,</span>
+ <span class=identifier>indexed_by</span><span class=special>&lt;</span>
+ <span class=identifier>sequenced</span><span class=special>&lt;&gt;,</span>
+ <span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
+ <span class=special>&gt;,</span>
+ <span class=identifier>shared_int_allocator</span>
+<span class=special>&gt;</span> <span class=identifier>unique_int_list</span><span class=special>;</span>
+
+<span class=special>...</span>
+
+<span class=comment>// create a managed memory segment</span>
+<span class=identifier>bip</span><span class=special>::</span><span class=identifier>managed_shared_memory</span> <span class=identifier>seg</span><span class=special>(</span>
+ <span class=identifier>bip</span><span class=special>::</span><span class=identifier>create_only</span><span class=special>,</span><span class=string>&quot;SharedMemoryID&quot;</span><span class=special>,</span><span class=number>65536</span><span class=special>);</span>
+
+<span class=comment>// construct a unique_int_list into the segment</span>
+<span class=identifier>unique_int_list</span><span class=special>*</span> <span class=identifier>puil</span><span class=special>=</span><span class=identifier>seg</span><span class=special>.</span><span class=identifier>construct</span><span class=special>&lt;</span><span class=identifier>unique_int_list</span><span class=special>&gt;</span>
+ <span class=special>(</span><span class=string>&quot;UniqueIntListID&quot;</span><span class=special>)</span> <span class=comment>// object identifier within the segment
+ // Construction args: first a ctor arg list, then a
+ // shared memory allocator obtained from the segment object.</span>
+ <span class=special>(</span><span class=identifier>unique_int_list</span><span class=special>::</span><span class=identifier>ctor_args_list</span><span class=special>(),</span>
+ <span class=identifier>unique_int_list</span><span class=special>::</span><span class=identifier>allocator_type</span><span class=special>(</span><span class=identifier>seg</span><span class=special>.</span><span class=identifier>get_segment_manager</span><span class=special>()));</span>
+ </pre></blockquote>
+
+<p>
+The examples section includes a program
+that further explores this capability.
+</p>
+
 <h2><a name="serialization">Serialization</a></h2>
 
 <p>
@@ -285,7 +340,7 @@
 
 <br>
 
-<p>Revised February 27th 2007</p>
+<p>Revised July 17th 2007</p>
 
 <p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software

Modified: trunk/libs/multi_index/doc/tutorial/indices.html
==============================================================================
--- trunk/libs/multi_index/doc/tutorial/indices.html (original)
+++ trunk/libs/multi_index/doc/tutorial/indices.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -48,6 +48,7 @@
         </ul>
   </li>
   <li>Index rearranging</li>
+ <li>iterator_to</li>
   <li>Ordered indices node compression</li>
 </ul>
 
@@ -90,6 +91,7 @@
 </tr>
 <tr class="odd_tr">
   <td align="center"><code>&nbsp;&nbsp;random_access&nbsp;&nbsp;</code></td>
+</tr>
 </table>
 </p>
 
@@ -608,7 +610,8 @@
 <blockquote><pre>
 <span class=comment>// undefined behavior: [rbegin(),rend()) is not free with respect
 // to the base index</span>
-<span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>rbegin</span><span class=special>());</span></pre></blockquote>
+<span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>rbegin</span><span class=special>());</span>
+</pre></blockquote>
 
 <p>
 The view concept is defined in detail in the
@@ -617,6 +620,57 @@
 for a demonstration of use of <code>rearrange</code>.
 </p>
 
+<h2><a name="iterator_to"><code>iterator_to</code></a></h2>
+
+<p>
+All indices of Boost.MultiIndex provide a member function called <code>iterator_to</code>
+which returns an iterator to a given element of the container:
+</p>
+
+<blockquote><pre>
+<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
+ <span class=keyword>int</span><span class=special>,</span>
+ <span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
+<span class=special>&gt;</span> <span class=identifier>c</span><span class=special>;</span>
+<span class=special>...</span>
+<span class=comment>// convoluted way to do to c.pop_back()</span>
+<span class=identifier>c</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>iterator_to</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>back</span><span class=special>()));</span>
+
+<span class=comment>// The following, though similar to the previous code,
+// does not work: iterator_to accepts a reference to
+// the element in the container, not a copy.</span>
+<span class=keyword>int</span> <span class=identifier>x</span><span class=special>=</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>back</span><span class=special>();</span>
+<span class=identifier>c</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>iterator_to</span><span class=special>(</span><span class=identifier>x</span><span class=special>));</span> <span class=comment>// run-time failure ensues</span>
+</pre></blockquote>
+
+<p>
+<code>iterator_to</code> provides a way to retrieve an iterator to an element
+from a pointer to the element, thus making iterators and pointers interchangeable
+for the purposes of element pointing (not so for traversal) in many situations.
+This notwithstanding, it is not the aim of <code>iterator_to</code> to
+promote the usage of pointers as substitutes for real iterators: the latter are
+specifically designed for handling the elements of a container,
+and not only benefit from the iterator orientation of container interfaces,
+but are also capable of exposing many more programming bugs than raw pointers, both
+at compile and run time. <code>iterator_to</code> is thus meant to be used
+in scenarios where access via iterators is not suitable or desireable:
+<ul>
+ <li>Interoperability with preexisting APIs based on pointers or references.</li>
+ <li>Publication of pointer-based interfaces (for instance, when
+ designing a C-compatible library).
+ </li>
+ <li>The exposure of pointers in place of iterators can act as a <i>type
+ erasure</i> barrier effectively decoupling the user of the code
+ from the implementation detail of which particular container is being
+ used. Similar techniques, like the famous Pimpl idiom, are used
+ in large projects to reduce dependencies and build times.
+ </li>
+ <li>Self-referencing contexts where an element acts upon its owner
+ container and no iterator to itself is available.
+ </li>
+</ul>
+</p>
+
 <h2><a name="ordered_node_compression">Ordered indices node compression</a></h2>
 
 <p>
@@ -664,9 +718,9 @@
 
 <br>
 
-<p>Revised February 6th 2006</p>
+<p>Revised July 17th 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/doc/tutorial/key_extraction.html
==============================================================================
--- trunk/libs/multi_index/doc/tutorial/key_extraction.html (original)
+++ trunk/libs/multi_index/doc/tutorial/key_extraction.html 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -41,6 +41,7 @@
       <li>member</li>
       <li><a href="#const_mem_fun"><code>const_mem_fun</code>
         and <code>mem_fun</code></a></li>
+ <li>global_fun</li>
     </ul>
   </li>
   <li>User-defined key extractors</li>
@@ -244,6 +245,68 @@
 provides a complete program showing how to use <code>const_mem_fun</code>.
 <p>
 
+<h3><a name="global_fun"><code>global_fun</code></a></h3>
+
+<p>
+Whereas <code>const_mem_fun</code> and <code>mem_fun</code> are based on a
+given member function of the base type from where the key is extracted,
+global_fun
+takes a global function (or static member function) accepting the base
+type as its parameter and returning the key:
+</p>
+
+<blockquote><pre>
+<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
+<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
+<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>global_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
+
+<span class=keyword>struct</span> <span class=identifier>rectangle</span>
+<span class=special>{</span>
+ <span class=keyword>int</span> <span class=identifier>x0</span><span class=special>,</span><span class=identifier>y0</span><span class=special>;</span>
+ <span class=keyword>int</span> <span class=identifier>x1</span><span class=special>,</span><span class=identifier>y1</span><span class=special>;</span>
+<span class=special>};</span>
+
+<span class=keyword>unsigned</span> <span class=keyword>long</span> <span class=identifier>area</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>rectangle</span><span class=special>&amp;</span> <span class=identifier>r</span><span class=special>)</span>
+<span class=special>{</span>
+ <span class=keyword>return</span> <span class=special>(</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>)(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x0</span><span class=special>)*(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x0</span><span class=special>)+</span>
+ <span class=special>(</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>)(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y0</span><span class=special>)*(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y0</span><span class=special>);</span>
+<span class=special>}</span>
+
+<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
+ <span class=identifier>rectangle</span><span class=special>,</span>
+ <span class=identifier>indexed_by</span><span class=special>&lt;</span>
+ <span class=comment>// sort by increasing area</span>
+ <span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>global_fun</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>rectangle</span><span class=special>&amp;,</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>,&amp;</span><span class=identifier>area</span><span class=special>&gt;</span> <span class=special>&gt;</span>
+ <span class=special>&gt;</span>
+<span class=special>&gt;</span> <span class=identifier>rectangle_container</span><span class=special>;</span>
+</pre></blockquote>
+
+<p>
+The specification of <code>global_fun</code> obeys the following syntax:
+</p>
+
+<blockquote><pre>
+<span class=identifier>global_fun</span><span class=special>&lt;</span><span class=identifier><i>(argument type)</i></span><span class=special>,</span><span class=identifier><i>(key type)</i></span><span class=special>,</span><span class=identifier><i>(pointer to function)</i></span><span class=special>&gt;</span>
+</pre></blockquote>
+
+<p>
+where the argument type and key type must match <i>exactly</i> those in the
+signature of the function used; for instance, in the example above the argument
+type is <code>const rectangle&amp;</code>, without omitting the "<code>const</code>"
+and "<code>&amp;</code>" parts. So, although most of the time the base type will be
+accepted by constant reference, <code>global_fun</code> is also prepared to take
+functions accepting their argument by value or by non-constant reference: this
+latter case cannot generally be used directly in the specification of
+<code>multi_index_container</code>s as their elements are treated as constant,
+but the section on <a href="#advanced_key_extractors">advanced features
+of Boost.MultiIndex key extractors</a> describes valid use cases of
+key extraction based on such functions with a non-constant reference argument.
+</p>
+
+<p>Example 2 in the examples section
+uses <code>gobal_fun</code>.
+<p>
+
 <h2><a name="user_defined_key_extractors">User-defined key extractors</a></h2>
 
 <p>
@@ -632,10 +695,12 @@
 <blockquote><pre>
 <span class=keyword>struct</span> <span class=identifier>T</span>
 <span class=special>{</span>
- <span class=keyword>int</span> <span class=identifier>i</span><span class=special>;</span>
- <span class=keyword>const</span> <span class=keyword>int</span> <span class=identifier>j</span><span class=special>;</span>
- <span class=keyword>int</span> <span class=identifier>f</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
- <span class=keyword>int</span> <span class=identifier>g</span><span class=special>();</span>
+ <span class=keyword>int</span> <span class=identifier>i</span><span class=special>;</span>
+ <span class=keyword>const</span> <span class=keyword>int</span> <span class=identifier>j</span><span class=special>;</span>
+ <span class=keyword>int</span> <span class=identifier>f</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
+ <span class=keyword>int</span> <span class=identifier>g</span><span class=special>();</span>
+ <span class=keyword>static</span> <span class=keyword>int</span> <span class=identifier>gf</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>T</span><span class=special>&amp;);</span>
+ <span class=keyword>static</span> <span class=keyword>int</span> <span class=identifier>gg</span><span class=special>(</span><span class=identifier>T</span><span class=special>&amp;);</span>
 <span class=special>};</span>
 </pre></blockquote>
 
@@ -656,7 +721,7 @@
   <th>read/write?</th>
 </tr>
 <tr>
- <td align="center" rowspan="4"><code>T</code></td>
+ <td align="center" rowspan="6"><code>T</code></td>
   <td><code>i</code></td>
   <td><code>member&lt;T,int,&amp;T::i></code></td>
   <td align="center">yes</td>
@@ -680,9 +745,21 @@
   <td align="center">no</td>
   <td align="center">no</td>
 </tr>
+<tr>
+ <td><code>gf()</code></td>
+ <td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
+ <td align="center">yes</td>
+ <td align="center">no</td>
+</tr>
+<tr>
+ <td><code>gg()</code></td>
+ <td><code>global_fun&lt;T&amp;,int,&amp;T::gg></code></td>
+ <td align="center">no</td>
+ <td align="center">no</td>
+</tr>
 
 <tr class="odd_tr">
- <td align="center" rowspan="4"><code>reference_wrapper&lt;T></code></td>
+ <td align="center" rowspan="6"><code>reference_wrapper&lt;T></code></td>
   <td><code>i</code></td>
   <td><code>member&lt;T,int,&amp;T::i></code></td>
   <td align="center">yes</td>
@@ -706,9 +783,21 @@
   <td align="center">yes</td>
   <td align="center">no</td>
 </tr>
+<tr class="odd_tr">
+ <td><code>gf()</code></td>
+ <td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
+ <td align="center">yes</td>
+ <td align="center">no</td>
+</tr>
+<tr class="odd_tr">
+ <td><code>gg()</code></td>
+ <td><code>global_fun&lt;T&amp;,int,&amp;T::gg></code></td>
+ <td align="center">yes</td>
+ <td align="center">no</td>
+</tr>
 
 <tr>
- <td align="center" rowspan="4"><code>reference_wrapper&lt;const T></code></td>
+ <td align="center" rowspan="6"><code>reference_wrapper&lt;const T></code></td>
   <td><code>i</code></td>
   <td><code>member&lt;T,const int,&amp;T::i></code></td>
   <td align="center">yes</td>
@@ -730,9 +819,19 @@
   <td><code>g()</code></td>
   <td colspan="3">&nbsp;</td>
 </tr>
+<tr>
+ <td><code>gf()</code></td>
+ <td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
+ <td align="center">yes</td>
+ <td align="center">no</td>
+</tr>
+<tr>
+ <td><code>gg()</code></td>
+ <td colspan="3">&nbsp;</td>
+</tr>
 
 <tr class="odd_tr">
- <td align="center" rowspan="4">chained pointer to <code>T</code><br>
+ <td align="center" rowspan="6">chained pointer to <code>T</code><br>
     or to <code>reference_wrapper&lt;T></code></td>
   <td><code>i</code></td>
   <td><code>member&lt;T,int,&amp;T::i></code></td>
@@ -757,9 +856,21 @@
   <td align="center">yes</td>
   <td align="center">no</td>
 </tr>
+<tr class="odd_tr">
+ <td><code>gf()</code></td>
+ <td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
+ <td align="center">yes</td>
+ <td align="center">no</td>
+</tr>
+<tr class="odd_tr">
+ <td><code>gg()</code></td>
+ <td><code>global_fun&lt;T&amp;,int,&amp;T::gg></code></td>
+ <td align="center">yes</td>
+ <td align="center">no</td>
+</tr>
 
 <tr>
- <td align="center" rowspan="4">chained pointer to <code>const T</code><br>
+ <td align="center" rowspan="6">chained pointer to <code>const T</code><br>
     or to <code>reference_wrapper&lt;const T></code></td>
   <td><code>i</code></td>
   <td><code>member&lt;T,const int,&amp;T::i></code></td>
@@ -782,6 +893,16 @@
   <td><code>g()</code></td>
   <td colspan="3">&nbsp;</td>
 </tr>
+<tr>
+ <td><code>gf()</code></td>
+ <td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
+ <td align="center">yes</td>
+ <td align="center">no</td>
+</tr>
+<tr>
+ <td><code>gg()</code></td>
+ <td colspan="3">&nbsp;</td>
+</tr>
 
 </table>
 </p>
@@ -790,10 +911,12 @@
 The column "applicable to <code>const</code> elements?" states whether the
 corresponding key extractor can be used when passed constant elements (this
 relates to the elements specified in the first column, not the referenced
-<code>T</code> objects). The only negative case is for <code>T::g</code> when
-the elements are raw <code>T</code> objects, which make sense as we are dealing
-with a non-constant member function: this also implies that <code>multi_index_container</code>s
-of elements of <code>T</code> cannot be sorted by <code>T::g</code>, because
+<code>T</code> objects). The only negative cases are for <code>T::g</code> and
+<code>T:gg</code> when the elements are raw <code>T</code> objects, which make sense
+as we are dealing with a non-constant member function (<code>T::g</code>)
+and a function taking <code>T</code> by
+non-constant reference: this also implies that <code>multi_index_container</code>s
+of elements of <code>T</code> cannot be sorted by <code>T::g</code> or <code>T::gg</code>, because
 elements contained within a <code>multi_index_container</code> are treated as constant.
 </p>
 
@@ -804,7 +927,7 @@
 
 <p>
 Some care has to be taken to preserve <code>const</code>-correctness in the
-specification of the key extractors: in some sense, the <code>const</code>
+specification of <code>member</code> key extractors: in some sense, the <code>const</code>
 qualifier is carried along to the member part, even if that particular
 member is not defined as <code>const</code>. For instance, if the elements
 are of type <code>const T *</code>, sorting by <code>T::i</code> is <i>not</i>
@@ -832,9 +955,9 @@
 
 <br>
 
-<p>Revised February 6th 2006</p>
+<p>Revised June 11th 2007</p>
 
-<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
+<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
 Distributed under the Boost Software
 License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
 LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

Modified: trunk/libs/multi_index/example/Jamfile.v2
==============================================================================
--- trunk/libs/multi_index/example/Jamfile.v2 (original)
+++ trunk/libs/multi_index/example/Jamfile.v2 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 # Boost.MultiIndex examples Jamfile
 #
-# Copyright 2003-2006 Joaquín M López Muñoz.
+# Copyright 2003-2007 Joaquín M López Muñoz.
 # Distributed under the Boost Software License, Version 1.0.
 # (See accompanying file LICENSE_1_0.txt or copy at
 # http://www.boost.org/LICENSE_1_0.txt)
@@ -27,14 +27,19 @@
     : <include>$(BOOST_ROOT)
     ;
 
+exe fun_key
+ : fun_key.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
 exe hashed
     : hashed.cpp
     : <include>$(BOOST_ROOT)
     ;
 
-exe memfun_key
- : memfun_key.cpp
- : <include>$(BOOST_ROOT)
+exe ip_allocator
+ : ip_allocator.cpp
+ : <include>$(BOOST_ROOT) <threading>multi
     ;
 
 exe non_default_ctor

Modified: trunk/libs/multi_index/example/composite_keys.cpp
==============================================================================
--- trunk/libs/multi_index/example/composite_keys.cpp (original)
+++ trunk/libs/multi_index/example/composite_keys.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex example of composite keys.
  *
- * Copyright 2003-2005 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -18,6 +18,7 @@
 #include <boost/multi_index/composite_key.hpp>
 #include <boost/multi_index/member.hpp>
 #include <boost/multi_index/ordered_index.hpp>
+#include <boost/next_prior.hpp>
 #include <boost/tokenizer.hpp>
 #include <functional>
 #include <iostream>
@@ -287,7 +288,7 @@
       continue;
     }
 
- it->second->execute(++tok.begin(),tok.end());
+ it->second->execute(boost::next(tok.begin()),tok.end());
   }
   
   return 0;

Added: trunk/libs/multi_index/example/fun_key.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/multi_index/example/fun_key.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -0,0 +1,100 @@
+/* Boost.MultiIndex example of functions used as key extractors.
+ *
+ * Copyright 2003-2007 Joaquín M López Muñoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/global_fun.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <iostream>
+#include <string>
+
+using namespace boost::multi_index;
+
+/* A name record consists of the given name (e.g. "Charlie")
+ * and the family name (e.g. "Brown"). The full name, calculated
+ * by name_record::name() is laid out in the "phonebook order"
+ * family name + given_name.
+ */
+
+struct name_record
+{
+ name_record(std::string given_name_,std::string family_name_):
+ given_name(given_name_),family_name(family_name_)
+ {}
+
+ std::string name()const
+ {
+ std::string str=family_name;
+ str+=" ";
+ str+=given_name;
+ return str;
+ }
+
+private:
+ std::string given_name;
+ std::string family_name;
+};
+
+std::string::size_type name_record_length(const name_record& r)
+{
+ return r.name().size();
+}
+
+/* multi_index_container with indices based on name_record::name()
+ * and name_record_length().
+ * See Compiler specifics: Use of const_mem_fun_explicit and
+ * mem_fun_explicit for info on BOOST_MULTI_INDEX_CONST_MEM_FUN.
+ */
+
+typedef multi_index_container<
+ name_record,
+ indexed_by<
+ ordered_unique<
+ BOOST_MULTI_INDEX_CONST_MEM_FUN(name_record,std::string,name)
+ >,
+ ordered_non_unique<
+ global_fun<const name_record&,std::string::size_type,name_record_length>
+ >
+ >
+> name_record_set;
+
+int main()
+{
+ name_record_set ns;
+
+ ns.insert(name_record("Joe","Smith"));
+ ns.insert(name_record("Robert","Nightingale"));
+ ns.insert(name_record("Robert","Brown"));
+ ns.insert(name_record("Marc","Tuxedo"));
+
+ /* list the names in ns in phonebook order */
+
+ std::cout<<"Phonenook order\n"
+ <<"---------------"<<std::endl;
+ for(name_record_set::iterator it=ns.begin();it!=ns.end();++it){
+ std::cout<<it->name()<<std::endl;
+ }
+
+ /* list the names in ns according to their length*/
+
+ std::cout<<"\nLength order\n"
+ << "------------"<<std::endl;
+ for(nth_index_iterator<name_record_set,1>::type it1=get<1>(ns).begin();
+ it1!=get<1>(ns).end();++it1){
+ std::cout<<it1->name()<<std::endl;
+ }
+
+ return 0;
+}

Added: trunk/libs/multi_index/example/ip_allocator.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/multi_index/example/ip_allocator.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -0,0 +1,293 @@
+/* Boost.MultiIndex example of use of Boost.Interprocess allocators.
+ *
+ * Copyright 2003-2007 Joaquín M López Muñoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <algorithm>
+#include <boost/interprocess/allocators/allocator.hpp>
+#include <boost/interprocess/containers/string.hpp>
+#include <boost/interprocess/managed_mapped_file.hpp>
+#include <boost/interprocess/sync/named_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/member.hpp>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <string>
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+namespace bip=boost::interprocess;
+
+/* shared_string is a string type placeable in shared memory,
+ * courtesy of Boost.Interprocess.
+ */
+
+typedef bip::basic_string<
+ char,std::char_traits<char>,
+ bip::allocator<char,bip::managed_mapped_file::segment_manager>
+> shared_string;
+
+/* Book record. All its members can be placed in shared memory,
+ * hence the structure itself can too.
+ */
+
+struct book
+{
+ shared_string name;
+ shared_string author;
+ unsigned pages;
+ unsigned prize;
+
+ book(const shared_string::allocator_type& al):
+ name(al),author(al),pages(0),prize(0)
+ {}
+
+ friend std::ostream& operator<<(std::ostream& os,const book& b)
+ {
+ os<<b.author<<": \""<<b.name<<"\", $"<<b.prize<<", "<<b.pages<<" pages\n";
+ return os;
+ }
+};
+
+/* partial_str_less allows for partial searches taking into account
+ * only the first n chars of the strings compared against. See
+ * Tutorial: Basics: Special lookup operations for more info on this
+ * type of comparison functors.
+ */
+
+/* partial_string is a mere string holder used to differentiate from
+ * a plain string.
+ */
+
+struct partial_string
+{
+ partial_string(const shared_string& str):str(str){}
+ shared_string str;
+};
+
+struct partial_str_less
+{
+ bool operator()(const shared_string& x,const shared_string& y)const
+ {
+ return x<y;
+ }
+
+ bool operator()(const shared_string& x,const partial_string& y)const
+ {
+ return x.substr(0,y.str.size())<y.str;
+ }
+
+ bool operator()(const partial_string& x,const shared_string& y)const
+ {
+ return x.str<y.substr(0,x.str.size());
+ }
+};
+
+/* Define a multi_index_container of book records with indices on
+ * author, name and prize. The index on names allows for partial
+ * searches. This container can be placed in shared memory because:
+ * * book can be placed in shared memory.
+ * * We are using a Boost.Interprocess specific allocator.
+ */
+
+/* see Compiler specifics: Use of member_offset for info on
+ * BOOST_MULTI_INDEX_MEMBER
+ */
+
+typedef multi_index_container<
+ book,
+ indexed_by<
+ ordered_non_unique<
+ BOOST_MULTI_INDEX_MEMBER(book,shared_string,author)
+ >,
+ ordered_non_unique<
+ BOOST_MULTI_INDEX_MEMBER(book,shared_string,name),
+ partial_str_less
+ >,
+ ordered_non_unique<
+ BOOST_MULTI_INDEX_MEMBER(book,unsigned,prize)
+ >
+ >,
+ bip::allocator<book,bip::managed_mapped_file::segment_manager>
+> book_container;
+
+/* A small utility to get data entered via std::cin */
+
+template<typename T>
+void enter(const char* msg,T& t)
+{
+ std::cout<<msg;
+ std::string str;
+ std::getline(std::cin,str);
+ std::istringstream iss(str);
+ iss>>t;
+}
+
+void enter(const char* msg,std::string& str)
+{
+ std::cout<<msg;
+ std::getline(std::cin,str);
+}
+
+void enter(const char* msg,shared_string& str)
+{
+ std::cout<<msg;
+ std::string stdstr;
+ std::getline(std::cin,stdstr);
+ str=stdstr.c_str();
+}
+
+int main()
+{
+ /* Create (or open) the memory mapped file where the book container
+ * is stored, along with a mutex for synchronized access.
+ */
+
+ bip::managed_mapped_file seg(
+ bip::open_or_create,"./book_container.db",
+ 65536);
+ bip::named_mutex mutex(
+ bip::open_or_create,"7FD6D7E8-320B-11DC-82CF-F0B655D89593");
+
+ /* create or open the book container in shared memory */
+
+ book_container* pbc=seg.find_or_construct<book_container>("book container")(
+ book_container::ctor_args_list(),
+ book_container::allocator_type(seg.get_segment_manager()));
+
+ std::string command_info=
+ "1. list books by author\n"
+ "2. list all books by prize\n"
+ "3. insert a book\n"
+ "4. delete a book\n"
+ "0. exit\n";
+
+ std::cout<<command_info;
+
+ /* main loop */
+
+ for(bool exit=false;!exit;){
+ int command=-1;
+ enter("command: ",command);
+
+ switch(command){
+ case 0:{ /* exit */
+ exit=true;
+ break;
+ }
+ case 1:{ /* list books by author */
+ std::string author;
+ enter("author (empty=all authors): ",author);
+
+ /* operations with the container must be mutex protected */
+
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+
+ std::pair<book_container::iterator,book_container::iterator> rng;
+ if(author.empty()){
+ rng=std::make_pair(pbc->begin(),pbc->end());
+ }
+ else{
+ rng=pbc->equal_range(
+ shared_string(
+ author.c_str(),
+ shared_string::allocator_type(seg.get_segment_manager())));
+ }
+
+ if(rng.first==rng.second){
+ std::cout<<"no entries\n";
+ }
+ else{
+ std::copy(
+ rng.first,rng.second,std::ostream_iterator<book>(std::cout));
+ }
+ break;
+ }
+ case 2:{ /* list all books by prize */
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+
+ std::copy(
+ get<2>(*pbc).begin(),get<2>(*pbc).end(),
+ std::ostream_iterator<book>(std::cout));
+ break;
+ }
+ case 3:{ /* insert a book */
+ book b(shared_string::allocator_type(seg.get_segment_manager()));
+
+ enter("author: ",b.author);
+ enter("name: " ,b.name);
+ enter("prize: " ,b.prize);
+ enter("pages: " ,b.pages);
+
+ std::cout<<"insert the following?\n"<<b<<"(y/n): ";
+ char yn='n';
+ enter("",yn);
+ if(yn=='y'||yn=='Y'){
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+ pbc->insert(b);
+ }
+
+ break;
+ }
+ case 4:{ /* delete a book */
+ shared_string name(
+ shared_string::allocator_type(seg.get_segment_manager()));
+ enter(
+ "name of the book (you can enter\nonly the first few characters): ",
+ name);
+
+ typedef nth_index<book_container,1>::type index_by_name;
+ index_by_name& idx=get<1>(*pbc);
+ index_by_name::iterator it;
+ book b(shared_string::allocator_type(seg.get_segment_manager()));
+
+ {
+ /* Look for a book whose title begins with name. Note that we
+ * are unlocking after doing the search so as to not leave the
+ * container blocked during user prompting. That is also why a
+ * local copy of the book is done.
+ */
+
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+
+ it=idx.find(partial_string(name));
+ if(it==idx.end()){
+ std::cout<<"no such book found\n";
+ break;
+ }
+ b=*it;
+ }
+
+ std::cout<<"delete the following?\n"<<b<<"(y/n): ";
+ char yn='n';
+ enter("",yn);
+ if(yn=='y'||yn=='Y'){
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+ idx.erase(it);
+ }
+
+ break;
+ }
+ default:{
+ std::cout<<"select one option:\n"<<command_info;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}

Modified: trunk/libs/multi_index/perf/test_perf.cpp
==============================================================================
--- trunk/libs/multi_index/perf/test_perf.cpp (original)
+++ trunk/libs/multi_index/perf/test_perf.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex performance test.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -16,6 +16,7 @@
 #include <boost/multi_index/identity.hpp>
 #include <boost/multi_index/ordered_index.hpp>
 #include <boost/multi_index/sequenced_index.hpp>
+#include <boost/next_prior.hpp>
 #include <climits>
 #include <ctime>
 #include <iomanip>
@@ -163,7 +164,7 @@
   pair<iterator,bool> insert(const value_type& v)
   {
     List::push_back(v);
- return pair<iterator,bool>(--List::end(),true);
+ return pair<iterator,bool>(boost::prior(List::end()),true);
   }
 };
 

Modified: trunk/libs/multi_index/test/Jamfile.v2
==============================================================================
--- trunk/libs/multi_index/test/Jamfile.v2 (original)
+++ trunk/libs/multi_index/test/Jamfile.v2 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 # Boost.MultiIndex tests Jamfile
 #
-# Copyright 2003-2006 Joaquín M López Muñoz.
+# Copyright 2003-2007 Joaquín M López Muñoz.
 # Distributed under the Boost Software License, Version 1.0.
 # (See accompanying file LICENSE_1_0.txt or copy at
 # http://www.boost.org/LICENSE_1_0.txt)
@@ -26,7 +26,8 @@
     [ run test_rearrange.cpp test_rearrange_main.cpp ]
     [ run test_safe_mode.cpp test_safe_mode_main.cpp ]
     [ run test_serialization.cpp test_serialization1.cpp
- test_serialization2.cpp test_serialization_main.cpp
+ test_serialization2.cpp test_serialization3.cpp
+ test_serialization_main.cpp
                 /boost/serialization//boost_serialization ]
     [ run test_set_ops.cpp test_set_ops_main.cpp ]
     [ run test_special_set_ops.cpp test_special_set_ops_main.cpp ]

Modified: trunk/libs/multi_index/test/employee.hpp
==============================================================================
--- trunk/libs/multi_index/test/employee.hpp (original)
+++ trunk/libs/multi_index/test/employee.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Used in Boost.MultiIndex tests.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -23,6 +23,7 @@
 #include <cstddef>
 #include <ostream>
 #include <string>
+#include "non_std_allocator.hpp"
 
 struct employee
 {
@@ -92,7 +93,8 @@
 typedef
   boost::multi_index::multi_index_container<
     employee,
- employee_set_indices> employee_set;
+ employee_set_indices,
+ non_std_allocator<employee> > employee_set;
 
 #if defined(BOOST_NO_MEMBER_TEMPLATES)
 typedef boost::multi_index::nth_index<

Added: trunk/libs/multi_index/test/non_std_allocator.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/multi_index/test/non_std_allocator.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -0,0 +1,136 @@
+/* Used in Boost.MultiIndex tests.
+ *
+ * Copyright 2003-2007 Joaquín M López Muñoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/multi_index for library home page.
+ */
+
+#ifndef BOOST_MULTI_INDEX_TEST_NON_STD_ALLOCATOR_HPP
+#define BOOST_MULTI_INDEX_TEST_NON_STD_ALLOCATOR_HPP
+
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <iterator>
+#include <cstddef>
+
+template<typename T>
+class non_raw_pointer
+{
+public:
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef std::random_access_iterator_tag iterator_category;
+
+ non_raw_pointer(){}
+ explicit non_raw_pointer(T* p_):p(p_){}
+
+ T& operator*()const{return *p;}
+ T* operator->()const{return p;}
+ non_raw_pointer& operator++(){++p;return *this;}
+ non_raw_pointer operator++(int){non_raw_pointer t(*this);++p;return t;}
+ non_raw_pointer& operator--(){--p;return *this;}
+ non_raw_pointer operator--(int){non_raw_pointer t(*this);--p;return t;}
+ non_raw_pointer& operator+=(std::ptrdiff_t n){p+=n;return *this;}
+ non_raw_pointer& operator-=(std::ptrdiff_t n){p-=n;return *this;}
+ T& operator[](std::ptrdiff_t n)const{return p[n];}
+
+private:
+ T* p;
+};
+
+template<typename T>
+non_raw_pointer<T> operator+(const non_raw_pointer<T>& x,std::ptrdiff_t n)
+{return non_raw_pointer<T>((&*x)+n);}
+
+template<typename T>
+non_raw_pointer<T> operator+(std::ptrdiff_t n,const non_raw_pointer<T>& x)
+{return non_raw_pointer<T>(n+(&*x));}
+
+template<typename T>
+non_raw_pointer<T> operator-(const non_raw_pointer<T>& x,std::ptrdiff_t n)
+{return non_raw_pointer<T>((&*x)-n);}
+
+template<typename T>
+std::ptrdiff_t operator-(
+ const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
+{return (&*x)-(&*y);}
+
+template<typename T>
+bool operator==(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
+{return (&*x)==(&*y);}
+
+template<typename T>
+bool operator!=(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
+{return (&*x)!=(&*y);}
+
+template<typename T>
+bool operator<(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
+{return (&*x)<(&*y);}
+
+template<typename T>
+bool operator>(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
+{return (&*x)>(&*y);}
+
+template<typename T>
+bool operator>=(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
+{return (&*x)>=(&*y);}
+
+template<typename T>
+bool operator<=(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
+{return (&*x)<=(&*y);}
+
+template<typename T>
+class non_std_allocator
+{
+public:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef non_raw_pointer<T> pointer;
+ typedef non_raw_pointer<const T> const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+ template<class U>struct rebind{typedef non_std_allocator<U> other;};
+
+ non_std_allocator(){}
+ non_std_allocator(const non_std_allocator<T>&){}
+ template<class U>non_std_allocator(const non_std_allocator<U>&,int=0){}
+
+ pointer allocate(size_type n)
+ {
+ return pointer((T*)(new char[n*sizeof(T)]));
+ }
+
+ void deallocate(pointer p,size_type)
+ {
+ delete[](char *)&*p;
+ }
+
+ size_type max_size() const{return (size_type )(-1);}
+
+ friend bool operator==(const non_std_allocator&,const non_std_allocator&)
+ {
+ return true;
+ }
+
+ friend bool operator!=(const non_std_allocator&,const non_std_allocator&)
+ {
+ return false;
+ }
+};
+
+template<>
+class non_std_allocator<void>
+{
+public:
+ typedef non_raw_pointer<void> pointer;
+ typedef non_raw_pointer<const void> const_pointer;
+ typedef void value_type;
+ template<class U>struct rebind{typedef non_std_allocator<U> other;};
+};
+
+#endif

Modified: trunk/libs/multi_index/test/pair_of_ints.hpp
==============================================================================
--- trunk/libs/multi_index/test/pair_of_ints.hpp (original)
+++ trunk/libs/multi_index/test/pair_of_ints.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Used in Boost.MultiIndex tests.
  *
- * Copyright 2003-2004 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -32,6 +32,21 @@
   ++x;
 }
 
+inline void decrement_first(pair_of_ints& p)
+{
+ --p.first;
+}
+
+inline void decrement_second(pair_of_ints& p)
+{
+ --p.second;
+}
+
+inline void decrement_int(int& x)
+{
+ --x;
+}
+
 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
 namespace boost{
 namespace serialization{

Modified: trunk/libs/multi_index/test/test_capacity.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_capacity.cpp (original)
+++ trunk/libs/multi_index/test/test_capacity.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex test for capacity memfuns.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -53,6 +53,9 @@
   ss.resize(5);
   BOOST_CHECK(ss.size()==5);
 
+ ss.resize(4);
+ BOOST_CHECK(ss.size()==4);
+
   multi_index_container<int,indexed_by<random_access<> > > rs;
 
   rs.resize(10);

Modified: trunk/libs/multi_index/test/test_copy_assignment.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_copy_assignment.cpp (original)
+++ trunk/libs/multi_index/test/test_copy_assignment.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex test for copying and assignment.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -57,6 +57,27 @@
 #pragma parse_func_templ reset
 #endif
 
+template<typename Sequence>
+static void test_integral_assign(BOOST_EXPLICIT_TEMPLATE_TYPE(Sequence))
+{
+ /* Special cases described in 23.1.1/9: integral types must not
+ * be taken as iterators in assign(f,l) and insert(p,f,l).
+ */
+
+ Sequence s;
+
+ s.assign(5,10);
+ BOOST_CHECK(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50);
+ s.assign(2u,5u);
+ BOOST_CHECK(s.size()==2&&std::accumulate(s.begin(),s.end(),0)==10);
+
+ s.clear();
+ s.insert(s.begin(),5,10);
+ BOOST_CHECK(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50);
+ s.insert(s.begin(),2u,5u);
+ BOOST_CHECK(s.size()==7&&std::accumulate(s.begin(),s.end(),0)==60);
+}
+
 void test_copy_assignment()
 {
   employee_set es;
@@ -130,7 +151,11 @@
   /* MSVC++ 6.0 chokes on test_assign without this explicit instantiation */
   multi_index_container<int,indexed_by<sequenced<> > > s1;
   test_assign<multi_index_container<int,indexed_by<sequenced<> > > >();
+ test_integral_assign<
+ multi_index_container<int,indexed_by<sequenced<> > > >();
 
   multi_index_container<int,indexed_by<random_access<> > > s2;
   test_assign<multi_index_container<int,indexed_by<random_access<> > > >();
+ test_integral_assign<
+ multi_index_container<int,indexed_by<random_access<> > > >();
 }

Modified: trunk/libs/multi_index/test/test_iterators.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_iterators.cpp (original)
+++ trunk/libs/multi_index/test/test_iterators.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex test for iterators.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -13,6 +13,7 @@
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 #include "pre_multi_index.hpp"
 #include "employee.hpp"
+#include <boost/next_prior.hpp>
 #include <boost/test/test_tools.hpp>
 
 using namespace boost::multi_index;
@@ -25,6 +26,7 @@
 
   int n=0;
   for(iterator it=i.begin();it!=i.end();++it){
+ BOOST_CHECK(i.iterator_to(*it)==it);
     n+=it->id;
   }
   int m=0;
@@ -51,8 +53,14 @@
   typedef typename Index::const_iterator const_iterator;
   typedef typename Index::const_reverse_iterator const_reverse_iterator;
 
+ BOOST_CHECK(i.cbegin()==i.begin());
+ BOOST_CHECK(i.cend()==i.end());
+ BOOST_CHECK(i.crbegin()==i.rbegin());
+ BOOST_CHECK(i.crend()==i.rend());
+
   int n=0;
   for(const_iterator it=i.begin();it!=i.end();++it){
+ BOOST_CHECK(i.iterator_to(*it)==it);
     n+=it->id;
   }
   int m=0;
@@ -82,11 +90,13 @@
 
   int n=0;
   for(iterator it=i.begin();it!=i.end();++it){
+ BOOST_CHECK(i.iterator_to(*it)==it);
     n+=it->id;
   }
   int m=0;
   for(size_type buc=0;buc<i.bucket_count();++buc){
     for(local_iterator it=i.begin(buc);it!=i.end(buc);++it){
+ BOOST_CHECK(i.local_iterator_to(*it)==it);
       m+=it->id;
     }
   }
@@ -101,13 +111,20 @@
   typedef typename Index::const_local_iterator const_local_iterator;
   typedef typename Index::size_type size_type;
 
+ BOOST_CHECK(i.cbegin()==i.begin());
+ BOOST_CHECK(i.cend()==i.end());
+
   int n=0;
   for(const_iterator it=i.begin();it!=i.end();++it){
+ BOOST_CHECK(i.iterator_to(*it)==it);
     n+=it->id;
   }
   int m=0;
   for(size_type buc=0;buc<i.bucket_count();++buc){
+ BOOST_CHECK(i.cbegin(buc)==i.begin(buc));
+ BOOST_CHECK(i.cend(buc)==i.end(buc));
     for(const_local_iterator it=i.begin(buc);it!=i.end(buc);++it){
+ BOOST_CHECK(i.local_iterator_to(*it)==it);
       m+=it->id;
     }
   }
@@ -129,16 +146,17 @@
 
   int n=0;
   for(iterator it=i.begin();it!=middle;++it){
+ BOOST_CHECK(i.iterator_to(*it)==it);
     n+=it->id;
     n+=it[off].id;
   }
- if(odd)n+=(--i.end())->id;
+ if(odd)n+=(boost::prior(i.end()))->id;
   int m=0;
   for(reverse_iterator rit=i.rbegin();rit!=rmiddle;++rit){
     m+=rit->id;
     m+=(rit+off)->id;
   }
- if(odd)m+=(--i.rend())->id;
+ if(odd)m+=(boost::prior(i.rend()))->id;
   int p=0;
   for(iterator it2=i.end();it2!=middle;){
     --it2;
@@ -164,6 +182,11 @@
   typedef typename Index::const_reverse_iterator const_reverse_iterator;
   typedef typename Index::difference_type difference_type;
 
+ BOOST_CHECK(i.cbegin()==i.begin());
+ BOOST_CHECK(i.cend()==i.end());
+ BOOST_CHECK(i.crbegin()==i.rbegin());
+ BOOST_CHECK(i.crend()==i.rend());
+
   const_iterator middle=i.begin()+(i.end()-i.begin())/2;
   difference_type off=middle-i.begin();
   const_reverse_iterator rmiddle=i.rbegin()+off;
@@ -171,16 +194,17 @@
 
   int n=0;
   for(const_iterator it=i.begin();it!=middle;++it){
+ BOOST_CHECK(i.iterator_to(*it)==it);
     n+=it->id;
     n+=it[off].id;
   }
- if(odd)n+=(--i.end())->id;
+ if(odd)n+=(boost::prior(i.end()))->id;
   int m=0;
   for(const_reverse_iterator rit=i.rbegin();rit!=rmiddle;++rit){
     m+=rit->id;
     m+=(rit+off)->id;
   }
- if(odd)m+=(--i.rend())->id;
+ if(odd)m+=(boost::prior(i.rend()))->id;
   int p=0;
   for(const_iterator it2=i.end();it2!=middle;){
     --it2;

Modified: trunk/libs/multi_index/test/test_key_extractors.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_key_extractors.cpp (original)
+++ trunk/libs/multi_index/test/test_key_extractors.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex test for key extractors.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -30,6 +30,10 @@
   bool bool_mem_fun_const()const{return true;}
   bool bool_mem_fun(){return false;}
 
+ static bool bool_global_fun(test_class){return true;}
+ static bool bool_global_fun_const_ref(const test_class&){return false;}
+ static bool bool_global_fun_ref(test_class&){return true;}
+
   test_class(int i=0):int_member(i),int_cmember(i){}
   test_class(int i,int j):int_member(i),int_cmember(j){}
 
@@ -69,6 +73,15 @@
 typedef BOOST_MULTI_INDEX_CONST_MEM_FUN(
           test_class,bool,bool_mem_fun_const) key_cmf;
 typedef BOOST_MULTI_INDEX_MEM_FUN(test_class,bool,bool_mem_fun) key_mf;
+typedef global_fun<test_class,bool,&test_class::bool_global_fun> key_gf;
+typedef global_fun<
+ const test_class&,bool,
+ &test_class::bool_global_fun_const_ref
+ > key_gcrf;
+typedef global_fun<
+ test_class&,bool,
+ &test_class::bool_global_fun_ref
+ > key_grf;
 typedef composite_key<
           test_class,
           idn,
@@ -84,7 +97,7 @@
 typedef composite_key<
           boost::reference_wrapper<test_class>,
           key_mf
- > ccompw_key;
+ > ccompw_key;
 
 #if !defined(BOOST_NO_SFINAE)
 /* testcases for problems with non-copyable classes reported at
@@ -99,6 +112,9 @@
   bool bool_mem_fun_const()const{return true;}
   bool bool_mem_fun(){return false;}
 
+ static bool bool_global_fun_const_ref(const test_nc_class&){return false;}
+ static bool bool_global_fun_ref(test_nc_class&){return true;}
+
   test_nc_class(int i=0):int_member(i),int_cmember(i){}
   test_nc_class(int i,int j):int_member(i),int_cmember(j){}
 
@@ -129,6 +145,14 @@
           test_nc_class,bool,bool_mem_fun_const) nc_key_cmf;
 typedef BOOST_MULTI_INDEX_MEM_FUN(
           test_nc_class,bool,bool_mem_fun) nc_key_mf;
+typedef global_fun<
+ const test_nc_class&,bool,
+ &test_nc_class::bool_global_fun_const_ref
+ > nc_key_gcrf;
+typedef global_fun<
+ test_nc_class&,bool,
+ &test_nc_class::bool_global_fun_ref
+ > nc_key_grf;
 typedef composite_key<
           test_nc_class,
           nc_idn,
@@ -147,6 +171,9 @@
   key_cm k_cm;
   key_cmf k_cmf;
   key_mf k_mf;
+ key_gf k_gf;
+ key_gcrf k_gcrf;
+ key_grf k_grf;
   compkey cmpk;
   ccompkey ccmpk;
   ccompw_key ccmpk_w;
@@ -329,6 +356,71 @@
   BOOST_CHECK(!k_mf(tpp));
   BOOST_CHECK(!k_mf(tap));
   BOOST_CHECK(!k_mf(tw));
+
+ BOOST_CHECK(k_gf(tr));
+ BOOST_CHECK(k_gf(ctr));
+
+#if !defined(BOOST_NO_SFINAE)
+ BOOST_CHECK(k_gf(td));
+ BOOST_CHECK(k_gf(ctdr));
+#endif
+
+ BOOST_CHECK(k_gf(tp));
+ BOOST_CHECK(k_gf(ctp));
+
+#if !defined(BOOST_NO_SFINAE)
+ BOOST_CHECK(k_gf(tdp));
+ BOOST_CHECK(k_gf(ctdp));
+#endif
+
+ BOOST_CHECK(k_gf(tpp));
+ BOOST_CHECK(k_gf(ctpp));
+ BOOST_CHECK(k_gf(tap));
+ BOOST_CHECK(k_gf(ctap));
+
+ BOOST_CHECK(k_gf(tw));
+ BOOST_CHECK(k_gf(ctw));
+
+ BOOST_CHECK(!k_gcrf(tr));
+ BOOST_CHECK(!k_gcrf(ctr));
+
+#if !defined(BOOST_NO_SFINAE)
+ BOOST_CHECK(!k_gcrf(td));
+ BOOST_CHECK(!k_gcrf(ctdr));
+#endif
+
+ BOOST_CHECK(!k_gcrf(tp));
+ BOOST_CHECK(!k_gcrf(ctp));
+
+#if !defined(BOOST_NO_SFINAE)
+ BOOST_CHECK(!k_gcrf(tdp));
+ BOOST_CHECK(!k_gcrf(ctdp));
+#endif
+
+ BOOST_CHECK(!k_gcrf(tpp));
+ BOOST_CHECK(!k_gcrf(ctpp));
+ BOOST_CHECK(!k_gcrf(tap));
+ BOOST_CHECK(!k_gcrf(ctap));
+
+ BOOST_CHECK(!k_gcrf(tw));
+ BOOST_CHECK(!k_gcrf(ctw));
+
+ BOOST_CHECK(k_grf(tr));
+
+#if !defined(BOOST_NO_SFINAE)
+ BOOST_CHECK(k_grf(td));
+#endif
+
+ BOOST_CHECK(k_grf(tp));
+
+#if !defined(BOOST_NO_SFINAE)
+ BOOST_CHECK(k_grf(tdp));
+#endif
+
+ BOOST_CHECK(k_grf(tpp));
+ BOOST_CHECK(k_grf(tap));
+ BOOST_CHECK(k_grf(tw));
+
   BOOST_CHECK(ccmpk_w(tw)==make_tuple(false));
 
 #if !defined(BOOST_NO_SFINAE)
@@ -342,6 +434,8 @@
   nc_ckey_m nc_ck_m;
   nc_key_cmf nc_k_cmf;
   nc_key_mf nc_k_mf;
+ nc_key_gcrf nc_k_gcrf;
+ nc_key_grf nc_k_grf;
   nc_compkey nc_cmpk;
 
   test_nc_derived_class nc_td(-1,0);
@@ -357,6 +451,9 @@
   BOOST_CHECK(nc_k_cmf(nc_td));
   BOOST_CHECK(!nc_k_mf(nc_td));
 
+ BOOST_CHECK(!nc_k_gcrf(nc_td));
+ BOOST_CHECK(nc_k_grf(nc_td));
+
   test_nc_class nc_t(1,0);
   BOOST_CHECK(nc_cmpk(nc_td)==make_tuple(boost::cref(nc_t),1,1,true));
 #endif
@@ -370,6 +467,9 @@
     BOOST_CHECK(k_cm(it)==j);
     BOOST_CHECK(k_cmf(it));
     BOOST_CHECK(!k_mf(it));
+ BOOST_CHECK(k_gf(it));
+ BOOST_CHECK(!k_gcrf(it));
+ BOOST_CHECK(k_grf(it));
     BOOST_CHECK(cmpk(it)==make_tuple(test_class(j),j,j,true));
     BOOST_CHECK(ccmpk(it)==make_tuple(test_class(j),j));
     ++j;

Modified: trunk/libs/multi_index/test/test_modifiers.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_modifiers.cpp (original)
+++ trunk/libs/multi_index/test/test_modifiers.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex test for modifier memfuns.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -11,9 +11,12 @@
 #include "test_modifiers.hpp"
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <boost/next_prior.hpp>
+#include <iterator>
 #include <vector>
 #include "pre_multi_index.hpp"
 #include "employee.hpp"
+#include <boost/next_prior.hpp>
 #include <boost/test/test_tools.hpp>
 
 class always_one
@@ -283,4 +286,31 @@
   aoc.insert(always_one());
   aoc.erase(*(aoc.begin()));
   BOOST_CHECK(aoc.empty());
+
+ /* Testcases for compliance with "as close to hint as possible"
+ * proposed behavior for associative containers:
+ * http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233
+ * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html
+ */
+
+ typedef multi_index_container<
+ int,
+ indexed_by<
+ ordered_non_unique<identity<int> >
+ >
+ > int_non_unique_container;
+
+ int_non_unique_container c;
+ c.insert(0);c.insert(0);
+ c.insert(1);c.insert(1);
+ c.insert(2);c.insert(2);
+
+ BOOST_CHECK(std::distance(c.begin(),c.insert(c.begin(),1))==2);
+ BOOST_CHECK(std::distance(c.begin(),c.insert(boost::next(c.begin()),1))==2);
+ BOOST_CHECK(std::distance(c.begin(),c.insert(c.lower_bound(1),1))==2);
+ BOOST_CHECK(
+ std::distance(c.begin(),c.insert(boost::next(c.lower_bound(1)),1))==3);
+ BOOST_CHECK(std::distance(c.begin(),c.insert(c.upper_bound(1),1))==8);
+ BOOST_CHECK(std::distance(c.begin(),c.insert(boost::prior(c.end()),1))==9);
+ BOOST_CHECK(std::distance(c.begin(),c.insert(c.end(),1))==10);
 }

Modified: trunk/libs/multi_index/test/test_range.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_range.cpp (original)
+++ trunk/libs/multi_index/test/test_range.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -104,15 +104,17 @@
     std::bind1st(std::less<int>(),7), /* 7 < x */
     std::bind2nd(std::less_equal<int>(),7)); /* x <= 7 */
   CHECK_VOID_RANGE(p);
+ BOOST_CHECK(p.first==is.upper_bound(7));
 
   p=is.range(
     std::bind1st(std::less_equal<int>(),8), /* 8 <= x */
     std::bind2nd(std::less<int>(),2)); /* x < 2 */
   CHECK_VOID_RANGE(p);
+ BOOST_CHECK(p.first==is.lower_bound(8));
 
   p=is.range(
     std::bind1st(std::less<int>(),4), /* 4 < x */
     std::bind2nd(std::less<int>(),5)); /* x < 5 */
   CHECK_VOID_RANGE(p);
- BOOST_CHECK(p.first!=is.end()&&p.second!=is.end());
+ BOOST_CHECK(p.first!=is.end());
 }

Modified: trunk/libs/multi_index/test/test_rearrange.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_rearrange.cpp (original)
+++ trunk/libs/multi_index/test/test_rearrange.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -17,6 +17,7 @@
 #include <boost/multi_index_container.hpp>
 #include <boost/multi_index/sequenced_index.hpp>
 #include <boost/multi_index/random_access_index.hpp>
+#include <boost/next_prior.hpp>
 #include <boost/ref.hpp>
 #include <boost/test/test_tools.hpp>
 #include <vector>
@@ -87,7 +88,7 @@
   CHECK_EQUAL(sc,{3 _ 2 _ 4 _ 5 _ 0 _ 1});
   BOOST_CHECK(std::distance(it,it2)==3);
 
- sc.relocate(--(sc.end()),it,it2);
+ sc.relocate(boost::prior(sc.end()),it,it2);
   CHECK_EQUAL(sc,{3 _ 0 _ 2 _ 4 _ 5 _ 1});
 
   std::vector<boost::reference_wrapper<const value_type> > v;

Modified: trunk/libs/multi_index/test/test_serialization.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_serialization.cpp (original)
+++ trunk/libs/multi_index/test/test_serialization.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex test for serialization.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -11,9 +11,11 @@
 #include "test_serialization.hpp"
 #include "test_serialization1.hpp"
 #include "test_serialization2.hpp"
+#include "test_serialization3.hpp"
 
 void test_serialization()
 {
   test_serialization1();
   test_serialization2();
+ test_serialization3();
 }

Modified: trunk/libs/multi_index/test/test_serialization1.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_serialization1.cpp (original)
+++ trunk/libs/multi_index/test/test_serialization1.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex test for serialization, part 1.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -8,7 +8,7 @@
  * See http://www.boost.org/libs/multi_index for library home page.
  */
 
-#include "test_serialization.hpp"
+#include "test_serialization1.hpp"
 #include "test_serialization_template.hpp"
 
 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
@@ -16,6 +16,7 @@
 #include <boost/multi_index/sequenced_index.hpp>
 #include <boost/multi_index/random_access_index.hpp>
 #include <boost/multi_index/key_extractors.hpp>
+#include "non_std_allocator.hpp"
 
 using namespace boost::multi_index;
 
@@ -49,7 +50,8 @@
         random_access<>,
         sequenced<>,
         ordered_non_unique<identity<int> >
- >
+ >,
+ non_std_allocator<int>
> multi_index_t;
 
     multi_index_t m;

Modified: trunk/libs/multi_index/test/test_serialization2.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_serialization2.cpp (original)
+++ trunk/libs/multi_index/test/test_serialization2.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex test for serialization, part 2.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -8,97 +8,18 @@
  * See http://www.boost.org/libs/multi_index for library home page.
  */
 
-#include "test_serialization.hpp"
+#include "test_serialization2.hpp"
 #include "test_serialization_template.hpp"
 
-#include <boost/multi_index/hashed_index.hpp>
 #include <boost/multi_index/ordered_index.hpp>
 #include <boost/multi_index/sequenced_index.hpp>
 #include <boost/multi_index/random_access_index.hpp>
 #include <boost/multi_index/key_extractors.hpp>
+#include "non_std_allocator.hpp"
 #include "pair_of_ints.hpp"
 
 using namespace boost::multi_index;
 
-void test_hashed_index_serialization()
-{
- const int N=100;
- const int SHUFFLE=10232;
-
- typedef multi_index_container<
- int,
- indexed_by<
- hashed_unique<identity<int> >,
- sequenced<>
- >
- > hashed_set;
-
- typedef hashed_set::iterator iterator;
- typedef hashed_set::local_iterator local_iterator;
-
- hashed_set hs;
-
- for(int i=0;i<N;++i){
- hs.insert(i*SHUFFLE);
- }
-
- std::ostringstream oss;
- {
- boost::archive::text_oarchive oa(oss);
- oa<<const_cast<const hashed_set&>(hs);
-
- std::vector<iterator> its(N);
- for(int i=0;i<N;++i){
- iterator it=hs.find(i*SHUFFLE);
- its.push_back(it);
- oa<<const_cast<const iterator&>(its.back());
- }
- iterator it=hs.end();
- oa<<const_cast<const iterator&>(it);
-
- std::vector<local_iterator> lits(2*N);
- for(std::size_t buc=0;buc<hs.bucket_count();++buc){
- for(local_iterator lit=hs.begin(buc),lit_end=hs.end(buc);
- lit!=lit_end;++lit){
- oa<<*lit;
- lits.push_back(lit);
- oa<<const_cast<const local_iterator&>(lits.back());
- }
- local_iterator lit2=hs.end(buc);
- lits.push_back(lit2);
- oa<<const_cast<const local_iterator&>(lits.back());
- }
- }
-
- hashed_set hs2;
- std::istringstream iss(oss.str());
- boost::archive::text_iarchive ia(iss);
- ia>>hs2;
- BOOST_CHECK(get<1>(hs)==get<1>(hs2));
-
- for(int j=0;j<N;++j){
- iterator it;
- ia>>it;
- BOOST_CHECK(*it==j*SHUFFLE);
- }
- iterator it;
- ia>>it;
- BOOST_CHECK(it==hs2.end());
-
- for(std::size_t buc=0;buc<hs2.bucket_count();++buc){
- for(std::size_t k=0;k<hs2.bucket_size(buc);++k){
- int n;
- local_iterator it;
- ia>>n;
- ia>>it;
- BOOST_CHECK(*it==n);
- }
- local_iterator it2;
- ia>>it2;
- BOOST_CHECK(it2==hs2.end(buc));
- }
-}
-
 void test_serialization2()
 {
   {
@@ -113,7 +34,8 @@
>,
         random_access<>,
         sequenced<>
- >
+ >,
+ non_std_allocator<pair_of_ints>
> multi_index_t;
 
     multi_index_t m;
@@ -156,5 +78,4 @@
     m.insert(pair_of_ints(3,2));
     test_serialization(m);
   }
- test_hashed_index_serialization();
 }

Added: trunk/libs/multi_index/test/test_serialization3.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/multi_index/test/test_serialization3.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -0,0 +1,99 @@
+/* Boost.MultiIndex test for serialization, part 3.
+ *
+ * Copyright 2003-2007 Joaquín M López Muñoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/multi_index for library home page.
+ */
+
+#include "test_serialization3.hpp"
+#include "test_serialization_template.hpp"
+
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/multi_index/key_extractors.hpp>
+#include "non_std_allocator.hpp"
+
+using namespace boost::multi_index;
+
+void test_serialization3()
+{
+ const int N=100;
+ const int SHUFFLE=10232;
+
+ typedef multi_index_container<
+ int,
+ indexed_by<
+ hashed_unique<identity<int> >,
+ sequenced<>
+ >,
+ non_std_allocator<int>
+ > hashed_set;
+
+ typedef hashed_set::iterator iterator;
+ typedef hashed_set::local_iterator local_iterator;
+
+ hashed_set hs;
+
+ for(int i=0;i<N;++i){
+ hs.insert(i*SHUFFLE);
+ }
+
+ std::ostringstream oss;
+ {
+ boost::archive::text_oarchive oa(oss);
+ oa<<const_cast<const hashed_set&>(hs);
+
+ std::vector<iterator> its(N);
+ for(int i=0;i<N;++i){
+ iterator it=hs.find(i*SHUFFLE);
+ its.push_back(it);
+ oa<<const_cast<const iterator&>(its.back());
+ }
+ iterator it=hs.end();
+ oa<<const_cast<const iterator&>(it);
+
+ std::vector<local_iterator> lits(2*N);
+ for(std::size_t buc=0;buc<hs.bucket_count();++buc){
+ for(local_iterator lit=hs.begin(buc),lit_end=hs.end(buc);
+ lit!=lit_end;++lit){
+ oa<<*lit;
+ lits.push_back(lit);
+ oa<<const_cast<const local_iterator&>(lits.back());
+ }
+ local_iterator lit2=hs.end(buc);
+ lits.push_back(lit2);
+ oa<<const_cast<const local_iterator&>(lits.back());
+ }
+ }
+
+ hashed_set hs2;
+ std::istringstream iss(oss.str());
+ boost::archive::text_iarchive ia(iss);
+ ia>>hs2;
+ BOOST_CHECK(boost::multi_index::get<1>(hs)==boost::multi_index::get<1>(hs2));
+
+ for(int j=0;j<N;++j){
+ iterator it;
+ ia>>it;
+ BOOST_CHECK(*it==j*SHUFFLE);
+ }
+ iterator it;
+ ia>>it;
+ BOOST_CHECK(it==hs2.end());
+
+ for(std::size_t buc=0;buc<hs2.bucket_count();++buc){
+ for(std::size_t k=0;k<hs2.bucket_size(buc);++k){
+ int n;
+ local_iterator it;
+ ia>>n;
+ ia>>it;
+ BOOST_CHECK(*it==n);
+ }
+ local_iterator it2;
+ ia>>it2;
+ BOOST_CHECK(it2==hs2.end(buc));
+ }
+}

Added: trunk/libs/multi_index/test/test_serialization3.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/multi_index/test/test_serialization3.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -0,0 +1,11 @@
+/* Boost.MultiIndex test for serialization, part 3.
+ *
+ * Copyright 2003-2007 Joaquín M López Muñoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/multi_index for library home page.
+ */
+
+void test_serialization3();

Modified: trunk/libs/multi_index/test/test_serialization_template.hpp
==============================================================================
--- trunk/libs/multi_index/test/test_serialization_template.hpp (original)
+++ trunk/libs/multi_index/test/test_serialization_template.hpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex serialization tests template.
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -26,9 +26,7 @@
   static bool compare(
     const MultiIndexContainer& m1,const MultiIndexContainer& m2)
   {
- using namespace boost::multi_index;
-
- if(!(get<N>(m1)==get<N>(m2))){
+ if(!(boost::multi_index::get<N>(m1)==boost::multi_index::get<N>(m2))){
       return false;
     }
     return all_indices_equal_helper<N-1>::compare(m1,m2);
@@ -60,8 +58,6 @@
 template<class MultiIndexContainer>
 void test_serialization(const MultiIndexContainer& m)
 {
- using namespace boost::multi_index;
-
   typedef typename MultiIndexContainer::iterator iterator;
   typedef typename MultiIndexContainer::const_iterator const_iterator;
 
@@ -100,10 +96,10 @@
     iterator it4;
     it4=--it2;
     BOOST_CHECK(it==it4);
- BOOST_CHECK(it==project<0>(m2,it4));
+ BOOST_CHECK(it==boost::multi_index::project<0>(m2,it4));
   }
   iterator it2;
   ia>>it2;
   BOOST_CHECK(it_end==it2);
- BOOST_CHECK(it_end==project<0>(m2,it2));
+ BOOST_CHECK(it_end==boost::multi_index::project<0>(m2,it2));
 }

Modified: trunk/libs/multi_index/test/test_update.cpp
==============================================================================
--- trunk/libs/multi_index/test/test_update.cpp (original)
+++ trunk/libs/multi_index/test/test_update.cpp 2007-10-11 06:57:30 EDT (Thu, 11 Oct 2007)
@@ -1,6 +1,6 @@
 /* Boost.MultiIndex test for replace(), modify() and modify_key().
  *
- * Copyright 2003-2006 Joaquín M López Muñoz.
+ * Copyright 2003-2007 Joaquín M López Muñoz.
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -15,6 +15,7 @@
 #include "pre_multi_index.hpp"
 #include "employee.hpp"
 #include "pair_of_ints.hpp"
+#include <boost/next_prior.hpp>
 #include <boost/test/test_tools.hpp>
 
 using namespace boost::multi_index;
@@ -64,34 +65,44 @@
     BOOST_CHECK(!ii2.replace(ii2.begin(),pair_of_ints(0,5)));
     BOOST_CHECK(!ii1.replace(project<1>(iis,iis.begin()),pair_of_ints(5,11)));
     BOOST_CHECK(!iis.replace(iis.begin(),pair_of_ints(11,5)));
- BOOST_CHECK(!iis.replace(++iis.begin(),pair_of_ints(10,5)));
+ BOOST_CHECK(!iis.replace(boost::next(iis.begin()),pair_of_ints(10,5)));
     BOOST_CHECK(!ii1.replace(
- project<1>(iis,++iis.begin()),pair_of_ints(5,10)));
- BOOST_CHECK(!iis.replace(--iis.end(),pair_of_ints(5,10)));
- BOOST_CHECK(!ii2.replace(--ii2.end(),pair_of_ints(10,5)));
+ project<1>(iis,boost::next(iis.begin())),pair_of_ints(5,10)));
+ BOOST_CHECK(!iis.replace(boost::prior(iis.end()),pair_of_ints(5,10)));
+ BOOST_CHECK(!ii2.replace(boost::prior(ii2.end()),pair_of_ints(10,5)));
 
     BOOST_CHECK(iis.modify(iis.begin(),increment_first));
     BOOST_CHECK(ii2.modify(ii2.begin(),increment_first));
     BOOST_CHECK(ii1.modify(project<1>(iis,iis.begin()),increment_first));
- BOOST_CHECK(ii2.modify(ii2.begin(),increment_first));
+ BOOST_CHECK(ii2.modify(ii2.begin(),increment_first,decrement_first));
+
+ BOOST_CHECK(!iis.modify(iis.begin(),increment_first,decrement_first));
+ BOOST_CHECK(iis.size()==3);
 
     BOOST_CHECK(!iis.modify(iis.begin(),increment_first));
     BOOST_CHECK(iis.size()==2);
 
     iis.insert(pair_of_ints(0,0));
- BOOST_CHECK(ii2.modify(--ii2.end(),increment_second));
- BOOST_CHECK(iis.modify(iis.begin(),increment_second));
- BOOST_CHECK(ii2.modify(--ii2.end(),increment_second));
+ BOOST_CHECK(ii2.modify(boost::prior(ii2.end()),increment_second));
     BOOST_CHECK(iis.modify(iis.begin(),increment_second));
+ BOOST_CHECK(ii2.modify(boost::prior(ii2.end()),increment_second));
+ BOOST_CHECK(iis.modify(iis.begin(),increment_second,decrement_second));
+
+ BOOST_CHECK(!ii2.modify(
+ boost::prior(ii2.end()),increment_second,decrement_second));
+ BOOST_CHECK(ii2.size()==3);
 
- BOOST_CHECK(!ii2.modify(--ii2.end(),increment_second));
+ BOOST_CHECK(!ii2.modify(boost::prior(ii2.end()),increment_second));
     BOOST_CHECK(ii2.size()==2);
 
     iis.insert(pair_of_ints(0,0));
     BOOST_CHECK(iis.modify_key(iis.begin(),increment_int));
+ BOOST_CHECK(iis.modify_key(iis.begin(),increment_int,decrement_int));
     BOOST_CHECK(iis.modify_key(iis.begin(),increment_int));
     BOOST_CHECK(iis.modify_key(iis.begin(),increment_int));
- BOOST_CHECK(iis.modify_key(iis.begin(),increment_int));
+
+ BOOST_CHECK(!iis.modify_key(iis.begin(),increment_int,decrement_int));
+ BOOST_CHECK(iis.size()==3);
 
     BOOST_CHECK(!iis.modify_key(iis.begin(),increment_int));
     BOOST_CHECK(iis.size()==2);
@@ -99,9 +110,12 @@
     nth_index_iterator<int_int_set,1>::type it=ii1.find(5);
     BOOST_CHECK(ii1.modify_key(it,increment_int));
     BOOST_CHECK(ii1.modify_key(it,increment_int));
- BOOST_CHECK(ii1.modify_key(it,increment_int));
+ BOOST_CHECK(ii1.modify_key(it,increment_int,decrement_int));
     BOOST_CHECK(ii1.modify_key(it,increment_int));
 
+ BOOST_CHECK(!ii1.modify_key(it,increment_int,decrement_int));
+ BOOST_CHECK(ii1.size()==2);
+
     BOOST_CHECK(!ii1.modify_key(it,increment_int));
     BOOST_CHECK(ii1.size()==1);
   }
@@ -127,23 +141,30 @@
     BOOST_CHECK(!iis.replace(p2,pair_of_ints(10,5)));
     BOOST_CHECK(!iis.replace(p2,pair_of_ints(5,10)));
     BOOST_CHECK(!iis.replace(p3,pair_of_ints(5,10)));
- BOOST_CHECK(!ii1.replace(--ii1.end(),pair_of_ints(10,5)));
+ BOOST_CHECK(!ii1.replace(boost::prior(ii1.end()),pair_of_ints(10,5)));
 
     BOOST_CHECK(iis.modify(p1,increment_first));
     BOOST_CHECK(ii1.modify(ii1.begin(),increment_first));
     BOOST_CHECK(iis.modify(p1,increment_first));
- BOOST_CHECK(ii1.modify(ii1.begin(),increment_first));
+ BOOST_CHECK(ii1.modify(ii1.begin(),increment_first,decrement_first));
+
+ BOOST_CHECK(!iis.modify(p1,increment_first,decrement_first));
+ BOOST_CHECK(iis.size()==3);
 
     BOOST_CHECK(!iis.modify(p1,increment_first));
     BOOST_CHECK(iis.size()==2);
 
     p1=iis.insert(pair_of_ints(0,0)).first;
- BOOST_CHECK(ii1.modify(--ii1.end(),increment_second));
- BOOST_CHECK(iis.modify(p1,increment_second));
- BOOST_CHECK(ii1.modify(--ii1.end(),increment_second));
+ BOOST_CHECK(ii1.modify(boost::prior(ii1.end()),increment_second));
+ BOOST_CHECK(iis.modify(p1,increment_second,decrement_second));
+ BOOST_CHECK(ii1.modify(boost::prior(ii1.end()),increment_second));
     BOOST_CHECK(iis.modify(p1,increment_second));
 
- BOOST_CHECK(!ii1.modify(--ii1.end(),increment_second));
+ BOOST_CHECK(!ii1.modify(
+ boost::prior(ii1.end()),increment_second,decrement_second));
+ BOOST_CHECK(ii1.size()==3);
+
+ BOOST_CHECK(!ii1.modify(boost::prior(ii1.end()),increment_second));
     BOOST_CHECK(ii1.size()==2);
   }
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk