Console: Implement enum registration and parsing/formatting
g0dil [Fri, 18 Apr 2008 13:59:32 +0000 (13:59 +0000)]
Add Boost.Bimap (v0.35) and Boost.MultiIndex (v0.35) to the repository (Bimap depends on a current MultiIndex)

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@819 270642c3-0616-0410-b53a-bc976706d245

167 files changed:
Console/Traits.cc [new file with mode: 0644]
Console/Traits.cti
Console/Traits.hh
Console/Traits.ih [new file with mode: 0644]
Console/Traits.test.cc
boost/bimap.hpp [new file with mode: 0644]
boost/bimap/bimap.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/associative_container_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/container_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/detail/comparison_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/detail/functor_bag.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/detail/identity_converters.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/detail/key_extractor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/list_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/list_map_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/map_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/multimap_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/multiset_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/sequence_container_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/set_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/support/iterator_facade_converters.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/unordered_map_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/unordered_multimap_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/unordered_multiset_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/unordered_set_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/vector_adaptor.hpp [new file with mode: 0644]
boost/bimap/container_adaptor/vector_map_adaptor.hpp [new file with mode: 0644]
boost/bimap/detail/bimap_core.hpp [new file with mode: 0644]
boost/bimap/detail/concept_tags.hpp [new file with mode: 0644]
boost/bimap/detail/debug/static_error.hpp [new file with mode: 0644]
boost/bimap/detail/generate_index_binder.hpp [new file with mode: 0644]
boost/bimap/detail/generate_relation_binder.hpp [new file with mode: 0644]
boost/bimap/detail/generate_view_binder.hpp [new file with mode: 0644]
boost/bimap/detail/is_set_type_of.hpp [new file with mode: 0644]
boost/bimap/detail/manage_additional_parameters.hpp [new file with mode: 0644]
boost/bimap/detail/manage_bimap_key.hpp [new file with mode: 0644]
boost/bimap/detail/map_view_base.hpp [new file with mode: 0644]
boost/bimap/detail/map_view_iterator.hpp [new file with mode: 0644]
boost/bimap/detail/modifier_adaptor.hpp [new file with mode: 0644]
boost/bimap/detail/non_unique_views_helper.hpp [new file with mode: 0644]
boost/bimap/detail/set_view_base.hpp [new file with mode: 0644]
boost/bimap/detail/set_view_iterator.hpp [new file with mode: 0644]
boost/bimap/detail/test/check_metadata.hpp [new file with mode: 0644]
boost/bimap/detail/user_interface_config.hpp [new file with mode: 0644]
boost/bimap/list_of.hpp [new file with mode: 0644]
boost/bimap/multiset_of.hpp [new file with mode: 0644]
boost/bimap/property_map/set_support.hpp [new file with mode: 0644]
boost/bimap/property_map/unordered_set_support.hpp [new file with mode: 0644]
boost/bimap/relation/detail/access_builder.hpp [new file with mode: 0644]
boost/bimap/relation/detail/metadata_access_builder.hpp [new file with mode: 0644]
boost/bimap/relation/detail/mutant.hpp [new file with mode: 0644]
boost/bimap/relation/detail/static_access_builder.hpp [new file with mode: 0644]
boost/bimap/relation/detail/to_mutable_relation_functor.hpp [new file with mode: 0644]
boost/bimap/relation/member_at.hpp [new file with mode: 0644]
boost/bimap/relation/mutant_relation.hpp [new file with mode: 0644]
boost/bimap/relation/pair_layout.hpp [new file with mode: 0644]
boost/bimap/relation/structured_pair.hpp [new file with mode: 0644]
boost/bimap/relation/support/data_extractor.hpp [new file with mode: 0644]
boost/bimap/relation/support/get.hpp [new file with mode: 0644]
boost/bimap/relation/support/get_pair_functor.hpp [new file with mode: 0644]
boost/bimap/relation/support/is_tag_of_member_at.hpp [new file with mode: 0644]
boost/bimap/relation/support/member_with_tag.hpp [new file with mode: 0644]
boost/bimap/relation/support/opposite_tag.hpp [new file with mode: 0644]
boost/bimap/relation/support/pair_by.hpp [new file with mode: 0644]
boost/bimap/relation/support/pair_type_by.hpp [new file with mode: 0644]
boost/bimap/relation/support/value_type_of.hpp [new file with mode: 0644]
boost/bimap/relation/symmetrical_base.hpp [new file with mode: 0644]
boost/bimap/set_of.hpp [new file with mode: 0644]
boost/bimap/support/data_type_by.hpp [new file with mode: 0644]
boost/bimap/support/iterator_type_by.hpp [new file with mode: 0644]
boost/bimap/support/key_type_by.hpp [new file with mode: 0644]
boost/bimap/support/lambda.hpp [new file with mode: 0644]
boost/bimap/support/map_by.hpp [new file with mode: 0644]
boost/bimap/support/map_type_by.hpp [new file with mode: 0644]
boost/bimap/support/value_type_by.hpp [new file with mode: 0644]
boost/bimap/tags/support/apply_to_value_type.hpp [new file with mode: 0644]
boost/bimap/tags/support/default_tagged.hpp [new file with mode: 0644]
boost/bimap/tags/support/is_tagged.hpp [new file with mode: 0644]
boost/bimap/tags/support/overwrite_tagged.hpp [new file with mode: 0644]
boost/bimap/tags/support/tag_of.hpp [new file with mode: 0644]
boost/bimap/tags/support/value_type_of.hpp [new file with mode: 0644]
boost/bimap/tags/tagged.hpp [new file with mode: 0644]
boost/bimap/unconstrained_set_of.hpp [new file with mode: 0644]
boost/bimap/unordered_multiset_of.hpp [new file with mode: 0644]
boost/bimap/unordered_set_of.hpp [new file with mode: 0644]
boost/bimap/vector_of.hpp [new file with mode: 0644]
boost/bimap/views/list_map_view.hpp [new file with mode: 0644]
boost/bimap/views/list_set_view.hpp [new file with mode: 0644]
boost/bimap/views/map_view.hpp [new file with mode: 0644]
boost/bimap/views/multimap_view.hpp [new file with mode: 0644]
boost/bimap/views/multiset_view.hpp [new file with mode: 0644]
boost/bimap/views/set_view.hpp [new file with mode: 0644]
boost/bimap/views/unconstrained_map_view.hpp [new file with mode: 0644]
boost/bimap/views/unconstrained_set_view.hpp [new file with mode: 0644]
boost/bimap/views/unordered_map_view.hpp [new file with mode: 0644]
boost/bimap/views/unordered_multimap_view.hpp [new file with mode: 0644]
boost/bimap/views/unordered_multiset_view.hpp [new file with mode: 0644]
boost/bimap/views/unordered_set_view.hpp [new file with mode: 0644]
boost/bimap/views/vector_map_view.hpp [new file with mode: 0644]
boost/bimap/views/vector_set_view.hpp [new file with mode: 0644]
boost/multi_index/composite_key.hpp [new file with mode: 0644]
boost/multi_index/detail/access_specifier.hpp [new file with mode: 0644]
boost/multi_index/detail/adl_swap.hpp [new file with mode: 0644]
boost/multi_index/detail/archive_constructed.hpp [new file with mode: 0644]
boost/multi_index/detail/auto_space.hpp [new file with mode: 0644]
boost/multi_index/detail/base_type.hpp [new file with mode: 0644]
boost/multi_index/detail/bidir_node_iterator.hpp [new file with mode: 0644]
boost/multi_index/detail/bucket_array.hpp [new file with mode: 0644]
boost/multi_index/detail/converter.hpp [new file with mode: 0644]
boost/multi_index/detail/copy_map.hpp [new file with mode: 0644]
boost/multi_index/detail/duplicates_iterator.hpp [new file with mode: 0644]
boost/multi_index/detail/has_tag.hpp [new file with mode: 0644]
boost/multi_index/detail/hash_index_args.hpp [new file with mode: 0644]
boost/multi_index/detail/hash_index_iterator.hpp [new file with mode: 0644]
boost/multi_index/detail/hash_index_node.hpp [new file with mode: 0644]
boost/multi_index/detail/header_holder.hpp [new file with mode: 0644]
boost/multi_index/detail/index_base.hpp [new file with mode: 0644]
boost/multi_index/detail/index_loader.hpp [new file with mode: 0644]
boost/multi_index/detail/index_matcher.hpp [new file with mode: 0644]
boost/multi_index/detail/index_node_base.hpp [new file with mode: 0644]
boost/multi_index/detail/index_saver.hpp [new file with mode: 0644]
boost/multi_index/detail/invariant_assert.hpp [new file with mode: 0644]
boost/multi_index/detail/is_index_list.hpp [new file with mode: 0644]
boost/multi_index/detail/iter_adaptor.hpp [new file with mode: 0644]
boost/multi_index/detail/modify_key_adaptor.hpp [new file with mode: 0644]
boost/multi_index/detail/msvc_index_specifier.hpp [new file with mode: 0644]
boost/multi_index/detail/no_duplicate_tags.hpp [new file with mode: 0644]
boost/multi_index/detail/node_type.hpp [new file with mode: 0644]
boost/multi_index/detail/ord_index_args.hpp [new file with mode: 0644]
boost/multi_index/detail/ord_index_node.hpp [new file with mode: 0644]
boost/multi_index/detail/ord_index_ops.hpp [new file with mode: 0644]
boost/multi_index/detail/prevent_eti.hpp [new file with mode: 0644]
boost/multi_index/detail/rnd_index_loader.hpp [new file with mode: 0644]
boost/multi_index/detail/rnd_index_node.hpp [new file with mode: 0644]
boost/multi_index/detail/rnd_index_ops.hpp [new file with mode: 0644]
boost/multi_index/detail/rnd_index_ptr_array.hpp [new file with mode: 0644]
boost/multi_index/detail/rnd_node_iterator.hpp [new file with mode: 0644]
boost/multi_index/detail/safe_ctr_proxy.hpp [new file with mode: 0644]
boost/multi_index/detail/safe_mode.hpp [new file with mode: 0644]
boost/multi_index/detail/scope_guard.hpp [new file with mode: 0644]
boost/multi_index/detail/seq_index_node.hpp [new file with mode: 0644]
boost/multi_index/detail/seq_index_ops.hpp [new file with mode: 0644]
boost/multi_index/detail/uintptr_type.hpp [new file with mode: 0644]
boost/multi_index/detail/unbounded.hpp [new file with mode: 0644]
boost/multi_index/detail/value_compare.hpp [new file with mode: 0644]
boost/multi_index/global_fun.hpp [new file with mode: 0644]
boost/multi_index/hashed_index.hpp [new file with mode: 0644]
boost/multi_index/hashed_index_fwd.hpp [new file with mode: 0644]
boost/multi_index/identity.hpp [new file with mode: 0644]
boost/multi_index/identity_fwd.hpp [new file with mode: 0644]
boost/multi_index/indexed_by.hpp [new file with mode: 0644]
boost/multi_index/key_extractors.hpp [new file with mode: 0644]
boost/multi_index/mem_fun.hpp [new file with mode: 0644]
boost/multi_index/member.hpp [new file with mode: 0644]
boost/multi_index/ordered_index.hpp [new file with mode: 0644]
boost/multi_index/ordered_index_fwd.hpp [new file with mode: 0644]
boost/multi_index/random_access_index.hpp [new file with mode: 0644]
boost/multi_index/random_access_index_fwd.hpp [new file with mode: 0644]
boost/multi_index/safe_mode_errors.hpp [new file with mode: 0644]
boost/multi_index/sequenced_index.hpp [new file with mode: 0644]
boost/multi_index/sequenced_index_fwd.hpp [new file with mode: 0644]
boost/multi_index/tag.hpp [new file with mode: 0644]
boost/multi_index_container.hpp [new file with mode: 0644]
boost/multi_index_container_fwd.hpp [new file with mode: 0644]

diff --git a/Console/Traits.cc b/Console/Traits.cc
new file mode 100644 (file)
index 0000000..9207a13
--- /dev/null
@@ -0,0 +1,68 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Traits non-inline non-template implementation */
+
+#include "Traits.hh"
+#include "Traits.ih"
+
+// Custom includes
+#include "../Utils/senfassert.hh"
+
+//#include "Traits.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+prefix_ long senf::console::detail::parseEnum(EnumTable const & table,
+                                              ParseCommandInfo::TokensRange const & tokens)
+{
+    if (tokens.size() != 1)
+        throw SyntaxErrorException("parameter syntax error");
+
+    EnumTable::left_map::const_iterator i (table.left.find(tokens.begin()[0].value()));
+    if (i == table.left.end())
+        throw SyntaxErrorException("parameter syntax error: Invalid enum value");
+    return i->second;
+}
+
+prefix_ std::string senf::console::detail::formatEnum(EnumTable const & table, long value)
+{
+    EnumTable::right_map::const_iterator i (table.right.find(value));
+    SENF_ASSERT( i != table.right.end() );
+    return i->second;
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Traits.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index e96392f..6e777ef 100644 (file)
 /** \file
     \brief Traits inline template implementation */
 
-//#include "Traits.ih"
+#include "Traits.ih"
 
 // Custom includes
+#include <sstream>
+#include <boost/lexical_cast.hpp>
 #include "../Utils/TypeInfo.hh"
 
 #define prefix_ inline
@@ -38,6 +40,12 @@ template <class Type>
 prefix_ void senf::console::ReturnValueTraits<Type>::format(Type const & value,
                                                             std::ostream & os)
 {
+    senf_console_format_value(value, os);
+}
+
+template <class Type>
+prefix_ void senf::console::senf_console_format_value(Type const & value, std::ostream & os)
+{
     os << value;
 }
 
@@ -48,6 +56,14 @@ template <class Type>
 prefix_ void senf::console::ArgumentTraits<Type>::
 parse(ParseCommandInfo::TokensRange const & tokens, Type & out)
 {
+    senf_console_parse_argument(tokens,out);
+}
+
+template <class Type>
+prefix_ void
+senf::console::senf_console_parse_argument(ParseCommandInfo::TokensRange const & tokens,
+                                           Type & out)
+{
     if (tokens.size() != 1)
         throw SyntaxErrorException("parameter syntax error");
 
@@ -70,7 +86,9 @@ prefix_ std::string senf::console::ArgumentTraits<Type>::description()
 template <class Type>
 prefix_ std::string senf::console::ArgumentTraits<Type>::str(Type const & value)
 {
-    return boost::lexical_cast<std::string>(value);
+    std::stringstream ss;
+    senf::console::ReturnValueTraits<Type>::format(value, ss);
+    return ss.str();
 }
 
 ///////////////////////////////cti.e///////////////////////////////////////
index 8176fb0..779ef30 100644 (file)
@@ -33,6 +33,7 @@
 #include "Parse.hh"
 #include "Node.hh"
 
+#include "Traits.ih"
 //#include "Traits.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
 
@@ -56,6 +57,9 @@ namespace console {
         static void format(Type const & value, std::ostream & os);
                                         ///< Write \a value to \a os
     };
+    
+    template <class Type>
+    void senf_console_format_value(Type const & value, std::ostream & os);
 
     /** \brief Customize argument parsing
         
@@ -91,9 +95,15 @@ namespace console {
         static std::string str(Type const & value); ///< Stringify value
                                         /**< To show default values in the online help, this
                                              function converts a value back into a one-line string
-                                             representation. */
+                                             representation. The default implementation uses the
+                                             ReturnValueTraits for this conversion. */
     };
-    
+
+    template <class Type>
+    void senf_console_parse_argument(ParseCommandInfo::TokensRange const & tokens, Type & out);
+
+#   define SENF_CONSOLE_REGISTER_ENUM(Type, Values) SENF_CONSOLE_REGISTER_ENUM_(Type, Values)
+
 }}
 
 ///////////////////////////////hh.e////////////////////////////////////////
diff --git a/Console/Traits.ih b/Console/Traits.ih
new file mode 100644 (file)
index 0000000..12fbb65
--- /dev/null
@@ -0,0 +1,96 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Traits internal header */
+
+#ifndef IH_Traits_
+#define IH_Traits_ 1
+
+// Custom includes
+#include <string>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/preprocessor/stringize.hpp>
+#include <boost/bimap.hpp>
+#include <boost/assign/list_inserter.hpp>
+#include "../Utils/singleton.hh"
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+namespace detail {
+
+    typedef boost::bimap<std::string, long> EnumTable;
+
+    long parseEnum(EnumTable const & table, ParseCommandInfo::TokensRange const & tokens);
+    std::string formatEnum(EnumTable const & table, long value);
+
+    template <class EnumType>
+    struct EnumTraits : public senf::singleton< EnumTraits<EnumType> >
+    {
+        using senf::singleton< EnumTraits<EnumType> >::instance;
+        EnumTable table;
+    };
+
+#   define SENF_CONSOLE_REGISTER_ENUM_ELT(r,d,e) (BOOST_PP_STRINGIZE(e), static_cast<long>(e))
+
+#   define SENF_CONSOLE_REGISTER_ENUM_(Type, Values)                                              \
+        void senf_console_init_enum_table(Type)                                                   \
+        {                                                                                         \
+            senf::console::detail::EnumTraits<Type> & traits (                                    \
+                senf::console::detail::EnumTraits<Type>::instance() );                            \
+            if (traits.table.empty())                                                             \
+                boost::assign::insert(traits.table)                                               \
+                    BOOST_PP_SEQ_FOR_EACH( SENF_CONSOLE_REGISTER_ENUM_ELT, _, Values );           \
+        }                                                                                         \
+        void senf_console_parse_argument(                                                         \
+            senf::console::ParseCommandInfo::TokensRange const & tokens, Type & out)              \
+        {                                                                                         \
+            senf_console_init_enum_table( Type() );                                               \
+            out = static_cast<Type>(                                                              \
+                senf::console::detail::parseEnum(                                                 \
+                    senf::console::detail::EnumTraits<Type>::instance().table, tokens));          \
+        }                                                                                         \
+        void senf_console_format_value(Type value, std::ostream & os)                             \
+        {                                                                                         \
+            senf_console_init_enum_table( Type() );                                               \
+            os << senf::console::detail::formatEnum(                                              \
+                senf::console::detail::EnumTraits<Type>::instance().table,                        \
+                static_cast<long>(value) );                                                       \
+        }
+
+}}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index 83f8af5..861d0f0 100644 (file)
 
 // Custom includes
 #include "Traits.hh"
+#include "ParsedCommand.hh"
+#include "Executor.hh"
+#include "Parse.hh"
+#include "ScopedDirectory.hh"
 
 #include "../Utils/auto_unit_test.hh"
 #include <boost/test/test_tools.hpp>
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-BOOST_AUTO_UNIT_TEST(parseParameter)
-{}
+namespace {
+    enum TestEnum { Foo, Bar };
+    SENF_CONSOLE_REGISTER_ENUM( TestEnum, (Foo)(Bar) );
+
+    TestEnum test (TestEnum value) { return value; }
+}
+
+BOOST_AUTO_UNIT_TEST(enumSupport)
+{
+    senf::console::Executor executor;
+    senf::console::CommandParser parser;
+    senf::console::ScopedDirectory<> dir;
+    senf::console::root().add("test", dir);
+
+    dir.add("test",&test);
+    
+    std::stringstream ss;
+    BOOST_CHECK_NO_THROW(
+        parser.parse("test/test Foo",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+    BOOST_CHECK_EQUAL( ss.str(), "Foo\n" );
+
+    ss.str("");
+    BOOST_CHECK_NO_THROW(
+        parser.parse("test/test Bar",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+    BOOST_CHECK_EQUAL( ss.str(), "Bar\n" );
+
+    BOOST_CHECK_THROW(
+        parser.parse("test/test (Foo Bar)",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )),
+        senf::console::SyntaxErrorException );
+
+    BOOST_CHECK_THROW(
+        parser.parse("test/test Baz",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )),
+        senf::console::SyntaxErrorException );
+}
+
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
diff --git a/boost/bimap.hpp b/boost/bimap.hpp
new file mode 100644 (file)
index 0000000..51d726d
--- /dev/null
@@ -0,0 +1,19 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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 www.boost.org/libs/bimap for documentation.
+
+// Convenience header
+
+#include <boost/bimap/bimap.hpp>
+
+namespace boost
+{
+    using ::boost::bimaps::bimap;
+}
+
diff --git a/boost/bimap/bimap.hpp b/boost/bimap/bimap.hpp
new file mode 100644 (file)
index 0000000..9af5cbf
--- /dev/null
@@ -0,0 +1,433 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file bimap.hpp
+/// \brief Includes the basic bimap container
+
+/** \mainpage notitle
+\n
+\image html http://matias.capeletto.googlepages.com/boost.bimap.reference.logo.png
+
+\section Introduction
+
+This is the complete reference of Boost.Bimap.
+
+After getting a good understanding of the library from a user perspective
+the next step will be:
+
+    - Understand the tagged idiom. (boost::bimaps::tags)
+    - Understand the internals of the relation class (boost::bimaps::relation)
+    - Read the container_adaptor toolbox docs (boost::bimaps::container_adaptor)
+    - Understand the internals of the bimap class. (boost::bimaps, boost::bimaps::views
+      and boost::bimaps::detail)
+
+
+                                                                        **/
+
+/** \defgroup mutant_group mutant idiom
+\brief A safe wrapper around reinterpret_cast
+                                                                        **/
+
+/** \defgroup relation_group relation
+\brief The relation
+                                                                        **/
+
+/** \defgroup tags_group tagged idiom
+\brief The tagged idiom
+                                                                        **/
+
+
+#ifndef BOOST_BIMAP_BIMAP_HPP
+#define BOOST_BIMAP_BIMAP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/bimap/detail/user_interface_config.hpp>
+#include <boost/mpl/aux_/na.hpp>
+
+#define BOOST_BIMAP_DISABLE_SERIALIZATION
+#define BOOST_MULTI_INDEX_DISABLE_SERIALIZATION
+
+#ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
+    #include <boost/serialization/nvp.hpp>
+#endif // BOOST_BIMAP_DISABLE_SERIALIZATION
+
+// Boost.Bimap
+#include <boost/bimap/detail/bimap_core.hpp>
+#include <boost/bimap/detail/map_view_base.hpp>
+#include <boost/bimap/detail/modifier_adaptor.hpp>
+#include <boost/bimap/relation/support/data_extractor.hpp>
+#include <boost/bimap/relation/support/member_with_tag.hpp>
+
+#include <boost/bimap/support/map_type_by.hpp>
+#include <boost/bimap/support/map_by.hpp>
+#include <boost/bimap/support/iterator_type_by.hpp>
+
+/// \brief The namespace where all the boost libraries lives.
+
+namespace boost {
+
+/// \brief Boost.Bimap library namespace
+/**
+All the entities in the library are defined in this namespace.
+                                                                    **/
+namespace bimaps {
+
+/// \brief The bimap class is the entry point to the library.
+/**
+This class manages the instantiation of the desired bimap type.
+As there are several types of bidirectional maps that can be
+created using it. the main job of it is to find the desired
+type. This is done using metaprogramming to obtain the relation
+type that will be stored, the map_view type of each side and
+the set_view type of the general relationship. The instantiation
+is kept simple using an extended standard set theory, where a
+bidirectional map type is defined by the set types it relates.
+For example, a bidirectional map that has multimap semantics
+viewed from both sides is defined by specifying that the two
+keys sets are of \c multiset_of<Key> type.
+This allows the bimap class to support seamingless N-N, 1-N,
+ordered/unordered and even vector-list types of mapping.
+The three last parameters are used to specify the set type of
+the relation, an inplace hooked data class and the allocator
+type. As a help to the bimap user, these parameters support
+default types but use a special idiom that allow them to be
+specified without interleaving the usual use_default keyword.
+The possible bimap instantiation are enumerated here:
+\c {Side}KeyType can be directly a type, this is default to
+\c set_of<{Side}KeyType>, or can be a \c {SetType}_of<Type>
+specification. Additionally this two parameters can be tagged
+to specify others tags instead of the usual \c member_at::{Side}
+ones.
+
+
+\code
+
+    typedef bimap
+    <
+        LeftCollectionType, RightCollectionType
+
+        [ , SetTypeOfRelation  ]  // Default to left_based
+        [ , info_hook< Info >  ]  // Default to no info
+        [ , Allocator          ]  // Default to std::allocator<>
+
+    > bm;
+
+\endcode
+
+                                                                       **/
+
+
+template
+<
+    class KeyTypeA, class KeyTypeB,
+    class AP1 = ::boost::mpl::na,
+    class AP2 = ::boost::mpl::na,
+    class AP3 = ::boost::mpl::na
+>
+class bimap
+:
+    // Bimap Core, use mpl magic to find the desired bimap type
+
+    public ::boost::bimaps::detail::bimap_core<KeyTypeA,KeyTypeB,AP1,AP2,AP3>,
+
+    // You can use bimap as a collection of relations
+
+    public ::boost::bimaps::detail::bimap_core<KeyTypeA,KeyTypeB,AP1,AP2,AP3>
+                ::relation_set,
+
+    // Include extra typedefs (i.e. left_local_iterator for unordered_map)
+
+    public ::boost::bimaps::detail:: left_map_view_extra_typedefs<
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail::left_map_view_type<
+            ::boost::bimaps::detail::bimap_core<KeyTypeA,KeyTypeB,AP1,AP2,AP3>
+        >::type
+    >,
+    public ::boost::bimaps::detail::right_map_view_extra_typedefs< 
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail::right_map_view_type<
+            ::boost::bimaps::detail::bimap_core<KeyTypeA,KeyTypeB,AP1,AP2,AP3>
+        >::type
+    >
+{
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail::
+        bimap_core<KeyTypeA,KeyTypeB,AP1,AP2,AP3> base_;
+
+    BOOST_DEDUCED_TYPENAME base_::core_type core;
+
+    public:
+
+    // metadata --------------------------------------------------------
+
+    /*
+    // The rest is computed in the core, because it is quite difficult to
+    // expose a nice interface with so many metaprogramming stuff.
+    // Here it is the complete metadat list.
+
+    // Map by {side} metadata
+
+    typedef -unspecified- {side}_tag;
+    typedef -unspecified- {side}_data_type;
+    typedef -unspecified- {side}_value_type;
+    typedef -unspecified- {side}_key_type;
+    typedef -unspecified- {side}_iterator;
+    typedef -unspecified- {side}_const_iterator;
+
+    ------------------------------------------------------------------*/
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail::
+          left_map_view_type<base_>::type  left_map;
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail::
+         right_map_view_type<base_>::type right_map;
+
+    typedef BOOST_DEDUCED_TYPENAME
+         left_map::reference        left_reference;
+    typedef BOOST_DEDUCED_TYPENAME
+         left_map::const_reference  left_const_reference;
+
+    typedef BOOST_DEDUCED_TYPENAME
+        right_map::reference       right_reference;
+    typedef BOOST_DEDUCED_TYPENAME
+        right_map::const_reference right_const_reference;
+
+    typedef BOOST_DEDUCED_TYPENAME base_::relation::info_type info_type;
+
+    /// Left map view
+    left_map  left;
+
+    /// Right map view
+    right_map right;
+
+    bimap() :
+
+        base_::relation_set(
+            ::boost::multi_index::get<
+                BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag 
+            >(core) 
+        ),
+        left (
+            ::boost::multi_index::get<
+                BOOST_DEDUCED_TYPENAME base_::logic_left_tag
+            >(core)
+        ),
+        right (
+            ::boost::multi_index::get<
+                BOOST_DEDUCED_TYPENAME base_::logic_right_tag 
+            >(core)
+        )
+
+    {}
+
+    template< class InputIterator >
+    bimap(InputIterator first,InputIterator last) :
+
+        base_::relation_set(
+            ::boost::multi_index::get<
+                BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag
+            >(core) 
+        ),
+
+        core(first,last),
+
+        left (
+            ::boost::multi_index::get<
+                BOOST_DEDUCED_TYPENAME base_::logic_left_tag
+            >(core)
+        ),
+        right (
+            ::boost::multi_index::get<
+                BOOST_DEDUCED_TYPENAME base_::logic_right_tag
+            >(core)
+        )
+
+    {}
+
+    bimap(const bimap& x) :
+
+        base_::relation_set(
+            ::boost::multi_index::get<
+                BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag
+            >(core) 
+        ),
+
+        core(x.core),
+
+        left (
+            ::boost::multi_index::get<
+                BOOST_DEDUCED_TYPENAME base_::logic_left_tag
+            >(core)
+        ),
+        right (
+            ::boost::multi_index::get<
+                BOOST_DEDUCED_TYPENAME base_::logic_right_tag
+            >(core)
+        )
+
+    {}
+
+    bimap& operator=(const bimap& x)
+    {
+        core = x.core;
+        return *this;
+    }
+
+    // Projection of iterators
+
+    template< class IteratorType >
+    BOOST_DEDUCED_TYPENAME base_::left_iterator
+        project_left(IteratorType iter)
+    {
+        return core.template project<
+            BOOST_DEDUCED_TYPENAME base_::logic_left_tag>(iter.base());
+    }
+
+    template< class IteratorType >
+    BOOST_DEDUCED_TYPENAME base_::left_const_iterator
+        project_left(IteratorType iter) const
+    {
+        return core.template project<
+            BOOST_DEDUCED_TYPENAME base_::logic_left_tag>(iter.base());
+    }
+
+    template< class IteratorType >
+    BOOST_DEDUCED_TYPENAME base_::right_iterator
+        project_right(IteratorType iter)
+    {
+        return core.template project<
+            BOOST_DEDUCED_TYPENAME base_::logic_right_tag>(iter.base());
+    }
+
+    template< class IteratorType >
+    BOOST_DEDUCED_TYPENAME base_::right_const_iterator
+        project_right(IteratorType iter) const
+    {
+        return core.template project<
+            BOOST_DEDUCED_TYPENAME base_::logic_right_tag>(iter.base());
+    }
+
+    template< class IteratorType >
+    BOOST_DEDUCED_TYPENAME base_::relation_set::iterator
+        project_up(IteratorType iter)
+    {
+        return core.template project<
+            BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag>(iter.base());
+    }
+
+    template< class IteratorType >
+    BOOST_DEDUCED_TYPENAME base_::relation_set::const_iterator
+        project_up(IteratorType iter) const
+    {
+        return core.template project<
+            BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag>(iter.base());
+    }
+
+    // Support for tags
+
+    template< class Tag, class IteratorType >
+    BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+    iterator_type_by<Tag,bimap>::type
+        project(IteratorType iter
+                BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
+    {
+        return core.template project<Tag>(iter.base());
+    }
+
+    template< class Tag, class IteratorType >
+    BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+    const_iterator_type_by<Tag,bimap>::type
+        project(IteratorType iter
+                BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag)) const
+    {
+        return core.template project<Tag>(iter.base());
+    }
+
+    template< class Tag >
+    struct map_by :
+        public ::boost::bimaps::support::map_type_by<Tag,bimap>::type
+    {
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+            map_type_by<Tag,bimap>::type type;
+
+        private: map_by() {}
+    };
+
+    template< class Tag >
+    BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+    map_type_by<Tag,bimap>::type &
+        by(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
+    {
+        return ::boost::bimaps::support::map_by<Tag>(*this);
+    }
+
+    template< class Tag >
+    const BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+    map_type_by<Tag,bimap>::type &
+        by(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const
+    {
+        return ::boost::bimaps::support::map_by<Tag>(*this);
+    }
+
+
+    #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
+
+    // Serialization support
+
+    private:
+
+    friend class boost::serialization::access;
+
+    template<class Archive>
+    void serialize(Archive & ar, const unsigned int version)
+    {
+        ar & serialization::make_nvp("mi_core",core);
+    }
+
+    #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
+};
+
+} // namespace bimaps
+} // namespace boost
+
+
+/** \namespace boost::bimaps::support
+\brief Metafunctions to help working with bimaps.
+                                                            **/
+
+/** \namespace boost::bimaps::views
+\brief Bimap views.
+                                                            **/
+
+/** \namespace boost::bimaps::views::detail
+\brief Bimap views details.
+                                                            **/
+
+
+
+// Include basic tools for user commodity
+
+#include <boost/bimap/tags/tagged.hpp>
+#include <boost/bimap/relation/member_at.hpp>
+#include <boost/multi_index/detail/unbounded.hpp>
+
+// Bring the most used namespaces directly to the user main namespace
+namespace boost {
+namespace bimaps {
+
+using ::boost::bimaps::tags::tagged;
+
+namespace member_at = ::boost::bimaps::relation::member_at;
+
+using ::boost::multi_index::unbounded;
+
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_BIMAP_HPP
diff --git a/boost/bimap/container_adaptor/associative_container_adaptor.hpp b/boost/bimap/container_adaptor/associative_container_adaptor.hpp
new file mode 100644 (file)
index 0000000..191a642
--- /dev/null
@@ -0,0 +1,287 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/associative_container_adaptor.hpp
+/// \brief Container adaptor to build a type that is compliant to the concept of an associative container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <utility>
+
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/bimap/container_adaptor/detail/identity_converters.hpp>
+#include <boost/bimap/container_adaptor/container_adaptor.hpp>
+#include <boost/call_traits.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template
+<
+    class Base, class Iterator, class ConstIterator, class KeyType,
+    class IteratorToBaseConverter, class IteratorFromBaseConverter,
+    class ValueToBaseConverter, class ValueFromBaseConverter, class KeyToBaseConverter,
+    class FunctorsFromDerivedClasses
+>
+struct associative_container_adaptor_base
+{
+    typedef container_adaptor
+    <
+        Base,
+
+        Iterator, ConstIterator,
+
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ValueToBaseConverter   , ValueFromBaseConverter,
+
+        BOOST_DEDUCED_TYPENAME mpl::push_front<
+
+            FunctorsFromDerivedClasses,
+
+            BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na<KeyToBaseConverter>,
+            // {
+                    detail::key_to_base_identity
+                    <
+                        BOOST_DEDUCED_TYPENAME Base::key_type, KeyType
+                    >,
+            // }
+            // else
+            // {
+                    KeyToBaseConverter
+            // }
+
+            >::type
+
+        >::type
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+
+/// \brief Container adaptor to build a type that is compliant to the concept of an associative container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+
+    class KeyType,
+
+    class IteratorToBaseConverter   = ::boost::mpl::na,
+    class IteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter      = ::boost::mpl::na,
+    class ValueFromBaseConverter    = ::boost::mpl::na,
+    class KeyToBaseConverter        = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class associative_container_adaptor :
+
+    public associative_container_adaptor_base
+    <
+        Base, Iterator, ConstIterator, KeyType,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    >::type
+{
+
+    // MetaData -------------------------------------------------------------
+
+    typedef typename associative_container_adaptor_base
+    <
+        Base, Iterator, ConstIterator, KeyType,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    >::type base_;
+
+    public:
+
+    typedef KeyType key_type;
+
+    protected:
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na<KeyToBaseConverter>,
+    // {
+            detail::key_to_base_identity
+            <
+                BOOST_DEDUCED_TYPENAME Base::key_type, KeyType
+            >,
+    // }
+    // else
+    // {
+            KeyToBaseConverter
+    // }
+
+    >::type key_to_base;
+
+    public:
+
+    explicit associative_container_adaptor(Base & c)
+        : base_(c) {}
+
+    protected:
+
+
+    typedef associative_container_adaptor associative_container_adaptor_;
+
+    // Interface --------------------------------------------------------------
+
+    public:
+
+    template< class CompatibleKey >
+    BOOST_DEDUCED_TYPENAME base_::size_type erase(const CompatibleKey & k)
+    {
+        return this->base().erase
+        (
+            this->template functor<key_to_base>()(k)
+        );
+    }
+
+    // As we redefine erase, the other overloads need to be manually routed
+
+    BOOST_DEDUCED_TYPENAME base_::iterator erase(
+        BOOST_DEDUCED_TYPENAME base_::iterator pos)
+    {
+        return base_::container_adaptor_::erase(pos);
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::iterator erase(
+        BOOST_DEDUCED_TYPENAME base_::iterator first,
+        BOOST_DEDUCED_TYPENAME base_::iterator last)
+    {
+        return base_::container_adaptor_::erase(first,last);
+    }
+
+    template< class CompatibleKey >
+    BOOST_DEDUCED_TYPENAME base_::size_type count(const CompatibleKey & k)
+    {
+        return this->base().count(
+            this->template functor<key_to_base>()(k)
+        );
+    }
+
+    template< class CompatibleKey >
+    BOOST_DEDUCED_TYPENAME base_::iterator find(const CompatibleKey & k)
+    {
+        return this->template functor<typename base_::iterator_from_base>()
+        (
+            this->base().find(
+                this->template functor<key_to_base>()(k)
+            )
+        );
+    }
+
+    template< class CompatibleKey >
+    BOOST_DEDUCED_TYPENAME base_::const_iterator
+        find(const CompatibleKey & k) const
+    {
+        return this->template functor<
+            BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()
+        (
+            this->base().find(
+                this->template functor<key_to_base>()(k)
+            )
+        );
+    }
+
+    template< class CompatibleKey >
+    std::pair
+    <
+        BOOST_DEDUCED_TYPENAME base_::iterator,
+        BOOST_DEDUCED_TYPENAME base_::iterator
+    >
+        equal_range(const CompatibleKey & k)
+    {
+        std::pair<
+
+            BOOST_DEDUCED_TYPENAME Base::iterator,
+            BOOST_DEDUCED_TYPENAME Base::iterator
+
+        > r( this->base().equal_range(
+                this->template functor<key_to_base>()(k)
+            )
+        );
+
+        return std::pair
+        <
+            BOOST_DEDUCED_TYPENAME base_::iterator,
+            BOOST_DEDUCED_TYPENAME base_::iterator
+        >(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_from_base
+            >()                                         ( r.first ),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_from_base
+            >()                                         ( r.second )
+        );
+    }
+
+    template< class CompatibleKey >
+    std::pair
+    <
+        BOOST_DEDUCED_TYPENAME base_::const_iterator,
+        BOOST_DEDUCED_TYPENAME base_::const_iterator
+    >
+        equal_range(const CompatibleKey & k) const
+    {
+        std::pair<
+
+            BOOST_DEDUCED_TYPENAME Base::const_iterator,
+            BOOST_DEDUCED_TYPENAME Base::const_iterator
+
+        > r( this->base().equal_range(
+                this->template functor<key_to_base>()(k)
+            )
+        );
+
+        return std::pair
+        <
+            BOOST_DEDUCED_TYPENAME base_::const_iterator,
+            BOOST_DEDUCED_TYPENAME base_::const_iterator
+        >(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_from_base
+            >()                                         ( r.first ),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_from_base
+            >()                                         ( r.second )
+        );
+    }
+
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP
+
+
+
diff --git a/boost/bimap/container_adaptor/container_adaptor.hpp b/boost/bimap/container_adaptor/container_adaptor.hpp
new file mode 100644 (file)
index 0000000..8e78090
--- /dev/null
@@ -0,0 +1,291 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/container_adaptor.hpp
+/// \brief Container adaptor to build a type that is compliant to the concept of a container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_CONTAINER_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_CONTAINER_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <utility>
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/bimap/container_adaptor/detail/identity_converters.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+
+#include <boost/bimap/container_adaptor/detail/functor_bag.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/front_inserter.hpp>
+#include <boost/call_traits.hpp>
+
+
+
+namespace boost {
+namespace bimaps {
+
+/// \brief Container Adaptor toolbox, easy way to build new containers from existing ones.
+
+namespace container_adaptor {
+
+/// \brief Container adaptor to build a type that is compliant to the concept of a container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+
+    class IteratorToBaseConverter   = ::boost::mpl::na,
+    class IteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter      = ::boost::mpl::na,
+    class ValueFromBaseConverter    = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class container_adaptor
+{
+    // MetaData -------------------------------------------------------------
+
+    public:
+
+    typedef Iterator iterator;
+    typedef ConstIterator const_iterator;
+
+    typedef BOOST_DEDUCED_TYPENAME iterator_value    <       iterator >::type value_type;
+    typedef BOOST_DEDUCED_TYPENAME iterator_pointer  <       iterator >::type pointer;
+    typedef BOOST_DEDUCED_TYPENAME iterator_reference<       iterator >::type reference;
+    typedef BOOST_DEDUCED_TYPENAME iterator_reference< const_iterator >::type const_reference;
+
+    typedef BOOST_DEDUCED_TYPENAME Base::size_type size_type;
+    typedef BOOST_DEDUCED_TYPENAME Base::difference_type difference_type;
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na<IteratorToBaseConverter>,
+        // {
+                ::boost::bimaps::container_adaptor::detail::
+                    iterator_to_base_identity
+                <
+                    BOOST_DEDUCED_TYPENAME Base::iterator                , iterator,
+                    BOOST_DEDUCED_TYPENAME Base::const_iterator          , const_iterator
+                >,
+        // }
+        // else
+        // {
+                IteratorToBaseConverter
+        // }
+
+        >::type iterator_to_base;
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na<IteratorFromBaseConverter>,
+        // {
+                ::boost::bimaps::container_adaptor::detail::
+                    iterator_from_base_identity
+                <
+                    BOOST_DEDUCED_TYPENAME Base::iterator                , iterator,
+                    BOOST_DEDUCED_TYPENAME Base::const_iterator          , const_iterator
+                >,
+        // }
+        // else
+        // {
+                IteratorFromBaseConverter
+        // }
+
+        >::type iterator_from_base;
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na<ValueToBaseConverter>,
+        // {
+                ::boost::bimaps::container_adaptor::detail::
+                    value_to_base_identity
+                <
+                    BOOST_DEDUCED_TYPENAME Base::value_type,
+                    value_type
+                >,
+        // }
+        // else
+        // {
+                ValueToBaseConverter
+        // }
+
+        >::type value_to_base;
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na<ValueFromBaseConverter>,
+        // {
+                ::boost::bimaps::container_adaptor::detail::
+                    value_from_base_identity
+                <
+                    BOOST_DEDUCED_TYPENAME Base::value_type,
+                    value_type
+                >,
+        // }
+        // else
+        // {
+                ValueFromBaseConverter
+        // }
+
+        >::type value_from_base;
+
+    // ACCESS -----------------------------------------------------------------
+
+    public:
+
+    explicit container_adaptor(Base & c) : dwfb(c) {}
+
+    protected:
+
+    typedef Base base_type;
+
+    typedef container_adaptor container_adaptor_;
+
+    const Base & base() const { return dwfb.data; }
+          Base & base()       { return dwfb.data; }
+
+    // Interface --------------------------------------------------------------
+
+    public:
+
+    size_type size() const                    { return base().size();         }
+    size_type max_size() const                { return base().max_size();     }
+    bool empty() const                        { return base().empty();        }
+
+    iterator begin()
+    {
+        return this->template functor<iterator_from_base>()( base().begin() );
+    }
+
+    iterator end()
+    {
+        return this->template functor<iterator_from_base>()( base().end() );
+    }
+
+    const_iterator begin() const
+    {
+        return this->template functor<iterator_from_base>()( base().begin() );
+    }
+
+    const_iterator end() const
+    {
+        return this->template functor<iterator_from_base>()( base().end() );
+    }
+
+
+    iterator erase(iterator pos)
+    {
+        return this->template functor<iterator_from_base>()(
+            base().erase(this->template functor<iterator_to_base>()(pos))
+        );
+    }
+
+    iterator erase(iterator first, iterator last)
+    {
+        return this->template functor<iterator_from_base>()(
+            base().erase(
+                this->template functor<iterator_to_base>()(first),
+                this->template functor<iterator_to_base>()(last)
+            )
+        );
+    }
+
+    void clear()
+    {
+        base().clear();
+    }
+
+    template< class InputIterator >
+    void insert(InputIterator iterBegin, InputIterator iterEnd)
+    {
+        for( ; iterBegin != iterEnd ; ++iterBegin )
+        {
+            base().insert( this->template
+                functor<value_to_base>()( *iterBegin )
+            );
+        }
+    }
+
+    std::pair<iterator, bool> insert(
+        BOOST_DEDUCED_TYPENAME ::boost::call_traits< value_type >::param_type x)
+    {
+        std::pair< BOOST_DEDUCED_TYPENAME Base::iterator, bool > r(
+            base().insert( this->template functor<value_to_base>()(x) )
+        );
+
+        return std::pair<iterator, bool>( this->template
+                    functor<iterator_from_base>()(r.first),r.second
+               );
+    }
+
+    iterator insert(iterator pos,
+                    BOOST_DEDUCED_TYPENAME ::boost::call_traits< value_type >::param_type x)
+    {
+        return this->template functor<iterator_from_base>()(
+            base().insert(
+                this->template functor<iterator_to_base>()(pos),
+                this->template functor<value_to_base>()(x))
+        );
+    }
+
+    void swap( container_adaptor & c )
+    {
+        base().swap( c.base() );
+    }
+
+    // Access to functors ----------------------------------------------------
+
+    protected:
+
+    template< class Functor >
+    Functor & functor()
+    {
+        return dwfb.template functor<Functor>();
+    }
+
+    template< class Functor >
+    Functor const & functor() const
+    {
+        return dwfb.template functor<Functor>();
+    }
+
+    // Data ------------------------------------------------------------------
+
+    private:
+
+    ::boost::bimaps::container_adaptor::detail::data_with_functor_bag
+    <
+        Base &,
+
+        BOOST_DEDUCED_TYPENAME mpl::copy
+        <
+            mpl::vector
+            <
+                iterator_to_base,
+                iterator_from_base,
+                value_to_base,
+                value_from_base
+            >,
+
+            mpl::front_inserter< FunctorsFromDerivedClasses >
+
+        >::type
+
+    > dwfb;
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_CONTAINER_ADAPTOR_HPP
diff --git a/boost/bimap/container_adaptor/detail/comparison_adaptor.hpp b/boost/bimap/container_adaptor/detail/comparison_adaptor.hpp
new file mode 100644 (file)
index 0000000..9051a46
--- /dev/null
@@ -0,0 +1,101 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/detail/comparison_adaptor.hpp
+/// \brief Comparison adaptor.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_COMPARISON_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_COMPARISON_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/call_traits.hpp>
+#include <functional>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+namespace detail {
+
+/// \brief Comparison adaptor
+/**
+
+A simple comparison adaptor.
+                                                                                    **/
+
+template < class Compare, class NewType, class Converter >
+struct comparison_adaptor : std::binary_function<NewType,NewType,bool>
+{
+    comparison_adaptor( const Compare & comp, const Converter & conv)
+        : compare(comp), converter(conv) {}
+
+    bool operator()( BOOST_DEDUCED_TYPENAME call_traits<NewType>::param_type x,
+                     BOOST_DEDUCED_TYPENAME call_traits<NewType>::param_type y) const
+    {
+        return compare( converter(x), converter(y) );
+    }
+
+    private:
+    Compare     compare;
+    Converter   converter;
+};
+
+template < class Compare, class NewType, class Converter >
+struct compatible_comparison_adaptor : std::binary_function<NewType,NewType,bool>
+{
+    compatible_comparison_adaptor( const Compare & comp, const Converter & conv)
+        : compare(comp), converter(conv) {}
+
+    template< class CompatibleTypeLeft, class CompatibleTypeRight >
+    bool operator()( const CompatibleTypeLeft  & x,
+                     const CompatibleTypeRight & y) const
+    {
+        return compare( converter(x), converter(y) );
+    }
+
+    private:
+    Compare     compare;
+    Converter   converter;
+};
+
+
+/// \brief Unary Check adaptor
+/**
+
+A simple unary check adaptor.
+                                                                                    **/
+
+template < class Compare, class NewType, class Converter >
+struct unary_check_adaptor : std::unary_function<NewType,bool>
+{
+    unary_check_adaptor( const Compare & comp, const Converter & conv ) :
+        compare(comp), converter(conv) {}
+
+    bool operator()( BOOST_DEDUCED_TYPENAME call_traits<NewType>::param_type x) const
+    {
+        return compare( converter(x) );
+    }
+
+    private:
+    Compare   compare;
+    Converter converter;
+};
+
+} // namespace detail
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_COMPARISON_ADAPTOR_HPP
+
+
diff --git a/boost/bimap/container_adaptor/detail/functor_bag.hpp b/boost/bimap/container_adaptor/detail/functor_bag.hpp
new file mode 100644 (file)
index 0000000..fd8c435
--- /dev/null
@@ -0,0 +1,100 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/detail/functor_bag.hpp
+/// \brief Defines a EBO optimizacion helper for functors.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_FUNCTOR_BAG_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_FUNCTOR_BAG_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+// This bogus warning will appear when add_const is applied to a
+// const volatile reference because we can't detect const volatile
+// references with MSVC6.
+#   pragma warning(push)
+#   pragma warning(disable:4181)
+// warning C4181: qualifier applied to reference type ignored
+#endif
+
+#include <boost/mpl/placeholders.hpp>
+
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+
+#include <boost/mpl/inherit_linearly.hpp>
+#include <boost/mpl/inherit.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+namespace detail {
+
+/// \brief EBO optimizacion helper for functors
+/**
+
+This class is a generalization of a helper class explained in an article by
+Nathan C. Myers.\n
+See it at \link http://www.cantrip.org/emptyopt.html
+                                                                                    **/
+
+template < class Data, class FunctorList >
+struct data_with_functor_bag :
+
+    public mpl::inherit_linearly<
+
+        FunctorList,
+        mpl::if_< is_base_of< mpl::_2, mpl::_1 >,
+        //   {
+                 mpl::_1,
+        //   }
+        //   else
+        //   {
+                 mpl::inherit< mpl::_1, mpl::_2 >
+        //   }
+        >
+
+    >::type
+{
+    Data data;
+
+    data_with_functor_bag() {}
+
+    data_with_functor_bag(BOOST_DEDUCED_TYPENAME add_reference<Data>::type d)
+        : data(d) {}
+
+    template< class Functor >
+    Functor& functor()
+    {
+        return *(static_cast<Functor*>(this));
+    }
+
+    template< class Functor >
+    const Functor& functor() const
+    {
+        return *(static_cast<Functor const *>(this));
+    }
+};
+
+} // namespace detail
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+#if defined(BOOST_MSVC)
+#   pragma warning(pop)
+#endif
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_FUNCTOR_BAG_HPP
+
+
diff --git a/boost/bimap/container_adaptor/detail/identity_converters.hpp b/boost/bimap/container_adaptor/detail/identity_converters.hpp
new file mode 100644 (file)
index 0000000..f6f5864
--- /dev/null
@@ -0,0 +1,191 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/detail/identity_converters.hpp
+/// \brief Value and iterators identity converters.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_IDENTITY_CONVERTERS_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_IDENTITY_CONVERTERS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Details of the container adaptor toolbox
+
+namespace detail {
+
+/// \brief Iterator identity converter used by default in container adaptors.
+/**
+If Iterator and ConstIterator are of the same type one of the convert function is not
+included.
+                                                                                    **/
+
+template
+<
+    class BaseIterator              , class Iterator,
+    class BaseConstIterator         , class ConstIterator
+>
+struct iterator_to_base_identity
+{
+    BaseIterator operator()(Iterator iter) const
+    {
+        return BaseIterator(iter);
+    }
+
+    BaseConstIterator operator()(ConstIterator iter) const
+    {
+        return BaseConstIterator(iter);
+    }
+};
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class BaseIterator, class Iterator >
+struct iterator_to_base_identity<BaseIterator,Iterator,BaseIterator,Iterator>
+{
+    BaseIterator operator()(Iterator iter) const
+    {
+        return BaseIterator(iter);
+    }
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+/// \brief Iterator from base identity converter used by default in container adaptors.
+/**
+If Iterator and ConstIterator are of the same type one of the convert function is not
+included.
+                                                                                    **/
+
+template
+<
+    class BaseIterator              , class Iterator,
+    class BaseConstIterator         , class ConstIterator
+>
+struct iterator_from_base_identity
+{
+    Iterator operator()(BaseIterator iter) const
+    {
+        return Iterator(iter);
+    }
+    ConstIterator operator()(BaseConstIterator iter) const
+    {
+        return ConstIterator(iter);
+    }
+};
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class BaseIterator, class Iterator, class ConstIterator >
+struct iterator_from_base_identity<BaseIterator,Iterator,BaseIterator,ConstIterator>
+{
+    Iterator operator()(BaseIterator iter) const
+    {
+        return Iterator(iter);
+    }
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+/// \brief Value to base identity converter used by default in container adaptors.
+
+template< class BaseValue, class Value >
+struct value_to_base_identity
+{
+    BaseValue operator()(const Value & val) const
+    {
+        return BaseValue(val);
+    }
+};
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class Value >
+struct value_to_base_identity< Value, Value >
+{
+    const Value & operator()(const Value & val) const
+    {
+        return val;
+    }
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+/// \brief Value from base identity converter used by default in container adaptors.
+
+template< class BaseValue, class Value >
+struct value_from_base_identity
+{
+    Value operator()(const BaseValue & val) const
+    {
+        return Value(val);
+    }
+};
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class Value >
+struct value_from_base_identity<Value,Value>
+{
+    Value & operator()(Value & val) const
+    {
+        return val;
+    }
+
+    const Value & operator()(const Value & val) const
+    {
+        return val;
+    }
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+/// \brief Key to base identity converter used by default in container adaptors.
+
+template< class BaseKey, class Key >
+struct key_to_base_identity
+{
+    BaseKey operator()(const Key & k) const
+    {
+        return BaseKey(k);
+    }
+};
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class Key >
+struct key_to_base_identity< Key, Key >
+{
+    // As default accept any type as key in order to allow container
+    // adaptors to work with compatible key types
+
+    template< class CompatibleKey >
+    const CompatibleKey & operator()(const CompatibleKey & k) const
+    {
+        return k;
+    }
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+} // namespace detail
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_IDENTITY_CONVERTERS_HPP
+
+
diff --git a/boost/bimap/container_adaptor/detail/key_extractor.hpp b/boost/bimap/container_adaptor/detail/key_extractor.hpp
new file mode 100644 (file)
index 0000000..3835b7c
--- /dev/null
@@ -0,0 +1,45 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/detail/key_extractor.hpp
+/// \brief Key extractor for a pair<Key,Data>.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_KEY_EXTRACTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_KEY_EXTRACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <functional>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+namespace detail {
+
+/// \brief Key Extractor
+
+template < class T >
+struct key_from_pair_extractor 
+    : std::unary_function< T, BOOST_DEDUCED_TYPENAME T::first_type >
+{
+    bool operator()( const T & p ) { return p.first; }
+};
+
+} // namespace detail
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_KEY_EXTRACTOR_HPP
+
+
diff --git a/boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp b/boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp
new file mode 100644 (file)
index 0000000..6957045
--- /dev/null
@@ -0,0 +1,62 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/detail/non_unique_container_helper.hpp
+/// \brief Details for non unique containers
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_NON_UNIQUE_CONTAINER_HELPER_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_NON_UNIQUE_CONTAINER_HELPER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+/*****************************************************************************/
+#define BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS             \
+                                                                              \
+template <class InputIterator>                                                \
+void insert(InputIterator iterBegin, InputIterator iterEnd)                   \
+{                                                                             \
+    for( ; iterBegin != iterEnd ; ++iterBegin )                               \
+    {                                                                         \
+        this->base().insert(                                                  \
+            this->template functor<                                           \
+                BOOST_DEDUCED_TYPENAME base_::value_to_base>()(               \
+                    BOOST_DEDUCED_TYPENAME base_::value_type(*iterBegin)) );  \
+    }                                                                         \
+}                                                                             \
+                                                                              \
+BOOST_DEDUCED_TYPENAME base_::iterator insert(                                \
+    BOOST_DEDUCED_TYPENAME ::boost::call_traits<                              \
+        BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x)             \
+{                                                                             \
+    return this->base().insert( this->template functor<                       \
+                                   BOOST_DEDUCED_TYPENAME base_::             \
+                                        value_to_base>()(x) );                \
+}                                                                             \
+                                                                              \
+BOOST_DEDUCED_TYPENAME base_::iterator                                        \
+    insert(BOOST_DEDUCED_TYPENAME base_::iterator pos,                        \
+               BOOST_DEDUCED_TYPENAME ::boost::call_traits<                   \
+                    BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x) \
+{                                                                             \
+    return this->template functor<                                            \
+        BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(                  \
+            this->base().insert(this->template functor<                       \
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(pos),       \
+            this->template functor<                                           \
+                BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x))            \
+    );                                                                        \
+}
+/*****************************************************************************/
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_NON_UNIQUE_CONTAINER_HELPER_HPP
+
+
diff --git a/boost/bimap/container_adaptor/list_adaptor.hpp b/boost/bimap/container_adaptor/list_adaptor.hpp
new file mode 100644 (file)
index 0000000..310e2b4
--- /dev/null
@@ -0,0 +1,249 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/list_adaptor.hpp
+/// \brief Container adaptor to easily build a std::list signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/sequence_container_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/comparison_adaptor.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/call_traits.hpp>
+#include <functional>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::list signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class IteratorToBaseConverter          = ::boost::mpl::na,
+    class IteratorFromBaseConverter        = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter             = ::boost::mpl::na,
+    class ValueFromBaseConverter           = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class list_adaptor :
+
+    public ::boost::bimaps::container_adaptor::sequence_container_adaptor
+    <
+        Base, Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+    typedef ::boost::bimaps::container_adaptor::sequence_container_adaptor
+    <
+        Base, Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit list_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef list_adaptor list_adaptor_;
+
+    // Interface -------------------------------------------------------------
+
+    public:
+
+    void splice(Iterator position, list_adaptor & x)
+    {
+        this->base().splice(
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()
+                (position),
+            x.base()
+        );
+    }
+
+    void splice(Iterator position, list_adaptor & x, Iterator i)
+    {
+        this->base().splice(
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()
+                (position),
+            x.base(),
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i)
+        );
+    }
+
+    void splice(Iterator position, list_adaptor & x, 
+                Iterator first, Iterator last)
+    {
+        this->base().splice(
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()
+                (position),
+            x.base(),
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first),
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last)
+        );
+    }
+
+    void remove(
+        BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+            BOOST_DEDUCED_TYPENAME base_::value_type
+        >::param_type value
+    )
+    {
+        this->base().remove(
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::value_to_base>()(value)
+        );
+    }
+
+    template< class Predicate >
+    void remove_if(Predicate pred)
+    {
+        this->base().remove_if(
+            ::boost::bimaps::container_adaptor::detail::unary_check_adaptor
+            <
+                Predicate,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( pred, this->template functor<BOOST_DEDUCED_TYPENAME base_::value_from_base>() )
+        );
+    }
+
+    void unique()
+    {
+        this->base().unique(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::equal_to<BOOST_DEDUCED_TYPENAME base_::value_type>,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >(
+                std::equal_to<BOOST_DEDUCED_TYPENAME base_::value_type>(),
+                this->template functor<BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+            )
+        );
+    }
+
+    template< class BinaryPredicate >
+    void unique(BinaryPredicate binary_pred)
+    {
+        this->base().unique(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                BinaryPredicate,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( binary_pred,
+               this->template functor<BOOST_DEDUCED_TYPENAME base_::value_from_base>() )
+        );
+    }
+
+    void merge(list_adaptor & x)
+    {
+        this->base().merge(x.base(),
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::less<BOOST_DEDUCED_TYPENAME base_::value_type>,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >(
+                std::less<BOOST_DEDUCED_TYPENAME base_::value_type>(),
+                this->template functor<BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+            )
+        );
+    }
+
+    template< class Compare >
+    void merge(list_adaptor & x, Compare comp)
+    {
+        this->base().merge(x.base(),
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                Compare,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( comp, this->template functor<BOOST_DEDUCED_TYPENAME base_::value_from_base>() )
+        );
+    }
+
+    void sort()
+    {
+        this->base().sort(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::less<BOOST_DEDUCED_TYPENAME base_::value_type>,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >(
+                std::less<BOOST_DEDUCED_TYPENAME base_::value_type>(),
+                this->template functor<BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+            )
+        );
+    }
+
+    template< class Compare >
+    void sort(Compare comp)
+    {
+        this->base().sort(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                Compare,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( comp, this->template functor<BOOST_DEDUCED_TYPENAME base_::value_from_base>() )
+        );
+    }
+
+    void reverse()
+    {
+        this->base().reverse();
+    }
+
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_SET_ADAPTOR_HPP
+
+
diff --git a/boost/bimap/container_adaptor/list_map_adaptor.hpp b/boost/bimap/container_adaptor/list_map_adaptor.hpp
new file mode 100644 (file)
index 0000000..ff7a540
--- /dev/null
@@ -0,0 +1,282 @@
+ // Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/list_map_adaptor.hpp
+/// \brief Container adaptor.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_MAP_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_MAP_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/list.hpp>
+#include <boost/mpl/push_front.hpp>
+
+#include <boost/bimap/container_adaptor/list_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/identity_converters.hpp>
+#include <boost/bimap/container_adaptor/detail/key_extractor.hpp>
+#include <boost/bimap/container_adaptor/detail/comparison_adaptor.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/if.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template
+<
+    class Base, class Iterator, class ConstIterator,
+    class ReverseIterator, class ConstReverseIterator,
+    class IteratorToBaseConverter, class IteratorFromBaseConverter,
+    class ReverseIteratorFromBaseConverter,
+    class ValueToBaseConverter, class ValueFromBaseConverter,
+    class KeyFromBaseValueConverter,
+    class FunctorsFromDerivedClasses
+>
+struct list_map_adaptor_base
+{
+    typedef list_adaptor
+    <
+        Base,
+
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+
+        ReverseIteratorFromBaseConverter,
+
+        ValueToBaseConverter, ValueFromBaseConverter,
+
+        BOOST_DEDUCED_TYPENAME mpl::push_front<
+
+            FunctorsFromDerivedClasses,
+
+            BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na<KeyFromBaseValueConverter>,
+            // {
+                    detail::key_from_pair_extractor
+                    <
+                        BOOST_DEDUCED_TYPENAME Iterator::value_type 
+                    >,
+            // }
+            // else
+            // {
+                    KeyFromBaseValueConverter
+            // }
+
+            >::type
+
+        >::type
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+/// \brief Container adaptor to easily build a list map container
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class IteratorToBaseConverter          = ::boost::mpl::na,
+    class IteratorFromBaseConverter        = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter             = ::boost::mpl::na,
+    class ValueFromBaseConverter           = ::boost::mpl::na,
+    class KeyFromBaseValueConverter        = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class list_map_adaptor :
+
+    public list_map_adaptor_base
+    <
+        Base, Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyFromBaseValueConverter,
+        FunctorsFromDerivedClasses
+
+    >::type
+{
+    typedef BOOST_DEDUCED_TYPENAME list_map_adaptor_base
+    <
+        Base, Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyFromBaseValueConverter,
+        FunctorsFromDerivedClasses
+
+    >::type base_;
+
+    // MetaData -------------------------------------------------------------
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type  key_type;
+    typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type;
+
+    protected:
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na<KeyFromBaseValueConverter>,
+    // {
+            detail::key_from_pair_extractor< BOOST_DEDUCED_TYPENAME Iterator::value_type >,
+    // }
+    // else
+    // {
+            KeyFromBaseValueConverter
+    // }
+
+    >::type key_from_base_value;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit list_map_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef list_map_adaptor list_map_adaptor_;
+
+    // Functions -------------------------------------------------------------
+
+    public:
+
+    // The following functions are overwritten in order to work 
+    // with key_type instead of value_type
+
+    template< class Predicate >
+    void remove_if(Predicate pred)
+    {
+        this->base().remove_if(
+            ::boost::bimaps::container_adaptor::detail::unary_check_adaptor
+            <
+                Predicate,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                key_from_base_value
+
+            >( pred, this->template functor<key_from_base_value>() )
+        );
+    }
+
+    void unique()
+    {
+        this->base().unique(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::equal_to<key_type>,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                key_from_base_value
+
+            >(
+                std::equal_to<key_type>(),
+                this->template functor<key_from_base_value>()
+            )
+        );
+    }
+
+    template< class BinaryPredicate >
+    void unique(BinaryPredicate binary_pred)
+    {
+        this->base().unique(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                BinaryPredicate,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                key_from_base_value
+
+            >( binary_pred, this->template functor<key_from_base_value>() )
+        );
+    }
+
+    void merge(list_map_adaptor & x)
+    {
+        this->base().merge(x.base(),
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::less<key_type>,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                key_from_base_value
+
+            >(
+                std::less<key_type>(),
+                this->template functor<key_from_base_value>()
+            )
+        );
+    }
+
+    template< class Compare >
+    void merge(list_map_adaptor & x, Compare comp)
+    {
+        this->base().merge(x.base(),
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                Compare,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                key_from_base_value
+
+            >( comp, this->template functor<key_from_base_value>() )
+        );
+    }
+
+    void sort()
+    {
+        this->base().sort(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::less<key_type>,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                key_from_base_value
+
+            >(
+                std::less<key_type>(),
+                this->template functor<key_from_base_value>()
+            )
+        );
+    }
+
+    template< class Compare >
+    void sort(Compare comp)
+    {
+        this->base().sort(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                Compare,
+                BOOST_DEDUCED_TYPENAME Base::value_type,
+                key_from_base_value
+
+            >( comp, this->template functor<key_from_base_value>() )
+        );
+    }
+
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_MAP_ADAPTOR_HPP
+
diff --git a/boost/bimap/container_adaptor/map_adaptor.hpp b/boost/bimap/container_adaptor/map_adaptor.hpp
new file mode 100644 (file)
index 0000000..f1a6f64
--- /dev/null
@@ -0,0 +1,131 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/map_adaptor.hpp
+/// \brief Container adaptor to easily build a std::map signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_MAP_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_MAP_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/call_traits.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::map signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class IteratorToBaseConverter          = ::boost::mpl::na,
+    class IteratorFromBaseConverter        = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter             = ::boost::mpl::na,
+    class ValueFromBaseConverter           = ::boost::mpl::na,
+    class KeyToBaseConverter               = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class map_adaptor :
+
+    public ::boost::bimaps::container_adaptor::
+                ordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+
+    typedef ::boost::bimaps::container_adaptor::
+                ordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // MetaData -------------------------------------------------------------
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit map_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef map_adaptor map_adaptor_;
+
+    // Interface --------------------------------------------------------------
+
+    public:
+
+    template< class CompatibleKey >
+    data_type& operator[](const CompatibleKey & k)
+    {
+        return this->base()
+            [this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k)];
+    }
+
+    template< class CompatibleKey >
+    data_type& at(const CompatibleKey & k)
+    {
+        return this->base().
+            at(this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k));
+    }
+
+    template< class CompatibleKey >
+    const data_type& at(const CompatibleKey & k) const
+    {
+        return this->base().
+            at(this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k));
+    }
+
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_MAP_ADAPTOR_HPP
+
diff --git a/boost/bimap/container_adaptor/multimap_adaptor.hpp b/boost/bimap/container_adaptor/multimap_adaptor.hpp
new file mode 100644 (file)
index 0000000..ad5edf2
--- /dev/null
@@ -0,0 +1,109 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/multimap_adaptor.hpp
+/// \brief Container adaptor to easily build a std::multimap signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_MULTIMAP_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_MULTIMAP_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::multimap signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class IteratorToBaseConverter          = ::boost::mpl::na,
+    class IteratorFromBaseConverter        = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter             = ::boost::mpl::na,
+    class ValueFromBaseConverter           = ::boost::mpl::na,
+    class KeyToBaseConverter               = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class multimap_adaptor :
+
+    public ::boost::bimaps::container_adaptor::
+                ordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+    typedef ::boost::bimaps::container_adaptor::
+                ordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // MetaData -------------------------------------------------------------
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit multimap_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef multimap_adaptor multimap_adaptor_;
+
+    public:
+
+    BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_MULTIMAP_ADAPTOR_HPP
+
+
diff --git a/boost/bimap/container_adaptor/multiset_adaptor.hpp b/boost/bimap/container_adaptor/multiset_adaptor.hpp
new file mode 100644 (file)
index 0000000..fe89d9a
--- /dev/null
@@ -0,0 +1,103 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/multiset_adaptor.hpp
+/// \brief Container adaptor to easily build a std::multiset signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_MULTISET_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_MULTISET_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::multiset signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class IteratorToBaseConverter          = ::boost::mpl::na,
+    class IteratorFromBaseConverter        = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter             = ::boost::mpl::na,
+    class ValueFromBaseConverter           = ::boost::mpl::na,
+    class KeyToBaseConverter               = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class multiset_adaptor :
+
+    public ::boost::bimaps::container_adaptor::
+                ordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+
+    typedef ::boost::bimaps::container_adaptor::
+                ordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit multiset_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef multiset_adaptor multiset_adaptor_;
+
+    public:
+
+    BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_MULTISET_ADAPTOR_HPP
+
diff --git a/boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp b/boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp
new file mode 100644 (file)
index 0000000..6278844
--- /dev/null
@@ -0,0 +1,312 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/ordered_associative_container_adaptor.hpp
+/// \brief Container adaptor to build a type that is compliant to the concept of an ordered associative container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_ORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_ORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/associative_container_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/comparison_adaptor.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/operators.hpp>
+#include <boost/call_traits.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template
+<
+    class Base, class Iterator, class ConstIterator,
+    class ReverseIterator, class ConstReverseIterator, class KeyType,
+    class IteratorToBaseConverter, class IteratorFromBaseConverter,
+    class ReverseIteratorFromBaseConverter,
+    class ValueToBaseConverter, class ValueFromBaseConverter, 
+    class KeyToBaseConverter,
+    class FunctorsFromDerivedClasses
+>
+struct ordered_associative_container_adaptor_base
+{
+    typedef associative_container_adaptor<
+        Base, Iterator, ConstIterator, KeyType,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter,
+
+        BOOST_DEDUCED_TYPENAME mpl::push_front<
+
+            FunctorsFromDerivedClasses,
+
+            BOOST_DEDUCED_TYPENAME mpl::if_<
+                ::boost::mpl::is_na<ReverseIteratorFromBaseConverter>,
+            // {
+                    detail::iterator_from_base_identity
+                    <
+                        BOOST_DEDUCED_TYPENAME Base::reverse_iterator,
+                        ReverseIterator,
+                        BOOST_DEDUCED_TYPENAME Base::const_reverse_iterator,
+                        ConstReverseIterator
+                    >,
+            // }
+            // else
+            // {
+                    ReverseIteratorFromBaseConverter
+            // }
+
+            >::type
+
+        >::type
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+/// \brief Container adaptor to build a type that is compliant to the concept of an ordered associative container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class KeyType,
+
+    class IteratorToBaseConverter          = ::boost::mpl::na,
+    class IteratorFromBaseConverter        = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter             = ::boost::mpl::na,
+    class ValueFromBaseConverter           = ::boost::mpl::na,
+    class KeyToBaseConverter               = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class ordered_associative_container_adaptor :
+
+    public ordered_associative_container_adaptor_base
+    <
+        Base, Iterator, ConstIterator,
+        ReverseIterator, ConstReverseIterator, KeyType,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    >::type,
+
+    ::boost::totally_ordered
+    <
+        ordered_associative_container_adaptor
+        <
+            Base, Iterator, ConstIterator,
+            ReverseIterator, ConstReverseIterator,
+            KeyType, IteratorToBaseConverter, IteratorFromBaseConverter,
+            ReverseIteratorFromBaseConverter,
+            ValueToBaseConverter, ValueFromBaseConverter,
+            KeyToBaseConverter, FunctorsFromDerivedClasses
+        >
+    >
+{
+    // MetaData -------------------------------------------------------------
+
+    typedef BOOST_DEDUCED_TYPENAME ordered_associative_container_adaptor_base
+    <
+        Base, Iterator, ConstIterator,
+        ReverseIterator, ConstReverseIterator, KeyType,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    >::type base_;
+
+    public:
+
+    typedef detail::compatible_comparison_adaptor
+    <
+        BOOST_DEDUCED_TYPENAME Base::key_compare,
+        BOOST_DEDUCED_TYPENAME base_::key_type,
+        BOOST_DEDUCED_TYPENAME base_::key_to_base
+
+    > key_compare;
+
+    typedef detail::comparison_adaptor
+    <
+        BOOST_DEDUCED_TYPENAME Base::value_compare,
+        BOOST_DEDUCED_TYPENAME base_::value_type,
+        BOOST_DEDUCED_TYPENAME base_::value_to_base
+
+    > value_compare;
+
+    typedef ReverseIterator      reverse_iterator;
+    typedef ConstReverseIterator const_reverse_iterator;
+
+    protected:
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+        ::boost::mpl::is_na<ReverseIteratorFromBaseConverter>,
+        // {
+                detail::iterator_from_base_identity
+                <
+                    BOOST_DEDUCED_TYPENAME Base::reverse_iterator,
+                    reverse_iterator,
+                    BOOST_DEDUCED_TYPENAME Base::const_reverse_iterator,
+                    const_reverse_iterator
+                >,
+        // }
+        // else
+        // {
+                ReverseIteratorFromBaseConverter
+        // }
+
+        >::type reverse_iterator_from_base;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit ordered_associative_container_adaptor(Base & c)
+        : base_(c) {}
+
+    protected:
+
+    typedef ordered_associative_container_adaptor
+                ordered_associative_container_adaptor_;
+
+    // Interface --------------------------------------------------------------
+
+    public:
+
+    reverse_iterator rbegin()
+    {
+        return this->template functor<
+            reverse_iterator_from_base
+        >()                            ( this->base().rbegin() );
+
+    }
+
+    reverse_iterator rend()
+    {
+        return this->template functor<
+            reverse_iterator_from_base
+        >()                            ( this->base().rend() );
+    }
+
+    const_reverse_iterator rbegin() const
+    {
+        return this->template functor<
+            reverse_iterator_from_base
+        >()                            ( this->base().rbegin() );
+    }
+
+    const_reverse_iterator rend() const
+    {
+        return this->template functor<
+            reverse_iterator_from_base
+        >()                            ( this->base().rend() );
+    }
+
+    key_compare key_comp() const
+    {
+        typedef BOOST_DEDUCED_TYPENAME base_::key_to_base key_to_base_;
+
+        return key_compare(
+            this->base().key_comp(),
+            this->template functor<key_to_base_>()
+        );
+    }
+
+    value_compare value_comp() const
+    {
+        typedef BOOST_DEDUCED_TYPENAME base_::value_to_base value_to_base_;
+
+        return value_compare(
+            this->base().value_comp(),
+            this->template functor<value_to_base_>()
+        );
+    }
+
+    template< class CompatibleKey >
+    BOOST_DEDUCED_TYPENAME base_::iterator lower_bound(const CompatibleKey & k)
+    {
+       return this->template functor<
+            BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(
+                this->base().lower_bound(
+                    this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k)
+                )
+            );
+    }
+
+    template< class CompatibleKey >
+    BOOST_DEDUCED_TYPENAME base_::const_iterator lower_bound(const CompatibleKey & k) const
+    {
+       return this->template functor<
+            BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(
+                this->base().lower_bound(
+                    this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k)
+                )
+            );
+    }
+
+    template< class CompatibleKey >
+    BOOST_DEDUCED_TYPENAME base_::iterator upper_bound(const CompatibleKey & k)
+    {
+       return this->template functor<
+            BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(
+                this->base().upper_bound(
+                    this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k)
+                )
+            );
+    }
+
+    template< class CompatibleKey >
+    BOOST_DEDUCED_TYPENAME base_::const_iterator upper_bound(const CompatibleKey & k) const
+    {
+        return this->template functor<
+            BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(
+                this->base().upper_bound(
+                    this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k)
+                )
+            );
+    }
+
+    // Totally ordered implementation
+
+    bool operator==(const ordered_associative_container_adaptor & c) const
+    {
+        return ( this->base() == c.base() );
+    }
+
+    bool operator<(const ordered_associative_container_adaptor & c) const
+    {
+        return ( this->base() < c.base() );
+    }
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_ORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP
diff --git a/boost/bimap/container_adaptor/sequence_container_adaptor.hpp b/boost/bimap/container_adaptor/sequence_container_adaptor.hpp
new file mode 100644 (file)
index 0000000..396635d
--- /dev/null
@@ -0,0 +1,355 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/sequence_container_adaptor.hpp
+/// \brief Container adaptor to build a type that is compliant to the concept of a weak associative container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_SEQUENCE_CONTAINER_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_SEQUENCE_CONTAINER_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <utility>
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/bimap/container_adaptor/detail/identity_converters.hpp>
+#include <boost/bimap/container_adaptor/container_adaptor.hpp>
+#include <boost/call_traits.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template
+<
+    class Base, class Iterator, class ConstIterator,
+    class ReverseIterator, class ConstReverseIterator,
+    class IteratorToBaseConverter, class IteratorFromBaseConverter,
+    class ReverseIteratorFromBaseConverter,
+    class ValueToBaseConverter, class ValueFromBaseConverter,
+    class FunctorsFromDerivedClasses
+>
+struct sequence_container_adaptor_base
+{
+    typedef container_adaptor
+    <
+        Base, Iterator, ConstIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+
+        BOOST_DEDUCED_TYPENAME mpl::push_front<
+
+            FunctorsFromDerivedClasses,
+
+            BOOST_DEDUCED_TYPENAME mpl::if_<
+                ::boost::mpl::is_na<ReverseIteratorFromBaseConverter>,
+            // {
+                    detail::iterator_from_base_identity
+                    <
+                        BOOST_DEDUCED_TYPENAME Base::reverse_iterator, 
+                        ReverseIterator,
+                        BOOST_DEDUCED_TYPENAME Base::const_reverse_iterator,
+                        ConstReverseIterator
+                    >,
+            // }
+            // else
+            // {
+                    ReverseIteratorFromBaseConverter
+            // }
+
+            >::type
+
+        >::type
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+/// \brief Container adaptor to build a type that is compliant to the concept of a sequence container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class IteratorToBaseConverter           = ::boost::mpl::na,
+    class IteratorFromBaseConverter         = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter  = ::boost::mpl::na,
+    class ValueToBaseConverter              = ::boost::mpl::na,
+    class ValueFromBaseConverter            = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class sequence_container_adaptor :
+
+    public sequence_container_adaptor_base
+    <
+        Base, Iterator, ConstIterator,
+        ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        FunctorsFromDerivedClasses
+
+    >::type,
+
+    ::boost::totally_ordered
+    <
+        sequence_container_adaptor
+        <
+            Base, Iterator, ConstIterator,
+            ReverseIterator, ConstReverseIterator,
+            IteratorToBaseConverter, IteratorFromBaseConverter,
+            ReverseIteratorFromBaseConverter,
+            ValueToBaseConverter, ValueFromBaseConverter,
+            FunctorsFromDerivedClasses
+        >
+    >
+{
+    typedef BOOST_DEDUCED_TYPENAME sequence_container_adaptor_base
+    <
+        Base, Iterator, ConstIterator,
+        ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        FunctorsFromDerivedClasses
+
+    >::type base_;
+
+    // MetaData -------------------------------------------------------------
+
+    public:
+
+    typedef ReverseIterator      reverse_iterator;
+    typedef ConstReverseIterator const_reverse_iterator;
+
+    protected:
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+        ::boost::mpl::is_na<ReverseIteratorFromBaseConverter>,
+        // {
+                detail::iterator_from_base_identity
+                <
+                    BOOST_DEDUCED_TYPENAME Base::reverse_iterator,
+                    reverse_iterator,
+                    BOOST_DEDUCED_TYPENAME Base::const_reverse_iterator,
+                    const_reverse_iterator
+                >,
+        // }
+        // else
+        // {
+                ReverseIteratorFromBaseConverter
+        // }
+
+        >::type reverse_iterator_from_base;
+
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit sequence_container_adaptor(Base & c)
+        : base_(c) {}
+
+    protected:
+
+
+    typedef sequence_container_adaptor sequence_container_adaptor_;
+
+    // Interface --------------------------------------------------------------
+
+    public:
+
+    reverse_iterator rbegin()
+    {
+        return this->template functor<
+            reverse_iterator_from_base
+        >()                            ( this->base().rbegin() );
+
+    }
+
+    reverse_iterator rend()
+    {
+        return this->template functor<
+            reverse_iterator_from_base
+        >()                            ( this->base().rend() );
+    }
+
+    const_reverse_iterator rbegin() const
+    {
+        return this->template functor<
+            reverse_iterator_from_base
+        >()                            ( this->base().rbegin() );
+    }
+
+    const_reverse_iterator rend() const
+    {
+        return this->template functor<
+            reverse_iterator_from_base
+        >()                            ( this->base().rend() );
+    }
+
+    void resize(BOOST_DEDUCED_TYPENAME base_::size_type n,
+                BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                    BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x =
+                        BOOST_DEDUCED_TYPENAME base_::value_type())
+    {
+        this->base().resize(n,
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x)
+        );
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::reference front()
+    {
+        return this->template functor<
+            BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+        (
+            this->base().front()
+        );
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::reference back()
+    {
+        return this->template functor<
+            BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+        (
+            this->base().back()
+        );
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::const_reference front() const
+    {
+        return this->template functor<
+            BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+        (
+            this->base().front()
+        );
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::const_reference back() const
+    {
+        return this->template functor<
+            BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+        (
+            this->base().back()
+        );
+    }
+
+    void push_front(
+        BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+            BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x)
+    {
+        this->base().push_front(
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x));
+    }
+
+    void pop_front()
+    {
+        this->base().pop_front();
+    }
+
+    void push_back(
+        BOOST_DEDUCED_TYPENAME ::boost::call_traits< 
+            BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x)
+    {
+        this->base().push_back(
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x));
+    }
+
+    void pop_back()
+    {
+        this->base().pop_back();
+    }
+
+    std::pair<BOOST_DEDUCED_TYPENAME base_::iterator,bool>
+    insert(BOOST_DEDUCED_TYPENAME base_::iterator position,
+           BOOST_DEDUCED_TYPENAME ::boost::call_traits< 
+                BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x)
+    {
+        std::pair< BOOST_DEDUCED_TYPENAME Base::iterator, bool > r(
+            this->base().insert(
+                this->template functor<
+                    BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+                this->template functor<
+                    BOOST_DEDUCED_TYPENAME base_::value_to_base   >()(x)
+            )
+        );
+
+        return std::pair<BOOST_DEDUCED_TYPENAME base_::iterator, bool>(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(r.first),
+            r.second
+        );
+    }
+
+    void insert(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                BOOST_DEDUCED_TYPENAME base_::size_type m,
+                BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                    BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x)
+    {
+        this->base().insert(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            m,
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::value_to_base   >()(x)
+        );
+    }
+
+    template< class InputIterator >
+    void insert(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                InputIterator first, InputIterator last)
+    {
+        // This is the same problem found in the insert function 
+        // of container_adaptor
+        // For now, do the simple thing. This can be optimized
+
+        for( ; first != last ; ++first )
+        {
+            this->base().insert(
+                this->template functor<
+                    BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()( position ),
+                this->template functor<
+                    BOOST_DEDUCED_TYPENAME base_::value_to_base   >()( *first )
+            );
+        }
+    }
+
+    // Totally ordered implementation
+
+    bool operator==(const sequence_container_adaptor & c) const
+    {
+        return ( this->base() == c.base() );
+    }
+
+    bool operator<(const sequence_container_adaptor & c) const
+    {
+        return ( this->base() < c.base() );
+    }
+};
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_SEQUENCE_CONTAINER_ADAPTOR_HPP
diff --git a/boost/bimap/container_adaptor/set_adaptor.hpp b/boost/bimap/container_adaptor/set_adaptor.hpp
new file mode 100644 (file)
index 0000000..6c8dbf3
--- /dev/null
@@ -0,0 +1,100 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/set_adaptor.hpp
+/// \brief Container adaptor to easily build a std::set signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_SET_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_SET_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/aux_/na.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::set signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class IteratorToBaseConverter          = ::boost::mpl::na,
+    class IteratorFromBaseConverter        = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter             = ::boost::mpl::na,
+    class ValueFromBaseConverter           = ::boost::mpl::na,
+    class KeyToBaseConverter               = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class set_adaptor :
+
+    public ::boost::bimaps::container_adaptor::
+                ordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+
+    typedef ::boost::bimaps::container_adaptor::
+                ordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit set_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef set_adaptor set_adaptor_;
+
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_SET_ADAPTOR_HPP
+
+
diff --git a/boost/bimap/container_adaptor/support/iterator_facade_converters.hpp b/boost/bimap/container_adaptor/support/iterator_facade_converters.hpp
new file mode 100644 (file)
index 0000000..4bde159
--- /dev/null
@@ -0,0 +1,77 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/support/iterator_facade_converters.hpp
+/// \brief Converter for Boost.Iterators based iterators.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_ITERATOR_FACADE_CONVERTERS_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_ITERATOR_FACADE_CONVERTERS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Utilities to help in the construction of a container adaptor
+
+namespace support {
+
+/// \brief Converter for Boost.Iterators based iterators.
+/**
+Container adaptor is dessigned to play well with Boost.Iterators. This
+converter can be used if this library is used to adapt the iterators.
+                                                                            **/
+template
+<
+    class Iterator,
+    class ConstIterator
+>
+struct iterator_facade_to_base
+{
+    BOOST_DEDUCED_TYPENAME Iterator::base_type operator()(Iterator iter) const
+    {
+        return iter.base();
+    }
+
+    BOOST_DEDUCED_TYPENAME ConstIterator::base_type operator()(ConstIterator iter) const
+    {
+        return iter.base();
+    }
+};
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template
+<
+    class Iterator
+>
+struct iterator_facade_to_base<Iterator,Iterator>
+{
+    BOOST_DEDUCED_TYPENAME Iterator::base_type operator()(Iterator iter) const
+    {
+        return iter.base();
+    }
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#undef BOOST_BIMAP_CONTAINER_ADAPTOR_IMPLEMENT_CONVERT_FACADE_FUNCTION
+
+
+} // namespace support
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_ITERATOR_FACADE_CONVERTERS_HPP
diff --git a/boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp b/boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp
new file mode 100644 (file)
index 0000000..937a0d8
--- /dev/null
@@ -0,0 +1,293 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/unordered_associative_container_adaptor.hpp
+/// \brief Container adaptor to build a type that is compliant to the concept of an unordered associative container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/associative_container_adaptor.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/call_traits.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template
+<
+    class Base, class Iterator, class ConstIterator,
+    class LocalIterator, class ConstLocalIterator,
+    class KeyType,
+    class IteratorToBaseConverter, class IteratorFromBaseConverter,
+    class LocalIteratorFromBaseConverter,
+    class ValueToBaseConverter, class ValueFromBaseConverter,
+    class KeyToBaseConverter,
+    class FunctorsFromDerivedClasses
+>
+struct unordered_associative_container_adaptor_base
+{
+
+    typedef associative_container_adaptor
+    <
+        Base, Iterator, ConstIterator, KeyType,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ValueToBaseConverter   , ValueFromBaseConverter,
+        KeyToBaseConverter,
+
+        BOOST_DEDUCED_TYPENAME mpl::push_front<
+
+            FunctorsFromDerivedClasses,
+
+            BOOST_DEDUCED_TYPENAME mpl::if_<
+                ::boost::mpl::is_na<LocalIteratorFromBaseConverter>,
+            // {
+                    detail::iterator_from_base_identity
+                    <
+                        BOOST_DEDUCED_TYPENAME Base::local_iterator,
+                        LocalIterator,
+                        BOOST_DEDUCED_TYPENAME Base::const_local_iterator,
+                        ConstLocalIterator
+                    >,
+            // }
+            // else
+            // {
+                    LocalIteratorFromBaseConverter
+            // }
+
+            >::type
+
+        >::type
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+
+/// \brief Container adaptor to build a type that is compliant to the concept of an unordered associative container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+
+    class LocalIterator,
+    class ConstLocalIterator,
+
+    class KeyType,
+
+    class IteratorToBaseConverter        = ::boost::mpl::na,
+    class IteratorFromBaseConverter      = ::boost::mpl::na,
+    class LocalIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter           = ::boost::mpl::na,
+    class ValueFromBaseConverter         = ::boost::mpl::na,
+    class KeyToBaseConverter             = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses     = mpl::vector<>
+
+>
+class unordered_associative_container_adaptor :
+
+    public unordered_associative_container_adaptor_base
+    <
+        Base, Iterator, ConstIterator,
+        LocalIterator, ConstLocalIterator,
+        KeyType,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    >::type
+{
+    typedef BOOST_DEDUCED_TYPENAME unordered_associative_container_adaptor_base
+    <
+        Base, Iterator, ConstIterator,
+        LocalIterator, ConstLocalIterator,
+        KeyType,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    >::type base_;
+
+    // Metadata ---------------------------------------------------------------
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME Base::key_equal key_equal;
+    typedef BOOST_DEDUCED_TYPENAME Base::hasher hasher;
+
+    typedef LocalIterator      local_iterator;
+    typedef ConstLocalIterator const_local_iterator;
+
+    protected:
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+        ::boost::mpl::is_na<LocalIteratorFromBaseConverter>,
+        // {
+                detail::iterator_from_base_identity
+                <
+                    BOOST_DEDUCED_TYPENAME Base::local_iterator,
+                    local_iterator,
+                    BOOST_DEDUCED_TYPENAME Base::const_local_iterator,
+                    const_local_iterator
+                >,
+        // }
+        // else
+        // {
+                LocalIteratorFromBaseConverter
+        // }
+
+        >::type local_iterator_from_base;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit unordered_associative_container_adaptor(Base & c)
+        : base_(c) {}
+
+    protected:
+
+
+    typedef unordered_associative_container_adaptor
+                unordered_associative_container_adaptor_;
+
+    // Interface --------------------------------------------------------------
+
+    public:
+
+    // bucket interface:
+
+    BOOST_DEDUCED_TYPENAME base_::size_type bucket_count() const
+    {
+        return this->base().bucket_count();
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::size_type max_bucket_count() const
+    {
+        return this->base().max_bucket_count();
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::size_type bucket_size(
+        BOOST_DEDUCED_TYPENAME base_::size_type n) const
+    {
+        return this->base().bucket_size(n);
+    }
+
+    template< class CompatibleKey >
+    BOOST_DEDUCED_TYPENAME base_::size_type bucket(
+        const CompatibleKey & k) const
+    {
+        typedef BOOST_DEDUCED_TYPENAME base_::key_to_base key_to_base;
+        return this->base().bucket(
+            this->template functor<key_to_base>()(k)
+        );
+    }
+
+    local_iterator       begin(BOOST_DEDUCED_TYPENAME base_::size_type n)
+    {
+        return this->template functor<
+            local_iterator_from_base
+        >()                          ( this->base().begin(n) );
+    }
+
+    const_local_iterator begin(BOOST_DEDUCED_TYPENAME base_::size_type n) const
+    {
+        return this->template functor<
+            local_iterator_from_base
+        >()                          ( this->base().begin(n) );
+    }
+
+    local_iterator       end(BOOST_DEDUCED_TYPENAME base_::size_type n)
+    {
+        return this->template functor<
+            local_iterator_from_base
+        >()                          ( this->base().end(n) );
+    }
+
+    const_local_iterator end(BOOST_DEDUCED_TYPENAME base_::size_type n) const
+    {
+        return this->template functor<
+            local_iterator_from_base
+        >()                          ( this->base().end(n) );
+    }
+
+    // hash policy
+
+    float load_factor() const
+    {
+        return this->base().load_factor();
+    }
+
+    float max_load_factor() const
+    {
+        return this->base().max_load_factor();
+    }
+
+    void max_load_factor(float z)
+    {
+        return this->base().max_load_factor(z);
+    }
+
+    void rehash(BOOST_DEDUCED_TYPENAME base_::size_type n)
+    {
+        return this->base().rehash(n);
+    }
+
+    // We have redefined end and begin so we have to manually route the old ones
+
+    BOOST_DEDUCED_TYPENAME base_::iterator begin()
+    {
+        return base_::container_adaptor_::begin();
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::iterator end()
+    {
+        return base_::container_adaptor_::end();
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::const_iterator begin() const
+    {
+        return base_::container_adaptor_::begin();
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::const_iterator end() const
+    {
+        return base_::container_adaptor_::end();
+    }
+
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP
diff --git a/boost/bimap/container_adaptor/unordered_map_adaptor.hpp b/boost/bimap/container_adaptor/unordered_map_adaptor.hpp
new file mode 100644 (file)
index 0000000..762a643
--- /dev/null
@@ -0,0 +1,132 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/unordered_map_adaptor.hpp
+/// \brief Container adaptor to easily build a std::unordered_map signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MAP_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MAP_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/call_traits.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::unordered_map signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class LocalIterator,
+    class ConstLocalIterator,
+
+    class IteratorToBaseConverter        = ::boost::mpl::na,
+    class IteratorFromBaseConverter      = ::boost::mpl::na,
+    class LocalIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter           = ::boost::mpl::na,
+    class ValueFromBaseConverter         = ::boost::mpl::na,
+    class KeyToBaseConverter             = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class unordered_map_adaptor :
+
+    public ::boost::bimaps::container_adaptor::
+                unordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, LocalIterator, ConstLocalIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+
+    typedef ::boost::bimaps::container_adaptor::
+                unordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, LocalIterator, ConstLocalIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // MetaData -------------------------------------------------------------
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit unordered_map_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef unordered_map_adaptor unordered_map_adaptor_;
+
+    // Interface --------------------------------------------------------------
+
+    public:
+
+    template< class CompatibleKey >
+    data_type& operator[](const CompatibleKey & k)
+    {
+        return this->base()
+            [this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k)];
+    }
+
+    template< class CompatibleKey >
+    data_type& at(const CompatibleKey & k)
+    {
+        return this->base().
+            at(this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k));
+    }
+
+    template< class CompatibleKey >
+    const data_type& at(const CompatibleKey & k) const
+    {
+        return this->base().
+            at(this->template functor<BOOST_DEDUCED_TYPENAME base_::key_to_base>()(k));
+    }
+
+};
+
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MAP_ADAPTOR_HPP
+
diff --git a/boost/bimap/container_adaptor/unordered_multimap_adaptor.hpp b/boost/bimap/container_adaptor/unordered_multimap_adaptor.hpp
new file mode 100644 (file)
index 0000000..be28b3a
--- /dev/null
@@ -0,0 +1,110 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/unordered_multimap_adaptor.hpp
+/// \brief Container adaptor to easily build a std::unordered_multimap signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTIMAP_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTIMAP_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::unordered_multimap signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class LocalIterator,
+    class ConstLocalIterator,
+
+    class IteratorToBaseConverter        = ::boost::mpl::na,
+    class IteratorFromBaseConverter      = ::boost::mpl::na,
+    class LocalIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter           = ::boost::mpl::na,
+    class ValueFromBaseConverter         = ::boost::mpl::na,
+    class KeyToBaseConverter             = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class unordered_multimap_adaptor :
+
+    public ::boost::bimaps::container_adaptor::
+                unordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, LocalIterator, ConstLocalIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+    typedef ::boost::bimaps::container_adaptor::
+                unordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, LocalIterator, ConstLocalIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // MetaData -------------------------------------------------------------
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit unordered_multimap_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef unordered_multimap_adaptor unordered_multimap_adaptor_;
+
+    public:
+
+    BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS
+};
+
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTIMAP_ADAPTOR_HPP
+
+
diff --git a/boost/bimap/container_adaptor/unordered_multiset_adaptor.hpp b/boost/bimap/container_adaptor/unordered_multiset_adaptor.hpp
new file mode 100644 (file)
index 0000000..1d8e4c9
--- /dev/null
@@ -0,0 +1,102 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/unordered_multiset_adaptor.hpp
+/// \brief Container adaptor to easily build a std::unordered_multiset signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTISET_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTISET_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::unordered_multiset signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class LocalIterator,
+    class ConstLocalIterator,
+
+    class IteratorToBaseConverter        = ::boost::mpl::na,
+    class IteratorFromBaseConverter      = ::boost::mpl::na,
+    class LocalIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter           = ::boost::mpl::na,
+    class ValueFromBaseConverter         = ::boost::mpl::na,
+    class KeyToBaseConverter             = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class unordered_multiset_adaptor :
+
+    public ::boost::bimaps::container_adaptor::
+                unordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, LocalIterator, ConstLocalIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+    typedef ::boost::bimaps::container_adaptor::
+                unordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, LocalIterator, ConstLocalIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit unordered_multiset_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef unordered_multiset_adaptor unordered_multiset_adaptor_;
+
+    public:
+
+    BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTISET_ADAPTOR_HPP
+
diff --git a/boost/bimap/container_adaptor/unordered_set_adaptor.hpp b/boost/bimap/container_adaptor/unordered_set_adaptor.hpp
new file mode 100644 (file)
index 0000000..cf00b0f
--- /dev/null
@@ -0,0 +1,98 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/unordered_set_adaptor.hpp
+/// \brief Container adaptor to easily build a std::unordered_set signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_SET_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_SET_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::unordered_set signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class LocalIterator,
+    class ConstLocalIterator,
+
+    class IteratorToBaseConverter        = ::boost::mpl::na,
+    class IteratorFromBaseConverter      = ::boost::mpl::na,
+    class LocalIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter           = ::boost::mpl::na,
+    class ValueFromBaseConverter         = ::boost::mpl::na,
+    class KeyToBaseConverter             = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class unordered_set_adaptor :
+
+    public ::boost::bimaps::container_adaptor::
+                unordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, LocalIterator, ConstLocalIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+    typedef ::boost::bimaps::container_adaptor::
+                unordered_associative_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, LocalIterator, ConstLocalIterator,
+        BOOST_DEDUCED_TYPENAME Iterator::value_type,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        LocalIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        KeyToBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    explicit unordered_set_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef unordered_set_adaptor unordered_set_adaptor_;
+
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_SET_ADAPTOR_HPP
+
diff --git a/boost/bimap/container_adaptor/vector_adaptor.hpp b/boost/bimap/container_adaptor/vector_adaptor.hpp
new file mode 100644 (file)
index 0000000..de6e391
--- /dev/null
@@ -0,0 +1,142 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/vector_adaptor.hpp
+/// \brief Container adaptor to easily build a std::vector signature compatible container.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/sequence_container_adaptor.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor to easily build a std::vector signature compatible container.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class IteratorToBaseConverter          = ::boost::mpl::na,
+    class IteratorFromBaseConverter        = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter             = ::boost::mpl::na,
+    class ValueFromBaseConverter           = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class vector_adaptor :
+
+    public ::boost::bimaps::container_adaptor::sequence_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+
+    typedef ::boost::bimaps::container_adaptor::sequence_container_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    vector_adaptor() {}
+
+    explicit vector_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef vector_adaptor vector_adaptor_;
+
+    // Interface --------------------------------------------------------------
+
+    public:
+
+    BOOST_DEDUCED_TYPENAME base_::size_type capacity() const
+    {
+        return this->base().capacity();
+    }
+
+    void reserve(BOOST_DEDUCED_TYPENAME base_::size_type m)
+    {
+        this->base().resize(m);
+    }
+
+    void resize(BOOST_DEDUCED_TYPENAME base_::size_type n,
+                BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                    BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x =
+                        BOOST_DEDUCED_TYPENAME base_::value_type())
+    {
+        this->base().resize(n,
+            this->template functor<BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x)
+        );
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::const_reference
+        operator[](BOOST_DEDUCED_TYPENAME base_::size_type n) const
+    {
+        return this->base().operator[](n);
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::const_reference
+        at(BOOST_DEDUCED_TYPENAME base_::size_type n) const
+    {
+        return this->base().at(n);
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::reference
+        operator[](BOOST_DEDUCED_TYPENAME base_::size_type n)
+    {
+        return this->base().operator[](n);
+    }
+
+    BOOST_DEDUCED_TYPENAME base_::reference
+        at(BOOST_DEDUCED_TYPENAME base_::size_type n)
+    {
+        return this->base().at(n);
+    }
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_ADAPTOR_HPP
+
+
diff --git a/boost/bimap/container_adaptor/vector_map_adaptor.hpp b/boost/bimap/container_adaptor/vector_map_adaptor.hpp
new file mode 100644 (file)
index 0000000..9b0b9d3
--- /dev/null
@@ -0,0 +1,103 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file container_adaptor/vector_map_adaptor.hpp
+/// \brief Container adaptor.
+
+#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_MAP_ADAPTOR_HPP
+#define BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_MAP_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/list.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/bimap/container_adaptor/vector_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/identity_converters.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace container_adaptor {
+
+/// \brief Container adaptor.
+
+template
+<
+    class Base,
+
+    class Iterator,
+    class ConstIterator,
+    class ReverseIterator,
+    class ConstReverseIterator,
+
+    class IteratorToBaseConverter          = ::boost::mpl::na,
+    class IteratorFromBaseConverter        = ::boost::mpl::na,
+    class ReverseIteratorFromBaseConverter = ::boost::mpl::na,
+    class ValueToBaseConverter             = ::boost::mpl::na,
+    class ValueFromBaseConverter           = ::boost::mpl::na,
+
+    class FunctorsFromDerivedClasses = mpl::vector<>
+>
+class vector_map_adaptor :
+
+    public vector_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        FunctorsFromDerivedClasses
+    >
+{
+    typedef vector_adaptor
+    <
+        Base,
+        Iterator, ConstIterator, ReverseIterator, ConstReverseIterator,
+        IteratorToBaseConverter, IteratorFromBaseConverter,
+        ReverseIteratorFromBaseConverter,
+        ValueToBaseConverter, ValueFromBaseConverter,
+        FunctorsFromDerivedClasses
+
+    > base_;
+
+    // MetaData -------------------------------------------------------------
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type  key_type;
+    typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type;
+
+    // Access -----------------------------------------------------------------
+
+    public:
+
+    vector_map_adaptor() {}
+
+    explicit vector_map_adaptor(Base & c) :
+        base_(c) {}
+
+    protected:
+
+    typedef vector_map_adaptor vector_map_adaptor_;
+
+};
+
+
+} // namespace container_adaptor
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_MAP_ADAPTOR_HPP
+
diff --git a/boost/bimap/detail/bimap_core.hpp b/boost/bimap/detail/bimap_core.hpp
new file mode 100644 (file)
index 0000000..247e93a
--- /dev/null
@@ -0,0 +1,520 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/bimap_core.hpp
+/// \brief Bimap base definition.
+
+#ifndef BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP
+#define BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/vector.hpp>
+
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/concept_check.hpp>
+
+// Boost.MultiIndex
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+
+// Boost.Bimap
+#include <boost/bimap/relation/mutant_relation.hpp>
+#include <boost/bimap/relation/member_at.hpp>
+#include <boost/bimap/relation/support/data_extractor.hpp>
+#include <boost/bimap/tags/support/default_tagged.hpp>
+#include <boost/bimap/tags/tagged.hpp>
+#include <boost/bimap/detail/manage_bimap_key.hpp>
+#include <boost/bimap/detail/manage_additional_parameters.hpp>
+#include <boost/bimap/detail/map_view_iterator.hpp>
+#include <boost/bimap/detail/set_view_iterator.hpp>
+
+#include <boost/bimap/set_of.hpp>
+#include <boost/bimap/unconstrained_set_of.hpp>
+
+namespace boost {
+namespace bimaps {
+
+/// \brief Library details
+
+namespace detail {
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class Type >
+struct get_value_type
+{
+    typedef BOOST_DEDUCED_TYPENAME Type::value_type type;
+};
+
+struct independent_index_tag {};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+
+/// \brief Base for the bimap class.
+/**
+
+
+See also bimap.
+                                                                        **/
+
+
+template< class LeftSetType, class RightSetType, class AP1, class AP2, class AP3 >
+class bimap_core
+{
+    // Manage bimap key instantiation
+    // --------------------------------------------------------------------
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME manage_bimap_key
+    <
+        LeftSetType
+
+    >::type left_set_type;
+
+    typedef BOOST_DEDUCED_TYPENAME manage_bimap_key
+    <
+        RightSetType
+    
+       >::type right_set_type;
+
+       
+       private:
+
+       typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::default_tagged
+       < 
+               BOOST_DEDUCED_TYPENAME left_set_type::user_type,
+               ::boost::bimaps::relation::member_at::left 
+       
+       >::type left_tagged_type;
+
+       typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::default_tagged
+       < 
+               BOOST_DEDUCED_TYPENAME right_set_type::user_type,
+               ::boost::bimaps::relation::member_at::right
+       
+       >::type right_tagged_type;
+
+       public:
+
+       //@{
+
+               typedef BOOST_DEDUCED_TYPENAME  left_tagged_type::tag  left_tag;
+               typedef BOOST_DEDUCED_TYPENAME right_tagged_type::tag right_tag;
+
+       //@}
+
+    //@{
+
+        typedef BOOST_DEDUCED_TYPENAME  left_set_type::value_type  left_key_type;
+        typedef BOOST_DEDUCED_TYPENAME right_set_type::value_type right_key_type;
+
+    //@}
+
+    //@{
+
+        typedef right_key_type  left_data_type;
+        typedef  left_key_type right_data_type;
+
+    //@}
+
+    // Manage the additional parameters
+    // --------------------------------------------------------------------
+    private:
+
+    typedef BOOST_DEDUCED_TYPENAME manage_additional_parameters<AP1,AP2,AP3>::type parameters;
+
+    /// \brief Relation type stored by the bimap.
+    // --------------------------------------------------------------------
+    public:
+
+    typedef ::boost::bimaps::relation::mutant_relation
+    <
+
+        ::boost::bimaps::tags::tagged<
+            BOOST_DEDUCED_TYPENAME mpl::if_<
+                mpl::and_
+                <
+                    BOOST_DEDUCED_TYPENAME left_set_type::mutable_key,
+                    BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation::left_mutable_key
+                >,
+            // {
+                    left_key_type,
+            // }
+            // else
+            // {
+                    BOOST_DEDUCED_TYPENAME ::boost::add_const< left_key_type >::type
+            // }
+
+            >::type,
+            left_tag
+        >,
+
+        ::boost::bimaps::tags::tagged<
+            BOOST_DEDUCED_TYPENAME mpl::if_<
+                mpl::and_
+                <
+                    BOOST_DEDUCED_TYPENAME right_set_type::mutable_key,
+                    BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation::right_mutable_key
+                >,
+            // {
+                    right_key_type,
+            // }
+            // else
+            // {
+                    BOOST_DEDUCED_TYPENAME ::boost::add_const< right_key_type >::type
+            // }
+
+            >::type,
+            right_tag
+        >,
+
+        // It is ::boost::mpl::na if no info_hook was included
+        BOOST_DEDUCED_TYPENAME parameters::additional_info,
+
+        // Force mutable keys
+        true
+
+    > relation;
+
+    //@{
+
+        typedef BOOST_DEDUCED_TYPENAME relation::left_pair  left_value_type;
+        typedef BOOST_DEDUCED_TYPENAME relation::right_pair right_value_type;
+
+    //@}
+
+    // Bind the member of the relation, so multi_index can manage them
+    // --------------------------------------------------------------------
+    private:
+
+    typedef BOOST_DEDUCED_TYPENAME relation::storage_base relation_storage_base;
+
+    typedef BOOST_MULTI_INDEX_MEMBER(relation_storage_base, left_key_type, left)
+        left_member_extractor;
+
+    typedef BOOST_MULTI_INDEX_MEMBER(relation_storage_base,right_key_type,right)
+        right_member_extractor;
+
+    // The core indices are somewhat complicated to calculate, because they
+    // can be zero, one, two or three indices, depending on the use of
+    // {side}_based set type of relations and unconstrained_set_of and
+    // unconstrained_set_of_relation specifications.
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+        ::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >,
+    // {
+            mpl::vector<>,
+    // }
+    // else
+    // {
+            mpl::vector
+            <
+                BOOST_DEDUCED_TYPENAME left_set_type::
+                BOOST_NESTED_TEMPLATE index_bind
+                <
+                    left_member_extractor,
+                    left_tag
+
+                >::type
+            >
+    // }
+    >::type left_core_indices;
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+        ::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >,
+    // {
+            left_core_indices,
+    // }
+    // else
+    // {
+            BOOST_DEDUCED_TYPENAME mpl::push_front
+            <
+                left_core_indices,
+
+                BOOST_DEDUCED_TYPENAME right_set_type::
+                BOOST_NESTED_TEMPLATE index_bind
+                <
+                    right_member_extractor,
+                    right_tag
+
+                >::type
+
+            >::type
+    // }
+    >::type basic_core_indices;
+
+    // If it is based either on the left or on the right, then only the side
+    // indices are needed. But the set type of the relation can be completely
+    // diferent from the one used for the sides in wich case we have to add yet
+    // another index to the core.
+
+    // TODO
+    // If all the set types are unsconstrained there must be readable compile
+    // time error.
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+
+        is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, left_based >,
+    // {
+            ::boost::bimaps::tags::tagged< left_set_type, left_tag >,
+    // }
+    /* else */ BOOST_DEDUCED_TYPENAME mpl::if_<
+            is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, right_based >,
+    // {
+                       ::boost::bimaps::tags::tagged< right_set_type, right_tag >,
+    // }
+    // else
+    // {
+            tags::tagged
+            <
+                BOOST_DEDUCED_TYPENAME parameters::
+                set_type_of_relation::BOOST_NESTED_TEMPLATE bind_to
+                <
+                    relation
+
+                >::type,
+                independent_index_tag
+            >
+    // }
+    >::type
+    >::type tagged_set_of_relation_type;
+
+    protected:
+
+    typedef BOOST_DEDUCED_TYPENAME tagged_set_of_relation_type::tag
+                        relation_set_tag;
+
+    typedef BOOST_DEDUCED_TYPENAME tagged_set_of_relation_type::value_type
+                        relation_set_type_of;
+
+    // Logic tags
+    // This is a necesary extra level of indirection to allow unconstrained
+    // sets to be plug in the design. The bimap constructors use this logic
+    // tags.
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+        ::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >,
+
+        BOOST_DEDUCED_TYPENAME mpl::if_<
+            ::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >,
+
+            independent_index_tag,
+            right_tag
+
+        >::type,
+
+        left_tag
+
+    >::type logic_left_tag;
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+        ::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >,
+
+        BOOST_DEDUCED_TYPENAME mpl::if_< 
+            ::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >,
+
+            independent_index_tag,
+            left_tag
+
+        >::type,
+
+        right_tag
+
+    >::type logic_right_tag;
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_< 
+        is_same< relation_set_tag, independent_index_tag >,
+
+        BOOST_DEDUCED_TYPENAME mpl::if_< 
+            ::boost::bimaps::detail::
+                is_unconstrained_set_of< relation_set_type_of >,
+
+            logic_left_tag,
+            independent_index_tag
+
+        >::type,
+
+        BOOST_DEDUCED_TYPENAME mpl::if_<
+            is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, left_based >,
+
+            logic_left_tag,
+            logic_right_tag
+
+        >::type
+
+    >::type logic_relation_set_tag;
+
+    private:
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+        mpl::and_< is_same< relation_set_tag, independent_index_tag >,
+                   mpl::not_<
+                       ::boost::bimaps::detail::
+                            is_unconstrained_set_of< relation_set_type_of > 
+                   >
+        >,
+    // {
+            BOOST_DEDUCED_TYPENAME mpl::push_front
+            <
+                basic_core_indices,
+
+                BOOST_DEDUCED_TYPENAME relation_set_type_of::
+                BOOST_NESTED_TEMPLATE index_bind
+                <
+                    ::boost::bimaps::relation::support::both_keys_extractor<relation>,
+                    independent_index_tag
+
+                >::type
+
+            >::type,
+    // }
+    // else
+    // {
+            basic_core_indices
+    // }
+
+    >::type complete_core_indices;
+
+    struct core_indices : public complete_core_indices {};
+
+    // Define the core using compute_index_type to translate the
+    // set type to an multi-index specification
+    // --------------------------------------------------------------------
+    public:
+
+    typedef multi_index::multi_index_container
+    <
+        relation,
+        core_indices,
+        BOOST_DEDUCED_TYPENAME parameters::allocator::
+            BOOST_NESTED_TEMPLATE rebind<relation>::other
+
+    > core_type;
+
+    // Core metadata
+    // --------------------------------------------------------------------
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index::
+        index<core_type, logic_left_tag>::type  left_index;
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index::
+        index<core_type,logic_right_tag>::type right_index;
+
+    typedef BOOST_DEDUCED_TYPENAME  left_index::iterator        left_core_iterator;
+    typedef BOOST_DEDUCED_TYPENAME  left_index::const_iterator  left_core_const_iterator;
+
+    typedef BOOST_DEDUCED_TYPENAME right_index::iterator       right_core_iterator;
+    typedef BOOST_DEDUCED_TYPENAME right_index::const_iterator right_core_const_iterator;
+
+    // Map by {side} iterator metadata
+    // --------------------------------------------------------------------
+    public:
+
+    //@{
+
+        typedef ::boost::bimaps::detail::map_view_iterator
+        <
+            left_tag,
+            relation,
+            left_core_iterator
+
+        > left_iterator;
+
+        typedef ::boost::bimaps::detail::map_view_iterator
+        <
+            right_tag,
+            relation,
+            right_core_iterator
+
+        > right_iterator;
+
+    //@}
+
+    //@{
+
+        typedef ::boost::bimaps::detail::const_map_view_iterator
+        <
+            left_tag,
+            relation,
+            left_core_const_iterator
+
+        > left_const_iterator;
+
+        typedef ::boost::bimaps::detail::const_map_view_iterator
+        <
+            right_tag,
+            relation,
+            right_core_const_iterator
+
+        > right_const_iterator;
+
+    //@}
+
+    // Relation set view
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index::index
+    <
+        core_type, logic_relation_set_tag
+
+    >::type relation_set_core_index;
+
+    typedef BOOST_DEDUCED_TYPENAME relation_set_type_of::
+    BOOST_NESTED_TEMPLATE set_view_bind
+    <
+        relation_set_core_index
+
+    >::type relation_set;
+
+    public:
+
+    typedef bimap_core bimap_core_;
+};
+
+// Two auxiliar metafunctions to compute the map view types
+// The map view type can not be computed inside the bimap core because a 
+// they need the bimap core to be parsed first.
+
+template< class BimapBaseType >
+struct left_map_view_type
+{
+       typedef BOOST_DEDUCED_TYPENAME BimapBaseType::left_set_type left_set_type;
+    typedef BOOST_DEDUCED_TYPENAME
+        left_set_type::BOOST_NESTED_TEMPLATE map_view_bind<
+            BOOST_DEDUCED_TYPENAME BimapBaseType::left_tag, BimapBaseType
+        >::type type;
+};
+
+template< class BimapBaseType >
+struct right_map_view_type
+{
+       typedef BOOST_DEDUCED_TYPENAME BimapBaseType::right_set_type right_set_type;
+    typedef BOOST_DEDUCED_TYPENAME
+        right_set_type::BOOST_NESTED_TEMPLATE map_view_bind<
+            BOOST_DEDUCED_TYPENAME BimapBaseType::right_tag, BimapBaseType
+        >::type type;
+};
+
+} // namespace detail
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP
diff --git a/boost/bimap/detail/concept_tags.hpp b/boost/bimap/detail/concept_tags.hpp
new file mode 100644 (file)
index 0000000..1f252e3
--- /dev/null
@@ -0,0 +1,97 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/concept_tags.hpp
+/// \brief Bimap tags and concepts
+
+#ifndef BOOST_BIMAP_DETAIL_CONCEPT_TAGS_HPP
+#define BOOST_BIMAP_DETAIL_CONCEPT_TAGS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/bool.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace detail {
+
+/// \brief Tag of {SetType}_of definition classes
+/**
+The {SetType}_of classes are derived from this class so it is easy to construct
+metafunctions. For example now is easy to create a is_set_type_of metafunction.
+                                                                                **/
+
+struct set_type_of_tag          {};
+
+/// \brief Tag of {SetType}_of_relation defition classes
+
+struct set_type_of_relation_tag {};
+
+/// \brief Tag of {Side}_based identifiers
+
+struct side_based_tag : set_type_of_relation_tag {};
+
+} // namespace detail
+
+
+/** \struct boost::bimaps::left_based
+    \brief Tag to indicate that the main view will be based on the left side.
+
+This is convenient because the multi-index core will be more efficient.
+If possible use this options or the right based one.
+
+See also right_based.
+                                                                            **/
+
+/** \struct boost::bimaps::right_based
+    \brief Tag to indicate that the main view will be based on the right side.
+
+This is convenient because the multi-index core will be more efficient.
+If possible use this options or the right based one.
+
+See also left_based.
+                                                                            **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+struct left_based : ::boost::bimaps::detail::side_based_tag
+{
+    // I run into troubles if I do not define bind for side based tags.
+    // Maybe a more coherent way of binding the relation can be developped.
+    template< class Relation > struct bind_to { typedef void type; };
+
+    typedef mpl::bool_<true>  left_mutable_key;
+    typedef mpl::bool_<true> right_mutable_key;
+};
+
+struct right_based : ::boost::bimaps::detail::side_based_tag
+{
+    // I run into troubles if I do not define bind for side based tags.
+    // Maybe a more coherent way of binding the relation can be developped.
+    template< class Relation > struct bind_to { typedef void type; };
+
+    typedef mpl::bool_<true>  left_mutable_key;
+    typedef mpl::bool_<true> right_mutable_key;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+typedef mpl::_ _relation;
+
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_DETAIL_CONCEPT_TAGS_HPP
+
diff --git a/boost/bimap/detail/debug/static_error.hpp b/boost/bimap/detail/debug/static_error.hpp
new file mode 100644 (file)
index 0000000..3a8ed63
--- /dev/null
@@ -0,0 +1,36 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/debug/static_error.hpp
+/// \brief Formatted compile time error
+
+#ifndef BOOST_BIMAP_DETAIL_DEBUG_STATIC_ERROR_HPP
+#define BOOST_BIMAP_DETAIL_DEBUG_STATIC_ERROR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+// Easier way to call BOOST_MPL_ASSERT_MSG in class scope to generate
+// a static error.
+/*===========================================================================*/
+#define BOOST_BIMAP_STATIC_ERROR(MESSAGE,VARIABLES)                           \
+        struct BOOST_PP_CAT(BIMAP_STATIC_ERROR__,MESSAGE) {};                 \
+        BOOST_MPL_ASSERT_MSG(false,                                           \
+                             BOOST_PP_CAT(BIMAP_STATIC_ERROR__,MESSAGE),      \
+                             VARIABLES)
+/*===========================================================================*/
+
+
+
+#endif // BOOST_BIMAP_DETAIL_DEBUG_STATIC_ERROR_HPP
diff --git a/boost/bimap/detail/generate_index_binder.hpp b/boost/bimap/detail/generate_index_binder.hpp
new file mode 100644 (file)
index 0000000..01c899d
--- /dev/null
@@ -0,0 +1,125 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/generate_index_binder.hpp
+/// \brief Define macros to help building the set type of definitions
+
+
+#ifndef BOOST_BIMAP_DETAIL_GENERATE_INDEX_BINDER_HPP
+#define BOOST_BIMAP_DETAIL_GENERATE_INDEX_BINDER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/multi_index/tag.hpp>
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_INDEX_BINDER_0CP(                                \
+                                                                              \
+    MULTI_INDEX_TYPE                                                          \
+                                                                              \
+)                                                                             \
+                                                                              \
+template< class KeyExtractor, class Tag >                                     \
+struct index_bind                                                             \
+{                                                                             \
+    typedef MULTI_INDEX_TYPE                                                  \
+    <                                                                         \
+        multi_index::tag< Tag >,                                              \
+        KeyExtractor                                                          \
+                                                                              \
+    > type;                                                                   \
+};
+/*===========================================================================*/
+
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_INDEX_BINDER_1CP(                                \
+                                                                              \
+    MULTI_INDEX_TYPE,                                                         \
+    CONFIG_PARAMETER                                                          \
+                                                                              \
+)                                                                             \
+                                                                              \
+template< class KeyExtractor, class Tag >                                     \
+struct index_bind                                                             \
+{                                                                             \
+    typedef MULTI_INDEX_TYPE                                                  \
+    <                                                                         \
+        multi_index::tag< Tag >,                                              \
+        KeyExtractor,                                                         \
+        CONFIG_PARAMETER                                                      \
+                                                                              \
+    > type;                                                                   \
+};
+/*===========================================================================*/
+
+
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_INDEX_BINDER_2CP(                                \
+                                                                              \
+    MULTI_INDEX_TYPE,                                                         \
+    CONFIG_PARAMETER_1,                                                       \
+    CONFIG_PARAMETER_2                                                        \
+)                                                                             \
+                                                                              \
+template< class KeyExtractor, class Tag >                                     \
+struct index_bind                                                             \
+{                                                                             \
+    typedef MULTI_INDEX_TYPE                                                  \
+    <                                                                         \
+        multi_index::tag< Tag >,                                              \
+        KeyExtractor,                                                         \
+        CONFIG_PARAMETER_1,                                                   \
+        CONFIG_PARAMETER_2                                                    \
+                                                                              \
+    > type;                                                                   \
+                                                                              \
+};
+/*===========================================================================*/
+
+
+// This is a special registration to allow sequenced and random access indices
+// to play along smoothly with the other index types.
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_INDEX_BINDER_0CP_NO_EXTRACTOR(                   \
+                                                                              \
+    MULTI_INDEX_TYPE                                                          \
+                                                                              \
+)                                                                             \
+                                                                              \
+template< class KeyExtractor, class Tag >                                     \
+struct index_bind                                                             \
+{                                                                             \
+    typedef MULTI_INDEX_TYPE< multi_index::tag< Tag > > type;                 \
+};
+/*===========================================================================*/
+
+
+// This is yet another special registration to allow unconstrained sets
+// to play along smoothly with the other index types.
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_INDEX_BINDER_FAKE                                \
+                                                                              \
+template< class KeyExtractor, class Tag >                                     \
+struct index_bind                                                             \
+{                                                                             \
+    typedef void type;                                                        \
+};                                                                            \
+/*===========================================================================*/
+
+#endif // BOOST_BIMAP_DETAIL_GENERATE_INDEX_BINDER_HPP
diff --git a/boost/bimap/detail/generate_relation_binder.hpp b/boost/bimap/detail/generate_relation_binder.hpp
new file mode 100644 (file)
index 0000000..0ff4762
--- /dev/null
@@ -0,0 +1,88 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/generate_relation_binder.hpp
+/// \brief Define macros to help building the set type of definitions
+
+#ifndef BOOST_BIMAP_DETAIL_GENERATE_RELATION_BINDER_HPP
+#define BOOST_BIMAP_DETAIL_GENERATE_RELATION_BINDER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/apply.hpp>
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_RELATION_BINDER_0CP(                             \
+                                                                              \
+        SET_TYPE_OF                                                           \
+    )                                                                         \
+                                                                              \
+    template< class Relation >                                                \
+    struct bind_to                                                            \
+    {                                                                         \
+        typedef SET_TYPE_OF<Relation> type;                                   \
+                                                                              \
+    };
+/*===========================================================================*/
+
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_RELATION_BINDER_1CP(                             \
+                                                                              \
+        SET_TYPE_OF,                                                          \
+        CP1                                                                   \
+    )                                                                         \
+                                                                              \
+    template< class Relation >                                                \
+    struct bind_to                                                            \
+    {                                                                         \
+        typedef SET_TYPE_OF                                                   \
+        <                                                                     \
+            Relation,                                                         \
+            BOOST_DEDUCED_TYPENAME mpl::apply<CP1,                            \
+                BOOST_DEDUCED_TYPENAME Relation::storage_base >::type         \
+                                                                              \
+        > type;                                                               \
+                                                                              \
+    };
+/*===========================================================================*/
+
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_RELATION_BINDER_2CP(                             \
+                                                                              \
+        SET_TYPE_OF,                                                          \
+        CP1,                                                                  \
+        CP2                                                                   \
+    )                                                                         \
+                                                                              \
+    template< class Relation >                                                \
+    struct bind_to                                                            \
+    {                                                                         \
+        typedef SET_TYPE_OF                                                   \
+        <                                                                     \
+            Relation,                                                         \
+            BOOST_DEDUCED_TYPENAME mpl::apply<CP1,                            \
+                BOOST_DEDUCED_TYPENAME Relation::storage_base >::type,        \
+            BOOST_DEDUCED_TYPENAME mpl::apply<CP2,                            \
+                BOOST_DEDUCED_TYPENAME Relation::storage_base >::type         \
+                                                                              \
+        > type;                                                               \
+                                                                              \
+    };
+/*===========================================================================*/
+
+
+
+#endif // BOOST_BIMAP_DETAIL_GENERATE_RELATION_BINDER_HPP
diff --git a/boost/bimap/detail/generate_view_binder.hpp b/boost/bimap/detail/generate_view_binder.hpp
new file mode 100644 (file)
index 0000000..925184c
--- /dev/null
@@ -0,0 +1,58 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/generate_view_binder.hpp
+/// \brief Define macros to help building the set type of definitions
+
+#ifndef BOOST_BIMAP_DETAIL_GENERATE_VIEW_BINDER_HPP
+#define BOOST_BIMAP_DETAIL_GENERATE_VIEW_BINDER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/multi_index/tag.hpp>
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER(                                 \
+                                                                              \
+    MAP_VIEW_TYPE                                                             \
+                                                                              \
+)                                                                             \
+                                                                              \
+template< class Tag, class BimapType >                                        \
+struct map_view_bind                                                          \
+{                                                                             \
+    typedef MAP_VIEW_TYPE                                                     \
+    <                                                                         \
+        Tag,                                                                  \
+        BimapType                                                             \
+                                                                              \
+    > type;                                                                   \
+};
+/*===========================================================================*/
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_GENERATE_SET_VIEW_BINDER(                                 \
+                                                                              \
+    SET_VIEW_TYPE                                                             \
+                                                                              \
+)                                                                             \
+                                                                              \
+template< class IndexType >                                                   \
+struct set_view_bind                                                          \
+{                                                                             \
+    typedef SET_VIEW_TYPE<IndexType> type;                                    \
+};
+/*===========================================================================*/
+
+
+#endif // BOOST_BIMAP_DETAIL_GENERATE_VIEW_BINDER_HPP
diff --git a/boost/bimap/detail/is_set_type_of.hpp b/boost/bimap/detail/is_set_type_of.hpp
new file mode 100644 (file)
index 0000000..13d52c1
--- /dev/null
@@ -0,0 +1,66 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/is_set_type_of.hpp
+/// \brief Is set type of and is set type of relation metafunctions.
+
+#ifndef BOOST_BIMAP_DETAIL_IS_SET_TYPE_OF_HPP
+#define BOOST_BIMAP_DETAIL_IS_SET_TYPE_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/bimap/detail/concept_tags.hpp>
+
+/** \struct boost::bimaps::detail::is_set_type_of
+
+\brief Type trait to check if a class is a set_type_of specification
+
+\code
+template< class Type >
+struct is_set_type_of : {true_|false_} {};
+\endcode
+                                                                        **/
+
+/** \struct boost::bimaps::detail::is_set_type_of_relation
+
+\brief Type trait to check if a class is a set_type_of_relation specification
+
+\code
+template< class Type >
+struct is_set_type_of_relation : {true_|false_} {};
+\endcode
+
+                                                                               **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace detail {
+
+template< class Type >
+struct is_set_type_of :
+    is_base_of< set_type_of_tag, Type > {};
+
+template< class Type >
+struct is_set_type_of_relation :
+    is_base_of< set_type_of_relation_tag, Type > {};
+
+} // namespace detail
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_DETAIL_IS_SET_TYPE_OF_HPP
+
diff --git a/boost/bimap/detail/manage_additional_parameters.hpp b/boost/bimap/detail/manage_additional_parameters.hpp
new file mode 100644 (file)
index 0000000..3d22d73
--- /dev/null
@@ -0,0 +1,243 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/manage_additional_parameters.hpp
+/// \brief Utility class to extract the additional parameters from the template parameters.
+
+#ifndef BOOST_BIMAP_DETAIL_MANAGE_ADDITIONAL_PARAMETERS_HPP
+#define BOOST_BIMAP_DETAIL_MANAGE_ADDITIONAL_PARAMETERS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <memory>
+
+// Boost.MPL
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/bimap/detail/is_set_type_of.hpp>
+
+namespace boost {
+namespace bimaps {
+
+template< class Type >
+struct with_info
+{
+    typedef Type value_type;
+};
+
+namespace detail {
+
+/// \brief Metafunction to check if a given type is a data_hook specification.
+
+template< class Type >
+struct is_with_info : ::boost::mpl::false_ {};
+
+template< class ValueType >
+struct is_with_info< with_info<ValueType> > : ::boost::mpl::true_ {};
+
+/** \struct boost::bimaps::detail::manage_additional_parameters
+\brief Utility class to extract the additional parameters from the template parameters.
+
+\code
+template< class AP1, class AP2, class AP3 >
+struct manage_additional_parameters
+{
+    struct parameters
+    {
+        typedef -unspecified- set_type_of_relation;
+        typedef -unspecified- data_hook;
+        typedef -unspecified- allocator;
+    };
+
+    typedef parameters type;
+};
+\endcode
+
+See also bimap, bimap_core.
+                                                                                **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class AP1, class AP2, class AP3 >
+struct manage_additional_parameters
+{
+    // (1) manage_additional_parameters<
+    //         not_specified,not_specified,not_specified>
+    //
+    //     set_type_of_relation: based on the left key type
+    //     info_hook:            no additional info
+    //     allocator:            default allocator
+
+    struct case_NNN
+    {
+        typedef left_based set_type_of_relation;
+        typedef std::allocator<void> allocator;
+        typedef ::boost::mpl::na additional_info;
+    };
+
+    // (2) manage_additional_parameters<Allocator,not_specified,not_specified>
+    //
+    //     set_type_of_relation: based on the left key type
+    //     info_hook:            no additional info
+    //     allocator:            Allocator
+
+    struct case_ANN
+    {
+        typedef left_based set_type_of_relation;
+        typedef AP1 allocator;
+        typedef ::boost::mpl::na additional_info;
+    };
+
+    // (3) manage_additional_parameters<
+    //         SetOfRelationType,not_specified,not_specified>
+    //
+    //     set_type_of_relation: SetTypeOfRelation
+    //     info_hook:            no additional info
+    //     allocator:            default allocator
+
+    struct case_SNN
+    {
+        typedef AP1 set_type_of_relation;
+        typedef std::allocator<void> allocator;
+        typedef ::boost::mpl::na additional_info;
+    };
+
+    // (4) manage_additional_parameters<
+    //          SetTypeOfRelation,Allocator,not_specified>
+    //
+    //     set_type_of_relation: SetTypeOfRelation
+    //     info_hook:            no additional info
+    //     allocator:            Allocator
+
+    struct case_SAN
+    {
+        typedef AP1 set_type_of_relation;
+        typedef AP2 allocator;
+        typedef ::boost::mpl::na additional_info;
+    };
+
+    // (5) manage_additional_parameters<InfoToHook,not_specified,not_specified>
+    //
+    //     set_type_of_relation: based on the left key type
+    //     info_hook:            InfoToHook
+    //     allocator:            default allocator
+
+    struct case_HNN
+    {
+        typedef left_based set_type_of_relation;
+        typedef std::allocator<void> allocator;
+        typedef BOOST_DEDUCED_TYPENAME AP1::value_type additional_info;
+    };
+
+    // (6) manage_additional_parameters<
+    //         SetTypeOfRelation,InfoToHook,not_specified>
+    //
+    //     set_type_of_relation: SetTypeOfRelation
+    //     info_hook:            InfoToHook
+    //     allocator:            default allocator
+
+    struct case_SHN
+    {
+        typedef AP1 set_type_of_relation;
+        typedef std::allocator<void> allocator;
+        typedef BOOST_DEDUCED_TYPENAME AP2::value_type additional_info;
+    };
+
+    // (7) manage_additional_parameters<
+    //         DataToHook,Allocator,not_specified>
+    //
+    //     set_type_of_relation: SetTypeOfRelation
+    //     info_hook:            InfoToHook
+    //     allocator:            default allocator
+
+    struct case_HAN
+    {
+        typedef left_based set_type_of_relation;
+        typedef AP2 allocator;
+        typedef BOOST_DEDUCED_TYPENAME AP1::value_type additional_info;
+    };
+
+    // (8) manage_additional_parameters<
+    //         SetTypeOfRelation,DataToHook,Allocator>
+    //
+    //     set_type_of_relation: SetTypeOfRelation
+    //     info_hook:            InfoToHook
+    //     allocator:            Allocator
+
+    struct case_SHA
+    {
+        typedef AP1 set_type_of_relation;
+        typedef AP2 allocator;
+        typedef BOOST_DEDUCED_TYPENAME AP2::value_type additional_info;
+    };
+
+    // Some annidated mpl::if_ and we are done!
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_
+    <
+        ::boost::mpl::is_na<AP1>,
+        case_NNN, // (1)
+        BOOST_DEDUCED_TYPENAME mpl::if_
+        <
+            ::boost::mpl::is_na<AP2>,
+            BOOST_DEDUCED_TYPENAME mpl::if_
+            <
+                is_set_type_of_relation<AP1>,
+                case_SNN, // (3)
+                BOOST_DEDUCED_TYPENAME mpl::if_
+                <
+                    is_with_info<AP1>,
+                    case_HNN, // (5)
+                    case_ANN  // (2)
+
+                >::type
+
+            >::type,
+            BOOST_DEDUCED_TYPENAME mpl::if_
+            <
+                ::boost::mpl::is_na<AP3>,
+                BOOST_DEDUCED_TYPENAME mpl::if_
+                <
+                    is_with_info<AP1>,
+                    case_HAN, // (7)
+                    BOOST_DEDUCED_TYPENAME mpl::if_
+                    <
+                        is_with_info<AP2>,
+                        case_SHN, // (6)
+                        case_SAN  // (4)
+
+                    >::type
+
+                >::type,
+
+                case_SHA // (8)
+
+            >::type
+
+        >::type
+
+    >::type type;
+
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+} // namespace detail
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_DETAIL_MANAGE_ADDITIONAL_PARAMETERS_HPP
+
diff --git a/boost/bimap/detail/manage_bimap_key.hpp b/boost/bimap/detail/manage_bimap_key.hpp
new file mode 100644 (file)
index 0000000..d485e50
--- /dev/null
@@ -0,0 +1,84 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/manage_bimap_key.hpp
+/// \brief Utility class to manage the set types of a bimap.
+
+#ifndef BOOST_BIMAP_DETAIL_MANAGE_BIMAP_KEY_HPP
+#define BOOST_BIMAP_DETAIL_MANAGE_BIMAP_KEY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+
+#include <boost/bimap/detail/is_set_type_of.hpp>
+
+#include <boost/bimap/set_of.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace detail {
+
+/** \struct boost::bimaps::detail::manage_bimap_key
+\brief Metafunction to manage the set types of a bimap.
+
+\code
+template< class Type >
+struct manage_bimap_key
+{
+    typedef -SetType- type;
+}
+\endcode
+
+See also bimap, bimap_core.
+                                                                                **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class Type >
+struct manage_bimap_key
+{
+
+typedef BOOST_DEDUCED_TYPENAME
+
+    mpl::eval_if< BOOST_DEDUCED_TYPENAME is_set_type_of< Type >::type,
+    // {
+            mpl::identity< Type >,
+    // }
+    // else
+    // {
+            // Default it to a set
+            mpl::identity< set_of< Type > >
+    // }
+
+    >::type set_type;
+
+    // Returns set_type and evaluate the concept_checked_type
+
+    typedef BOOST_DEDUCED_TYPENAME mpl::if_c< true, set_type, 
+        BOOST_DEDUCED_TYPENAME set_type::lazy_concept_checked::type
+    >::type type;
+};
+
+
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+} // namespace detail
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_DETAIL_MANAGE_BIMAP_KEY_HPP
+
+
diff --git a/boost/bimap/detail/map_view_base.hpp b/boost/bimap/detail/map_view_base.hpp
new file mode 100644 (file)
index 0000000..7479937
--- /dev/null
@@ -0,0 +1,552 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/map_view_base.hpp
+/// \brief Helper base for the construction of the bimap views types.
+
+#ifndef BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP
+#define BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <stdexcept>
+#include <utility>
+
+#include <boost/type_traits/is_const.hpp>
+#include <boost/mpl/if.hpp>
+
+#include <boost/bimap/relation/support/get_pair_functor.hpp>
+#include <boost/bimap/relation/detail/to_mutable_relation_functor.hpp>
+#include <boost/bimap/container_adaptor/support/iterator_facade_converters.hpp>
+#include <boost/bimap/relation/support/data_extractor.hpp>
+#include <boost/bimap/relation/support/opposite_tag.hpp>
+#include <boost/bimap/relation/support/pair_type_by.hpp>
+#include <boost/bimap/support/iterator_type_by.hpp>
+#include <boost/bimap/support/key_type_by.hpp>
+#include <boost/bimap/support/data_type_by.hpp>
+#include <boost/bimap/support/value_type_by.hpp>
+#include <boost/bimap/detail/modifier_adaptor.hpp>
+#include <boost/bimap/detail/debug/static_error.hpp>
+
+namespace boost {
+namespace bimaps {
+
+namespace detail {
+
+
+// The next macro can be converted in a metafunctor to gain code robustness.
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(                               \
+    CONTAINER_ADAPTOR, TAG,BIMAP, OTHER_ITER, CONST_OTHER_ITER                \
+)                                                                             \
+::boost::bimaps::container_adaptor::CONTAINER_ADAPTOR                         \
+<                                                                             \
+    BOOST_DEDUCED_TYPENAME BIMAP::core_type::                                 \
+        BOOST_NESTED_TEMPLATE index<TAG>::type,                               \
+    BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::                         \
+        iterator_type_by<TAG,BIMAP>::type,                                    \
+    BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::                         \
+        const_iterator_type_by<TAG,BIMAP>::type,                              \
+    BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::                         \
+        OTHER_ITER<TAG,BIMAP>::type,                                          \
+    BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::                         \
+        CONST_OTHER_ITER<TAG,BIMAP>::type,                                    \
+    ::boost::bimaps::container_adaptor::support::iterator_facade_to_base      \
+    <                                                                         \
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::                     \
+                  iterator_type_by<TAG,BIMAP>::type,                          \
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::                     \
+            const_iterator_type_by<TAG,BIMAP>::type                           \
+                                                                              \
+    >,                                                                        \
+    ::boost::mpl::na,                                                         \
+    ::boost::mpl::na,                                                         \
+    ::boost::bimaps::relation::detail::                                       \
+        pair_to_relation_functor<TAG,BOOST_DEDUCED_TYPENAME BIMAP::relation>, \
+    ::boost::bimaps::relation::support::                                      \
+        get_pair_functor<TAG, BOOST_DEDUCED_TYPENAME BIMAP::relation >        \
+>
+/*===========================================================================*/
+
+
+#if defined(BOOST_MSVC)
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP)                      \
+    typedef ::boost::bimaps::detail::map_view_base<                           \
+        TYPE<TAG,BIMAP>,TAG,BIMAP > friend_map_view_base;                     \
+    friend class friend_map_view_base;
+/*===========================================================================*/
+#else
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP)                      \
+    friend class ::boost::bimaps::detail::map_view_base<                      \
+        TYPE<TAG,BIMAP>,TAG,BIMAP >;
+/*===========================================================================*/
+#endif
+
+
+/// \brief Common base for map views.
+
+template< class Derived, class Tag, class BimapType>
+class map_view_base
+{
+    typedef ::boost::bimaps::container_adaptor::support::
+        iterator_facade_to_base<
+
+            BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                iterator_type_by<Tag,BimapType>::type,
+
+            BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                const_iterator_type_by<Tag,BimapType>::type
+
+        > iterator_to_base_;
+
+    typedef ::boost::bimaps::relation::detail::
+        pair_to_relation_functor<Tag,
+            BOOST_DEDUCED_TYPENAME BimapType::relation>      value_to_base_;
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                           key_type_by<Tag,BimapType>::type       key_type_;
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                          data_type_by<Tag,BimapType>::type      data_type_;
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+           pair_type_by<Tag,
+              BOOST_DEDUCED_TYPENAME BimapType::relation>::type value_type_;
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                    iterator_type_by<Tag,BimapType>::type         iterator_;
+
+    public:
+
+    bool replace(iterator_ position, const value_type_ & x)
+    {
+        return derived().base().replace(
+            derived().template functor<iterator_to_base_>()(position),
+            derived().template functor<value_to_base_>()(x)
+        );
+    }
+
+    template< class CompatibleKey >
+    bool replace_key(iterator_ position, const CompatibleKey & k)
+    {
+        return derived().base().replace(
+            derived().template functor<iterator_to_base_>()(position),
+            derived().template functor<value_to_base_>()(
+                value_type_(k,position->second)
+            )
+        );
+    }
+
+    template< class CompatibleData >
+    bool replace_data(iterator_ position, const CompatibleData & d)
+    {
+        return derived().base().replace(
+            derived().template functor<iterator_to_base_>()(position),
+            derived().template functor<value_to_base_>()(
+                value_type_(position->first,d)
+            )
+        );
+    }
+
+    /* This function may be provided in the future
+
+    template< class Modifier >
+    bool modify(iterator_ position, Modifier mod)
+    {
+        return derived().base().modify(
+
+            derived().template functor<iterator_to_base_>()(position),
+
+            ::boost::bimaps::detail::relation_modifier_adaptor
+            <
+                Modifier,
+                BOOST_DEDUCED_TYPENAME BimapType::relation,
+                BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+                data_extractor
+                <
+                    Tag, BOOST_DEDUCED_TYPENAME BimapType::relation
+
+                >::type,
+                BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+                data_extractor
+                <
+                    BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+                        opossite_tag<Tag,BimapType>::type,
+                    BOOST_DEDUCED_TYPENAME BimapType::relation
+
+                >::type
+
+            >(mod)
+        );
+    }
+    */
+
+    template< class Modifier >
+    bool modify_key(iterator_ position, Modifier mod)
+    {
+        return derived().base().modify_key(
+            derived().template functor<iterator_to_base_>()(position), mod
+        );
+    }
+
+    template< class Modifier >
+    bool modify_data(iterator_ position, Modifier mod)
+    {
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+        data_extractor
+        <
+            BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+                        opossite_tag<Tag,BimapType>::type,
+            BOOST_DEDUCED_TYPENAME BimapType::relation
+
+        >::type data_extractor_;
+
+        return derived().base().modify(
+
+            derived().template functor<iterator_to_base_>()(position),
+
+            // this may be replaced later by
+            // ::boost::bind( mod, ::boost::bind(data_extractor_(),_1) )
+
+            ::boost::bimaps::detail::unary_modifier_adaptor
+            <
+                Modifier,
+                BOOST_DEDUCED_TYPENAME BimapType::relation,
+                data_extractor_
+
+            >(mod)
+        );
+    }
+
+    protected:
+
+    typedef map_view_base map_view_base_;
+
+    private:
+
+    // Curiously Recurring Template interface.
+
+    Derived& derived()
+    {
+        return *static_cast<Derived*>(this);
+    }
+
+    Derived const& derived() const
+    {
+        return *static_cast<Derived const*>(this);
+    }
+};
+
+
+
+
+template< class Derived, class Tag, class BimapType>
+class mutable_data_unique_map_view_access
+{
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                          data_type_by<Tag,BimapType>::type      data_type_;
+
+    public:
+
+    template< class CompatibleKey >
+    data_type_ & at(const CompatibleKey& k)
+    {
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                            iterator_type_by<Tag,BimapType>::type iterator;
+
+        iterator iter = derived().find(k);
+        if( iter == derived().end() )
+        {
+            ::boost::throw_exception(
+                std::out_of_range("bimap<>: invalid key")
+            );
+        }
+        return iter->second;
+    }
+
+    template< class CompatibleKey >
+    const data_type_ & at(const CompatibleKey& k) const
+    {
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                const_iterator_type_by<Tag,BimapType>::type const_iterator;
+
+        const_iterator iter = derived().find(k);
+        if( iter == derived().end() )
+        {
+            ::boost::throw_exception(
+                std::out_of_range("bimap<>: invalid key")
+            );
+        }
+        return iter->second;
+    }
+
+    template< class CompatibleKey >
+    data_type_ & operator[](const CompatibleKey& k)
+    {
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                      iterator_type_by<Tag,BimapType>::type       iterator;
+
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                         value_type_by<Tag,BimapType>::type     value_type;
+
+        iterator iter = derived().find(k);
+        if( iter == derived().end() )
+        {
+            iter = derived().insert( value_type(k,data_type_()) ).first;
+        }
+        return iter->second;
+    }
+
+    protected:
+
+    typedef mutable_data_unique_map_view_access
+                mutable_data_unique_map_view_access_;
+
+    private:
+
+    // Curiously Recurring Template interface.
+
+    Derived& derived()
+    {
+        return *static_cast<Derived*>(this);
+    }
+
+    Derived const& derived() const
+    {
+        return *static_cast<Derived const*>(this);
+    }
+};
+
+
+template< class Derived, class Tag, class BimapType>
+class non_mutable_data_unique_map_view_access
+{
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                          data_type_by<Tag,BimapType>::type      data_type_;
+
+    public:
+
+    template< class CompatibleKey >
+    const data_type_ & at(const CompatibleKey& k) const
+    {
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                const_iterator_type_by<Tag,BimapType>::type const_iterator;
+
+        const_iterator iter = derived().find(k);
+        if( iter == derived().end() )
+        {
+            ::boost::throw_exception(
+                std::out_of_range("bimap<>: invalid key")
+            );
+        }
+        return iter->second;
+    }
+
+    template< class CompatibleKey >
+    data_type_ & operator[](const CompatibleKey& k)
+    {
+        BOOST_BIMAP_STATIC_ERROR( OPERATOR_BRACKET_IS_NOT_SUPPORTED, (Derived));
+    }
+
+    protected:
+
+    typedef non_mutable_data_unique_map_view_access
+                non_mutable_data_unique_map_view_access_;
+
+    private:
+
+    // Curiously Recurring Template interface.
+
+    Derived& derived()
+    {
+        return *static_cast<Derived*>(this);
+    }
+
+    Derived const& derived() const
+    {
+        return *static_cast<Derived const*>(this);
+    }
+};
+
+
+template< class Derived, class Tag, class BimapType>
+struct unique_map_view_access
+{
+    private:
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+        value_type_by<Tag,BimapType>::type value_type;
+
+    public:
+    typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_
+    <
+        typename ::boost::is_const<
+            BOOST_DEDUCED_TYPENAME value_type::second_type >::type,
+
+        non_mutable_data_unique_map_view_access<Derived,Tag,BimapType>,
+        mutable_data_unique_map_view_access<Derived,Tag,BimapType>
+
+    >::type type;
+};
+
+// Map views specialize the following structs to provide to the bimap class
+// the extra side typedefs (i.e. left_local_iterator for unordered_maps, 
+// right_range_type for maps)
+
+template< class MapView >
+struct  left_map_view_extra_typedefs {};
+
+template< class MapView >
+struct right_map_view_extra_typedefs {};
+
+} // namespace detail
+
+// This function is already part of Boost.Lambda.
+// They may be moved to Boost.Utility.
+
+template <class T> inline const T&  make_const(const T& t) { return t; }
+
+} // namespace bimaps
+} // namespace boost
+
+
+// The following macros avoids code duplication in map views
+// Maybe this can be changed in the future using a scheme similar to
+// the one used with map_view_base.
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_RANGE_IMPLEMENTATION(BASE)                       \
+                                                                              \
+typedef std::pair<                                                            \
+    BOOST_DEDUCED_TYPENAME base_::iterator,                                   \
+    BOOST_DEDUCED_TYPENAME base_::iterator> range_type;                       \
+                                                                              \
+typedef std::pair<                                                            \
+    BOOST_DEDUCED_TYPENAME base_::const_iterator,                             \
+    BOOST_DEDUCED_TYPENAME base_::const_iterator> const_range_type;           \
+                                                                              \
+                                                                              \
+template< class LowerBounder, class UpperBounder>                             \
+range_type range(LowerBounder lower,UpperBounder upper)                       \
+{                                                                             \
+    std::pair<                                                                \
+                                                                              \
+        BOOST_DEDUCED_TYPENAME BASE::base_type::iterator,                     \
+        BOOST_DEDUCED_TYPENAME BASE::base_type::iterator                      \
+                                                                              \
+    > r( this->base().range(lower,upper) );                                   \
+                                                                              \
+    return range_type(                                                        \
+        this->template functor<                                               \
+            BOOST_DEDUCED_TYPENAME BASE::iterator_from_base                   \
+        >()                                         ( r.first ),              \
+        this->template functor<                                               \
+            BOOST_DEDUCED_TYPENAME BASE::iterator_from_base                   \
+        >()                                         ( r.second )              \
+    );                                                                        \
+}                                                                             \
+                                                                              \
+template< class LowerBounder, class UpperBounder>                             \
+const_range_type range(LowerBounder lower,UpperBounder upper) const           \
+{                                                                             \
+    std::pair<                                                                \
+                                                                              \
+        BOOST_DEDUCED_TYPENAME BASE::base_type::const_iterator,               \
+        BOOST_DEDUCED_TYPENAME BASE::base_type::const_iterator                \
+                                                                              \
+    > r( this->base().range(lower,upper) );                                   \
+                                                                              \
+    return const_range_type(                                                  \
+        this->template functor<                                               \
+            BOOST_DEDUCED_TYPENAME BASE::iterator_from_base                   \
+        >()                                         ( r.first ),              \
+        this->template functor<                                               \
+            BOOST_DEDUCED_TYPENAME BASE::iterator_from_base                   \
+        >()                                         ( r.second )              \
+    );                                                                        \
+}
+/*===========================================================================*/
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(BASE)                          \
+                                                                              \
+template< class InputIterator >                                               \
+void assign(InputIterator first,InputIterator last)                           \
+{                                                                             \
+    this->clear();                                                            \
+    this->insert(this->end(),first,last);                                     \
+}                                                                             \
+                                                                              \
+void assign(BOOST_DEDUCED_TYPENAME BASE::size_type n,                         \
+            const BOOST_DEDUCED_TYPENAME BASE::value_type& v)                 \
+{                                                                             \
+    this->clear();                                                            \
+    for(BOOST_DEDUCED_TYPENAME BASE::size_type i = 0 ; i < n ; ++n)           \
+    {                                                                         \
+        this->push_back(v);                                                   \
+    }                                                                         \
+}
+/*===========================================================================*/
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(BASE)                      \
+                                                                              \
+BOOST_DEDUCED_TYPENAME BASE::reference front()                                \
+{                                                                             \
+    return this->template functor<                                            \
+        BOOST_DEDUCED_TYPENAME base_::value_from_base>()                      \
+    (                                                                         \
+        const_cast                                                            \
+        <                                                                     \
+            BOOST_DEDUCED_TYPENAME BASE::base_type::value_type &              \
+                                                                              \
+        > ( this->base().front() )                                            \
+    );                                                                        \
+}                                                                             \
+                                                                              \
+BOOST_DEDUCED_TYPENAME BASE::reference back()                                 \
+{                                                                             \
+    return this->template functor<                                            \
+        BOOST_DEDUCED_TYPENAME base_::value_from_base>()                      \
+    (                                                                         \
+        const_cast                                                            \
+        <                                                                     \
+            BOOST_DEDUCED_TYPENAME BASE::base_type::value_type &              \
+                                                                              \
+        >( this->base().back() )                                              \
+    );                                                                        \
+}                                                                             \
+                                                                              \
+BOOST_DEDUCED_TYPENAME BASE::const_reference front() const                    \
+{                                                                             \
+    return this->template functor<                                            \
+        BOOST_DEDUCED_TYPENAME BASE::value_from_base>()                       \
+    (                                                                         \
+        this->base().front()                                                  \
+    );                                                                        \
+}                                                                             \
+                                                                              \
+BOOST_DEDUCED_TYPENAME BASE::const_reference back() const                     \
+{                                                                             \
+    return this->template functor<                                            \
+        BOOST_DEDUCED_TYPENAME BASE::value_from_base>()                       \
+    (                                                                         \
+        this->base().back()                                                   \
+    );                                                                        \
+}
+/*===========================================================================*/
+
+
+#endif // BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP
diff --git a/boost/bimap/detail/map_view_iterator.hpp b/boost/bimap/detail/map_view_iterator.hpp
new file mode 100644 (file)
index 0000000..897cbe6
--- /dev/null
@@ -0,0 +1,200 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/map_view_iterator.hpp
+/// \brief Iterator adaptors from multi-index to bimap.
+
+#ifndef BOOST_BIMAP_DETAIL_MAP_VIEW_ITERATOR_HPP
+#define BOOST_BIMAP_DETAIL_MAP_VIEW_ITERATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+// Boost
+// #include <boost/serialization/nvp.hpp>
+#include <boost/iterator/detail/enable_if.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/bimap/relation/support/pair_by.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace detail {
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class Tag, class Relation, class CoreIterator > struct map_view_iterator;
+
+template< class Tag, class Relation, class CoreIterator >
+struct map_view_iterator_base
+{
+    typedef iterator_adaptor
+    <
+        map_view_iterator< Tag, Relation, CoreIterator >,
+        CoreIterator,
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+            pair_type_by<Tag,Relation>::type
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+/** \brief Map View Iterator adaptor from multi index to bimap.
+
+This is class is based on transform iterator from Boost.Iterator that is
+modified to allow serialization. It has been specialized for this
+library, and EBO optimization was applied to the functor.
+
+                                                                      **/
+
+template< class Tag, class Relation, class CoreIterator >
+struct map_view_iterator : public map_view_iterator_base<Tag,Relation,CoreIterator>::type
+{
+    typedef BOOST_DEDUCED_TYPENAME
+        map_view_iterator_base<Tag,Relation,CoreIterator>::type base_;
+
+    public:
+
+    map_view_iterator() {}
+
+    map_view_iterator(CoreIterator const& iter)
+      : base_(iter) {}
+
+    map_view_iterator(map_view_iterator const & iter)
+      : base_(iter.base()) {}
+
+    BOOST_DEDUCED_TYPENAME base_::reference dereference() const
+    {
+        return ::boost::bimaps::relation::support::pair_by<Tag>(
+            *const_cast<BOOST_DEDUCED_TYPENAME base_::base_type::value_type*>(
+                &(*this->base())
+            )
+        );
+    }
+
+    private:
+
+    friend class iterator_core_access;
+
+    #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
+
+    // Serialization support
+
+    BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    friend class ::boost::serialization::access;
+
+    template< class Archive >
+    void save(Archive & ar, const unsigned int version) const
+    {
+        ar << ::boost::serialization::make_nvp("mi_iterator",this->base());
+    }
+
+    template< class Archive >
+    void load(Archive & ar, const unsigned int version)
+    {
+        CoreIterator iter;
+        ar >> ::boost::serialization::make_nvp("mi_iterator",iter);
+        this->base_reference() = iter;
+    }
+
+    #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
+};
+
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class Tag, class Relation, class CoreIterator > struct const_map_view_iterator;
+
+template< class Tag, class Relation, class CoreIterator >
+struct const_map_view_iterator_base
+{
+    typedef iterator_adaptor
+    <
+        const_map_view_iterator< Tag, Relation, CoreIterator >,
+        CoreIterator,
+        const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+             pair_type_by<Tag,Relation>::type
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+
+/** \brief Const Map View Iterator adaptor from multi index to bimap.
+
+See also map_view_iterator.
+                                                                      **/
+
+template< class Tag, class Relation, class CoreIterator >
+struct const_map_view_iterator :
+
+    public const_map_view_iterator_base<Tag,Relation,CoreIterator>::type
+{
+    typedef BOOST_DEDUCED_TYPENAME
+        const_map_view_iterator_base<Tag,Relation,CoreIterator>::type base_;
+
+    public:
+
+    const_map_view_iterator() {}
+
+    const_map_view_iterator(CoreIterator const& iter)
+      : base_(iter) {}
+
+    const_map_view_iterator(const_map_view_iterator const & iter)
+      : base_(iter.base()) {}
+
+    const_map_view_iterator(map_view_iterator<Tag,Relation,CoreIterator> i)
+      : base_(i.base()) {}
+
+    BOOST_DEDUCED_TYPENAME base_::reference dereference() const
+    {
+        return ::boost::bimaps::relation::support::pair_by<Tag>(*this->base());
+    }
+
+    private:
+
+    friend class iterator_core_access;
+
+    #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
+
+    // Serialization support
+
+    BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    friend class ::boost::serialization::access;
+
+    template< class Archive >
+    void save(Archive & ar, const unsigned int version) const
+    {
+        ar << ::boost::serialization::make_nvp("mi_iterator",this->base());
+    }
+
+    template< class Archive >
+    void load(Archive & ar, const unsigned int version)
+    {
+        CoreIterator iter;
+        ar >> ::boost::serialization::make_nvp("mi_iterator",iter);
+        this->base_reference() = iter;
+    }
+
+    #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
+};
+
+
+} // namespace detail
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DETAIL_MAP_VIEW_ITERATOR_HPP
+
+
diff --git a/boost/bimap/detail/modifier_adaptor.hpp b/boost/bimap/detail/modifier_adaptor.hpp
new file mode 100644 (file)
index 0000000..b170549
--- /dev/null
@@ -0,0 +1,89 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/modifier_adaptor.hpp
+/// \brief A binary to unary functor relation modifier adaptor.
+
+#ifndef BOOST_BIMAP_DETAIL_MODIFIER_ADAPTOR_HPP
+#define BOOST_BIMAP_DETAIL_MODIFIER_ADAPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <functional>
+
+namespace boost {
+namespace bimaps {
+namespace detail {
+
+/// \brief A binary to unary functor relation modifier adaptor.
+
+template
+<
+    class Modifier,
+    class NewArgument,
+    class FirstExtractor,
+    class SecondExtractor 
+>
+struct relation_modifier_adaptor :
+    public std::unary_function<NewArgument,bool>,
+    Modifier,
+    FirstExtractor,
+    SecondExtractor
+{
+    relation_modifier_adaptor( const Modifier & m ) : Modifier(m) {}
+    relation_modifier_adaptor( const Modifier & m,
+                               const FirstExtractor & fe,
+                               const SecondExtractor & se ) :
+        Modifier(m), FirstExtractor(fe), SecondExtractor(se) {}
+
+    void operator()( NewArgument & x ) const
+    {
+        Modifier::operator()(
+            FirstExtractor ::operator()( x ),
+            SecondExtractor::operator()( x )
+        );
+    }
+};
+
+/// \brief A simple unary modifier adaptor.
+// This modifier is equivalent to bind( Modifier, bind( Extractor, _1 ) )
+// It may be a good idea to start using Boost.Bind instead of it.
+
+template
+<
+    class Modifier,
+    class NewArgument,
+    class Extractor
+>
+struct unary_modifier_adaptor :
+    public std::unary_function<NewArgument,bool>,
+    Modifier,
+    Extractor
+{
+    unary_modifier_adaptor( const Modifier & m ) : Modifier(m) {}
+    unary_modifier_adaptor( const Modifier & m,
+                            const Extractor & fe) :
+        Modifier(m), Extractor(fe) {}
+
+    void operator()( NewArgument & x ) const
+    {
+        Modifier::operator()( Extractor::operator()( x ) );
+    }
+};
+
+
+} // namespace detail
+} // namespace bimap
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_DETAIL_MODIFIER_ADAPTOR_HPP
diff --git a/boost/bimap/detail/non_unique_views_helper.hpp b/boost/bimap/detail/non_unique_views_helper.hpp
new file mode 100644 (file)
index 0000000..6801632
--- /dev/null
@@ -0,0 +1,71 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/non_unique_views_helper.hpp
+/// \brief Details for non unique views
+
+#ifndef BOOST_BIMAP_DETAIL_NON_UNIQUE_VIEWS_HELPER_HPP
+#define BOOST_BIMAP_DETAIL_NON_UNIQUE_VIEWS_HELPER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+/*===========================================================================*/
+#define BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS                         \
+                                                                             \
+template <class InputIterator>                                               \
+void insert(InputIterator iterBegin, InputIterator iterEnd)                  \
+{                                                                            \
+    for( ; iterBegin != iterEnd ; ++iterBegin )                              \
+    {                                                                        \
+        this->base().insert(                                                 \
+            this->template functor<                                          \
+                BOOST_DEDUCED_TYPENAME base_::value_to_base>()(              \
+                    BOOST_DEDUCED_TYPENAME base_::value_type(*iterBegin)) ); \
+    }                                                                        \
+}                                                                            \
+                                                                             \
+std::pair<BOOST_DEDUCED_TYPENAME base_::iterator, bool> insert(              \
+    BOOST_DEDUCED_TYPENAME ::boost::call_traits<                             \
+        BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x)            \
+{                                                                            \
+    typedef BOOST_DEDUCED_TYPENAME base_::base_type::iterator base_iterator; \
+                                                                             \
+    std::pair< base_iterator, bool > r(                                      \
+        this->base().insert(                                                 \
+            this->template functor<                                          \
+                BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x) )          \
+    );                                                                       \
+                                                                             \
+    return std::pair<typename base_::iterator, bool>(                        \
+        this->template functor<                                              \
+            BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(r.first),    \
+            r.second                                                         \
+    );                                                                       \
+}                                                                            \
+                                                                             \
+BOOST_DEDUCED_TYPENAME base_::iterator insert(                               \
+    BOOST_DEDUCED_TYPENAME base_::iterator pos,                              \
+        BOOST_DEDUCED_TYPENAME ::boost::call_traits<                         \
+            BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x)        \
+{                                                                            \
+    return this->template functor<                                           \
+        BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(                 \
+            this->base().insert(                                             \
+                this->template functor<                                      \
+                    BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(pos),  \
+            this->template functor<                                          \
+                BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x))           \
+    );                                                                       \
+}
+/*===========================================================================*/
+
+#endif // BOOST_BIMAP_DETAIL_NON_UNIQUE_VIEWS_HELPER_HPP
diff --git a/boost/bimap/detail/set_view_base.hpp b/boost/bimap/detail/set_view_base.hpp
new file mode 100644 (file)
index 0000000..b867145
--- /dev/null
@@ -0,0 +1,330 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/set_view_base.hpp
+/// \brief Helper base for the construction of the bimap views types.
+
+#ifndef BOOST_BIMAP_DETAIL_SET_VIEW_BASE_HPP
+#define BOOST_BIMAP_DETAIL_SET_VIEW_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/member_at.hpp>
+#include <boost/bimap/relation/support/data_extractor.hpp>
+#include <boost/bimap/detail/modifier_adaptor.hpp>
+#include <boost/bimap/detail/set_view_iterator.hpp>
+#include <boost/bimap/relation/support/get_pair_functor.hpp>
+#include <boost/bimap/relation/detail/to_mutable_relation_functor.hpp>
+#include <boost/bimap/relation/mutant_relation.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace detail {
+
+template< class Key, class Value, class KeyToBase >
+class set_view_key_to_base
+{
+    public:
+    const Key operator()( const Value & v ) const
+    {
+        return keyToBase( v );
+    }
+    private:
+    KeyToBase keyToBase;
+};
+
+template< class MutantRelationStorage, class KeyToBase >
+class set_view_key_to_base<MutantRelationStorage,MutantRelationStorage,KeyToBase>
+{
+       typedef BOOST_DEDUCED_TYPENAME MutantRelationStorage::non_mutable_storage non_mutable_storage;
+    public:
+    const MutantRelationStorage & operator()( const non_mutable_storage & k ) const
+    {
+        return ::boost::bimaps::relation::detail::mutate<MutantRelationStorage>(k);
+    }
+    const MutantRelationStorage & operator()( const MutantRelationStorage & k ) const
+    {
+        return k;
+    }
+};
+
+
+// The next macro can be converted in a metafunctor to gain code robustness.
+/*===========================================================================*/
+#define BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR(                               \
+    CONTAINER_ADAPTOR, CORE_INDEX, OTHER_ITER, CONST_OTHER_ITER               \
+)                                                                             \
+::boost::bimaps::container_adaptor::CONTAINER_ADAPTOR                         \
+<                                                                             \
+    CORE_INDEX,                                                               \
+    ::boost::bimaps::detail::                                                 \
+              set_view_iterator<                                              \
+                    BOOST_DEDUCED_TYPENAME CORE_INDEX::iterator         >,    \
+    ::boost::bimaps::detail::                                                 \
+        const_set_view_iterator<                                              \
+                    BOOST_DEDUCED_TYPENAME CORE_INDEX::const_iterator   >,    \
+    ::boost::bimaps::detail::                                                 \
+              set_view_iterator<                                              \
+                    BOOST_DEDUCED_TYPENAME CORE_INDEX::OTHER_ITER       >,    \
+    ::boost::bimaps::detail::                                                 \
+        const_set_view_iterator<                                              \
+                    BOOST_DEDUCED_TYPENAME CORE_INDEX::CONST_OTHER_ITER >,    \
+    ::boost::bimaps::container_adaptor::support::iterator_facade_to_base      \
+    <                                                                         \
+        ::boost::bimaps::detail::      set_view_iterator<                     \
+            BOOST_DEDUCED_TYPENAME CORE_INDEX::iterator>,                     \
+        ::boost::bimaps::detail::const_set_view_iterator<                     \
+            BOOST_DEDUCED_TYPENAME CORE_INDEX::const_iterator>                \
+                                                                              \
+    >,                                                                        \
+    ::boost::mpl::na,                                                         \
+    ::boost::mpl::na,                                                         \
+    ::boost::bimaps::relation::detail::                                       \
+        get_mutable_relation_functor<                                         \
+            BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type >,                  \
+    ::boost::bimaps::relation::support::                                      \
+        get_above_view_functor<                                               \
+            BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type >,                  \
+    ::boost::bimaps::detail::set_view_key_to_base<                            \
+        BOOST_DEDUCED_TYPENAME CORE_INDEX::key_type,                          \
+        BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type,                        \
+        BOOST_DEDUCED_TYPENAME CORE_INDEX::key_from_value                     \
+    >                                                                         \
+>
+/*===========================================================================*/
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR(                     \
+    CONTAINER_ADAPTOR, CORE_INDEX, OTHER_ITER, CONST_OTHER_ITER               \
+)                                                                             \
+::boost::bimaps::container_adaptor::CONTAINER_ADAPTOR                         \
+<                                                                             \
+    CORE_INDEX,                                                               \
+    ::boost::bimaps::detail::                                                 \
+              set_view_iterator<                                              \
+                    BOOST_DEDUCED_TYPENAME CORE_INDEX::iterator         >,    \
+    ::boost::bimaps::detail::                                                 \
+        const_set_view_iterator<                                              \
+                    BOOST_DEDUCED_TYPENAME CORE_INDEX::const_iterator   >,    \
+    ::boost::bimaps::detail::                                                 \
+              set_view_iterator<                                              \
+                    BOOST_DEDUCED_TYPENAME CORE_INDEX::OTHER_ITER       >,    \
+    ::boost::bimaps::detail::                                                 \
+        const_set_view_iterator<                                              \
+                    BOOST_DEDUCED_TYPENAME CORE_INDEX::CONST_OTHER_ITER >,    \
+    ::boost::bimaps::container_adaptor::support::iterator_facade_to_base      \
+    <                                                                         \
+        ::boost::bimaps::detail::      set_view_iterator<                     \
+            BOOST_DEDUCED_TYPENAME CORE_INDEX::iterator>,                     \
+        ::boost::bimaps::detail::const_set_view_iterator<                     \
+            BOOST_DEDUCED_TYPENAME CORE_INDEX::const_iterator>                \
+                                                                              \
+    >,                                                                        \
+    ::boost::mpl::na,                                                         \
+    ::boost::mpl::na,                                                         \
+    ::boost::bimaps::relation::detail::                                       \
+        get_mutable_relation_functor<                                         \
+            BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type >,                  \
+    ::boost::bimaps::relation::support::                                      \
+        get_above_view_functor<                                               \
+            BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type >                   \
+>
+/*===========================================================================*/
+
+
+#if defined(BOOST_MSVC)
+/*===========================================================================*/
+#define BOOST_BIMAP_SET_VIEW_BASE_FRIEND(TYPE,INDEX_TYPE)                     \
+    typedef ::boost::bimaps::detail::set_view_base<                           \
+        TYPE< INDEX_TYPE >, INDEX_TYPE > template_class_friend;               \
+    friend class template_class_friend;
+/*===========================================================================*/
+#else
+/*===========================================================================*/
+#define BOOST_BIMAP_SET_VIEW_BASE_FRIEND(TYPE,INDEX_TYPE)                     \
+    friend class ::boost::bimaps::detail::set_view_base<                      \
+        TYPE< INDEX_TYPE >, INDEX_TYPE >;
+/*===========================================================================*/
+#endif
+
+
+/// \brief Common base for set views.
+
+template< class Derived, class Index >
+class set_view_base
+{
+    typedef ::boost::bimaps::container_adaptor::support::
+    iterator_facade_to_base
+    <
+        ::boost::bimaps::detail::
+                  set_view_iterator<BOOST_DEDUCED_TYPENAME Index::      iterator>,
+        ::boost::bimaps::detail::
+            const_set_view_iterator<BOOST_DEDUCED_TYPENAME Index::const_iterator>
+
+    > iterator_to_base_;
+
+    typedef BOOST_DEDUCED_TYPENAME Index::value_type::left_value_type          left_type_;
+
+    typedef BOOST_DEDUCED_TYPENAME Index::value_type::right_value_type        right_type_;
+
+    typedef BOOST_DEDUCED_TYPENAME Index::value_type                          value_type_;
+
+    typedef ::boost::bimaps::detail::
+                    set_view_iterator<BOOST_DEDUCED_TYPENAME Index::iterator>   iterator_;
+
+    public:
+
+    bool replace(iterator_ position,
+                 const value_type_ & x)
+    {
+        return derived().base().replace(
+            derived().template functor<iterator_to_base_>()(position),x
+        );
+    }
+
+    template< class CompatibleLeftType >
+    bool replace_left(iterator_ position,
+                      const CompatibleLeftType & l)
+    {
+        return derived().base().replace(
+            derived().template functor<iterator_to_base_>()(position),
+            value_type_(l,position->right)
+        );
+    }
+
+    template< class CompatibleRightType >
+    bool replace_right(iterator_ position,
+                       const CompatibleRightType & r)
+    {
+        return derived().base().replace(
+            derived().template functor<iterator_to_base_>()(position),
+            value_type_(position->left,r)
+        );
+    }
+
+    /* This function may be provided in the future
+
+    template< class Modifier >
+    bool modify(iterator_ position,
+                Modifier mod)
+    {
+        return derived().base().modify(
+
+            derived().template functor<iterator_to_base_>()(position),
+
+            ::boost::bimaps::detail::relation_modifier_adaptor
+            <
+                Modifier,
+                BOOST_DEDUCED_TYPENAME Index::value_type,
+                BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+                data_extractor
+                <
+                    ::boost::bimaps::relation::member_at::left,
+                    BOOST_DEDUCED_TYPENAME Index::value_type
+
+                >::type,
+                BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+                data_extractor
+                <
+                    ::boost::bimaps::relation::member_at::right,
+                    BOOST_DEDUCED_TYPENAME Index::value_type
+
+                >::type
+
+            >(mod)
+        );
+    }
+    */
+    /*
+    template< class Modifier >
+    bool modify_left(iterator_ position, Modifier mod)
+    {
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+        data_extractor
+        <
+            BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::member_at::right,
+            BOOST_DEDUCED_TYPENAME Index::value_type
+
+        >::type left_data_extractor_;
+
+        return derived().base().modify(
+
+            derived().template functor<iterator_to_base_>()(position),
+
+            // this may be replaced later by
+            // ::boost::bind( mod, ::boost::bind(data_extractor_(),_1) )
+
+            ::boost::bimaps::detail::unary_modifier_adaptor
+            <
+                Modifier,
+                BOOST_DEDUCED_TYPENAME Index::value_type,
+                left_data_extractor_
+
+            >(mod)
+        );
+    }
+
+    template< class Modifier >
+    bool modify_right(iterator_ position, Modifier mod)
+    {
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+        data_extractor
+        <
+            BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::member_at::right,
+            BOOST_DEDUCED_TYPENAME Index::value_type
+
+        >::type right_data_extractor_;
+
+        return derived().base().modify(
+
+            derived().template functor<iterator_to_base_>()(position),
+
+            // this may be replaced later by
+            // ::boost::bind( mod, ::boost::bind(data_extractor_(),_1) )
+
+            ::boost::bimaps::detail::unary_modifier_adaptor
+            <
+                Modifier,
+                BOOST_DEDUCED_TYPENAME Index::value_type,
+                right_data_extractor_
+
+            >(mod)
+        );
+    }
+    */
+    protected:
+
+    typedef set_view_base set_view_base_;
+
+    private:
+
+    // Curiously Recurring Template interface.
+
+    Derived& derived()
+    {
+        return *static_cast<Derived*>(this);
+    }
+
+    Derived const& derived() const
+    {
+        return *static_cast<Derived const*>(this);
+    }
+};
+
+
+
+} // namespace detail
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DETAIL_SET_VIEW_BASE_HPP
diff --git a/boost/bimap/detail/set_view_iterator.hpp b/boost/bimap/detail/set_view_iterator.hpp
new file mode 100644 (file)
index 0000000..93daa15
--- /dev/null
@@ -0,0 +1,193 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/set_view_iterator.hpp
+/// \brief Iterator adaptors from multi-index to bimap.
+
+#ifndef BOOST_BIMAP_DETAIL_SET_VIEW_ITERATOR_HPP
+#define BOOST_BIMAP_DETAIL_SET_VIEW_ITERATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+// Boost
+// #include <boost/serialization/nvp.hpp>
+#include <boost/iterator/detail/enable_if.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/bimap/relation/support/get_pair_functor.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace detail {
+
+
+/** \brief Set View Iterator adaptor from multi index to bimap.
+
+This is class is based on transform iterator from Boost.Iterator that is
+modified to allow serialization. It has been specialized for this
+library, and EBO optimization was applied to the functor.
+
+                                                                      **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class CoreIterator > struct set_view_iterator;
+
+template< class CoreIterator >
+struct set_view_iterator_base
+{
+    typedef iterator_adaptor
+    <
+        set_view_iterator< CoreIterator >,
+        CoreIterator,
+        BOOST_DEDUCED_TYPENAME CoreIterator::value_type::above_view
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class CoreIterator >
+struct set_view_iterator : public set_view_iterator_base<CoreIterator>::type
+{
+    typedef BOOST_DEDUCED_TYPENAME set_view_iterator_base<CoreIterator>::type base_;
+
+    public:
+
+    set_view_iterator() {}
+
+    set_view_iterator(CoreIterator const& iter)
+      : base_(iter) {}
+
+    set_view_iterator(set_view_iterator const & iter)
+      : base_(iter.base()) {}
+
+    typename base_::reference dereference() const
+    {
+        return const_cast<
+            BOOST_DEDUCED_TYPENAME base_::base_type::value_type*>(
+                &(*this->base())
+            )->get_view();
+    }
+
+    private:
+
+    friend class iterator_core_access;
+
+    #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
+
+    // Serialization support
+
+    BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    friend class ::boost::serialization::access;
+
+    template< class Archive >
+    void save(Archive & ar, const unsigned int version) const
+    {
+        ar << ::boost::serialization::make_nvp("mi_iterator",this->base());
+    }
+
+    template< class Archive >
+    void load(Archive & ar, const unsigned int version)
+    {
+        CoreIterator iter;
+        ar >> ::boost::serialization::make_nvp("mi_iterator",iter);
+        this->base_reference() = iter;
+    }
+
+    #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
+};
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class CoreIterator > struct const_set_view_iterator;
+
+template< class CoreIterator >
+struct const_set_view_iterator_base
+{
+    typedef iterator_adaptor
+    <
+        const_set_view_iterator< CoreIterator >,
+        CoreIterator,
+        const BOOST_DEDUCED_TYPENAME CoreIterator::value_type::above_view
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+
+/** \brief Const Set View Iterator adaptor from multi index to bimap.
+
+See also set_view_iterator.
+                                                                      **/
+
+template< class CoreIterator >
+struct const_set_view_iterator : public const_set_view_iterator_base<CoreIterator>::type
+{
+    typedef BOOST_DEDUCED_TYPENAME const_set_view_iterator_base<CoreIterator>::type base_;
+
+    public:
+
+    const_set_view_iterator() {}
+
+    const_set_view_iterator(CoreIterator const& iter)
+      : base_(iter) {}
+
+    const_set_view_iterator(const_set_view_iterator const & iter)
+      : base_(iter.base()) {}
+
+    const_set_view_iterator(set_view_iterator<CoreIterator> i)
+      : base_(i.base()) {}
+
+    BOOST_DEDUCED_TYPENAME base_::reference dereference() const
+    {
+        return this->base()->get_view();
+    }
+
+    private:
+
+    friend class iterator_core_access;
+
+    #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
+
+    // Serialization support
+
+    BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    friend class ::boost::serialization::access;
+
+    template< class Archive >
+    void save(Archive & ar, const unsigned int version) const
+    {
+        ar << ::boost::serialization::make_nvp("mi_iterator",this->base());
+    }
+
+    template< class Archive >
+    void load(Archive & ar, const unsigned int version)
+    {
+        CoreIterator iter;
+        ar >> ::boost::serialization::make_nvp("mi_iterator",iter);
+        this->base_reference() = iter;
+    }
+
+    #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
+};
+
+
+} // namespace detail
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DETAIL_MAP_VIEW_ITERATOR_HPP
+
+
diff --git a/boost/bimap/detail/test/check_metadata.hpp b/boost/bimap/detail/test/check_metadata.hpp
new file mode 100644 (file)
index 0000000..b669ee0
--- /dev/null
@@ -0,0 +1,113 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+#ifndef BOOST_BIMAP_DETAIL_CHECK_METADATA_HPP
+#define BOOST_BIMAP_DETAIL_CHECK_METADATA_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+
+// Easier way to call BOOST_MPL_ASSERT_MSG in class scope
+/*===========================================================================*/
+#define BOOST_BIMAP_MPL_ASSERT_MSG_ACS(p1,p2,p3)                              \
+                                                                              \
+    struct p2 {};                                                             \
+    BOOST_MPL_ASSERT_MSG(p1,p2,p3);                                           \
+/*===========================================================================*/
+
+
+// Build a descriptive name.
+/*===========================================================================*/
+#define BOOST_BIMAP_WRONG_METADATA_MESSAGE(                                   \
+                                                                              \
+        P_CLASS,                                                              \
+        P_NAME,                                                               \
+        P_CORRECT_TYPE                                                        \
+                                                                              \
+    )                                                                         \
+                                                                              \
+    BOOST_PP_CAT                                                              \
+    (                                                                         \
+        WRONG_METADATA__,                                                     \
+        BOOST_PP_CAT                                                          \
+        (                                                                     \
+            P_CLASS,                                                          \
+            BOOST_PP_CAT                                                      \
+            (                                                                 \
+                __AT__,                                                       \
+                BOOST_PP_CAT                                                  \
+                (                                                             \
+                    P_NAME,                                                   \
+                    BOOST_PP_CAT                                              \
+                    (                                                         \
+                        __IS_DIFERENT_TO__,                                   \
+                        P_CORRECT_TYPE                                        \
+                    )                                                         \
+                )                                                             \
+            )                                                                 \
+        )                                                                     \
+    )
+/*===========================================================================*/
+
+
+// Check if the metadata have the correct type, and if not inform
+// it with a useful compile time message.
+/*===========================================================================*/
+#define BOOST_BIMAP_CHECK_METADATA(                                           \
+                                                                              \
+        P_CLASS,                                                              \
+        P_NAME,                                                               \
+        P_CORRECT_TYPE                                                        \
+                                                                              \
+    )                                                                         \
+                                                                              \
+    BOOST_BIMAP_MPL_ASSERT_MSG_ACS                                            \
+    (                                                                         \
+        (                                                                     \
+            ::boost::is_same                                                  \
+            <                                                                 \
+                P_CLASS::P_NAME,                                              \
+                P_CORRECT_TYPE                                                \
+                                                                              \
+            >::value                                                          \
+        ),                                                                    \
+        BOOST_BIMAP_WRONG_METADATA_MESSAGE                                    \
+        (                                                                     \
+            P_CLASS,                                                          \
+            P_NAME,                                                           \
+            P_CORRECT_TYPE                                                    \
+        ),                                                                    \
+        (P_CLASS::P_NAME,P_CORRECT_TYPE)                                      \
+    )
+/*===========================================================================*/
+
+
+// Just for autodocumment the test code
+/*===========================================================================*/
+#define BOOST_BIMAP_TEST_STATIC_FUNCTION(NAME)                                \
+    namespace NAME
+/*===========================================================================*/
+
+
+// Just for autodocument the test code
+/*===========================================================================*/
+#define BOOST_BIMAP_CALL_TEST_STATIC_FUNCTION(NAME)
+/*===========================================================================*/
+
+
+
+#endif // BOOST_BIMAP_DETAIL_CHECK_METADATA_HPP
+
diff --git a/boost/bimap/detail/user_interface_config.hpp b/boost/bimap/detail/user_interface_config.hpp
new file mode 100644 (file)
index 0000000..1d9a8e8
--- /dev/null
@@ -0,0 +1,24 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file detail/user_interface_config.hpp
+/// \brief General configuration directives
+
+
+#ifndef BOOST_BIMAP_DETAIL_USER_INTERFACE_CONFIG_HPP
+#define BOOST_BIMAP_DETAIL_USER_INTERFACE_CONFIG_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#ifdef BOOST_BIMAP_DISABLE_SERIALIZATION
+    #define BOOST_MULTI_INDEX_DISABLE_SERIALIZATION
+#endif
+
+#endif // BOOST_BIMAP_DETAIL_USER_INTERFACE_CONFIG_HPP
diff --git a/boost/bimap/list_of.hpp b/boost/bimap/list_of.hpp
new file mode 100644 (file)
index 0000000..b3cfee3
--- /dev/null
@@ -0,0 +1,181 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file list_of.hpp
+/// \brief Include support for list constrains for the bimap container
+
+#ifndef BOOST_BIMAP_LIST_OF_HPP
+#define BOOST_BIMAP_LIST_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/detail/user_interface_config.hpp>
+
+#include <boost/mpl/bool.hpp>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/bimap/detail/concept_tags.hpp>
+
+#include <boost/bimap/tags/support/value_type_of.hpp>
+
+#include <boost/bimap/detail/generate_index_binder.hpp>
+#include <boost/bimap/detail/generate_view_binder.hpp>
+#include <boost/bimap/detail/generate_relation_binder.hpp>
+
+#include <boost/multi_index/sequenced_index.hpp>
+
+#include <boost/bimap/views/list_map_view.hpp>
+#include <boost/bimap/views/list_set_view.hpp>
+
+namespace boost {
+namespace bimaps {
+
+
+/// \brief Set Type Specification
+/**
+This struct is used to specify a set specification.
+It is not a container, it is just a metaprogramming facility to
+express the type of a set. Generally, this specification will
+be used in other place to create a container.
+It has the same syntax that an std::list instantiation, except
+that the allocator cannot be specified. The rationale behind
+this difference is that the allocator is not part of the set
+type specification, rather it is a container configuration
+parameter.
+
+\code
+using namespace support;
+
+BOOST_STATIC_ASSERT( is_set_type_of< list_of<Type> >::value )
+
+BOOST_STATIC_ASSERT
+(
+     is_same
+     <
+        list_of<Type>::index_bind
+        <
+            KeyExtractor,
+            Tag
+
+        >::type,
+
+        sequenced< tag<Tag>, KeyExtractor >
+
+    >::value
+)
+
+typedef bimap
+<
+    list_of<Type>, RightKeyType
+
+> bimap_with_left_type_as_list;
+
+BOOST_STATIC_ASSERT
+(
+    is_same
+    <
+        list_of<Type>::map_view_bind
+        <
+            member_at::left,
+            bimap_with_left_type_as_list
+
+        >::type,
+        list_map_view< member_at::left, bimap_with_left_type_as_list >
+
+    >::value
+)
+
+\endcode
+
+See also list_of_relation.
+                                                                        **/
+
+template< class Type >
+struct list_of : public ::boost::bimaps::detail::set_type_of_tag
+{
+    /// User type, can be tagged
+    typedef Type user_type;
+
+    /// Type of the object that will be stored in the list
+       typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
+               value_type_of<user_type>::type value_type;
+
+
+    struct lazy_concept_checked
+    {
+        BOOST_CLASS_REQUIRE ( value_type,
+                              boost, AssignableConcept );
+
+        typedef list_of type;
+    };
+
+    BOOST_BIMAP_GENERATE_INDEX_BINDER_0CP_NO_EXTRACTOR(
+
+        // binds to
+        multi_index::sequenced
+    )
+
+    BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER(
+
+        // binds to
+        views::list_map_view
+    )
+
+    BOOST_BIMAP_GENERATE_SET_VIEW_BINDER(
+
+        // binds to
+        views::list_set_view
+    )
+
+    typedef mpl::bool_<true> mutable_key;
+};
+
+
+/// \brief List Of Relation Specification
+/**
+This struct is similar to list_of but it is bind logically to a
+relation. It is used in the bimap instantiation to specify the
+desired type of the main view. This struct implements internally
+a metafunction named bind_to that manages the quite complicated
+task of finding the right type of the set for the relation.
+
+\code
+template<class Relation>
+struct bind_to
+{
+    typedef -unspecified- type;
+};
+\endcode
+
+See also list_of, is_set_type_of_relation.
+                                                                **/
+
+struct list_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag
+{
+    BOOST_BIMAP_GENERATE_RELATION_BINDER_0CP(
+
+        // binds to
+        list_of
+    )
+
+    typedef mpl::bool_<true>  left_mutable_key;
+    typedef mpl::bool_<true> right_mutable_key;
+};
+
+
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_LIST_OF_HPP
+
diff --git a/boost/bimap/multiset_of.hpp b/boost/bimap/multiset_of.hpp
new file mode 100644 (file)
index 0000000..f99e330
--- /dev/null
@@ -0,0 +1,205 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file multiset_of.hpp
+/// \brief Include support for multiset constrains for the bimap container
+
+#ifndef BOOST_BIMAP_MULTISET_OF_HPP
+#define BOOST_BIMAP_MULTISET_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/detail/user_interface_config.hpp>
+
+#include <functional>
+#include <boost/mpl/bool.hpp>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/bimap/detail/concept_tags.hpp>
+
+#include <boost/bimap/tags/support/value_type_of.hpp>
+
+#include <boost/bimap/detail/generate_index_binder.hpp>
+#include <boost/bimap/detail/generate_view_binder.hpp>
+#include <boost/bimap/detail/generate_relation_binder.hpp>
+
+#include <boost/multi_index/ordered_index.hpp>
+
+#include <boost/bimap/views/multimap_view.hpp>
+#include <boost/bimap/views/multiset_view.hpp>
+
+namespace boost {
+namespace bimaps {
+
+/// \brief Set Type Specification
+/**
+This struct is used to specify a multiset specification.
+It is not a container, it is just a metaprogramming facility to
+express the type of a set. Generally, this specification will
+be used in other place to create a container.
+It has the same syntax that an std::set instantiation, except
+that the allocator cannot be specified. The rationale behind
+this difference is that the allocator is not part of the set
+type specification, rather it is a container configuration
+parameter.
+The first parameter is the type of the objects in the multiset,
+and the second one is a Functor that compares them.
+Bimap binding metafunctions can be used with this class in
+the following way:
+
+\code
+using namespace support;
+
+BOOST_STATIC_ASSERT( is_set_type_of< multiset_of<Type> >::value )
+
+BOOST_STATIC_ASSERT
+(
+     is_same
+     <
+        compute_index_type
+        <
+            multiset_of<Type,KeyCompare>,
+            KeyExtractor,
+            Tag
+
+        >::type
+        ,
+        ordered_nonunique< tag<Tag>, KeyExtractor, KeyCompare >
+
+    >::value
+)
+
+typedef bimap
+<
+    multiset_of<Type>, RightKeyType
+
+> bimap_with_left_type_as_multiset;
+
+BOOST_STATIC_ASSERT
+(
+    is_same
+    <
+        compute_map_view_type
+        <
+            member_at::left,
+            bimap_with_left_type_as_multiset
+
+        >::type,
+        multimap_view< member_at::left, bimap_with_left_type_as_multiset >
+
+    >::value
+)
+
+\endcode
+
+See also multiset_of_relation.
+                                                                        **/
+
+template
+<
+    class KeyType,
+    class KeyCompare = std::less< BOOST_DEDUCED_TYPENAME 
+               ::boost::bimaps::tags::support::value_type_of<KeyType>::type >
+>
+struct multiset_of : public ::boost::bimaps::detail::set_type_of_tag
+{
+    /// User type, can be tagged
+    typedef KeyType user_type;
+
+    /// Type of the object that will be stored in the multiset
+       typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
+               value_type_of<user_type>::type value_type;
+
+    /// Functor that compare two keys
+    typedef KeyCompare key_compare;
+
+    struct lazy_concept_checked
+    {
+        BOOST_CLASS_REQUIRE ( value_type,
+                              boost, AssignableConcept );
+
+        BOOST_CLASS_REQUIRE4( key_compare, bool, value_type, value_type,
+                              boost, BinaryFunctionConcept );
+
+        typedef multiset_of type;
+    };
+
+    BOOST_BIMAP_GENERATE_INDEX_BINDER_1CP(
+
+        // binds to
+        multi_index::ordered_non_unique,
+
+        // with
+        key_compare
+    )
+
+    BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER(
+
+        // binds to
+        views::multimap_view
+    )
+
+    BOOST_BIMAP_GENERATE_SET_VIEW_BINDER(
+
+        // binds to
+        views::multiset_view
+    )
+
+    typedef mpl::bool_<false> mutable_key;
+};
+
+
+/// \brief Set Of Relation Specification
+/**
+This struct is similar to multiset_of but it is bind logically to a
+relation. It is used in the bimap instantiation to specify the
+desired type of the main view. This struct implements internally
+a metafunction named bind_to that manages the quite complicated
+task of finding the right type of the set for the relation.
+
+\code
+template<class Relation>
+struct bind_to
+{
+    typedef -unspecified- type;
+};
+\endcode
+
+See also multiset_of, is_set_type_of_relation.
+                                                                **/
+
+template< class KeyCompare = std::less< _relation > >
+struct multiset_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag
+{
+    /// Functor that compare two keys
+    typedef KeyCompare key_compare;
+
+
+    BOOST_BIMAP_GENERATE_RELATION_BINDER_1CP(
+
+        // binds to
+        multiset_of,
+
+        // with
+        key_compare
+    )
+
+    typedef mpl::bool_<false>  left_mutable_key;
+    typedef mpl::bool_<false> right_mutable_key;
+};
+
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_MULTISET_OF_HPP
diff --git a/boost/bimap/property_map/set_support.hpp b/boost/bimap/property_map/set_support.hpp
new file mode 100644 (file)
index 0000000..ae497e0
--- /dev/null
@@ -0,0 +1,55 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file property_map/set_support.hpp
+/// \brief Support for the property map concept.
+
+#ifndef BOOST_BIMAP_PROPERTY_MAP_SET_SUPPORT_HPP
+#define BOOST_BIMAP_PROPERTY_MAP_SET_SUPPORT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/property_map.hpp>
+#include <boost/bimap/set_of.hpp>
+#include <boost/bimap/support/data_type_by.hpp>
+#include <boost/bimap/support/key_type_by.hpp>
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+
+template< class Tag, class Bimap >
+struct property_traits< ::boost::bimaps::views::map_view<Tag,Bimap> >
+{
+    typedef BOOST_DEDUCED_TYPENAME
+        ::boost::bimaps::support::data_type_by<Tag,Bimap>::type value_type;
+    typedef BOOST_DEDUCED_TYPENAME
+        ::boost::bimaps::support:: key_type_by<Tag,Bimap>::type   key_type;
+
+    typedef readable_property_map_tag category;
+};
+
+
+template< class Tag, class Bimap >
+const BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::data_type_by<Tag,Bimap>::type &
+    get(const ::boost::bimaps::views::map_view<Tag,Bimap> & m,
+        const BOOST_DEDUCED_TYPENAME
+            ::boost::bimaps::support::key_type_by<Tag,Bimap>::type & key)
+{
+    return m.at(key);
+}
+
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_PROPERTY_MAP_SET_SUPPORT_HPP
diff --git a/boost/bimap/property_map/unordered_set_support.hpp b/boost/bimap/property_map/unordered_set_support.hpp
new file mode 100644 (file)
index 0000000..2673ccc
--- /dev/null
@@ -0,0 +1,55 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file property_map/unordered_set_support.hpp
+/// \brief Support for the property map concept.
+
+#ifndef BOOST_BIMAP_PROPERTY_MAP_UNORDERED_SET_SUPPORT_HPP
+#define BOOST_BIMAP_PROPERTY_MAP_UNORDERED_SET_SUPPORT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/property_map.hpp>
+#include <boost/bimap/unordered_set_of.hpp>
+#include <boost/bimap/support/data_type_by.hpp>
+#include <boost/bimap/support/key_type_by.hpp>
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+
+template< class Tag, class Bimap >
+struct property_traits< ::boost::bimaps::views::unordered_map_view<Tag,Bimap> >
+{
+    typedef BOOST_DEDUCED_TYPENAME
+        ::boost::bimaps::support::data_type_by<Tag,Bimap>::type value_type;
+    typedef BOOST_DEDUCED_TYPENAME
+        ::boost::bimaps::support:: key_type_by<Tag,Bimap>::type   key_type;
+
+    typedef readable_property_map_tag category;
+};
+
+
+template< class Tag, class Bimap >
+const BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::data_type_by<Tag,Bimap>::type &
+    get(const ::boost::bimaps::views::unordered_map_view<Tag,Bimap> & m,
+        const BOOST_DEDUCED_TYPENAME
+            ::boost::bimaps::support::key_type_by<Tag,Bimap>::type & key)
+{
+    return m.at(key);
+}
+
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_PROPERTY_MAP_UNORDERED_SET_SUPPORT_HPP
diff --git a/boost/bimap/relation/detail/access_builder.hpp b/boost/bimap/relation/detail/access_builder.hpp
new file mode 100644 (file)
index 0000000..a1e939f
--- /dev/null
@@ -0,0 +1,170 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/detail/access_builder.hpp
+/// \brief Define macros to help building metafunctions
+
+#ifndef BOOST_BIMAP_RELATION_ACCESS_BUILDER_HPP
+#define BOOST_BIMAP_RELATION_ACCESS_BUILDER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/support/member_with_tag.hpp>
+#include <boost/bimap/relation/member_at.hpp>
+#include <boost/call_traits.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/utility/enable_if.hpp>
+
+
+/******************************************************************************
+                   BIMAP SYMMETRIC ACCESS RESULT OF
+*******************************************************************************
+
+namespace result_of {
+
+template< class Tag, class SymmetricType >
+struct NAME
+{
+    typedef -unspecified- type;
+};
+
+} // namespace result_of
+
+******************************************************************************/
+
+/*===========================================================================*/
+#define BOOST_BIMAP_SYMMETRIC_ACCESS_RESULT_OF_BUILDER(                       \
+                                                                              \
+        NAME,                                                                 \
+        METAFUNCTION_BASE                                                     \
+    )                                                                         \
+                                                                              \
+    namespace result_of {                                                     \
+                                                                              \
+    template< class Tag, class SymmetricType >                                \
+    struct NAME                                                               \
+    {                                                                         \
+        typedef BOOST_DEDUCED_TYPENAME METAFUNCTION_BASE                      \
+        <                                                                     \
+            Tag,SymmetricType                                                 \
+                                                                              \
+        >::type value_type;                                                   \
+                                                                              \
+        typedef BOOST_DEDUCED_TYPENAME mpl::if_< is_const<SymmetricType>,     \
+                                                                              \
+            BOOST_DEDUCED_TYPENAME call_traits<value_type>::const_reference,  \
+                                                                              \
+            BOOST_DEDUCED_TYPENAME call_traits<value_type>::reference         \
+                                                                              \
+        >::type type;                                                         \
+    };                                                                        \
+                                                                              \
+    }
+/*===========================================================================*/
+
+
+
+/******************************************************************************
+                   BIMAP SYMMETRIC ACCESS IMPLEMENTATION
+*******************************************************************************
+
+namespace detail {
+
+template< class Tag, class SymmetricType >
+typename result_of::NAME<Tag,SymmetricType>::type
+    NAME( Tag , const Relation & );
+
+} // namespace detail
+
+******************************************************************************/
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_SYMMETRIC_ACCESS_IMPLEMENTATION_BUILDER(                  \
+                                                                              \
+        NAME,                                                                 \
+        TP_SYMMETRIC,                                                         \
+        PARAMETER_NAME,                                                       \
+        LEFT_BODY,                                                            \
+        RIGHT_BODY                                                            \
+    )                                                                         \
+                                                                              \
+    namespace detail {                                                        \
+                                                                              \
+                                                                              \
+                                                                              \
+    template< class TP_SYMMETRIC >                                            \
+    BOOST_DEDUCED_TYPENAME result_of::NAME                                    \
+    <                                                                         \
+        ::boost::bimaps::relation::member_at::left,TP_SYMMETRIC               \
+                                                                              \
+    >::type                                                                   \
+                                                                              \
+    NAME( ::boost::bimaps::relation::member_at::left,                         \
+                  TP_SYMMETRIC & PARAMETER_NAME )                             \
+    {                                                                         \
+        LEFT_BODY;                                                            \
+    }                                                                         \
+                                                                              \
+    template< class TP_SYMMETRIC >                                            \
+    BOOST_DEDUCED_TYPENAME result_of::NAME                                    \
+    <                                                                         \
+        ::boost::bimaps::relation::member_at::right,TP_SYMMETRIC              \
+                                                                              \
+    >::type                                                                   \
+                                                                              \
+    NAME( ::boost::bimaps::relation::member_at::right,                        \
+                  TP_SYMMETRIC & PARAMETER_NAME )                             \
+    {                                                                         \
+        RIGHT_BODY;                                                           \
+    }                                                                         \
+                                                                              \
+    }
+/*===========================================================================*/
+
+
+/******************************************************************************
+                   BIMAP RELATION ACCESS INTERFACE
+*******************************************************************************
+
+template< class Tag, class SymmetricType >
+typename result_of::NAME<Tag,SymmetricType>::type
+    NAME( const SymmetricType & );
+
+******************************************************************************/
+
+/*===========================================================================*/
+#define BOOST_BIMAP_SYMMETRIC_ACCESS_INTERFACE_BUILDER(                       \
+                                                                              \
+        NAME                                                                  \
+    )                                                                         \
+                                                                              \
+    template< class Tag, class SymmetricType >                                \
+    BOOST_DEDUCED_TYPENAME result_of::NAME<Tag,SymmetricType>::type           \
+    NAME( SymmetricType & s )                                                 \
+    {                                                                         \
+        typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::   \
+            member_with_tag                                                   \
+            <                                                                 \
+                Tag,SymmetricType                                             \
+                                                                              \
+            >::type member_at_tag;                                            \
+                                                                              \
+        return detail::NAME(member_at_tag(),s);                               \
+    }
+/*===========================================================================*/
+
+
+#endif // BOOST_BIMAP_RELATION_ACCESS_BUILDER_HPP
+
diff --git a/boost/bimap/relation/detail/metadata_access_builder.hpp b/boost/bimap/relation/detail/metadata_access_builder.hpp
new file mode 100644 (file)
index 0000000..4ef6cae
--- /dev/null
@@ -0,0 +1,103 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/detail/metadata_access_builder.hpp
+/// \brief Define macros to help building metafunctions
+
+#ifndef BOOST_BIMAP_RELATION_DETAIL_METADATA_ACCESS_BUILDER_HPP
+#define BOOST_BIMAP_RELATION_DETAIL_METADATA_ACCESS_BUILDER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/support/is_tag_of_member_at.hpp>
+#include <boost/bimap/detail/debug/static_error.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+
+
+/******************************************************************************
+              BIMAP SYMMETRIC METADATA ACCESS INTERFACE
+*******************************************************************************
+
+template< class Tag, class SymmetricType >
+struct NAME
+{
+    typedef -unspecified- type;
+};
+
+******************************************************************************/
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER(                        \
+                                                                              \
+        NAME,                                                                 \
+        METADATA_BY_LEFT,                                                     \
+        METADATA_BY_RIGHT                                                     \
+    )                                                                         \
+                                                                              \
+    template                                                                  \
+    <                                                                         \
+        class Tag,                                                            \
+        class SymmetricType,                                                  \
+        class Enable = void                                                   \
+    >                                                                         \
+    struct NAME                                                               \
+    {                                                                         \
+        BOOST_BIMAP_STATIC_ERROR(                                             \
+            BOOST_PP_CAT(NAME,_FAILURE),                                      \
+            (SymmetricType,Tag)                                               \
+        );                                                                    \
+    };                                                                        \
+                                                                              \
+    template< class Tag, class SymmetricType >                                \
+    struct NAME                                                               \
+    <                                                                         \
+        Tag, SymmetricType,                                                   \
+        BOOST_DEDUCED_TYPENAME enable_if                                      \
+        <                                                                     \
+            ::boost::bimaps::relation::support::is_tag_of_member_at_left      \
+            <                                                                 \
+                Tag,                                                          \
+                SymmetricType                                                 \
+            >                                                                 \
+                                                                              \
+        >::type                                                               \
+    >                                                                         \
+    {                                                                         \
+        typedef BOOST_DEDUCED_TYPENAME SymmetricType::METADATA_BY_LEFT type;  \
+    };                                                                        \
+                                                                              \
+    template< class Tag, class SymmetricType >                                \
+    struct NAME                                                               \
+    <                                                                         \
+        Tag, SymmetricType,                                                   \
+        BOOST_DEDUCED_TYPENAME enable_if                                      \
+        <                                                                     \
+            ::boost::bimaps::relation::support::is_tag_of_member_at_right     \
+            <                                                                 \
+                Tag,                                                          \
+                SymmetricType                                                 \
+            >                                                                 \
+                                                                              \
+        >::type                                                               \
+    >                                                                         \
+    {                                                                         \
+        typedef BOOST_DEDUCED_TYPENAME SymmetricType::METADATA_BY_RIGHT type; \
+    };
+/*===========================================================================*/
+
+
+#endif // BOOST_BIMAP_RELATION_DETAIL_METADATA_ACCES_BUILDER_HPP
+
+
diff --git a/boost/bimap/relation/detail/mutant.hpp b/boost/bimap/relation/detail/mutant.hpp
new file mode 100644 (file)
index 0000000..e601ad3
--- /dev/null
@@ -0,0 +1,83 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/detail/mutant.hpp
+/// \brief Mutate functions to extract views of mutant classes.
+
+#ifndef BOOST_BIMAP_RELATION_DETAIL_MUTANT_HPP
+#define BOOST_BIMAP_RELATION_DETAIL_MUTANT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/detail/debug/static_error.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/utility.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/utility/enable_if.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+
+/// \brief Relation details, mutant idiom and symmetrical metafunctions builders.
+
+namespace detail {
+
+//@{
+/// \brief Converts a mutant class to a view with zero overhead.
+/**
+
+This function is a safe wrapper around reinterpret_cast. It checks at
+compile time that the desired view is supported by the mutant class.
+See also mutant, can_mutate_in.
+\ingroup mutant_group
+                                                                            **/
+
+
+template< class View, class Type >
+BOOST_DEDUCED_TYPENAME enable_if< mpl::not_< is_const< Type > >,
+
+View&
+
+>::type mutate( Type & m )
+{
+    BOOST_MPL_ASSERT((
+        ::boost::mpl::contains<BOOST_DEDUCED_TYPENAME Type::mutant_views,View>
+    ));
+    return *reinterpret_cast< View* >(addressof(m));
+}
+
+template< class View, class Type >
+BOOST_DEDUCED_TYPENAME enable_if< is_const< Type >,
+
+const View&
+
+>::type mutate( Type & m )
+{
+    BOOST_MPL_ASSERT((
+        ::boost::mpl::contains<BOOST_DEDUCED_TYPENAME Type::mutant_views,View> 
+    ));
+    return *reinterpret_cast< const View* >(addressof(m));
+}
+
+//@}
+
+} // namespace detail
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_RELATION_DETAIL_MUTANT_HPP
+
diff --git a/boost/bimap/relation/detail/static_access_builder.hpp b/boost/bimap/relation/detail/static_access_builder.hpp
new file mode 100644 (file)
index 0000000..72f9925
--- /dev/null
@@ -0,0 +1,105 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+
+/// \file relation/detail/static_access_builder.hpp
+/// \brief Define macros to help building metafunctions
+
+#ifndef BOOST_BIMAP_RELATION_DETAIL_STATIC_ACCESS_BUILDER_HPP
+#define BOOST_BIMAP_RELATION_DETAIL_STATIC_ACCESS_BUILDER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/support/is_tag_of_member_at.hpp>
+#include <boost/bimap/detail/debug/static_error.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+
+
+/******************************************************************************
+              BIMAP SYMMETRIC STATIC ACCESS INTERFACE
+*******************************************************************************
+
+template< class Tag, class SYMETRIC_TYPE >
+struct NAME
+{
+    -UNDEFINED BODY-;
+};
+
+******************************************************************************/
+
+
+/*===========================================================================*/
+#define BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER(                          \
+                                                                              \
+        NAME,                                                                 \
+        SYMMETRIC_TYPE,                                                       \
+        LEFT_BODY,                                                            \
+        RIGHT_BODY                                                            \
+    )                                                                         \
+                                                                              \
+    template                                                                  \
+    <                                                                         \
+        class Tag,                                                            \
+        class SYMMETRIC_TYPE,                                                 \
+        class Enable = void                                                   \
+    >                                                                         \
+    struct NAME                                                               \
+    {                                                                         \
+        BOOST_BIMAP_STATIC_ERROR(                                             \
+            BOOST_PP_CAT(NAME,_FAILURE),                                      \
+            (SYMMETRIC_TYPE,Tag)                                              \
+        );                                                                    \
+    };                                                                        \
+                                                                              \
+    template< class Tag, class SYMMETRIC_TYPE >                               \
+    struct NAME                                                               \
+    <                                                                         \
+        Tag, SYMMETRIC_TYPE,                                                  \
+        BOOST_DEDUCED_TYPENAME enable_if                                      \
+        <                                                                     \
+            ::boost::bimaps::relation::support::is_tag_of_member_at_left      \
+            <                                                                 \
+                Tag,                                                          \
+                SYMMETRIC_TYPE                                                \
+            >                                                                 \
+                                                                              \
+        >::type                                                               \
+    >                                                                         \
+    {                                                                         \
+        LEFT_BODY;                                                            \
+    };                                                                        \
+                                                                              \
+    template< class Tag, class SYMMETRIC_TYPE >                               \
+    struct NAME                                                               \
+    <                                                                         \
+        Tag, SYMMETRIC_TYPE,                                                  \
+        BOOST_DEDUCED_TYPENAME enable_if                                      \
+        <                                                                     \
+            ::boost::bimaps::relation::support::is_tag_of_member_at_right     \
+            <                                                                 \
+                Tag,                                                          \
+                SYMMETRIC_TYPE                                                \
+            >                                                                 \
+                                                                              \
+        >::type                                                               \
+    >                                                                         \
+    {                                                                         \
+        RIGHT_BODY;                                                           \
+    };
+/*===========================================================================*/
+
+
+#endif // BOOST_BIMAP_RELATION_DETAIL_STATIC_ACCES_BUILDER_HPP
+
+
diff --git a/boost/bimap/relation/detail/to_mutable_relation_functor.hpp b/boost/bimap/relation/detail/to_mutable_relation_functor.hpp
new file mode 100644 (file)
index 0000000..1e8b521
--- /dev/null
@@ -0,0 +1,102 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/detail/to_mutable_relation_functor.hpp
+/// \brief functors to convert types to mutable relations
+
+#ifndef BOOST_BIMAP_RELATION_DETAIL_TO_MUTABLE_RELATION_FUNCTOR_HPP
+#define BOOST_BIMAP_RELATION_DETAIL_TO_MUTABLE_RELATION_FUNCTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/support/pair_type_by.hpp>
+#include <boost/bimap/relation/detail/mutant.hpp>
+#include <boost/bimap/relation/mutant_relation.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace detail {
+
+/// \brief Functor used in map views
+
+template< class Tag, class Relation >
+struct pair_to_relation_functor
+{
+    const Relation
+        operator()(const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+                            pair_type_by<Tag,Relation>::type & p) const
+    {
+        return Relation(p);
+    }
+};
+
+template< class Tag, class TA, class TB, class Info >
+struct pair_to_relation_functor<
+    Tag,::boost::bimaps::relation::mutant_relation<TA,TB,Info,true> >
+{
+    typedef ::boost::bimaps::relation::mutant_relation<TA,TB,Info,true> Relation;
+
+    Relation &
+        operator()( BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+            pair_type_by<Tag,Relation>::type & p ) const
+    {
+        return ::boost::bimaps::relation::detail::mutate<Relation>(p);
+    }
+
+    const Relation &
+        operator()( const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+            pair_type_by<Tag,Relation>::type & p) const
+    {
+        return ::boost::bimaps::relation::detail::mutate<Relation>(p);
+    }
+};
+
+
+/// \brief Used in set views
+
+template< class Relation >
+struct get_mutable_relation_functor
+{
+    const Relation
+    operator()( const BOOST_DEDUCED_TYPENAME Relation::above_view & r ) const
+    {
+        return Relation(r);
+    }
+};
+
+template< class TA, class TB, class Info >
+struct get_mutable_relation_functor< ::boost::bimaps::relation::mutant_relation<TA,TB,Info,true> >
+{
+    typedef ::boost::bimaps::relation::mutant_relation<TA,TB,Info,true> Relation;
+
+    Relation &
+    operator()( BOOST_DEDUCED_TYPENAME Relation::above_view & r ) const
+    {
+        return ::boost::bimaps::relation::detail::mutate<Relation>(r);
+    }
+
+    const Relation &
+    operator()( const BOOST_DEDUCED_TYPENAME Relation::above_view & r ) const
+    {
+        return ::boost::bimaps::relation::detail::mutate<Relation>(r);
+    }
+};
+
+} // namespace detail
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_RELATION_DETAIL_TO_MUTABLE_RELATION_FUNCTOR_HPP
+
diff --git a/boost/bimap/relation/member_at.hpp b/boost/bimap/relation/member_at.hpp
new file mode 100644 (file)
index 0000000..c39738f
--- /dev/null
@@ -0,0 +1,72 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/member_at.hpp
+/// \brief Defines the tags for the member_at::side idiom
+
+#ifndef BOOST_BIMAP_RELATION_MEMBER_AT_HPP
+#define BOOST_BIMAP_RELATION_MEMBER_AT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+
+/// \brief member_at::side idiom to access relation values and types using metaprogramming. 
+/**
+
+This tags are used to specify which member you want to acces when using a metafunction over
+a symmetrical type. The idea is to be able to write code like:
+
+\code
+result_of::get<member_at::left,relation>::type data = get<member_at::left>(rel);
+\endcode
+
+The relation class supports this idiom even when the elements are tagged. This is useful
+because a user can decide to start tagging in any moment of the development.
+
+See also member_with_tag, is_tag_of_member_at_left, is_tag_of_member_at_right, get
+value_type_of, pair_by, pair_type_by.
+
+\ingroup relation_group
+                                                                                        **/
+namespace member_at {
+
+    /// \brief Member at left tag
+    /**
+    See also member_at, rigth.
+                                            **/
+
+    struct left  {};
+
+    /// \brief Member at right tag
+    /**
+    See also member_at, left.
+                                            **/
+
+    struct right {};
+
+    /// \brief Member info tag
+    /**
+    See also member_at, left, right.
+                                            **/
+
+    struct info  {};
+
+}
+
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_RELATION_MEMBER_AT_HPP
diff --git a/boost/bimap/relation/mutant_relation.hpp b/boost/bimap/relation/mutant_relation.hpp
new file mode 100644 (file)
index 0000000..517557f
--- /dev/null
@@ -0,0 +1,430 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/mutant_relation.hpp
+/// \brief Defines the mutant_relation class
+
+#ifndef BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP
+#define BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/vector.hpp>
+#include <boost/operators.hpp>
+#include <boost/call_traits.hpp>
+// #include <boost/serialization/nvp.hpp>
+
+#include <boost/functional/hash/hash.hpp>
+
+#include <boost/mpl/aux_/na.hpp>
+
+// Boost.Bimap
+#include <boost/bimap/tags/tagged.hpp>
+#include <boost/bimap/tags/support/default_tagged.hpp>
+#include <boost/bimap/tags/support/tag_of.hpp>
+#include <boost/bimap/tags/support/value_type_of.hpp>
+
+#include <boost/bimap/relation/member_at.hpp>
+#include <boost/bimap/relation/detail/mutant.hpp>
+#include <boost/bimap/relation/structured_pair.hpp>
+#include <boost/bimap/relation/symmetrical_base.hpp>
+#include <boost/bimap/relation/support/get.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+
+namespace detail {
+
+// This class is included so structured_pair and mutant_relation share
+// exactly the same class layout
+
+template< class LeftType, class RightType, bool force_mutable >
+class relation_storage :
+    public symmetrical_base<LeftType,RightType,force_mutable>
+{
+    typedef symmetrical_base<LeftType,RightType,force_mutable> base_;
+
+    typedef relation_storage storage_;
+
+    public:
+
+    typedef relation_storage<LeftType,RightType,false> non_mutable_storage;
+
+    typedef ::boost::mpl::vector2
+    <
+        relation_storage< LeftType, RightType, true  >,
+        relation_storage< LeftType, RightType, false >
+
+    > mutant_views;
+
+    //@{
+        /// data
+        BOOST_DEDUCED_TYPENAME base_::left_value_type  left;
+        BOOST_DEDUCED_TYPENAME base_::right_value_type right;
+    //@}
+
+    relation_storage() {}
+
+    relation_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                         BOOST_DEDUCED_TYPENAME base_::left_value_type
+                     >::param_type l,
+                     BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::right_value_type
+                     >::param_type r)
+
+        : left(l), right(r) {}
+
+          BOOST_DEDUCED_TYPENAME base_:: left_value_type &  get_left()      { return left;  }
+    const BOOST_DEDUCED_TYPENAME base_:: left_value_type &  get_left()const { return left;  }
+          BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()      { return right; }
+    const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return right; }
+};
+
+
+
+template< class TA, class TB, class Info, bool force_mutable >
+class relation_info_hook : public
+ ::boost::bimaps::relation::detail::relation_storage<TA,TB,force_mutable>
+{
+    typedef ::boost::bimaps::relation::detail::
+                relation_storage<TA,TB,force_mutable> base_;
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
+        default_tagged<Info,member_at::info>::type tagged_info_type;
+
+    public:
+    typedef BOOST_DEDUCED_TYPENAME tagged_info_type::value_type info_type;
+    typedef BOOST_DEDUCED_TYPENAME tagged_info_type::tag        info_tag;
+
+    info_type info;
+
+    protected:
+
+    relation_info_hook() {}
+
+    relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                           BOOST_DEDUCED_TYPENAME base_::left_value_type
+                        >::param_type l,
+                        BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                            BOOST_DEDUCED_TYPENAME base_::right_value_type
+                        >::param_type r,
+                        BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                            info_type
+                        >::param_type i = info_type() )
+
+        : base_(l,r), info(i) {}
+
+    template< class Relation >
+    relation_info_hook( const Relation & rel ) :
+        base_(rel.left,rel.right),
+        info(rel.info) {}
+
+    template< class Relation >
+    void change_to( const Relation & rel )
+    {
+        base_::left  = rel.left ;
+        base_::right = rel.right;
+        info         = rel.info ;
+    }
+
+    #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
+    template< class Archive >
+    void serialize(Archive & ar, const unsigned int version)
+    {
+        ar & ::boost::serialization::make_nvp("left" , base_::left );
+        ar & ::boost::serialization::make_nvp("right", base_::right);
+        ar & ::boost::serialization::make_nvp("info" , info        );
+    }
+    #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
+};
+
+template< class TA, class TB, bool force_mutable>
+class relation_info_hook<TA,TB,::boost::mpl::na,force_mutable> :
+    public ::boost::bimaps::relation::detail::relation_storage<TA,TB,force_mutable>
+{
+    typedef ::boost::bimaps::relation::detail::
+                relation_storage<TA,TB,force_mutable> base_;
+
+    public:
+    typedef ::boost::mpl::na info_type;
+    typedef member_at::info info_tag;
+
+    protected:
+
+    relation_info_hook() {}
+
+    relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                           BOOST_DEDUCED_TYPENAME base_::left_value_type
+                        >::param_type l,
+                        BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                            BOOST_DEDUCED_TYPENAME base_::right_value_type
+                        >::param_type r)
+
+        : base_(l,r) {}
+
+    template< class Relation >
+    relation_info_hook( const Relation & rel ) :
+        base_(rel.left,rel.right) {}
+
+    template< class Relation >
+    void change_to( const Relation & rel )
+    {
+        base_::left  = rel.left ;
+        base_::right = rel.right;
+    }
+
+    #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
+    template< class Archive >
+    void serialize(Archive & ar, const unsigned int version)
+    {
+        ar & ::boost::serialization::make_nvp("left" , base_::left );
+        ar & ::boost::serialization::make_nvp("right", base_::right);
+    }
+    #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
+};
+
+
+} // namespace detail
+
+/// \brief Abstraction of a related pair of values, that extends the std::pair class.
+/**
+The mutant_relation is a mutant class. A mutant class can mutate
+with zero overhead in other classes that are called views.
+Each view has to be StorageCompatible with the base class
+of the mutant. Note that all the views have the following
+storage structure:
+
+\verbatim
+                        __________
+                       |          |
+                       |    TA    |
+                       |__________|
+                       |          |
+                       |    TB    |
+                       |__________|
+
+\endverbatim
+
+See also select_relation, standard_relation.
+\ingroup relation_group
+                                                           **/
+
+
+template< class TA, class TB, class Info = ::boost::mpl::na, bool force_mutable = false >
+class mutant_relation : public
+    ::boost::bimaps::relation::detail::
+        relation_info_hook<TA,TB,Info,force_mutable>
+{
+    typedef ::boost::bimaps::relation::detail::
+        relation_info_hook<TA,TB,Info,force_mutable> base_;
+
+    public:
+
+    // We have to know the type of the base where the types are
+    // defined because Boost.MultiIndex requires it.
+
+    typedef ::boost::bimaps::relation::detail::
+                relation_storage<TA,TB,force_mutable> storage_base;
+
+    /// Above view, non mutable view of the relation
+
+    typedef mutant_relation<TA,TB,Info,false> above_view;
+
+    //@{
+        /// A signature compatible std::pair that is a view of the relation.
+
+        typedef structured_pair< TA, TB, Info, normal_layout >  left_pair;
+        typedef structured_pair< TB, TA, Info, mirror_layout > right_pair;
+    //@}
+
+    typedef ::boost::mpl::vector4
+    <
+         left_pair,
+        right_pair,
+
+        mutant_relation< TA, TB, Info, true  >,
+        mutant_relation< TA, TB, Info, false >
+
+    > mutant_views;
+
+    mutant_relation() {}
+
+    mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_:: left_value_type
+                    >::param_type l,
+                    BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::right_value_type
+                    >::param_type r) :
+        base_(l,r) {}
+
+    mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_:: left_value_type
+                    >::param_type l,
+                    BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::right_value_type
+                    >::param_type r,
+                    BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::info_type
+                    >::param_type i) :
+        base_(l,r,i) {}
+
+    mutant_relation(const mutant_relation<TA,TB,Info,false> & rel) :
+        base_(rel) {}
+
+    mutant_relation(const mutant_relation<TA,TB,Info,true> & rel) :
+        base_(rel) {}
+
+    // Operators
+
+    template< bool FM >
+    mutant_relation& operator=(const mutant_relation<TA,TB,Info,FM> & rel)
+    {
+        base_::change_to(rel);
+        return *this;
+    }
+
+    // The following functions are redundant if you only consider this class.
+    // They are included to make easier the construction of the get and the
+    // pair_by metafunction. Remember that not all compiler supports the mutant
+    // idiom.
+
+    left_pair & get_left_pair()
+    {
+        return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
+    }
+
+    const left_pair & get_left_pair() const
+    {
+        return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
+    }
+
+    right_pair & get_right_pair()
+    {
+        return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
+    }
+
+    const right_pair & get_right_pair() const
+    {
+        return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
+    }
+
+    above_view & get_view()
+    {
+        return ::boost::bimaps::relation::detail::mutate<above_view>(*this);
+    }
+
+    const above_view & get_view() const
+    {
+        return ::boost::bimaps::relation::detail::mutate<above_view>(*this);
+    }
+
+    template< class Tag >
+    const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+        result_of::get<Tag,const mutant_relation>::type
+    get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const
+    {
+        return ::boost::bimaps::relation::support::get<Tag>(*this);
+    }
+
+    template< class Tag >
+    BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+        result_of::get<Tag,mutant_relation>::type
+    get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
+    {
+        return ::boost::bimaps::relation::support::get<Tag>(*this);
+    }
+
+    #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
+
+    private:
+    friend class ::boost::serialization::access;
+
+    template<class Archive>
+    void serialize(Archive & ar, const unsigned int version)
+    {
+        base_::serialize(ar,version);
+    }
+
+    #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
+};
+
+// hash value
+
+template< class FirstType, class SecondType, bool FM >
+std::size_t hash_value(const detail::relation_storage<FirstType,SecondType,FM> & r)
+{
+    std::size_t seed = 0;
+    ::boost::hash_combine(seed, r. left );
+    ::boost::hash_combine(seed, r.right );
+
+    return seed;
+}
+
+// mutant_relation - mutant_relation
+
+template< class FirstType, class SecondType, bool FM1, bool FM2 >
+bool operator==(const detail::relation_storage<FirstType,SecondType,FM1> & a,
+                const detail::relation_storage<FirstType,SecondType,FM2> & b)
+{
+    return ( ( a.left  == b.left  ) &&
+             ( a.right == b.right ) );
+}
+
+template< class FirstType, class SecondType, bool FM1, bool FM2 >
+bool operator!=(const detail::relation_storage<FirstType,SecondType,FM1> & a,
+                const detail::relation_storage<FirstType,SecondType,FM2> & b)
+{
+    return ! ( a == b );
+}
+
+template< class FirstType, class SecondType, bool FM1, bool FM2 >
+bool operator<(const detail::relation_storage<FirstType,SecondType,FM1> & a,
+               const detail::relation_storage<FirstType,SecondType,FM2> & b)
+{
+    return (  ( a.left  <  b.left  ) ||
+             (( a.left == b.left ) && ( a.right < b.right )));
+}
+
+template< class FirstType, class SecondType, bool FM1, bool FM2 >
+bool operator<=(const detail::relation_storage<FirstType,SecondType,FM1> & a,
+                const detail::relation_storage<FirstType,SecondType,FM2> & b)
+{
+    return (  ( a.left  <  b.left  ) ||
+             (( a.left == b.left ) && ( a.right <= b.right )));
+}
+
+template< class FirstType, class SecondType, bool FM1, bool FM2 >
+bool operator>(const detail::relation_storage<FirstType,SecondType,FM1> & a,
+               const detail::relation_storage<FirstType,SecondType,FM2> & b)
+{
+    return ( ( a.left  >  b.left  ) ||
+             (( a.left == b.left ) && ( a.right > b.right )));
+}
+
+template< class FirstType, class SecondType, bool FM1, bool FM2 >
+bool operator>=(const detail::relation_storage<FirstType,SecondType,FM1> & a,
+                const detail::relation_storage<FirstType,SecondType,FM2> & b)
+{
+    return ( ( a.left  >  b.left  ) ||
+             (( a.left == b.left ) && ( a.right >= b.right )));
+}
+
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP
+
+
+
diff --git a/boost/bimap/relation/pair_layout.hpp b/boost/bimap/relation/pair_layout.hpp
new file mode 100644 (file)
index 0000000..24368db
--- /dev/null
@@ -0,0 +1,72 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/pair_layout.hpp
+/// \brief Tags for pair layouts
+
+#ifndef BOOST_BIMAP_RELATION_PAIR_LAYOUT_HPP
+#define BOOST_BIMAP_RELATION_PAIR_LAYOUT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+
+//@{
+
+/// \brief Tag for normal layout. ( A,B -> A,B )
+
+struct normal_layout {};
+
+/// \brief Tag for mirror layout. ( A,B -> B,A )
+
+struct mirror_layout {};
+
+//@}
+
+/** \struct boost::bimaps::relation::inverse_layout
+\brief Metafunction to obtain the inverse of a layout.
+
+\code
+template< class Layout >
+struct inverse_layout
+{
+    typedef {InverseLayout} type;
+};
+\endcode
+
+See also normal_layout, mirror_layout.
+                                                                    **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class Layout >
+struct inverse_layout
+{
+    typedef normal_layout type;
+};
+
+template<>
+struct inverse_layout< normal_layout >
+{
+    typedef mirror_layout type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_RELATION_DETAIL_PAIR_LAYOUT_HPP
+
diff --git a/boost/bimap/relation/structured_pair.hpp b/boost/bimap/relation/structured_pair.hpp
new file mode 100644 (file)
index 0000000..2325b3d
--- /dev/null
@@ -0,0 +1,508 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/structured_pair.hpp
+/// \brief Defines the structured_pair class.
+
+#ifndef BOOST_BIMAP_RELATION_STRUCTURED_PAIR_HPP
+#define BOOST_BIMAP_RELATION_STRUCTURED_PAIR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <utility>
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/mpl/aux_/na.hpp>
+
+#include <boost/call_traits.hpp>
+
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/vector.hpp>
+
+#include <boost/bimap/detail/debug/static_error.hpp>
+#include <boost/bimap/relation/pair_layout.hpp>
+#include <boost/bimap/relation/symmetrical_base.hpp>
+#include <boost/bimap/relation/support/get.hpp>
+#include <boost/bimap/tags/support/value_type_of.hpp>
+
+
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+
+namespace detail {
+
+/// \brief Storage definition of the left view of a mutant relation.
+/**
+
+See also storage_finder, mirror_storage.
+                                                                            **/
+
+template< class FirstType, class SecondType >
+class normal_storage :
+    public symmetrical_base<FirstType,SecondType>
+{
+    typedef symmetrical_base<FirstType,SecondType> base_;
+
+    public:
+
+    typedef normal_storage storage_;
+
+    typedef BOOST_DEDUCED_TYPENAME base_::left_value_type  first_type;
+    typedef BOOST_DEDUCED_TYPENAME base_::right_value_type second_type;
+
+    first_type   first;
+    second_type  second;
+
+    normal_storage() {}
+
+    normal_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        first_type >::param_type f,
+                   BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        second_type>::param_type s)
+
+        : first(f), second(s) {}
+
+          BOOST_DEDUCED_TYPENAME base_:: left_value_type &  get_left()      { return first;  }
+    const BOOST_DEDUCED_TYPENAME base_:: left_value_type &  get_left()const { return first;  }
+          BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()      { return second; }
+    const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return second; }
+};
+
+/// \brief Storage definition of the right view of a mutant relation.
+/**
+
+See also storage_finder, normal_storage.
+                                                                            **/
+
+template< class FirstType, class SecondType >
+class mirror_storage :
+    public symmetrical_base<SecondType,FirstType>
+{
+    typedef symmetrical_base<SecondType,FirstType> base_;
+
+    public:
+
+    typedef mirror_storage storage_;
+
+    typedef BOOST_DEDUCED_TYPENAME base_::left_value_type   second_type;
+    typedef BOOST_DEDUCED_TYPENAME base_::right_value_type  first_type;
+
+    second_type  second;
+    first_type   first;
+
+    mirror_storage() {}
+
+    mirror_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits<first_type  >::param_type f,
+                   BOOST_DEDUCED_TYPENAME ::boost::call_traits<second_type >::param_type s)
+
+        : second(s), first(f)  {}
+
+          BOOST_DEDUCED_TYPENAME base_:: left_value_type &  get_left()      { return second; }
+    const BOOST_DEDUCED_TYPENAME base_:: left_value_type &  get_left()const { return second; }
+          BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()      { return first;  }
+    const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return first;  }
+};
+
+/** \struct boost::bimaps::relation::storage_finder
+\brief Obtain the a storage with the correct layout.
+
+\code
+template< class FirstType, class SecondType, class Layout >
+struct storage_finder
+{
+    typedef {normal/mirror}_storage<FirstType,SecondType> type;
+};
+\endcode
+
+See also normal_storage, mirror_storage.
+                                                                        **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template
+<
+    class FirstType,
+    class SecondType,
+    class Layout
+>
+struct storage_finder
+{
+    typedef normal_storage<FirstType,SecondType> type;
+};
+
+template
+<
+    class FirstType,
+    class SecondType
+>
+struct storage_finder<FirstType,SecondType,mirror_layout>
+{
+    typedef mirror_storage<FirstType,SecondType> type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+
+template< class TA, class TB, class Info, class Layout >
+class pair_info_hook :
+    public ::boost::bimaps::relation::detail::storage_finder<TA,TB,Layout>::type
+{
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::storage_finder<TA,TB,Layout>::type base_;
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
+        default_tagged<Info,member_at::info>::type tagged_info_type;
+
+    public:
+    typedef BOOST_DEDUCED_TYPENAME tagged_info_type::value_type info_type;
+    typedef BOOST_DEDUCED_TYPENAME tagged_info_type::tag        info_tag;
+
+    info_type info;
+
+    protected:
+
+    pair_info_hook() {}
+
+    pair_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::first_type
+                    >::param_type f,
+                    BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::second_type
+                    >::param_type s,
+                    BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        info_type
+                    >::param_type i = info_type() )
+        : base_(f,s), info(i) {}
+
+    template< class Pair >
+    pair_info_hook( const Pair & p) :
+        base_(p.first,p.second),
+        info(p.info) {}
+
+    template< class Pair >
+    void change_to( const Pair & p )
+    {
+        base_::first  = p.first ;
+        base_::second = p.second;
+        info          = p.info  ;
+    }
+
+    void clear_info()
+    {
+        info = info_type();
+    };
+};
+
+template< class TA, class TB, class Layout>
+class pair_info_hook<TA,TB,::boost::mpl::na,Layout> :
+    public ::boost::bimaps::relation::detail::storage_finder<TA,TB,Layout>::type
+{
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::storage_finder<TA,TB,Layout>::type base_;
+
+    public:
+    typedef ::boost::mpl::na info_type;
+    typedef member_at::info info_tag;
+
+    protected:
+
+    pair_info_hook() {}
+
+    pair_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::first_type
+                    >::param_type f,
+                    BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::second_type
+                    >::param_type s)
+
+        : base_(f,s) {}
+
+    template< class Pair >
+    pair_info_hook( const Pair & p ) :
+        base_(p.first,p.second) {}
+
+    template< class Pair >
+    void change_to( const Pair & p )
+    {
+        base_::first  = p.first ;
+        base_::second = p.second;
+    }
+
+    void clear_info() {};
+};
+
+
+
+} // namespace detail
+
+template< class TA, class TB, class Info, bool FM >
+class mutant_relation;
+
+
+/// \brief A std::pair signature compatible class that allows you to control
+///        the internal structure of the data.
+/**
+This class allows you to specify the order in wich the two data types will be
+in the layout of the class.
+                                                                               **/
+
+template< class FirstType, class SecondType, class Info, class Layout = normal_layout >
+class structured_pair :
+
+    public ::boost::bimaps::relation::detail::pair_info_hook
+    <
+        FirstType, SecondType,
+        Info,
+        Layout
+
+    >
+
+{
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::pair_info_hook
+    <
+        FirstType, SecondType,
+        Info,
+        Layout
+
+    > base_;
+
+    public:
+
+    typedef ::boost::mpl::vector3<
+        structured_pair< FirstType, SecondType, Info, normal_layout >,
+        structured_pair< FirstType, SecondType, Info, mirror_layout >,
+        BOOST_DEDUCED_TYPENAME ::boost::mpl::if_<
+            BOOST_DEDUCED_TYPENAME ::boost::is_same<Layout, normal_layout>::type,
+            mutant_relation< FirstType, SecondType, Info, true >,
+            mutant_relation< SecondType, FirstType, Info, true >
+        >::type
+
+    > mutant_views;
+
+    structured_pair() {}
+
+    structured_pair(BOOST_DEDUCED_TYPENAME boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::first_type  >::param_type f,
+                    BOOST_DEDUCED_TYPENAME boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::second_type >::param_type s)
+        : base_(f,s) {}
+
+    structured_pair(BOOST_DEDUCED_TYPENAME boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::first_type  >::param_type f,
+                    BOOST_DEDUCED_TYPENAME boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::second_type >::param_type s,
+                    BOOST_DEDUCED_TYPENAME boost::call_traits<
+                        BOOST_DEDUCED_TYPENAME base_::info_type   >::param_type i)
+        : base_(f,s,i) {}
+
+    template< class OtherLayout >
+    structured_pair(
+        const structured_pair<FirstType,SecondType,Info,OtherLayout> & p)
+        : base_(p) {}
+
+    template< class OtherLayout >
+    structured_pair& operator=(
+        const structured_pair<FirstType,SecondType,OtherLayout> & p)
+    {
+        base_::change_to(p);
+        return *this;
+    }
+
+    template< class First, class Second >
+    structured_pair(const std::pair<First,Second> & p) :
+        base_(p.first,p.second)
+    {}
+
+    template< class First, class Second >
+    structured_pair& operator=(const std::pair<First,Second> & p)
+    {
+        base_::first  = p.first;
+        base_::second = p.second;
+        base_::clear_info();
+        return *this;
+    }
+
+    template< class Tag >
+    const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+        result_of::get<Tag,const structured_pair>::type
+    get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const
+    {
+        return ::boost::bimaps::relation::support::get<Tag>(*this);
+    }
+
+    template< class Tag >
+    BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
+        result_of::get<Tag,structured_pair>::type
+    get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
+    {
+        return ::boost::bimaps::relation::support::get<Tag>(*this);
+    }
+};
+
+// structured_pair - structured_pair
+
+template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 >
+bool operator==(const structured_pair<FirstType,SecondType,Info,Layout1> & a,
+                const structured_pair<FirstType,SecondType,Info,Layout2> & b)
+{
+    return ( ( a.first  == b.first  ) &&
+             ( a.second == b.second ) );
+}
+
+template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 >
+bool operator!=(const structured_pair<FirstType,SecondType,Info,Layout1> & a,
+                const structured_pair<FirstType,SecondType,Info,Layout2> & b)
+{
+    return ! ( a == b );
+}
+
+template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 >
+bool operator<(const structured_pair<FirstType,SecondType,Info,Layout1> & a,
+               const structured_pair<FirstType,SecondType,Info,Layout2> & b)
+{
+    return (  ( a.first  <  b.first  ) ||
+             (( a.first == b.first ) && ( a.second < b.second )));
+}
+
+template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 >
+bool operator<=(const structured_pair<FirstType,SecondType,Info,Layout1> & a,
+                const structured_pair<FirstType,SecondType,Info,Layout2> & b)
+{
+    return (  ( a.first  <  b.first  ) ||
+             (( a.first == b.first ) && ( a.second <= b.second )));
+}
+
+template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 >
+bool operator>(const structured_pair<FirstType,SecondType,Info,Layout1> & a,
+               const structured_pair<FirstType,SecondType,Info,Layout2> & b)
+{
+    return ( ( a.first  >  b.first  ) ||
+             (( a.first == b.first ) && ( a.second > b.second )));
+}
+
+template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 >
+bool operator>=(const structured_pair<FirstType,SecondType,Info,Layout1> & a,
+                const structured_pair<FirstType,SecondType,Info,Layout2> & b)
+{
+    return ( ( a.first  >  b.first  ) ||
+             (( a.first == b.first ) && ( a.second >= b.second )));
+}
+
+// structured_pair - std::pair
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator==(const structured_pair<FirstType,SecondType,Info,Layout> & a,
+                const std::pair<F,S> & b)
+{
+    return ( ( a.first  == b.first  ) &&
+             ( a.second == b.second ) );
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator!=(const structured_pair<FirstType,SecondType,Info,Layout> & a,
+                const std::pair<F,S> & b)
+{
+    return ! ( a == b );
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator<(const structured_pair<FirstType,SecondType,Info,Layout> & a,
+               const std::pair<F,S> & b)
+{
+    return (  ( a.first  <  b.first  ) ||
+             (( a.first == b.first ) && ( a.second < b.second )));
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator<=(const structured_pair<FirstType,SecondType,Info,Layout> & a,
+                const std::pair<F,S> & b)
+{
+    return (  ( a.first  <  b.first  ) ||
+             (( a.first == b.first ) && ( a.second <= b.second )));
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator>(const structured_pair<FirstType,SecondType,Info,Layout> & a,
+               const std::pair<F,S> & b)
+{
+    return ( ( a.first  >  b.first  ) ||
+             (( a.first == b.first ) && ( a.second > b.second )));
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator>=(const structured_pair<FirstType,SecondType,Info,Layout> & a,
+                const std::pair<F,S> & b)
+{
+    return ( ( a.first  >  b.first  ) ||
+             (( a.first == b.first ) && ( a.second >= b.second )));
+}
+
+// std::pair - sturctured_pair
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator==(const std::pair<F,S> & a,
+                const structured_pair<FirstType,SecondType,Info,Layout> & b)
+{
+    return ( ( a.first  == b.first  ) &&
+             ( a.second == b.second ) );
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator!=(const std::pair<F,S> & a,
+                const structured_pair<FirstType,SecondType,Info,Layout> & b)
+{
+    return ! ( a == b );
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator<(const std::pair<F,S> & a,
+               const structured_pair<FirstType,SecondType,Info,Layout> & b)
+{
+    return (  ( a.first  <  b.first  ) ||
+             (( a.first == b.first ) && ( a.second < b.second )));
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator<=(const std::pair<F,S> & a,
+                const structured_pair<FirstType,SecondType,Info,Layout> & b)
+{
+    return (  ( a.first  <  b.first  ) ||
+             (( a.first == b.first ) && ( a.second <= b.second )));
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator>(const std::pair<F,S> & a,
+               const structured_pair<FirstType,SecondType,Info,Layout> & b)
+{
+    return ( ( a.first  >  b.first  ) ||
+             (( a.first == b.first ) && ( a.second > b.second )));
+}
+
+template< class FirstType, class SecondType, class Info, class Layout, class F, class S >
+bool operator>=(const std::pair<F,S> & a,
+                const structured_pair<FirstType,SecondType,Info,Layout> & b)
+{
+    return ( ( a.first  >  b.first  ) ||
+             (( a.first == b.first ) && ( a.second >= b.second )));
+}
+
+
+
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_RELATION_STRUCTURED_PAIR_HPP
+
diff --git a/boost/bimap/relation/support/data_extractor.hpp b/boost/bimap/relation/support/data_extractor.hpp
new file mode 100644 (file)
index 0000000..b00c607
--- /dev/null
@@ -0,0 +1,109 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/support/data_extractor.hpp
+/// \brief Data extraction functor.
+
+#ifndef BOOST_BIMAP_RELATION_SUPPORT_DATA_EXTRACTOR_HPP
+#define BOOST_BIMAP_RELATION_SUPPORT_DATA_EXTRACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/detail/metadata_access_builder.hpp>
+
+/** \struct boost::bimaps::relation::support::data_extractor
+
+\brief Data extraction functor.
+
+\ingroup relation_group
+                                                                    **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+template< class Tag, class Relation >
+struct data_extractor_implementation;
+
+template< class Relation >
+struct data_extractor_implementation< member_at::left, Relation > :
+    public std::unary_function<Relation,BOOST_DEDUCED_TYPENAME Relation::left_value_type>
+{
+    BOOST_DEDUCED_TYPENAME Relation::left_value_type const &
+        operator()(Relation const & rel) const
+    {
+        return rel.left;
+    }
+
+    BOOST_DEDUCED_TYPENAME Relation::left_value_type &
+        operator()(Relation       & rel) const
+    {
+        return rel.left;
+    }
+};
+
+template< class Relation >
+struct data_extractor_implementation< member_at::right, Relation > :
+    public std::unary_function<Relation,BOOST_DEDUCED_TYPENAME Relation::right_value_type>
+{
+    BOOST_DEDUCED_TYPENAME Relation::right_value_type const & 
+        operator()(Relation const & rel) const
+    {
+        return rel.right;
+    }
+
+    BOOST_DEDUCED_TYPENAME Relation::right_value_type & 
+        operator()(Relation       & rel) const
+    {
+        return rel.right;
+    }
+};
+
+template< class Tag, class Relation >
+struct data_extractor
+{
+    typedef data_extractor_implementation
+    <
+        BOOST_DEDUCED_TYPENAME member_with_tag<Tag,Relation>::type,
+        Relation
+
+    > type;
+};
+
+template< class Relation >
+struct both_keys_extractor
+{
+    typedef BOOST_DEDUCED_TYPENAME Relation::storage_base result_type;
+
+     const result_type & operator()(const Relation & rel) const
+    {
+        return rel;
+    }
+
+    result_type & operator()( Relation & rel) const
+    {
+        return rel;
+    }
+};
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_RELATION_SUPPORT_DATA_EXTRACTOR_HPP
+
diff --git a/boost/bimap/relation/support/get.hpp b/boost/bimap/relation/support/get.hpp
new file mode 100644 (file)
index 0000000..3a3afde
--- /dev/null
@@ -0,0 +1,140 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/support/get.hpp
+/// \brief get<tag>(r) function
+
+#ifndef BOOST_BIMAP_RELATION_SUPPORT_GET_HPP
+#define BOOST_BIMAP_RELATION_SUPPORT_GET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/support/value_type_of.hpp>
+
+#include <boost/bimap/relation/detail/access_builder.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_const.hpp>
+
+#ifdef BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES
+
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+/** \brief Gets a pair view of the relation.
+
+\ingroup relation_group
+                                                                        **/
+
+template< class Tag, class SymmetricType >
+BOOST_DEDUCED_TYPENAME result_of::get<Tag,SymmetricType>::type
+    get( SymmetricType & );
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES
+
+
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+// Since it is very error-prone to directly write the hole bunch
+// of relation accesor. They are buil from litle macro blocks that
+// are both more readable, leading to self docummenting code and a
+// lot more easier to understand and mantain.
+// It is very important to note that the three building blocks have
+// to laid in the same namespace in order to work. There is also
+// important to keep them in order.
+// The forward declaration are not necesary but they help a lot to
+// the reader, as they undercover what is the signature of the
+// result code.
+// In the end, it is not quicker to do it in this way because you
+// write a lot. But this code has no complexity at all and almost
+// every word writed is for documentation.
+
+// Result of
+// -------------------------------------------------------------------------
+/*
+    namespace result_of {
+
+    template< class Tag, class Relation >
+    struct get<Tag,Relation>;
+    {
+        typedef -unspecified- type;
+    };
+
+    } // namespace result_of
+
+*/
+
+BOOST_BIMAP_SYMMETRIC_ACCESS_RESULT_OF_BUILDER
+(
+    get,
+    value_type_of
+)
+
+
+
+// Implementation
+// -------------------------------------------------------------------------
+
+BOOST_BIMAP_SYMMETRIC_ACCESS_IMPLEMENTATION_BUILDER
+(
+    get,
+    SymmetricType,
+    st,
+    return st.get_left(),
+    return st.get_right()
+)
+
+namespace detail {
+
+template< class SymmetricType >
+BOOST_DEDUCED_TYPENAME result_of::get<
+    ::boost::bimaps::relation::member_at::info, SymmetricType >::type
+get(::boost::bimaps::relation::member_at::info, SymmetricType & rel)
+{
+    return rel.info;
+}
+
+} // namespace detail
+
+// Interface
+//----------------------------------------------------------------------------
+
+BOOST_BIMAP_SYMMETRIC_ACCESS_INTERFACE_BUILDER
+(
+    get
+)
+
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_RELATION_SUPPORT_GET_HPP
+
diff --git a/boost/bimap/relation/support/get_pair_functor.hpp b/boost/bimap/relation/support/get_pair_functor.hpp
new file mode 100644 (file)
index 0000000..5f37bf6
--- /dev/null
@@ -0,0 +1,85 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/support/get_pair_functor.hpp
+/// \brief get_pair_functor definition
+
+#ifndef BOOST_BIMAP_RELATION_SUPPORT_GET_PAIR_FUNCTOR_HPP
+#define BOOST_BIMAP_RELATION_SUPPORT_GET_PAIR_FUNCTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/support/pair_by.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+/// \brief A Functor that takes a relation as a parameter an return the desired view.
+/**
+
+This functor is included to help users of the relation class when using
+stl algorithms.
+
+See also member_at, pair_by().
+\ingroup relation_group
+
+                                                                                  **/
+
+template< class Tag, class Relation >
+struct get_pair_functor
+{
+    BOOST_DEDUCED_TYPENAME result_of::pair_by<Tag,Relation>::type
+    operator()( Relation & r ) const
+    {
+        return pair_by<Tag>(r);
+    }
+
+    BOOST_DEDUCED_TYPENAME result_of::pair_by<Tag,const Relation>::type
+    operator()( const Relation & r ) const
+    {
+        return pair_by<Tag>(r);
+    }
+};
+
+
+/// \brief A Functor that takes a relation as a parameter an return the above view.
+/**
+
+\ingroup relation_group
+                                                                                  **/
+
+template< class Relation >
+struct get_above_view_functor
+{
+    BOOST_DEDUCED_TYPENAME Relation::above_view &
+    operator()( Relation & r ) const
+    {
+        return r.get_view();
+    }
+
+    const BOOST_DEDUCED_TYPENAME Relation::above_view &
+    operator()( const Relation & r ) const
+    {
+        return r.get_view();
+    }
+};
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_RELATION_SUPPORT_GET_PAIR_FUNCTOR_HPP
+
diff --git a/boost/bimap/relation/support/is_tag_of_member_at.hpp b/boost/bimap/relation/support/is_tag_of_member_at.hpp
new file mode 100644 (file)
index 0000000..b2b1b74
--- /dev/null
@@ -0,0 +1,181 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/support/is_tag_of_member_at.hpp
+/// \brief is_tag_of_member_at<tag,relation> metafunction
+
+#ifndef BOOST_BIMAP_RELATION_SUPPORT_IS_TAG_OF_MEMBER_AT_HPP
+#define BOOST_BIMAP_RELATION_SUPPORT_IS_TAG_OF_MEMBER_AT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/member_at.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/mpl/bool.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/bimap/relation/support/member_with_tag.hpp>
+
+/** \struct boost::bimaps::relation::support::is_tag_of_member_at_left
+
+\brief Metafunction to test if a user tag is refering to the left member.
+
+\code
+
+template< class Tag, class Relation >
+struct is_tag_of_member_at_left : {true_|false_} {};
+
+\endcode
+
+This metafunction is somewhat redundant with member_with_tag, but it is included
+because it is a lot easier to metaprogram with it. The result type is the
+same that:
+
+\code
+
+ is_same< member_with_tag<Tag,Relation>::type , member_at::left >::type
+
+\endcode
+
+See also member_with_tag, member_at, is_tag_of_member_at_right.
+\ingroup relation_group
+                                                                             **/
+
+
+/** \struct boost::bimaps::relation::support::is_tag_of_member_at_right
+
+\brief Metafunction to test if a user tag is refering to the left member.
+
+\code
+
+template< class Tag, class Relation >
+struct is_tag_of_member_at_right : {true_|false_} {};
+
+\endcode
+
+This metafunction is somewhat redundat with member_with_tag, but it is included
+because it is a lot easier to metaprogram with it. The result type is the
+same that:
+
+\code
+
+ is_same< member_with_tag<Tag,Relation>::type , member_at::right >::type
+
+\endcode
+
+See also member_with_tag, member_at, is_tag_of_member_at_left.
+\ingroup relation_group
+                                                                             **/
+
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+// Metafunction is_tag_of_member_at_left
+// Easiear metaprogramming
+
+template
+<
+    class Tag,
+    class Relation,
+    class Enable = void
+>
+struct is_tag_of_member_at_left :
+    ::boost::mpl::false_ {};
+
+template< class Tag, class Relation >
+struct is_tag_of_member_at_left
+<
+    Tag, Relation,
+    BOOST_DEDUCED_TYPENAME enable_if
+    <
+        is_same
+        <
+            BOOST_DEDUCED_TYPENAME member_with_tag<Tag,Relation>::type,
+            member_at::left
+        >
+
+    >::type
+> :
+    ::boost::mpl::true_ {};
+
+// Metafunction is_tag_of_member_at_right
+// Easiear metaprogramming
+
+template
+<
+    class Tag,
+    class Relation,
+    class Enable = void
+>
+struct is_tag_of_member_at_right :
+    ::boost::mpl::false_ {};
+
+template< class Tag, class Relation >
+struct is_tag_of_member_at_right
+<
+    Tag, Relation,
+    BOOST_DEDUCED_TYPENAME enable_if
+    <
+        is_same
+        <
+            BOOST_DEDUCED_TYPENAME member_with_tag<Tag,Relation>::type,
+            member_at::right
+        >
+
+    >::type
+> :
+    ::boost::mpl::true_ {};
+
+
+// Metafunction is_tag_of_member_at_info
+// Easiear metaprogramming
+
+template
+<
+    class Tag,
+    class Relation,
+    class Enable = void
+>
+struct is_tag_of_member_at_info :
+    ::boost::mpl::false_ {};
+
+template< class Tag, class Relation >
+struct is_tag_of_member_at_info
+<
+    Tag, Relation,
+    BOOST_DEDUCED_TYPENAME enable_if
+    <
+        is_same
+        <
+            BOOST_DEDUCED_TYPENAME member_with_tag<Tag,Relation>::type,
+            member_at::info
+        >
+
+    >::type
+> :
+    ::boost::mpl::true_ {};
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_RELATION_SUPPORT_IS_TAG_OF_MEMBER_AT_HPP
+
+
diff --git a/boost/bimap/relation/support/member_with_tag.hpp b/boost/bimap/relation/support/member_with_tag.hpp
new file mode 100644 (file)
index 0000000..a8324ff
--- /dev/null
@@ -0,0 +1,180 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/support/member_with_tag.hpp
+/// \brief member_with_tag<tag,relation> metafunction
+
+#ifndef BOOST_BIMAP_RELATION_SUPPORT_MEMBER_WITH_TAG_HPP
+#define BOOST_BIMAP_RELATION_SUPPORT_MEMBER_WITH_TAG_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/member_at.hpp>
+#include <boost/bimap/detail/debug/static_error.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/and.hpp>
+
+/** \struct boost::bimaps::relation::support::member_with_tag
+
+\brief Metafunction to convert user tags to the member_at idiom.
+
+\code
+
+template< class Tag, class Relation >
+struct member_with_tag
+{
+    typedef member_at::{side} type;
+};
+
+\endcode
+
+We have to allow that all the metafunctions that works with tags
+and retrieves data from a Relation will work with member_at idiom
+even if the type was tagged. This will be great for the user,
+because he can choose to tag a member after he is using the
+relation and the code will still work.
+
+If we perform this check in every metafunction it will be very
+tedious and error prone, so instead of that all metafunctions
+that works with relations first call this metafunction that
+convert the tag to a member_at tag.
+
+See also member_at, is_tag_of_member_at_left, is_tag_of_member_at_right.
+\ingroup relation_group
+                                                                    **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+template
+<
+    class Tag,
+    class Relation,
+    class Enable = void
+>
+struct member_with_tag
+{
+    BOOST_BIMAP_STATIC_ERROR( MEMBER_WITH_TAG_FAILURE, (Relation,Tag) );
+};
+
+template< class Relation >
+struct member_with_tag
+<
+    member_at::left, Relation, void
+>
+{
+    typedef member_at::left type;
+};
+
+template< class Relation >
+struct member_with_tag
+<
+    member_at::right, Relation, void
+>
+{
+    typedef member_at::right type;
+};
+
+template< class Relation >
+struct member_with_tag
+<
+    member_at::info, Relation, void
+>
+{
+    typedef member_at::info type;
+};
+
+
+template< class Tag, class Relation >
+struct member_with_tag
+<
+    Tag, Relation,
+    BOOST_DEDUCED_TYPENAME enable_if
+    <
+        mpl::and_
+        <
+            mpl::not_< is_same<Tag,member_at::left> >,
+            is_same
+            <
+                Tag,
+                BOOST_DEDUCED_TYPENAME Relation::left_tag
+            >
+        >
+
+    >::type
+>
+{
+    typedef member_at::left type;
+};
+
+template< class Tag, class Relation >
+struct member_with_tag
+<
+    Tag,
+    Relation,
+    BOOST_DEDUCED_TYPENAME enable_if
+    <
+        mpl::and_
+        <
+            mpl::not_< is_same<Tag,member_at::right> >,
+            is_same
+            <
+                Tag,
+                BOOST_DEDUCED_TYPENAME Relation::right_tag
+            >
+        >
+
+    >::type
+>
+{
+    typedef member_at::right type;
+};
+
+template< class Tag, class Relation >
+struct member_with_tag
+<
+    Tag, Relation,
+    BOOST_DEDUCED_TYPENAME enable_if
+    <
+        mpl::and_
+        <
+            mpl::not_< is_same<Tag,member_at::info> >,
+            is_same
+            <
+                Tag,
+                BOOST_DEDUCED_TYPENAME Relation::info_tag
+            >
+        >
+
+    >::type
+>
+{
+    typedef member_at::info type;
+};
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_RELATION_SUPPORT_MEMBER_WITH_TAG_HPP
+
+
diff --git a/boost/bimap/relation/support/opposite_tag.hpp b/boost/bimap/relation/support/opposite_tag.hpp
new file mode 100644 (file)
index 0000000..174bd98
--- /dev/null
@@ -0,0 +1,61 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/support/opposite_tag.hpp
+/// \brief Metafunction to obtain the opposite tag in a relation.
+
+#ifndef BOOST_BIMAP_RELATION_SUPPORT_OPPOSITE_TAG_HPP
+#define BOOST_BIMAP_RELATION_SUPPORT_OPPOSITE_TAG_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/detail/metadata_access_builder.hpp>
+
+/** \struct boost::bimaps::relation::support::opposite_tag
+
+\brief Metafunction to obtain the opposite tag in a relation.
+
+\code
+
+template< class Tag, class Relation >
+struct opposite_tag
+{
+        typedef {OppositeTag} type;
+};
+
+\endcode
+
+\ingroup relation_group
+                                                                    **/
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+// Implementation of const pair reference type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER
+(
+    opossite_tag,
+    right_tag,
+    left_tag
+)
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_RELATION_SUPPORT_OPPOSITE_TAG_HPP
+
diff --git a/boost/bimap/relation/support/pair_by.hpp b/boost/bimap/relation/support/pair_by.hpp
new file mode 100644 (file)
index 0000000..1ce25fb
--- /dev/null
@@ -0,0 +1,120 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/support/pair_by.hpp
+/// \brief pair_by<member>(r) function
+
+#ifndef BOOST_BIMAP_RELATION_SUPPORT_PAIR_BY_HPP
+#define BOOST_BIMAP_RELATION_SUPPORT_PAIR_BY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/support/pair_type_by.hpp>
+#include <boost/bimap/relation/detail/access_builder.hpp>
+
+#ifdef BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+/** \brief Gets a pair view of the relation.
+
+\ingroup relation_group
+                                                                        **/
+
+template< class Tag, class Relation >
+BOOST_DEDUCED_TYPENAME result_of::pair_by<Tag,Relation>::type
+    pair_by( Relation & rel );
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES
+
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+
+// Since it is very error-prone to directly write the hole bunch
+// of relation accesor. They are buil from litle macro blocks that
+// are both more readable, leading to self docummenting code and a
+// lot more easier to understand and mantain.
+// It is very important to note that the three building blocks have
+// to laid in the same namespace in order to work. There is also
+// important to keep them in order.
+// The forward declaration are not necesary but they help a lot to
+// the reader, as they undercover what is the signature of the
+// result code.
+// In the end, it is not quicker to do it in this way because you
+// write a lot. But this code has no complexity at all and almost
+// every word writed is for documentation.
+
+// Result of
+// -------------------------------------------------------------------------
+/*
+    namespace result_of {
+
+    template< class Tag, class Relation >
+    struct pair_by<Tag,Relation>;
+    {
+        typedef -unspecified- type;
+    };
+
+    } // namespace result_of
+*/
+
+BOOST_BIMAP_SYMMETRIC_ACCESS_RESULT_OF_BUILDER
+(
+    pair_by,
+    pair_type_by
+)
+
+
+
+// Implementation
+// -------------------------------------------------------------------------
+
+BOOST_BIMAP_SYMMETRIC_ACCESS_IMPLEMENTATION_BUILDER
+(
+    pair_by,
+    Relation,
+    rel,
+    return rel.get_left_pair(),
+    return rel.get_right_pair()
+)
+
+// Interface
+// --------------------------------------------------------------------------
+
+BOOST_BIMAP_SYMMETRIC_ACCESS_INTERFACE_BUILDER
+(
+    pair_by
+)
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_DOXIGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_RELATION_SUPPORT_PAIR_BY_HPP
diff --git a/boost/bimap/relation/support/pair_type_by.hpp b/boost/bimap/relation/support/pair_type_by.hpp
new file mode 100644 (file)
index 0000000..64f98d1
--- /dev/null
@@ -0,0 +1,62 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/support/pair_type_by.hpp
+/// \brief pair_type_by<tag,relation> metafunction
+
+#ifndef BOOST_BIMAP_RELATION_SUPPORT_PAIR_TYPE_BY_HPP
+#define BOOST_BIMAP_RELATION_SUPPORT_PAIR_TYPE_BY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/detail/metadata_access_builder.hpp>
+
+/** \struct boost::bimaps::relation::support::pair_type_by
+
+\brief Metafunction to obtain the view type indexed by one of the sides.
+
+\code
+
+template< class Tag, class Relation >
+struct pair_type_by
+{
+        typedef {signature-compatible with std::pair} type;
+};
+
+\endcode
+
+See also member_at, pair_by().
+\ingroup relation_group
+                                                                    **/
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+// Implementation of pair type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER
+(
+    pair_type_by,
+    left_pair,
+    right_pair
+)
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_RELATION_SUPPORT_PAIR_BY_TYPE_HPP
+
diff --git a/boost/bimap/relation/support/value_type_of.hpp b/boost/bimap/relation/support/value_type_of.hpp
new file mode 100644 (file)
index 0000000..9dc5761
--- /dev/null
@@ -0,0 +1,91 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/support/value_type_of.hpp
+/// \brief value_type_of<tag,relation> metafunction
+
+#ifndef BOOST_BIMAP_RELATION_SUPPORT_VALUE_TYPE_OF_HPP
+#define BOOST_BIMAP_RELATION_SUPPORT_VALUE_TYPE_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/detail/metadata_access_builder.hpp>
+
+/** \struct boost::bimaps::relation::support::value_type_of
+
+\brief Metafunction to obtain the value type of one of the sides.
+
+\code
+
+template< class Tag, class Relation >
+struct value_type_of
+{
+        typedef typename Relation::{side}_type type;
+};
+
+\endcode
+
+See also member_at, get().
+\ingroup relation_group
+                                                                    **/
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+namespace support {
+
+// Metafunction value_type_of
+/*
+
+    template< class Tag, class Relation >
+    struct value_type_of
+    {
+        typedef -unspecified- type;
+    };
+
+*/
+
+BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER
+(
+    value_type_of,
+    left_value_type,
+    right_value_type
+)
+
+// Add support for info tags to value_type_of
+
+template< class Tag, class SymmetricType >
+struct value_type_of
+<
+    Tag, SymmetricType,
+    BOOST_DEDUCED_TYPENAME enable_if
+    <
+        ::boost::bimaps::relation::support::is_tag_of_member_at_info
+        <
+            Tag,
+            SymmetricType
+        >
+
+    >::type
+>
+{
+    typedef BOOST_DEDUCED_TYPENAME SymmetricType::info_type type;
+};
+
+} // namespace support
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_RELATION_SUPPORT_VALUE_TYPE_OF_HPP
+
diff --git a/boost/bimap/relation/symmetrical_base.hpp b/boost/bimap/relation/symmetrical_base.hpp
new file mode 100644 (file)
index 0000000..ea787c3
--- /dev/null
@@ -0,0 +1,97 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file relation/symmetrical_base.hpp
+/// \brief Base class for symmetrical types
+
+#ifndef BOOST_BIMAP_RELATION_SYMMETRICAL_BASE_HPP
+#define BOOST_BIMAP_RELATION_SYMMETRICAL_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+// Boost.Bimap
+#include <boost/bimap/tags/tagged.hpp>
+#include <boost/bimap/tags/support/default_tagged.hpp>
+
+#include <boost/bimap/relation/member_at.hpp>
+
+
+namespace boost {
+namespace bimaps {
+namespace relation {
+
+/// \brief Base of symetrical tagged types.
+/**
+
+                                                           **/
+
+template< class TA, class TB, bool force_mutable = false >
+class symmetrical_base
+{
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME tags::support::default_tagged
+    <
+        TA,
+        member_at::left
+
+    >::type tagged_left_type;
+
+    typedef BOOST_DEDUCED_TYPENAME tags::support::default_tagged
+    <
+        TB,
+        member_at::right
+
+    >::type tagged_right_type;
+
+    public:
+
+    //@{
+        /// The type stored in the relation
+
+        typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< force_mutable,
+
+            BOOST_DEDUCED_TYPENAME ::boost::remove_const<
+                BOOST_DEDUCED_TYPENAME tagged_left_type::value_type >::type,
+            BOOST_DEDUCED_TYPENAME tagged_left_type::value_type
+
+        >::type left_value_type;
+
+        typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< force_mutable,
+
+            BOOST_DEDUCED_TYPENAME ::boost::remove_const<
+                BOOST_DEDUCED_TYPENAME tagged_right_type::value_type >::type,
+            BOOST_DEDUCED_TYPENAME tagged_right_type::value_type
+
+        >::type right_value_type;
+    //@}
+
+    //@{
+        /// The tag of the member. By default it is \c member_at::{side}
+        typedef BOOST_DEDUCED_TYPENAME tagged_left_type ::tag  left_tag;
+        typedef BOOST_DEDUCED_TYPENAME tagged_right_type::tag right_tag;
+    //@}
+};
+
+
+
+} // namespace relation
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_RELATION_SYMMETRICAL_BASE_HPP
+
diff --git a/boost/bimap/set_of.hpp b/boost/bimap/set_of.hpp
new file mode 100644 (file)
index 0000000..b5a0c20
--- /dev/null
@@ -0,0 +1,206 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file set_of.hpp
+/// \brief Include support for set constrains for the bimap container
+
+#ifndef BOOST_BIMAP_SET_OF_HPP
+#define BOOST_BIMAP_SET_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/detail/user_interface_config.hpp>
+
+#include <functional>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/aux_/na.hpp>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/bimap/detail/concept_tags.hpp>
+
+#include <boost/bimap/detail/generate_index_binder.hpp>
+#include <boost/bimap/detail/generate_view_binder.hpp>
+#include <boost/bimap/detail/generate_relation_binder.hpp>
+
+#include <boost/bimap/tags/support/value_type_of.hpp>
+
+#include <boost/multi_index/ordered_index.hpp>
+
+#include <boost/bimap/views/map_view.hpp>
+#include <boost/bimap/views/set_view.hpp>
+
+namespace boost {
+namespace bimaps {
+
+/// \brief Set Type Specification
+/**
+This struct is used to specify a set specification.
+It is not a container, it is just a metaprogramming facility to
+express the type of a set. Generally, this specification will
+be used in other place to create a container.
+It has the same syntax that an std::set instantiation, except
+that the allocator cannot be specified. The rationale behind
+this difference is that the allocator is not part of the set
+type specification, rather it is a container configuration
+parameter.
+The first parameter is the type of the objects in the set, and
+the second one is a Functor that compares them.
+Bimap binding metafunctions can be used with this class in
+the following way:
+
+\code
+using namespace support;
+
+BOOST_STATIC_ASSERT( is_set_type_of< set_of<Type> >::value )
+
+BOOST_STATIC_ASSERT
+(
+     is_same
+     <
+        set_of<Type,KeyCompare>::index_bind
+        <
+            KeyExtractor,
+            Tag
+
+        >::type,
+
+        ordered_unique< tag<Tag>, KeyExtractor, KeyCompare >
+
+    >::value
+)
+
+typedef bimap
+<
+    set_of<Type>, RightKeyType
+
+> bimap_with_left_type_as_set;
+
+BOOST_STATIC_ASSERT
+(
+    is_same
+    <
+        set_of<Type>::map_view_bind
+        <
+            member_at::left,
+            bimap_with_left_type_as_set
+
+        >::type,
+
+        map_view< member_at::left, bimap_with_left_type_as_set >
+
+    >::value
+)
+
+\endcode
+
+See also set_of_relation.
+                                                                        **/
+
+template
+<
+    class KeyType,
+    class KeyCompare = std::less< BOOST_DEDUCED_TYPENAME 
+               ::boost::bimaps::tags::support::value_type_of<KeyType>::type >
+>
+struct set_of : public ::boost::bimaps::detail::set_type_of_tag
+{
+       /// User type, can be tagged
+    typedef KeyType user_type;
+
+    /// Type of the object that will be stored in the set
+       typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
+               value_type_of<user_type>::type value_type;
+
+    /// Functor that compare two keys
+    typedef KeyCompare key_compare;
+
+    struct lazy_concept_checked
+    {
+        BOOST_CLASS_REQUIRE ( value_type,
+                              boost, AssignableConcept );
+
+        BOOST_CLASS_REQUIRE4( key_compare, bool, value_type, value_type,
+                              boost, BinaryFunctionConcept );
+
+        typedef set_of type;
+    };
+
+    BOOST_BIMAP_GENERATE_INDEX_BINDER_1CP(
+
+        // binds to
+        multi_index::ordered_unique,
+
+        // with
+        key_compare
+    )
+
+    BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER(
+
+        // binds to
+        views::map_view
+    )
+
+    BOOST_BIMAP_GENERATE_SET_VIEW_BINDER(
+
+        // binds to
+        views::set_view
+    )
+
+    typedef mpl::bool_<false> mutable_key;
+};
+
+
+/// \brief Set Of Relation Specification
+/**
+This struct is similar to set_of but it is bind logically to a
+relation. It is used in the bimap instantiation to specify the
+desired type of the main view. This struct implements internally
+a metafunction named bind_to that manages the quite complicated
+task of finding the right type of the set for the relation.
+
+\code
+template<class Relation>
+struct bind_to
+{
+    typedef -unspecified- type;
+};
+\endcode
+
+See also set_of, is_set_type_of_relation.
+                                                                **/
+
+template< class KeyCompare = std::less< _relation > >
+struct set_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag
+{
+    /// Functor that compare two keys
+    typedef KeyCompare key_compare;
+
+    BOOST_BIMAP_GENERATE_RELATION_BINDER_1CP(
+
+        // binds to
+        set_of,
+
+        // with
+        key_compare
+    )
+
+    typedef mpl::bool_<false>  left_mutable_key;
+    typedef mpl::bool_<false> right_mutable_key;
+};
+
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_SET_OF_HPP
+
diff --git a/boost/bimap/support/data_type_by.hpp b/boost/bimap/support/data_type_by.hpp
new file mode 100644 (file)
index 0000000..c6d2e2c
--- /dev/null
@@ -0,0 +1,73 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file support/data_type_by.hpp
+/// \brief Metafunction to access the data types of a bimap
+
+#ifndef BOOST_BIMAP_SUPPORT_DATA_TYPE_BY_HPP
+#define BOOST_BIMAP_SUPPORT_DATA_TYPE_BY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/detail/metadata_access_builder.hpp>
+
+/** \struct boost::bimaps::support::data_type_by
+
+\brief Metafunction to obtain the data type of one of the sides in a bimap
+
+The tag parameter can be either a user defined tag or \c member_at::{side}.
+This is the actual data type stored in the bimap.
+\code
+
+template< class Tag, class Bimap >
+struct data_type_by
+{
+    typedef typename Bimap::{side}_data_type type;
+};
+
+\endcode
+
+The following holds:
+
+\code
+
+BOOST_STATIC_ASSERT
+(
+    is_same< data_type_by< member_at::left, bimap<A,B> >::type, A >::value
+)
+
+\endcode
+
+See also member_at.
+\ingroup bimap_group
+                                                                    **/
+
+namespace boost {
+namespace bimaps {
+namespace support {
+
+// Implementation of data type of metafunction
+
+BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER
+(
+    data_type_by,
+    left_data_type,
+    right_data_type
+)
+
+} // namespace support
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_SUPPORT_DATA_TYPE_BY_HPP
+
diff --git a/boost/bimap/support/iterator_type_by.hpp b/boost/bimap/support/iterator_type_by.hpp
new file mode 100644 (file)
index 0000000..6d1cff3
--- /dev/null
@@ -0,0 +1,228 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file support/iterator_type_by.hpp
+/// \brief Metafunctions to access the iterator types of a bimap
+
+#ifndef BOOST_BIMAP_SUPPORT_ITERATOR_TYPE_BY_HPP
+#define BOOST_BIMAP_SUPPORT_ITERATOR_TYPE_BY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/detail/metadata_access_builder.hpp>
+#include <boost/bimap/relation/detail/static_access_builder.hpp>
+
+#include <boost/bimap/relation/support/pair_type_by.hpp>
+
+#include <boost/bimap/detail/map_view_iterator.hpp>
+
+/** \struct boost::bimaps::support::iterator_type_by
+
+\brief Metafunction to obtain the iterator type of the map view by one of the sides.
+
+\code
+
+template< class Tag, class Bimap >
+struct iterator_type_by
+{
+    typedef -unspecified- type;
+};
+
+template< class Tag, class Bimap >
+struct const_iterator_type_by
+{
+    typedef -unspecified- type;
+};
+
+template< class Tag, class Bimap >
+struct reverse_iterator_type_by
+{
+    typedef -unspecified- type;
+};
+
+template< class Tag, class Bimap >
+struct const_reverse_iterator_type_by
+{
+    typedef -unspecified- type;
+};
+
+template< class Tag, class Bimap >
+struct local_iterator_type_by
+{
+    typedef -unspecified- type;
+};
+
+template< class Tag, class Bimap >
+struct const_local_iterator_type_by
+{
+    typedef -unspecified- type;
+};
+
+\endcode
+
+See also member_at.
+\ingroup bimap_group
+                                                                    **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace support {
+
+
+// Implementation of iterator type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER
+(
+    iterator_type_by,
+    left_iterator,
+    right_iterator
+)
+
+// Implementation of const iterator type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER
+(
+    const_iterator_type_by,
+    left_const_iterator,
+    right_const_iterator
+)
+
+
+// Implementation of reverse iterator type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER
+(
+    core_reverse_iterator_type_by,
+    BimapCore,
+
+    typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE
+        index<BOOST_DEDUCED_TYPENAME BimapCore::left_tag>
+            ::type::reverse_iterator type,
+
+    typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE
+        index<BOOST_DEDUCED_TYPENAME BimapCore::right_tag>
+            ::type::reverse_iterator type
+)
+
+template< class Tag, class BimapCore >
+struct reverse_iterator_type_by
+{
+    typedef ::boost::bimaps::detail::map_view_iterator
+    <
+        Tag,
+        BOOST_DEDUCED_TYPENAME BimapCore::relation,
+        BOOST_DEDUCED_TYPENAME core_reverse_iterator_type_by<Tag,BimapCore>::type
+
+    > type;
+};
+
+// Implementation of const reverse iterator type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER
+(
+    core_const_reverse_iterator_type_by,
+    BimapCore,
+
+    typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE
+        index<BOOST_DEDUCED_TYPENAME BimapCore::left_tag>
+            ::type::const_reverse_iterator type,
+
+    typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE
+        index<BOOST_DEDUCED_TYPENAME BimapCore::right_tag>
+            ::type::const_reverse_iterator type
+)
+
+template< class Tag, class BimapCore >
+struct const_reverse_iterator_type_by
+{
+
+    typedef ::boost::bimaps::detail::map_view_iterator
+    <
+        Tag,
+        BOOST_DEDUCED_TYPENAME BimapCore::relation,
+        BOOST_DEDUCED_TYPENAME core_const_reverse_iterator_type_by<Tag,BimapCore>::type
+
+    > type;
+};
+
+
+// Implementation of local iterator type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER
+(
+    core_local_iterator_type_by,
+    BimapCore,
+
+    typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE
+        index<BOOST_DEDUCED_TYPENAME BimapCore::left_tag>
+            ::type::local_iterator type,
+
+    typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE
+        index<BOOST_DEDUCED_TYPENAME BimapCore::right_tag>
+            ::type::local_iterator type
+)
+
+
+template< class Tag, class BimapCore >
+struct local_iterator_type_by
+{
+
+    typedef ::boost::bimaps::detail::map_view_iterator
+    <
+        Tag,
+        BOOST_DEDUCED_TYPENAME BimapCore::relation,
+        BOOST_DEDUCED_TYPENAME core_local_iterator_type_by<Tag,BimapCore>::type
+
+    > type;
+};
+
+
+// Implementation of const local iterator type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER
+(
+    core_const_local_iterator_type_by,
+    BimapCore,
+
+    typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE
+        index<BOOST_DEDUCED_TYPENAME BimapCore::left_tag>
+            ::type::const_local_iterator type,
+
+    typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE
+        index<BOOST_DEDUCED_TYPENAME BimapCore::right_tag>
+            ::type::const_local_iterator type
+)
+
+template< class Tag, class BimapCore >
+struct const_local_iterator_type_by
+{
+
+    typedef ::boost::bimaps::detail::map_view_iterator
+    <
+        Tag,
+        BOOST_DEDUCED_TYPENAME BimapCore::relation,
+        BOOST_DEDUCED_TYPENAME core_const_local_iterator_type_by<Tag,BimapCore>::type
+
+    > type;
+};
+
+
+} // namespace support
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_SUPPORT_ITERATOR_TYPE_BY_HPP
+
diff --git a/boost/bimap/support/key_type_by.hpp b/boost/bimap/support/key_type_by.hpp
new file mode 100644 (file)
index 0000000..0b4abb5
--- /dev/null
@@ -0,0 +1,64 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file support/key_type_by.hpp
+/// \brief Metafunction to access the set types of a bimap
+
+#ifndef BOOST_BIMAP_SUPPORT_KEY_TYPE_BY_HPP
+#define BOOST_BIMAP_SUPPORT_KEY_TYPE_BY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/detail/metadata_access_builder.hpp>
+
+/** \struct boost::bimaps::support::key_type_by
+
+\brief Metafunction to obtain the key type of one of the sides in a bimap
+
+The tag parameter can be either a user defined tag or \c member_at::{side}.
+The returned type is one of the {SetType}_of definition classes.
+
+\code
+
+template< class Tag, class Bimap >
+struct key_type_by
+{
+    typedef typename Bimap::{side}_key_type type;
+};
+
+\endcode
+
+See also member_at.
+\ingroup bimap_group
+                                                                    **/
+
+
+namespace boost {
+namespace bimaps {
+namespace support {
+
+// Implementation of key type type of metafunction
+
+BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER
+(
+    key_type_by,
+    left_key_type,
+    right_key_type
+)
+
+
+} // namespace support
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_SUPPORT_KEY_TYPE_BY_HPP
+
diff --git a/boost/bimap/support/lambda.hpp b/boost/bimap/support/lambda.hpp
new file mode 100644 (file)
index 0000000..cffa2c3
--- /dev/null
@@ -0,0 +1,46 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file support/lambda.hpp
+/// \brief Placeholders definition to help in bimap modify function
+
+#ifndef BOOST_BIMAP_SUPPORT_LAMBDA_HPP
+#define BOOST_BIMAP_SUPPORT_LAMBDA_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/lambda/lambda.hpp>
+
+namespace boost {
+namespace bimaps {
+
+namespace {
+
+/*
+boost::lambda::placeholder1_type & _first  = boost::lambda::_1;
+boost::lambda::placeholder2_type & _second = boost::lambda::_2;
+
+boost::lambda::placeholder1_type & _left   = boost::lambda::_1;
+boost::lambda::placeholder2_type & _right  = boost::lambda::_2;
+*/
+
+boost::lambda::placeholder1_type & _key  = boost::lambda::_1;
+boost::lambda::placeholder1_type & _data = boost::lambda::_1;
+
+}
+
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_SUPPORT_LAMBDA_HPP
+
diff --git a/boost/bimap/support/map_by.hpp b/boost/bimap/support/map_by.hpp
new file mode 100644 (file)
index 0000000..ac57f1b
--- /dev/null
@@ -0,0 +1,132 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file support/map_by.hpp
+/// \brief map_by<tag>(b) function
+
+#ifndef BOOST_BIMAP_SUPPORT_MAP_BY_HPP
+#define BOOST_BIMAP_SUPPORT_MAP_BY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/support/map_type_by.hpp>
+#include <boost/bimap/relation/detail/access_builder.hpp>
+
+
+#ifdef BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace support {
+
+/** \brief Gets a map view of a bidirectional map
+
+Convertible to \c map_type_by<Tag,Bimap>::type
+Instead of using \c map_type_by<Tag,Bimap>::type this functions use
+\b Boost.call_traits to find the best way to return this value. To help
+the user of this function the following metafunction is provided
+\code
+
+namespace result_of {
+
+template< class Tag, class Bimap >
+struct map_by( Bimap & b );
+
+} // namespace result_of
+
+\endcode
+
+See also member_at, value_type_of.
+\ingroup bimap_group
+                                                                        **/
+
+template< class Tag, class Bimap >
+BOOST_DEDUCED_TYPENAME result_of::map_by<Tag,Bimap>::type
+    map_by( Bimap & b );
+
+} // namespace support
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES
+
+
+
+#ifndef BOOST_BIMAP_DOXIGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace support {
+
+// Since it is very error-prone to directly write the hole bunch
+// of relation accesor. They are buil from litle macro blocks that
+// are both more readable, leading to self docummenting code and a
+// lot more easier to understand and mantain.
+// It is very important to note that the three building blocks have
+// to laid in the same namespace in order to work. There is also
+// important to keep them in order.
+// The forward declaration are not necesary but they help a lot to
+// the reader, as they undercover what is the signature of the
+// result code.
+// In the end, it is not quicker to do it in this way because you
+// write a lot. But this code has no complexity at all and almost
+// every word writed is for documentation.
+
+// Result of
+// -------------------------------------------------------------------------
+/*
+    namespace result_of {
+
+    template< class Tag, class Bimap >
+    struct map_by<Tag,Bimap>;
+    {
+        typedef -unspecified- type;
+    };
+
+    } // namespace result_of
+
+*/
+
+BOOST_BIMAP_SYMMETRIC_ACCESS_RESULT_OF_BUILDER
+(
+    map_by,
+    map_type_by
+)
+
+// Implementation
+// -------------------------------------------------------------------------
+
+BOOST_BIMAP_SYMMETRIC_ACCESS_IMPLEMENTATION_BUILDER
+(
+    map_by,
+    Bimap,
+    b,
+    return b.left,
+    return b.right
+)
+
+// Interface
+// --------------------------------------------------------------------------
+
+BOOST_BIMAP_SYMMETRIC_ACCESS_INTERFACE_BUILDER
+(
+    map_by
+)
+
+} // namespace support
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXIGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_SUPPORT_MAP_BY_HPP
+
diff --git a/boost/bimap/support/map_type_by.hpp b/boost/bimap/support/map_type_by.hpp
new file mode 100644 (file)
index 0000000..00b4d20
--- /dev/null
@@ -0,0 +1,65 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file support/map_type_by.hpp
+/// \brief Metafunction to access the map view types of a bimap
+
+#ifndef BOOST_BIMAP_SUPPORT_MAP_TYPE_BY_HPP
+#define BOOST_BIMAP_SUPPORT_MAP_TYPE_BY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/detail/metadata_access_builder.hpp>
+
+/** \struct boost::bimaps::support::map_type_by
+
+\brief Metafunction to obtain the map view type of a bimap indexed by one of the sides.
+
+The tag parameter can be either a user defined tag or \c member_at::{side}.
+The returned type is signature-compatible with std::pair.
+
+\code
+
+template< class Tag, class Bimap >
+struct map_type_by
+{
+    typedef typename Bimap::{side}_map_type type;
+};
+
+\endcode
+
+See also member_at.
+\ingroup bimap_group
+                                                                    **/
+
+namespace boost {
+namespace bimaps {
+namespace support {
+
+// Implementation of map type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER
+(
+    map_type_by,
+    left_map,
+    right_map
+)
+
+
+
+} // namespace support
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_SUPPORT_MAP_TYPE_BY_HPP
+
diff --git a/boost/bimap/support/value_type_by.hpp b/boost/bimap/support/value_type_by.hpp
new file mode 100644 (file)
index 0000000..a7ce6c0
--- /dev/null
@@ -0,0 +1,65 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file support/value_type_by.hpp
+/// \brief Metafunction to access the value types (std::pair compatibles) of a bimap
+
+#ifndef BOOST_BIMAP_SUPPORT_VALUE_TYPE_BY_HPP
+#define BOOST_BIMAP_SUPPORT_VALUE_TYPE_BY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/relation/detail/metadata_access_builder.hpp>
+
+/** \struct boost::bimaps::support::value_type_by
+
+\brief Metafunction to obtain the value type of a bimap indexed by one of the sides.
+
+The tag parameter can be either a user defined tag or \c member_at::{side}.
+The returned type is signature-compatible with std::pair.
+
+\code
+
+template< class Tag, class Bimap >
+struct value_type_by
+{
+    typedef typename Bimap::{side}_value_type type;
+};
+
+\endcode
+
+See also member_at.
+\ingroup bimap_group
+                                                                    **/
+
+namespace boost {
+namespace bimaps {
+namespace support {
+
+// Implementation of value type by metafunction
+
+BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER
+(
+    value_type_by,
+    left_value_type,
+    right_value_type
+)
+
+
+
+} // namespace support
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_SUPPORT_VALUE_TYPE_BY_HPP
+
diff --git a/boost/bimap/tags/support/apply_to_value_type.hpp b/boost/bimap/tags/support/apply_to_value_type.hpp
new file mode 100644 (file)
index 0000000..bb6aa60
--- /dev/null
@@ -0,0 +1,70 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file tags/support/apply_to_value_type.hpp
+/// \brief Similar to mpl::apply but for tagged types.
+
+#ifndef BOOST_BIMAP_TAGS_SUPPORT_APPLY_TO_VALUE_TYPE_HPP
+#define BOOST_BIMAP_TAGS_SUPPORT_APPLY_TO_VALUE_TYPE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/tags/tagged.hpp>
+#include <boost/mpl/apply.hpp>
+
+/** \struct boost::bimaps::tags::support::apply_to_value_type
+\brief Higger order metafunction similar to mpl::apply but for tagged types.
+
+\code
+template< class Metafunction, class TaggedType >
+struct apply_to_value_type
+{
+    typedef tagged
+    <
+        Metafuntion< value_type_of< TaggedType >::type >::type,
+        tag_of< TaggedType >::type
+
+    > type;
+};
+\endcode
+
+This higher order metafunctions is very useful, and it can be used with lambda
+expresions.
+
+See also tagged.
+                                                                                **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace tags {
+namespace support {
+
+template < class F, class TaggedType >
+struct apply_to_value_type;
+
+template < class F, class ValueType, class Tag >
+struct apply_to_value_type<F, tagged<ValueType,Tag> >
+{
+    typedef BOOST_DEDUCED_TYPENAME mpl::apply< F, ValueType >::type new_value_type;
+    typedef tagged< new_value_type, Tag > type;
+};
+
+} // namespace support
+} // namespace tags
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_TAGS_SUPPORT_APPLY_TO_VALUE_TYPE_HPP
diff --git a/boost/bimap/tags/support/default_tagged.hpp b/boost/bimap/tags/support/default_tagged.hpp
new file mode 100644 (file)
index 0000000..4c02a65
--- /dev/null
@@ -0,0 +1,73 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file tags/support/default_tagged.hpp
+/// \brief Weak tagging
+
+#ifndef BOOST_BIMAP_TAGS_SUPPORT_DEFAULT_TAGGED_HPP
+#define BOOST_BIMAP_TAGS_SUPPORT_DEFAULT_TAGGED_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/tags/tagged.hpp>
+
+/** \struct boost::bimaps::tags::support::default_tagged
+\brief Weak tagging metafunction
+
+\code
+template< class Type, class Tag >
+struct default_tagged
+{
+    typedef {TaggedType} type;
+};
+\endcode
+
+If the type is not tagged, this metafunction returns a tagged type with the
+default tag. If it is tagged, the returns the type unchanged.
+
+See also tagged, overwrite_tagged.
+                                                                                **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace tags {
+namespace support {
+
+
+// Default Tagging
+// A metafunction that create a tagged type with a default tag value.
+
+template< class Type, class DefaultTag >
+struct default_tagged
+{
+    typedef tagged<Type,DefaultTag> type;
+};
+
+template< class Type, class OldTag, class NewTag >
+struct default_tagged< tagged< Type, OldTag >, NewTag >
+{
+    typedef tagged<Type,OldTag> type;
+};
+
+} // namespace support
+} // namespace tags
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_TAGS_SUPPORT_DEFAULT_TAGGED_HPP
+
+
+
diff --git a/boost/bimap/tags/support/is_tagged.hpp b/boost/bimap/tags/support/is_tagged.hpp
new file mode 100644 (file)
index 0000000..892b3b1
--- /dev/null
@@ -0,0 +1,64 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file tags/support/is_tagged.hpp
+/// \brief type_traits extension
+
+#ifndef BOOST_BIMAP_TAGS_SUPPORT_IS_TAGGED_HPP
+#define BOOST_BIMAP_TAGS_SUPPORT_IS_TAGGED_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/mpl/bool.hpp>
+#include <boost/bimap/tags/tagged.hpp>
+
+/** \struct boost::bimaps::tags::support::is_tagged
+\brief Type trait to check if a type is tagged.
+
+\code
+template< class Type >
+struct is_tagged
+{
+    typedef {mpl::true_/mpl::false_} type;
+};
+\endcode
+
+See also tagged.
+                                                                                **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace tags {
+namespace support {
+
+
+// is_tagged metafunction
+
+template< class Type >
+struct is_tagged :
+    ::boost::mpl::false_ {};
+
+template< class Type, class Tag >
+struct is_tagged< tagged< Type, Tag > > :
+    ::boost::mpl::true_ {};
+
+} // namespace support
+} // namespace tags
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_TAGS_SUPPORT_IS_TAGGED_HPP
+
diff --git a/boost/bimap/tags/support/overwrite_tagged.hpp b/boost/bimap/tags/support/overwrite_tagged.hpp
new file mode 100644 (file)
index 0000000..55cd0fc
--- /dev/null
@@ -0,0 +1,73 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file tags/support/overwrite_tagged.hpp
+/// \brief Hard tagging
+
+#ifndef BOOST_BIMAP_TAGS_SUPPORT_OVERWRITE_TAGGED_HPP
+#define BOOST_BIMAP_TAGS_SUPPORT_OVERWRITE_TAGGED_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/tags/tagged.hpp>
+
+/** \struct boost::bimaps::tags::support::overwrite_tagged
+\brief Hard tagging metafunction
+
+\code
+template< class Type, class Tag >
+struct overwrite_tagged
+{
+    typedef {TaggedType} type;
+};
+\endcode
+
+If the type is not tagged, this metafunction returns a tagged type with the
+passed tag. If it is tagged it returns a new tagged type with the tag replaced
+by the one passed as a parameter.
+
+See also tagged, default_tagged.
+                                                                                **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace tags {
+namespace support {
+
+
+// Change the tag
+
+template< class Type, class NewTag >
+struct overwrite_tagged
+{
+    typedef tagged<Type,NewTag> type;
+};
+
+template< class Type, class OldTag, class NewTag >
+struct overwrite_tagged< tagged< Type, OldTag >, NewTag >
+{
+    typedef tagged<Type,NewTag> type;
+};
+
+
+} // namespace support
+} // namespace tags
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_TAGS_SUPPORT_OVERWRITE_TAGGED_HPP
+
+
diff --git a/boost/bimap/tags/support/tag_of.hpp b/boost/bimap/tags/support/tag_of.hpp
new file mode 100644 (file)
index 0000000..413703b
--- /dev/null
@@ -0,0 +1,75 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file tags/support/tag_of.hpp
+/// \brief Safe way to acces the tag of a type
+
+#ifndef BOOST_BIMAP_TAGS_SUPPORT_TAG_OF_HPP
+#define BOOST_BIMAP_TAGS_SUPPORT_TAG_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/tags/tagged.hpp>
+#include <boost/bimap/detail/debug/static_error.hpp>
+
+/** \struct boost::bimaps::tags::support::tag_of
+\brief Metafunction to obtain the tag of a type.
+
+\code
+template< class TaggedType >
+struct tag_of
+{
+    typedef {Tag} type;
+};
+\endcode
+
+If the type is not tagged you will get a compile timer error with the following message:
+
+\verbatim
+USING_TAG_OF_WITH_AN_UNTAGGED_TYPE, TaggedType
+\endverbatim
+
+See also tagged, value_type_of.
+                                                                                **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace boost {
+namespace bimaps {
+namespace tags {
+namespace support {
+
+
+// tag_of metafunction
+
+template< class Type >
+struct tag_of
+{
+    BOOST_BIMAP_STATIC_ERROR( USING_TAG_OF_WITH_AN_UNTAGGED_TYPE, (Type) );
+};
+
+template< class Type, class Tag >
+struct tag_of< tagged< Type, Tag > >
+{
+    typedef Tag type;
+};
+
+
+} // namespace support
+} // namespace tags
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_TAGS_SUPPORT_TAG_OF_HPP
+
diff --git a/boost/bimap/tags/support/value_type_of.hpp b/boost/bimap/tags/support/value_type_of.hpp
new file mode 100644 (file)
index 0000000..a4ea828
--- /dev/null
@@ -0,0 +1,74 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file tags/support/value_type_of.hpp
+/// \brief Consistent way to access the value type of a tagged or untagged type.
+
+#ifndef BOOST_BIMAP_TAGS_SUPPORT_VALUE_TYPE_OF_HPP
+#define BOOST_BIMAP_TAGS_SUPPORT_VALUE_TYPE_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/tags/tagged.hpp>
+
+/** \struct boost::bimaps::tags::support::value_type_of
+\brief Metafunction to work with tagged and untagged type uniformly
+
+\code
+template< class Type >
+struct value_type_of
+{
+    typedef {UntaggedType} type;
+};
+\endcode
+
+If the type is tagged this metafunction returns Type::value_type, and if it is not
+tagged it return the same type. This allows to work consistenly with tagged and
+untagged types.
+
+See also tagged, tag_of.
+                                                                                **/
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+
+namespace boost {
+namespace bimaps {
+namespace tags {
+namespace support {
+
+
+// value_type_of metafunction
+
+template< class Type >
+struct value_type_of
+{
+    typedef Type type;
+};
+
+template< class Type, class Tag >
+struct value_type_of< tagged< Type, Tag > >
+{
+    typedef Type type;
+};
+
+
+} // namespace support
+} // namespace tags
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+#endif // BOOST_BIMAP_TAGS_SUPPORT_VALUE_TYPE_OF_HPP
+
+
diff --git a/boost/bimap/tags/tagged.hpp b/boost/bimap/tags/tagged.hpp
new file mode 100644 (file)
index 0000000..ca2a24c
--- /dev/null
@@ -0,0 +1,107 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file tags/tagged.hpp
+/// \brief Defines the tagged class
+
+#ifndef BOOST_BIMAP_TAGS_TAGGED_HPP
+#define BOOST_BIMAP_TAGS_TAGGED_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+namespace boost {
+namespace bimaps {
+
+/// \brief A light non-invasive idiom to tag a type.
+/**
+
+There are a lot of ways of tagging a type. The standard library for example
+defines tags (empty structs) that are then inherited by the tagged class. To
+support built-in types and other types that simple cannot inherit from the
+tag, the standard builds another level of indirection. An example of this is
+the type_traits metafunction. This approach is useful if the tags are intended
+to be used in the library internals, and if the user does not have to create
+new tagged types often.
+
+Boost.MultiIndex is an example of a library that defines a tagged idiom that
+is better suited to the user. As an option, in the indexed by declaration
+of a multi-index container a user can \b attach a tag to each index, so it
+can be referred by it instead of by the index number. It is a very user
+friendly way of specifying a tag but is very invasive from the library writer's
+point of view. Each index must now support this additional parameter. Maybe
+not in the case of the multi-index container, but in simpler classes
+the information of the tags is used by the father class rather than by the
+tagged types.
+
+\b tagged is a light non-invasive idiom to tag a type. It is very intuitive
+and user-friendly. With the use of the defined metafunctions the library
+writer can enjoy the coding too.
+
+                                                                            **/
+
+namespace tags {
+
+/// \brief The tag holder
+/**
+
+The idea is to add a level of indirection to the type being tagged. With this
+class you wrapped a type and apply a tag to it. The only thing to remember is
+that if you write
+
+\code
+typedef tagged<type,tag> taggedType;
+\endcode
+
+Then instead to use directly the tagged type, in order to access it you have
+to write \c taggedType::value_type. The tag can be obtained using \c taggedType::tag.
+The idea is not to use this metadata directly but rather using the metafunctions
+that are defined in the support namespace. With this metafunctions you can work
+with tagged and untagged types in a consistent way. For example, the following
+code is valid:
+
+\code
+BOOST_STATIC_ASSERT( is_same< value_type_of<taggedType>, value_type_of<type> >::value );
+\endcode
+
+The are other useful metafunctions there too.
+See also value_type_of, tag_of, is_tagged, apply_to_value_type.
+
+\ingroup tagged_group
+                                                                                    **/
+template< class Type, class Tag >
+struct tagged
+{
+    typedef Type value_type;
+    typedef Tag tag;
+};
+
+} // namespace tags
+} // namespace bimaps
+} // namespace boost
+
+/** \namespace boost::bimaps::tags::support
+\brief Metafunctions to work with tagged types.
+
+This metafunctions aims to make easier the manage of tagged types. They are all mpl
+compatible metafunctions and can be used with lambda expresions.
+The metafunction value_type_of and tag_of get the data in a tagged type in a secure
+and consistent way.
+default_tagged and overwrite_tagged allows to work with the tag of a tagged type,
+and apply_to_value_type is a higher order metafunction that allow the user to change
+the type of a TaggedType.
+                                                                                    **/
+
+#endif // BOOST_BIMAP_TAGS_TAGGED_HPP
+
+
+
+
diff --git a/boost/bimap/unconstrained_set_of.hpp b/boost/bimap/unconstrained_set_of.hpp
new file mode 100644 (file)
index 0000000..a2aa241
--- /dev/null
@@ -0,0 +1,150 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file unconstrained_set_of.hpp
+/// \brief Include support for set constrains for the bimap container
+
+#ifndef BOOST_BIMAP_UNCONSTRAINED_SET_OF_HPP
+#define BOOST_BIMAP_UNCONSTRAINED_SET_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/detail/user_interface_config.hpp>
+
+#include <boost/mpl/bool.hpp>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/bimap/detail/concept_tags.hpp>
+
+#include <boost/bimap/tags/support/value_type_of.hpp>
+
+#include <boost/bimap/detail/generate_index_binder.hpp>
+#include <boost/bimap/detail/generate_view_binder.hpp>
+#include <boost/bimap/detail/generate_relation_binder.hpp>
+
+#include <boost/bimap/views/unconstrained_map_view.hpp>
+#include <boost/bimap/views/unconstrained_set_view.hpp>
+
+namespace boost {
+namespace bimaps {
+
+/// \brief Set Type Specification
+/**
+This struct is used to specify a set specification.
+It is not a container, it is just a metaprogramming facility to
+express the type of a set. Generally, this specification will
+be used in other place to create a container.
+The first parameter is the type of the objects in the set.
+
+\code
+
+using namespace support;
+
+BOOST_STATIC_ASSERT( is_set_type_of< unconstrained_set_of<Type> >::value )
+
+\endcode
+
+See also unconstrained_set_of_relation.
+                                                                        **/
+
+template
+<
+    class KeyType
+>
+struct unconstrained_set_of : public ::boost::bimaps::detail::set_type_of_tag
+{
+    /// User type, can be tagged
+    typedef KeyType user_type;
+
+    /// Type of the object that will be stored in the container
+       typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
+               value_type_of<user_type>::type value_type;
+
+    struct lazy_concept_checked
+    {
+        BOOST_CLASS_REQUIRE ( value_type,
+                              boost, AssignableConcept );
+
+        typedef unconstrained_set_of type;
+    };
+
+    BOOST_BIMAP_GENERATE_INDEX_BINDER_FAKE
+
+    BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER(
+
+        // binds to
+        views::unconstrained_map_view
+    )
+
+    BOOST_BIMAP_GENERATE_SET_VIEW_BINDER(
+
+        // binds to
+        views::unconstrained_set_view
+    )
+
+    typedef mpl::bool_<true> mutable_key;
+};
+
+/// \brief Set Of Relation Specification
+/**
+This struct is similar to unconstrained_set_of but it is bind
+logically to a relation. It is used in the bimap instantiation to
+specify the desired type of the main view.
+
+See also unconstrained_set_of, is_set_type_of_relation.
+                                                                **/
+
+struct unconstrained_set_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag
+{
+
+    BOOST_BIMAP_GENERATE_RELATION_BINDER_0CP(
+
+        // binds to
+        unconstrained_set_of
+    )
+
+    typedef mpl::bool_<true>  left_mutable_key;
+    typedef mpl::bool_<true> right_mutable_key;
+};
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+namespace detail {
+
+template<class T>
+struct is_unconstrained_set_of :
+    ::boost::mpl::false_ {};
+
+template<class T>
+struct is_unconstrained_set_of< unconstrained_set_of<T> > :
+    ::boost::mpl::true_ {};
+
+} // namespace detail
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+} // namespace bimaps
+} // namespace boost
+
+
+/** \struct boost::bimaps::detail::is_unconstrained_set_of
+\brief Trait to check if a type is unconstrained_set_of.
+\code
+template< class T >
+struct is_unconstrained_set_of;
+\endcode
+                                                                            **/
+
+
+#endif // BOOST_BIMAP_UNCONSTRAINED_SET_OF_HPP
+
diff --git a/boost/bimap/unordered_multiset_of.hpp b/boost/bimap/unordered_multiset_of.hpp
new file mode 100644 (file)
index 0000000..c41f202
--- /dev/null
@@ -0,0 +1,233 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file unordered_multiset_of.hpp
+/// \brief Include support for unordered_multiset constrains for the bimap container
+
+#ifndef BOOST_BIMAP_UNORDERED_MULTISET_OF_HPP
+#define BOOST_BIMAP_UNORDERED_MULTISET_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/detail/user_interface_config.hpp>
+
+#include <cstdlib>
+#include <functional>
+#include <boost/functional/hash.hpp>
+#include <boost/mpl/bool.hpp>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/bimap/detail/concept_tags.hpp>
+
+#include <boost/bimap/tags/support/value_type_of.hpp>
+
+#include <boost/bimap/detail/generate_index_binder.hpp>
+#include <boost/bimap/detail/generate_view_binder.hpp>
+#include <boost/bimap/detail/generate_relation_binder.hpp>
+
+#include <boost/multi_index/hashed_index.hpp>
+
+#include <boost/bimap/views/unordered_multimap_view.hpp>
+#include <boost/bimap/views/unordered_multiset_view.hpp>
+
+namespace boost {
+namespace bimaps {
+
+
+/// \brief Set Type Specification
+/**
+This struct is used to specify an unordered_multiset specification.
+It is not a container, it is just a metaprogramming facility to
+express the type of a set. Generally, this specification will
+be used in other place to create a container.
+It has the same syntax that an tr1::unordered_multiset instantiation,
+except that the allocator cannot be specified. The rationale behind
+this difference is that the allocator is not part of the
+unordered_multiset type specification, rather it is a container
+configuration parameter.
+The first parameter is the type of the objects in the set, the
+second one is a Hash Functor that takes objects of this type, and
+the third one is a Functor that compares them for equality.
+Bimap binding metafunctions can be used with this class in
+the following way:
+
+\code
+using namespace support;
+
+BOOST_STATIC_ASSERT( is_set_type_of< unordered_multiset_of<Type> >::value )
+
+BOOST_STATIC_ASSERT
+(
+     is_same
+     <
+        compute_index_type
+        <
+            unordered_multiset_of<Type,HashFunctor,EqualKey>,
+            KeyExtractor,
+            Tag
+
+        >::type
+        ,
+        hashed_nonunique< tag<Tag>, KeyExtractor, HashFunctor, EqualKey >
+
+    >::value
+)
+
+typedef bimap
+<
+    unordered_multiset_of<Type>, RightKeyType
+
+> bimap_with_left_type_as_unordered_multiset;
+
+BOOST_STATIC_ASSERT
+(
+    is_same
+    <
+        compute_map_view_type
+        <
+            member_at::left,
+            bimap_with_left_type_as_unordered_multiset
+
+        >::type,
+
+        unordered_multimap_view
+        <
+            member_at::left,
+            bimap_with_left_type_as_unordered_multiset
+        >
+
+    >::value
+)
+
+\endcode
+
+See also unordered_multiset_of_relation.
+                                                                        **/
+
+template
+<
+    class KeyType,
+    class HashFunctor   = hash< BOOST_DEDUCED_TYPENAME 
+               ::boost::bimaps::tags::support::value_type_of<KeyType>::type >,
+    class EqualKey      = std::equal_to< BOOST_DEDUCED_TYPENAME 
+               ::boost::bimaps::tags::support::value_type_of<KeyType>::type >
+>
+struct unordered_multiset_of : public ::boost::bimaps::detail::set_type_of_tag
+{
+    /// User type, can be tagged
+    typedef KeyType user_type;
+
+    /// Type of the object that will be stored in the container
+       typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
+               value_type_of<user_type>::type value_type;
+
+    /// Hash Functor that takes value_type objects
+    typedef HashFunctor     hasher;
+
+    /// Functor that compare two value_type objects for equality
+    typedef EqualKey        key_equal;
+
+    struct lazy_concept_checked
+    {
+        BOOST_CLASS_REQUIRE ( value_type,
+                              boost, AssignableConcept );
+
+        BOOST_CLASS_REQUIRE3( hasher, std::size_t, value_type,
+                              boost, UnaryFunctionConcept );
+
+        BOOST_CLASS_REQUIRE4( key_equal, bool, value_type, value_type,
+                              boost, BinaryFunctionConcept );
+
+        typedef unordered_multiset_of type;
+    };
+
+    BOOST_BIMAP_GENERATE_INDEX_BINDER_2CP(
+
+        // binds to
+        multi_index::hashed_non_unique,
+
+        // with
+        hasher,
+        key_equal
+    )
+
+    BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER(
+
+        // binds to
+        views::unordered_multimap_view
+    )
+
+    BOOST_BIMAP_GENERATE_SET_VIEW_BINDER(
+
+        // binds to
+        views::unordered_multiset_view
+    )
+
+    typedef mpl::bool_<false> mutable_key;
+};
+
+
+/// \brief Set Of Relation Specification
+/**
+This struct is similar to unordered_multiset_of but it is bind logically
+to a relation. It is used in the bimap instantiation to specify the
+desired type of the main view. This struct implements internally
+a metafunction named bind_to that manages the quite complicated
+task of finding the right type of the set for the relation.
+
+\code
+template<class Relation>
+struct bind_to
+{
+    typedef -unspecified- type;
+};
+\endcode
+
+See also unordered_multiset_of, is_set_type_of_relation.
+                                                                **/
+
+template
+<
+    class HashFunctor   = hash< _relation >,
+    class EqualKey      = std::equal_to< _relation >
+>
+struct unordered_multiset_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag
+{
+    /// Hash Functor that takes value_type objects
+    typedef HashFunctor     hasher;
+
+    /// Functor that compare two value_type objects for equality
+    typedef EqualKey        key_equal;
+
+
+    BOOST_BIMAP_GENERATE_RELATION_BINDER_2CP(
+
+        // binds to
+        unordered_multiset_of,
+
+        // with
+        hasher,
+        key_equal
+    )
+
+    typedef mpl::bool_<false>  left_mutable_key;
+    typedef mpl::bool_<false> right_mutable_key;
+};
+
+
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_UNORDERED_MULTISET_OF_HPP
+
diff --git a/boost/bimap/unordered_set_of.hpp b/boost/bimap/unordered_set_of.hpp
new file mode 100644 (file)
index 0000000..e39c231
--- /dev/null
@@ -0,0 +1,230 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file unordered_set_of.hpp
+/// \brief Include support for unordered_set constrains for the bimap container
+
+#ifndef BOOST_BIMAP_UNORDERED_SET_OF_HPP
+#define BOOST_BIMAP_UNORDERED_SET_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/detail/user_interface_config.hpp>
+
+#include <functional>
+#include <boost/functional/hash.hpp>
+#include <boost/mpl/bool.hpp>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/bimap/detail/concept_tags.hpp>
+
+#include <boost/bimap/tags/support/value_type_of.hpp>
+
+#include <boost/bimap/detail/generate_index_binder.hpp>
+#include <boost/bimap/detail/generate_view_binder.hpp>
+#include <boost/bimap/detail/generate_relation_binder.hpp>
+
+#include <boost/multi_index/hashed_index.hpp>
+
+#include <boost/bimap/views/unordered_map_view.hpp>
+#include <boost/bimap/views/unordered_set_view.hpp>
+
+namespace boost {
+namespace bimaps {
+
+/// \brief Set Type Specification
+/**
+This struct is used to specify an unordered_set specification.
+It is not a container, it is just a metaprogramming facility to
+express the type of a set. Generally, this specification will
+be used in other place to create a container.
+It has the same syntax that an tr1::unordered_set instantiation,
+except that the allocator cannot be specified. The rationale behind
+this difference is that the allocator is not part of the
+unordered_set type specification, rather it is a container
+configuration parameter.
+The first parameter is the type of the objects in the set, the
+second one is a Hash Functor that takes objects of this type, and
+the third one is a Functor that compares them for equality.
+Bimap binding metafunctions can be used with this class in
+the following way:
+
+\code
+using namespace support;
+
+BOOST_STATIC_ASSERT( is_set_type_of< unordered_set_of<Type> >::value )
+
+BOOST_STATIC_ASSERT
+(
+     is_same
+     <
+        unordered_set_of<Type,HashFunctor,EqualKey>::index_bind
+        <
+            KeyExtractor,
+            Tag
+
+        >::type,
+
+        hashed_unique< tag<Tag>, KeyExtractor, HashFunctor, EqualKey >
+
+    >::value
+)
+
+typedef bimap
+<
+    unordered_set_of<Type>, RightKeyType
+
+> bimap_with_left_type_as_unordered_set;
+
+BOOST_STATIC_ASSERT
+(
+    is_same
+    <
+        unordered_set_of<Type>::map_view_bind
+        <
+            member_at::left,
+            bimap_with_left_type_as_unordered_set
+
+        >::type,
+
+        unordered_map_view
+        <
+            member_at::left,
+            bimap_with_left_type_as_unordered_set
+        >
+
+    >::value
+)
+
+\endcode
+
+See also unordered_set_of_relation.
+                                                                        **/
+
+template
+<
+    class KeyType,
+    class HashFunctor   = hash< BOOST_DEDUCED_TYPENAME 
+               ::boost::bimaps::tags::support::value_type_of<KeyType>::type >,
+    class EqualKey      = std::equal_to< BOOST_DEDUCED_TYPENAME 
+               ::boost::bimaps::tags::support::value_type_of<KeyType>::type >
+>
+struct unordered_set_of : public ::boost::bimaps::detail::set_type_of_tag
+{
+    /// User type, can be tagged
+    typedef KeyType user_type;
+
+    /// Type of the object that will be stored in the container
+       typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
+               value_type_of<user_type>::type value_type;
+
+    /// Hash Functor that takes value_type objects
+    typedef HashFunctor     hasher;
+
+    /// Functor that compare two value_type objects for equality
+    typedef EqualKey        key_equal;
+
+    struct lazy_concept_checked
+    {
+        BOOST_CLASS_REQUIRE ( value_type,
+                              boost, AssignableConcept );
+
+        BOOST_CLASS_REQUIRE3( hasher, std::size_t, value_type,
+                              boost, UnaryFunctionConcept );
+
+        BOOST_CLASS_REQUIRE4( key_equal, bool, value_type, value_type,
+                              boost, BinaryFunctionConcept );
+
+        typedef unordered_set_of type; 
+    };
+
+    BOOST_BIMAP_GENERATE_INDEX_BINDER_2CP(
+
+        // binds to
+        multi_index::hashed_unique,
+
+        // with
+        hasher,
+        key_equal
+    )
+
+    BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER(
+
+        // binds to
+        views::unordered_map_view
+    )
+
+    BOOST_BIMAP_GENERATE_SET_VIEW_BINDER(
+
+        // binds to
+        views::unordered_set_view
+    )
+
+    typedef mpl::bool_<false> mutable_key;
+};
+
+
+/// \brief Set Of Relation Specification
+/**
+This struct is similar to unordered_set_of but it is bind logically to
+a relation. It is used in the bimap instantiation to specify the
+desired type of the main view. This struct implements internally
+a metafunction named bind_to that manages the quite complicated
+task of finding the right type of the set for the relation.
+
+\code
+template<class Relation>
+struct bind_to
+{
+    typedef -unspecified- type;
+};
+\endcode
+
+See also unordered_set_of, is_set_type_of_relation.
+                                                                **/
+
+template
+<
+    class HashFunctor   = hash< _relation >,
+    class EqualKey      = std::equal_to< _relation >
+>
+struct unordered_set_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag
+{
+    /// Hash Functor that takes value_type objects
+    typedef HashFunctor     hasher;
+
+    /// Functor that compare two value_type objects for equality
+    typedef EqualKey        key_equal;
+
+
+    BOOST_BIMAP_GENERATE_RELATION_BINDER_2CP(
+
+        // binds to
+        unordered_set_of,
+
+        // with
+        hasher,
+        key_equal
+    )
+
+    typedef mpl::bool_<false>  left_mutable_key;
+    typedef mpl::bool_<false> right_mutable_key;
+};
+
+
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_UNORDERED_SET_OF_HPP
+
diff --git a/boost/bimap/vector_of.hpp b/boost/bimap/vector_of.hpp
new file mode 100644 (file)
index 0000000..28e01ba
--- /dev/null
@@ -0,0 +1,186 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file vector_of.hpp
+/// \brief Include support for vector constrains for the bimap container
+
+#ifndef BOOST_BIMAP_VECTOR_OF_HPP
+#define BOOST_BIMAP_VECTOR_OF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/detail/user_interface_config.hpp>
+
+#include <boost/mpl/bool.hpp>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/bimap/detail/concept_tags.hpp>
+
+#include <boost/bimap/tags/support/value_type_of.hpp>
+
+#include <boost/bimap/detail/generate_index_binder.hpp>
+#include <boost/bimap/detail/generate_view_binder.hpp>
+#include <boost/bimap/detail/generate_relation_binder.hpp>
+
+#include <boost/multi_index/random_access_index.hpp>
+
+#include <boost/bimap/views/vector_map_view.hpp>
+#include <boost/bimap/views/vector_set_view.hpp>
+
+namespace boost {
+namespace bimaps {
+
+
+/// \brief Set Type Specification
+/**
+This struct is used to specify a set specification.
+It is not a container, it is just a metaprogramming facility to
+express the type of a set. Generally, this specification will
+be used in other place to create a container.
+It has the same syntax that an std::vector instantiation, except
+that the allocator cannot be specified. The rationale behind
+this difference is that the allocator is not part of the set
+type specification, rather it is a container configuration
+parameter.
+The first parameter is the type of the objects in the set, and
+the second one is a Functor that compares them.
+Bimap binding metafunctions can be used with this class in
+the following way:
+
+\code
+using namespace support;
+
+BOOST_STATIC_ASSERT( is_set_type_of< vector_of<Type> >::value )
+
+BOOST_STATIC_ASSERT
+(
+     is_same
+     <
+        vector_of<Type>::index_bind
+        <
+            KeyExtractor,
+            Tag
+
+        >::type,
+
+        random_access< tag<Tag>, KeyExtractor >
+
+    >::value
+)
+
+typedef bimap
+<
+    vector_of<Type>, RightKeyType
+
+> bimap_with_left_type_as_vector;
+
+BOOST_STATIC_ASSERT
+(
+    is_same
+    <
+        vector_of<Type>::map_view_bind
+        <
+            member_at::left,
+            bimap_with_left_type_as_vector
+
+        >::type,
+
+        vector_map_view< member_at::left, bimap_with_left_type_as_vector >
+
+    >::value
+)
+
+\endcode
+
+See also vector_of_relation.
+                                                                        **/
+
+template< class Type >
+struct vector_of : public ::boost::bimaps::detail::set_type_of_tag
+{
+    /// User type, can be tagged
+    typedef Type user_type;
+
+    /// Type of the object that will be stored in the vector
+       typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
+               value_type_of<user_type>::type value_type;
+
+
+    struct lazy_concept_checked
+    {
+        BOOST_CLASS_REQUIRE ( value_type,
+                              boost, AssignableConcept );
+
+        typedef vector_of type;
+    };
+
+    BOOST_BIMAP_GENERATE_INDEX_BINDER_0CP_NO_EXTRACTOR(
+
+        // binds to
+        multi_index::random_access
+    )
+
+    BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER(
+
+        // binds to
+        views::vector_map_view
+    )
+
+    BOOST_BIMAP_GENERATE_SET_VIEW_BINDER(
+
+        // binds to
+        views::vector_set_view
+    )
+
+    typedef mpl::bool_<true> mutable_key;
+};
+
+
+/// \brief Set Of Relation Specification
+/**
+This struct is similar to vector_of but it is bind logically to a
+relation. It is used in the bimap instantiation to specify the
+desired type of the main view. This struct implements internally
+a metafunction named bind_to that manages the quite complicated
+task of finding the right type of the set for the relation.
+
+\code
+template<class Relation>
+struct bind_to
+{
+    typedef -unspecified- type;
+};
+\endcode
+
+See also vector_of, is_set_type_of_relation.
+                                                                **/
+
+struct vector_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag
+{
+    BOOST_BIMAP_GENERATE_RELATION_BINDER_0CP(
+
+        // binds to
+        vector_of
+    )
+
+    typedef mpl::bool_<true>  left_mutable_key;
+    typedef mpl::bool_<true> right_mutable_key;
+};
+
+
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_VECTOR_OF_HPP
+
diff --git a/boost/bimap/views/list_map_view.hpp b/boost/bimap/views/list_map_view.hpp
new file mode 100644 (file)
index 0000000..2a7d2b1
--- /dev/null
@@ -0,0 +1,182 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/list_map_view.hpp
+/// \brief View of a side of a bimap.
+
+#ifndef BOOST_BIMAP_VIEWS_LIST_MAP_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_LIST_MAP_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/list_map_adaptor.hpp>
+#include <boost/bimap/relation/support/pair_by.hpp>
+#include <boost/bimap/support/iterator_type_by.hpp>
+#include <boost/bimap/detail/map_view_base.hpp>
+#include <boost/bimap/relation/support/data_extractor.hpp>
+#include <boost/bimap/relation/detail/to_mutable_relation_functor.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+template< class Tag, class BimapType >
+struct list_map_view_base
+{
+    typedef ::boost::bimaps::container_adaptor::list_map_adaptor
+    <
+        BOOST_DEDUCED_TYPENAME BimapType::core_type::BOOST_NESTED_TEMPLATE index<Tag>::type,
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                    iterator_type_by<Tag,BimapType>::type,
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                    const_iterator_type_by<Tag,BimapType>::type,
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                   reverse_iterator_type_by<Tag,BimapType>::type,
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                   const_reverse_iterator_type_by<Tag,BimapType>::type,
+        ::boost::bimaps::container_adaptor::support::iterator_facade_to_base
+        <
+            BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                iterator_type_by<Tag,BimapType>::type,
+            BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
+                const_iterator_type_by<Tag,BimapType>::type
+
+        >,
+        ::boost::mpl::na,
+        ::boost::mpl::na,
+        ::boost::bimaps::relation::detail::
+            pair_to_relation_functor<Tag, BOOST_DEDUCED_TYPENAME BimapType::relation >,
+        ::boost::bimaps::relation::support::
+            get_pair_functor<Tag, BOOST_DEDUCED_TYPENAME BimapType::relation >,
+
+        BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::data_extractor
+        <
+            Tag,
+            BOOST_DEDUCED_TYPENAME BimapType::relation
+
+        >::type
+
+    > type;
+};
+
+#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
+
+/// \brief View of a side of a bimap.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core.
+
+See also const_list_map_view.
+                                                                                    **/
+template< class Tag, class BimapType >
+class list_map_view
+:
+    public list_map_view_base<Tag,BimapType>::type,
+    public ::boost::bimaps::detail::
+            map_view_base< list_map_view<Tag,BimapType>,Tag,BimapType >
+
+{
+    typedef BOOST_DEDUCED_TYPENAME list_map_view_base<Tag,BimapType>::type base_;
+
+    BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(list_map_view,Tag,BimapType)
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type;
+
+    list_map_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) :
+        base_(c) {}
+
+    list_map_view & operator=(const list_map_view & v)
+    {
+        this->base() = v.base(); 
+        return *this;
+    }
+
+    BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(base_)
+
+    BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(base_)
+
+    // Rearrange Operations
+
+    void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                  BOOST_DEDUCED_TYPENAME base_::iterator i)
+    {
+        this->base().relocate(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i)
+        );
+    }
+
+    void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                  BOOST_DEDUCED_TYPENAME base_::iterator first,
+                  BOOST_DEDUCED_TYPENAME base_::iterator last)
+    {
+        this->base().relocate(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last)
+        );
+    }
+};
+
+
+} // namespace views
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME)            \
+typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME                             \
+    BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME));
+/*===========================================================================*/
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE)               \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,reverse_iterator)        \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_reverse_iterator)  \
+/*===========================================================================*/
+
+namespace detail {
+
+template< class Tag, class BimapType >
+struct left_map_view_extra_typedefs< ::boost::bimaps::views::list_map_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::list_map_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left)
+};
+
+template< class Tag, class BimapType >
+struct right_map_view_extra_typedefs< ::boost::bimaps::views::list_map_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::list_map_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right)
+};
+
+} // namespace detail
+
+/*===========================================================================*/
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY
+/*===========================================================================*/
+
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_LIST_MAP_VIEW_HPP
+
diff --git a/boost/bimap/views/list_set_view.hpp b/boost/bimap/views/list_set_view.hpp
new file mode 100644 (file)
index 0000000..4b5887f
--- /dev/null
@@ -0,0 +1,108 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/list_set_view.hpp
+/// \brief View of a side of a bimap that is signature compatible with std::list.
+
+#ifndef BOOST_BIMAP_VIEWS_LIST_SET_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_LIST_SET_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/list_adaptor.hpp>
+#include <boost/bimap/detail/set_view_base.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a bimap that is signature compatible with std::list.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a std::list.
+
+See also const_list_set_view.
+                                                                                    **/
+
+template< class CoreIndex >
+class list_set_view
+:
+    public BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR(
+        list_adaptor,
+        CoreIndex,
+        reverse_iterator, const_reverse_iterator
+    ),
+
+    public ::boost::bimaps::detail::
+        set_view_base< list_set_view< CoreIndex >, CoreIndex >
+{
+    BOOST_BIMAP_SET_VIEW_BASE_FRIEND(list_set_view,CoreIndex)
+
+    typedef BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR(
+        list_adaptor,
+        CoreIndex,
+        reverse_iterator, const_reverse_iterator
+
+    ) base_;
+
+    public:
+
+    list_set_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) :
+        base_(c) {}
+
+    list_set_view & operator=(const list_set_view & v) 
+    {
+        this->base() = v.base();
+        return *this;
+    }
+
+    BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(base_)
+
+    BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(base_)
+
+    // Rearrange Operations
+
+    void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, 
+                  BOOST_DEDUCED_TYPENAME base_::iterator i)
+    {
+        this->base().relocate(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i)
+        );
+    }
+
+    void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                  BOOST_DEDUCED_TYPENAME base_::iterator first,
+                  BOOST_DEDUCED_TYPENAME base_::iterator last)
+    {
+        this->base().relocate(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last)
+        );
+    }
+};
+
+
+} // namespace views
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_VIEWS_LIST_SET_VIEW_HPP
+
diff --git a/boost/bimap/views/map_view.hpp b/boost/bimap/views/map_view.hpp
new file mode 100644 (file)
index 0000000..245b5d6
--- /dev/null
@@ -0,0 +1,156 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/map_view.hpp
+/// \brief View of a side of a bimap that is signature compatible with std::map.
+
+#ifndef BOOST_BIMAP_VIEWS_MAP_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_MAP_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/map_adaptor.hpp>
+#include <boost/bimap/detail/map_view_base.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a side of a bimap that is signature compatible with std::map.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a std::map.
+
+See also const_map_view.
+                                                                            **/
+
+template< class Tag, class BimapType >
+class map_view
+:
+    public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        map_adaptor,
+        Tag,BimapType,
+        reverse_iterator_type_by,const_reverse_iterator_type_by
+    ),
+    public ::boost::bimaps::detail::
+        map_view_base< map_view<Tag,BimapType>,Tag,BimapType >,
+    public ::boost::bimaps::detail::
+        unique_map_view_access< map_view<Tag,BimapType>, Tag,  BimapType>::type
+{
+    typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        map_adaptor,
+        Tag,BimapType,
+        reverse_iterator_type_by,const_reverse_iterator_type_by
+
+    ) base_;
+
+    BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(map_view,Tag,BimapType)
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail::
+        unique_map_view_access<
+            map_view<Tag,BimapType>, Tag,  BimapType
+
+        >::type unique_map_view_access_;
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type;
+
+    map_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : base_(c) {}
+
+    using unique_map_view_access_::at;
+    using unique_map_view_access_::operator[];
+
+    BOOST_BIMAP_MAP_VIEW_RANGE_IMPLEMENTATION(base_)
+
+    map_view & operator=(const map_view & v) 
+    {
+        this->base() = v.base();
+        return *this;
+    }
+
+    // It can be used enable_if here but the error message when there 
+    // is no info is very clear like this
+
+    template< class CompatibleKey >
+    const info_type & info_at(const CompatibleKey& k) const
+    {
+        BOOST_DEDUCED_TYPENAME base_::const_iterator iter = this->find(k);
+        if( iter == this->end() )
+        {
+            ::boost::throw_exception(
+                std::out_of_range("bimap<>: invalid key")
+            );
+        }
+        return iter->info;
+    }
+
+    template< class CompatibleKey >
+    info_type & info_at(const CompatibleKey& k)
+    {
+        BOOST_DEDUCED_TYPENAME base_::iterator iter = this->find(k);
+        if( iter == this->end() )
+        {
+            ::boost::throw_exception(
+                std::out_of_range("bimap<>: invalid key")
+            );
+        }
+        return iter->info;
+    }
+};
+
+} // namespace views
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME)            \
+typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME                             \
+    BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME));
+/*===========================================================================*/
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE)               \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,reverse_iterator)        \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_reverse_iterator)  \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,range_type)              \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_range_type)        \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,key_compare)
+/*===========================================================================*/
+
+namespace detail {
+
+template< class Tag, class BimapType >
+struct left_map_view_extra_typedefs< ::boost::bimaps::views::map_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::map_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left)
+};
+
+template< class Tag, class BimapType >
+struct right_map_view_extra_typedefs< ::boost::bimaps::views::map_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::map_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right)
+};
+
+} // namespace detail
+
+/*===========================================================================*/
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY
+/*===========================================================================*/
+
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_MAP_VIEW_HPP
+
diff --git a/boost/bimap/views/multimap_view.hpp b/boost/bimap/views/multimap_view.hpp
new file mode 100644 (file)
index 0000000..4176949
--- /dev/null
@@ -0,0 +1,123 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/multimap_view.hpp
+/// \brief View of a side of a bimap that is signature compatible with std::multimap.
+
+#ifndef BOOST_BIMAP_VIEWS_MULTIMAP_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_MULTIMAP_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/multimap_adaptor.hpp>
+#include <boost/bimap/detail/non_unique_views_helper.hpp>
+#include <boost/bimap/support/iterator_type_by.hpp>
+#include <boost/bimap/detail/map_view_base.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a side of a bimap that is signature compatible with std::multimap.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a std::multimap.
+
+See also const_multimap_view.
+                                                                                    **/
+
+template< class Tag, class BimapType >
+class multimap_view
+:
+    public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        multimap_adaptor,
+        Tag,BimapType,
+        reverse_iterator_type_by,const_reverse_iterator_type_by
+    ),
+    public ::boost::bimaps::detail::
+                map_view_base< multimap_view<Tag,BimapType>,Tag,BimapType >
+
+{
+    typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        multimap_adaptor,
+        Tag,BimapType,
+        reverse_iterator_type_by,const_reverse_iterator_type_by
+
+    ) base_;
+
+    BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(multimap_view,Tag,BimapType)
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type;
+
+    multimap_view(BOOST_DEDUCED_TYPENAME base_::base_type & c)
+        : base_(c) {}
+
+    BOOST_BIMAP_MAP_VIEW_RANGE_IMPLEMENTATION(base_)
+
+    multimap_view & operator=(const multimap_view & v) 
+    {
+        this->base() = v.base();
+        return *this;
+    }
+
+    BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS
+};
+
+
+} // namespace views
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME)            \
+typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME                             \
+    BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME));
+/*===========================================================================*/
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE)               \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,reverse_iterator)        \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_reverse_iterator)  \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,range_type)              \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_range_type)        \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,key_compare)
+/*===========================================================================*/
+
+namespace detail {
+
+template< class Tag, class BimapType >
+struct left_map_view_extra_typedefs< ::boost::bimaps::views::multimap_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::multimap_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left)
+};
+
+template< class Tag, class BimapType >
+struct right_map_view_extra_typedefs< ::boost::bimaps::views::multimap_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::multimap_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right)
+};
+
+} // namespace detail
+
+/*===========================================================================*/
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY
+/*===========================================================================*/
+
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_MAP_VIEW_HPP
+
diff --git a/boost/bimap/views/multiset_view.hpp b/boost/bimap/views/multiset_view.hpp
new file mode 100644 (file)
index 0000000..c49230b
--- /dev/null
@@ -0,0 +1,110 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/multiset_view.hpp
+/// \brief View of a bimap that is signature compatible with std::multiset.
+
+#ifndef BOOST_BIMAP_VIEWS_MULTISET_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_MULTISET_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/multiset_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/comparison_adaptor.hpp>
+#include <boost/bimap/detail/non_unique_views_helper.hpp>
+#include <boost/bimap/detail/set_view_base.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a bimap that is signature compatible with std::multiset.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a std::multiset.
+
+See also const_multiset_view.
+                                                                                    **/
+
+template< class CoreIndex >
+class multiset_view
+:
+    public BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR(
+        multiset_adaptor,
+        CoreIndex,
+        reverse_iterator,
+        const_reverse_iterator
+    ),
+
+    public ::boost::bimaps::detail::
+                set_view_base< multiset_view< CoreIndex >, CoreIndex >
+{
+    BOOST_BIMAP_SET_VIEW_BASE_FRIEND(multiset_view, CoreIndex)
+
+    typedef BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR(
+        multiset_adaptor,
+        CoreIndex,
+        reverse_iterator,
+        const_reverse_iterator
+
+    ) base_;
+
+    public:
+
+    multiset_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : base_(c) {}
+
+    /*
+    template< class LowerBounder, class UpperBounder >
+    std::pair<BOOST_DEDUCED_TYPENAME base_::const_iterator,
+              BOOST_DEDUCED_TYPENAME base_::const_iterator>
+        range(LowerBounder lower,UpperBounder upper) const
+    {
+        return this->base().range(
+
+            ::boost::bimaps::container_adaptor::detail::unary_check_adaptor
+            <
+                LowerBounder,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( lower, this->template functor<
+                            BOOST_DEDUCED_TYPENAME base_::value_from_base>() ),
+
+            ::boost::bimaps::container_adaptor::detail::unary_check_adaptor
+            <
+                UpperBounder,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( upper, this->template functor<
+                            BOOST_DEDUCED_TYPENAME base_::value_from_base>() )
+
+        );
+    }
+    */
+
+    multiset_view & operator=(const multiset_view & v) 
+    {
+        this->base() = v.base(); return *this;
+    }
+
+    BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS
+};
+
+
+} // namespace views
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_MULTISET_VIEW_HPP
+
diff --git a/boost/bimap/views/set_view.hpp b/boost/bimap/views/set_view.hpp
new file mode 100644 (file)
index 0000000..8a857af
--- /dev/null
@@ -0,0 +1,106 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/set_view.hpp
+/// \brief View of a bimap that is signature compatible with std::set.
+
+#ifndef BOOST_BIMAP_VIEWS_SET_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_SET_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/set_adaptor.hpp>
+#include <boost/bimap/detail/set_view_base.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a bimap that is signature compatible with std::set.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a std::set.
+
+See also const_set_view.
+                                                                                    **/
+
+template< class CoreIndex >
+class set_view
+:
+    public BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR(
+        set_adaptor,
+        CoreIndex,
+        reverse_iterator, const_reverse_iterator
+    ),
+
+    public ::boost::bimaps::detail::
+                set_view_base< set_view< CoreIndex >, CoreIndex >
+{
+    typedef BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR(
+        set_adaptor,
+        CoreIndex,
+        reverse_iterator, const_reverse_iterator
+
+    ) base_;
+
+    BOOST_BIMAP_SET_VIEW_BASE_FRIEND(set_view,CoreIndex)
+
+    public:
+
+    set_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : base_(c) {}
+
+    /*
+    template< class LowerBounder, class UpperBounder >
+    std::pair<BOOST_DEDUCED_TYPENAME base_::const_iterator,
+              BOOST_DEDUCED_TYPENAME base_::const_iterator>
+        range(LowerBounder lower,UpperBounder upper) const
+    {
+        return this->base().range(
+
+            ::boost::bimaps::container_adaptor::detail::unary_check_adaptor
+            <
+                LowerBounder,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( lower, this->template functor<
+                            BOOST_DEDUCED_TYPENAME base_::value_from_base>() ),
+
+            ::boost::bimaps::container_adaptor::detail::unary_check_adaptor
+            <
+                UpperBounder,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( upper, this->template functor<
+                            BOOST_DEDUCED_TYPENAME base_::value_from_base>() )
+
+        );
+    }
+    */
+
+    set_view & operator=(const set_view & v) 
+    {
+        this->base() = v.base();
+        return *this;
+    }
+};
+
+
+} // namespace views
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_SET_VIEW_HPP
+
+
diff --git a/boost/bimap/views/unconstrained_map_view.hpp b/boost/bimap/views/unconstrained_map_view.hpp
new file mode 100644 (file)
index 0000000..da9b4b4
--- /dev/null
@@ -0,0 +1,44 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/unconstrained_map_view.hpp
+/// \brief Unconstrained view of a side of a bimap.
+
+#ifndef BOOST_BIMAP_VIEWS_UNCONSTRAINED_MAP_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_UNCONSTRAINED_MAP_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief Unconstrained view of a side of a bimap.
+
+template< class Tag, class BimapType>
+class unconstrained_map_view
+{
+    public:
+    template< class T >
+    unconstrained_map_view(const T & t) {}
+
+    typedef void reference;
+    typedef void const_reference;
+    typedef void info_type;
+};
+
+} // namespace views
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_UNCONSTRAINED_MAP_VIEW_HPP
+
diff --git a/boost/bimap/views/unconstrained_set_view.hpp b/boost/bimap/views/unconstrained_set_view.hpp
new file mode 100644 (file)
index 0000000..6b4a6e2
--- /dev/null
@@ -0,0 +1,42 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/unconstrained_set_view.hpp
+/// \brief Unconstrained view of a bimap.
+
+#ifndef BOOST_BIMAP_VIEWS_UNCONSTRAINED_SET_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_UNCONSTRAINED_SET_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief Unconstrained view of a bimap.
+
+template< class CoreIndex >
+class unconstrained_set_view
+{
+    public:
+    template< class T >
+    unconstrained_set_view(const T & t) {}
+
+    typedef void iterator;
+    typedef void const_iterator;
+};
+
+} // namespace views
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_UNCONSTRAINED_SET_VIEW_HPP
diff --git a/boost/bimap/views/unordered_map_view.hpp b/boost/bimap/views/unordered_map_view.hpp
new file mode 100644 (file)
index 0000000..14813e2
--- /dev/null
@@ -0,0 +1,174 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/unordered_map_view.hpp
+/// \brief View of a side of a bimap that is signature compatible with tr1::unordered_map.
+
+#ifndef BOOST_BIMAP_VIEWS_UNOREDERED_MAP_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_UNOREDERED_MAP_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <utility>
+
+#include <boost/bimap/container_adaptor/unordered_map_adaptor.hpp>
+#include <boost/bimap/detail/map_view_base.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief Map View of a bimap, signature compatible with tr1::unordered_map.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a tr1::unordered_map.
+
+See also const_unordered_map_view.
+                                                                             **/
+
+
+template< class Tag, class BimapType >
+class unordered_map_view
+:
+    public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        unordered_map_adaptor,
+        Tag,BimapType,
+        local_iterator_type_by,const_local_iterator_type_by
+    ),
+
+    public ::boost::bimaps::detail::map_view_base<
+                unordered_map_view<Tag,BimapType>,Tag,BimapType >,
+    public ::boost::bimaps::detail::
+                unique_map_view_access<
+                    unordered_map_view<Tag,BimapType>, Tag,  BimapType>::type
+
+{
+    typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        unordered_map_adaptor,
+        Tag,BimapType,
+        local_iterator_type_by,const_local_iterator_type_by
+
+    ) base_;
+
+    BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(unordered_map_view,Tag,BimapType)
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail::
+        unique_map_view_access<
+            unordered_map_view<Tag,BimapType>, Tag,  BimapType
+
+        >::type unique_map_view_access_;
+
+    public:
+
+    typedef std::pair<
+        BOOST_DEDUCED_TYPENAME base_::iterator,
+        BOOST_DEDUCED_TYPENAME base_::iterator
+    > range_type;
+
+    typedef std::pair<
+        BOOST_DEDUCED_TYPENAME base_::const_iterator,
+        BOOST_DEDUCED_TYPENAME base_::const_iterator
+    > const_range_type;
+
+    typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type;
+
+    unordered_map_view(BOOST_DEDUCED_TYPENAME base_::base_type & c)
+        : base_(c) {}
+
+    using unique_map_view_access_::at;
+    using unique_map_view_access_::operator[];
+
+    unordered_map_view & operator=(const unordered_map_view & v) 
+    {
+        this->base() = v.base();
+        return *this;
+    }
+
+    // It can be used enable_if here but the error message when there 
+    // is no info is very clear like this
+
+    template< class CompatibleKey >
+    const info_type & info_at(const CompatibleKey& k) const
+    {
+        BOOST_DEDUCED_TYPENAME base_::const_iterator iter = this->find(k);
+        if( iter == this->end() )
+        {
+            ::boost::throw_exception(
+                std::out_of_range("bimap<>: invalid key")
+            );
+        }
+        return iter->info;
+    }
+
+    template< class CompatibleKey >
+    info_type & info_at(const CompatibleKey& k)
+    {
+        BOOST_DEDUCED_TYPENAME base_::iterator iter = this->find(k);
+        if( iter == this->end() )
+        {
+            ::boost::throw_exception(
+                std::out_of_range("bimap<>: invalid key")
+            );
+        }
+        return iter->info;
+    }
+};
+
+
+} // namespace views
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME)            \
+typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME                             \
+    BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME));
+/*===========================================================================*/
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE)               \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,local_iterator)          \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_local_iterator)    \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,range_type)              \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_range_type)        \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,hasher)                  \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,key_equal)
+/*===========================================================================*/
+
+namespace detail {
+
+template< class Tag, class BimapType >
+struct left_map_view_extra_typedefs< ::boost::bimaps::views::unordered_map_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::unordered_map_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left)
+};
+
+template< class Tag, class BimapType >
+struct right_map_view_extra_typedefs< ::boost::bimaps::views::unordered_map_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::unordered_map_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right)
+};
+
+} // namespace detail
+
+/*===========================================================================*/
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY
+/*===========================================================================*/
+
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_UNOREDERED_MAP_VIEW_HPP
+
+
diff --git a/boost/bimap/views/unordered_multimap_view.hpp b/boost/bimap/views/unordered_multimap_view.hpp
new file mode 100644 (file)
index 0000000..db22205
--- /dev/null
@@ -0,0 +1,136 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/unordered_multimap_view.hpp
+/// \brief View of a side of a bimap that is signature compatible with tr1::unordered_multimap.
+
+#ifndef BOOST_BIMAP_VIEWS_UNOREDERED_MULTIMAP_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_UNOREDERED_MULTIMAP_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <utility>
+
+#include <boost/bimap/container_adaptor/unordered_multimap_adaptor.hpp>
+#include <boost/bimap/detail/non_unique_views_helper.hpp>
+#include <boost/bimap/support/iterator_type_by.hpp>
+#include <boost/bimap/detail/map_view_base.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a side of a bimap that is signature compatible with tr1::unordered_multimap.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a tr1::unordered_multimap.
+
+See also const_unordered_multimap_view.
+                                                                             **/
+
+template< class Tag, class BimapType >
+class unordered_multimap_view
+:
+    public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        unordered_multimap_adaptor,
+        Tag,BimapType,
+        local_iterator_type_by,const_local_iterator_type_by
+    ),
+
+    public ::boost::bimaps::detail::map_view_base<
+                unordered_multimap_view<Tag,BimapType>,Tag,BimapType >
+
+{
+    typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        unordered_multimap_adaptor,
+        Tag,BimapType,
+        local_iterator_type_by,const_local_iterator_type_by
+
+    ) base_;
+
+    BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(unordered_multimap_view,Tag,BimapType)
+
+    public:
+
+    typedef std::pair<
+        BOOST_DEDUCED_TYPENAME base_::iterator,
+        BOOST_DEDUCED_TYPENAME base_::iterator
+    > range_type;
+
+    typedef std::pair<
+        BOOST_DEDUCED_TYPENAME base_::const_iterator,
+        BOOST_DEDUCED_TYPENAME base_::const_iterator
+    > const_range_type;
+
+    typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type;
+
+    unordered_multimap_view(BOOST_DEDUCED_TYPENAME base_::base_type & c)
+        : base_(c) {}
+
+    BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS
+
+    unordered_multimap_view & operator=(const unordered_multimap_view & v) 
+    {
+        this->base() = v.base();
+        return *this;
+    }
+};
+
+
+} // namespace views
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME)            \
+typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME                             \
+    BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME));
+/*===========================================================================*/
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE)               \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,local_iterator)          \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_local_iterator)    \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,range_type)              \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_range_type)        \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,hasher)                  \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,key_equal)
+/*===========================================================================*/
+
+namespace detail {
+
+template< class Tag, class BimapType >
+struct left_map_view_extra_typedefs< ::boost::bimaps::views::unordered_multimap_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::unordered_multimap_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left)
+};
+
+template< class Tag, class BimapType >
+struct right_map_view_extra_typedefs< ::boost::bimaps::views::unordered_multimap_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::unordered_multimap_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right)
+};
+
+} // namespace detail
+
+/*===========================================================================*/
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY
+/*===========================================================================*/
+
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_UNOREDERED_MULTIMAP_VIEW_HPP
+
+
diff --git a/boost/bimap/views/unordered_multiset_view.hpp b/boost/bimap/views/unordered_multiset_view.hpp
new file mode 100644 (file)
index 0000000..3a72e36
--- /dev/null
@@ -0,0 +1,83 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/unordered_multiset_view.hpp
+/// \brief View of a bimap that is signature compatible with tr1::unordered_multiset.
+
+#ifndef BOOST_BIMAP_VIEWS_UNORDERED_MULTISET_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_UNORDERED_MULTISET_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/unordered_multiset_adaptor.hpp>
+#include <boost/bimap/detail/non_unique_views_helper.hpp>
+#include <boost/bimap/detail/set_view_base.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a bimap that is signature compatible with std::unordered_multiset.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a std::unordered_multiset.
+
+See also const_unordered_multiset_view.
+                                                                                    **/
+
+template< class CoreIndex >
+class unordered_multiset_view
+:
+    public BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR(
+        unordered_multiset_adaptor,
+        CoreIndex,
+        local_iterator,
+        const_local_iterator
+
+    ),
+
+    public ::boost::bimaps::detail::
+                set_view_base< unordered_multiset_view< CoreIndex >, CoreIndex >
+{
+    BOOST_BIMAP_SET_VIEW_BASE_FRIEND(unordered_multiset_view,CoreIndex)
+
+    typedef BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR(
+        unordered_multiset_adaptor,
+        CoreIndex,
+        local_iterator,
+        const_local_iterator
+
+    ) base_;
+
+    public:
+
+    unordered_multiset_view(BOOST_DEDUCED_TYPENAME base_::base_type & c)
+        : base_(c) {}
+
+    BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS
+
+    unordered_multiset_view & operator=(const unordered_multiset_view & v)
+    {
+        this->base() = v.base();
+        return *this;
+    }
+};
+
+
+} // namespace views
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_UNORDERED_MULTISET_VIEW_HPP
+
+
diff --git a/boost/bimap/views/unordered_set_view.hpp b/boost/bimap/views/unordered_set_view.hpp
new file mode 100644 (file)
index 0000000..02187ae
--- /dev/null
@@ -0,0 +1,78 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/unordered_set_view.hpp
+/// \brief View of a bimap that is signature compatible with tr1::unordered_set.
+
+#ifndef BOOST_BIMAP_VIEWS_UNORDERED_SET_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_UNORDERED_SET_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/unordered_set_adaptor.hpp>
+#include <boost/bimap/detail/set_view_base.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a bimap that is signature compatible with std::unordered_set.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a std::unordered_set.
+
+See also const_unordered_set_view.
+                                                                             **/
+
+template< class CoreIndex >
+class unordered_set_view
+:
+    public BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR(
+        unordered_set_adaptor,
+        CoreIndex,
+        local_iterator,
+        const_local_iterator
+    ),
+
+    public ::boost::bimaps::detail::
+        set_view_base< unordered_set_view< CoreIndex >, CoreIndex >
+{
+    BOOST_BIMAP_SET_VIEW_BASE_FRIEND(unordered_set_view,CoreIndex)
+
+    typedef BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR(
+        unordered_set_adaptor,
+        CoreIndex,
+        local_iterator,
+        const_local_iterator
+
+    ) base_;
+
+    public:
+
+    unordered_set_view(BOOST_DEDUCED_TYPENAME base_::base_type & c)
+        : base_(c) {}
+
+    unordered_set_view & operator=(const unordered_set_view & v) 
+    {
+        this->base() = v.base();
+        return *this;
+    }
+};
+
+
+} // namespace views
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_UNORDERED_SET_VIEW_HPP
+
diff --git a/boost/bimap/views/vector_map_view.hpp b/boost/bimap/views/vector_map_view.hpp
new file mode 100644 (file)
index 0000000..1837c27
--- /dev/null
@@ -0,0 +1,306 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/vector_map_view.hpp
+/// \brief View of a side of a bimap.
+
+#ifndef BOOST_BIMAP_VIEWS_VECTOR_MAP_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_VECTOR_MAP_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/vector_map_adaptor.hpp>
+#include <boost/bimap/support/iterator_type_by.hpp>
+#include <boost/bimap/detail/map_view_base.hpp>
+#include <boost/bimap/container_adaptor/detail/comparison_adaptor.hpp>
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a side of a bimap.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core.
+
+See also const_map_view.
+                                                                             **/
+template< class Tag, class BimapType >
+class vector_map_view
+:
+    public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        vector_map_adaptor,
+        Tag,BimapType,
+        reverse_iterator_type_by, const_reverse_iterator_type_by
+    ),
+
+    public ::boost::bimaps::detail::
+                map_view_base< vector_map_view<Tag,BimapType>,Tag,BimapType >
+{
+    typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR(
+        vector_map_adaptor,
+        Tag,BimapType,
+        reverse_iterator_type_by, const_reverse_iterator_type_by
+
+    ) base_;
+
+    BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(vector_map_view,Tag,BimapType)
+
+    typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::data_extractor
+    <
+        Tag,
+        BOOST_DEDUCED_TYPENAME BimapType::relation
+
+    >::type key_from_base_value;
+
+    public:
+
+    typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type;
+
+    vector_map_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) :
+        base_(c) {}
+
+    vector_map_view & operator=(const vector_map_view & v)
+    {
+        this->base() = v.base();
+        return *this;
+    }
+
+    BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(base_)
+
+    BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(base_)
+
+    // Lists operations
+
+    void splice(BOOST_DEDUCED_TYPENAME base_::iterator position, vector_map_view & x)
+    {
+        this->base().splice(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            x.base()
+        );
+    }
+
+    void splice(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                vector_map_view & x,
+                BOOST_DEDUCED_TYPENAME base_::iterator i)
+    {
+        this->base().splice(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            x.base(),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i)
+        );
+    }
+
+    void splice(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                vector_map_view & x,
+                BOOST_DEDUCED_TYPENAME base_::iterator first,
+                BOOST_DEDUCED_TYPENAME base_::iterator last)
+    {
+        this->base().splice(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            x.base(),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last)
+        );
+    }
+
+    void remove(BOOST_DEDUCED_TYPENAME ::boost::call_traits< 
+                    BOOST_DEDUCED_TYPENAME base_::value_type >::param_type value)
+    {
+        this->base().remove(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::value_to_base>()(value)
+        );
+    }
+
+    template< class Predicate >
+    void remove_if(Predicate pred)
+    {
+        this->base().remove_if(
+            ::boost::bimaps::container_adaptor::detail::unary_check_adaptor
+            <
+                Predicate,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                key_from_base_value
+
+            >( pred, key_from_base_value() )
+        );
+    }
+
+    void unique()
+    {
+        this->base().unique(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::equal_to<BOOST_DEDUCED_TYPENAME base_::key_type>,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                key_from_base_value
+
+            >(std::equal_to<BOOST_DEDUCED_TYPENAME base_::key_type>(),
+                    key_from_base_value() )
+        );
+    }
+
+    template< class BinaryPredicate >
+    void unique(BinaryPredicate binary_pred)
+    {
+        this->base().unique(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                BinaryPredicate,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                key_from_base_value
+
+            >( binary_pred, key_from_base_value() )
+        );
+    }
+
+    void merge(vector_map_view & x)
+    {
+        this->base().merge(x.base(),
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::less<BOOST_DEDUCED_TYPENAME base_::key_type>,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                key_from_base_value
+
+            >( std::less<BOOST_DEDUCED_TYPENAME base_::key_type>(), 
+                    key_from_base_value() )
+        );
+    }
+
+    template< class Compare >
+    void merge(vector_map_view & x, Compare comp)
+    {
+        this->base().merge(x.base(),
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                Compare,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                key_from_base_value
+
+            >( comp, key_from_base_value() )
+        );
+    }
+
+    void sort()
+    {
+        this->base().sort(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::less<BOOST_DEDUCED_TYPENAME base_::key_type>,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                key_from_base_value
+
+            >( std::less<BOOST_DEDUCED_TYPENAME base_::key_type>(),
+                    key_from_base_value() )
+        );
+    }
+
+    template< class Compare >
+    void sort(Compare comp)
+    {
+        this->base().sort(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                Compare,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                key_from_base_value
+
+            >( comp, key_from_base_value() )
+        );
+    }
+
+    void reverse()
+    {
+        this->base().reverse();
+    }
+
+    // Rearrange Operations
+
+    void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, 
+                  BOOST_DEDUCED_TYPENAME base_::iterator i)
+    {
+        this->base().relocate(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i)
+        );
+    }
+
+    void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                  BOOST_DEDUCED_TYPENAME base_::iterator first, 
+                  BOOST_DEDUCED_TYPENAME base_::iterator last)
+    {
+        this->base().relocate(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last)
+        );
+    }
+
+};
+
+
+} // namespace views
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME)            \
+typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME                             \
+    BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME));
+/*===========================================================================*/
+
+/*===========================================================================*/
+#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE)               \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,reverse_iterator)        \
+    BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_reverse_iterator)  \
+/*===========================================================================*/
+
+namespace detail {
+
+template< class Tag, class BimapType >
+struct left_map_view_extra_typedefs< ::boost::bimaps::views::vector_map_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::vector_map_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left)
+};
+
+template< class Tag, class BimapType >
+struct right_map_view_extra_typedefs< ::boost::bimaps::views::vector_map_view<Tag,BimapType> >
+{
+    private: typedef ::boost::bimaps::views::vector_map_view<Tag,BimapType> map_view_;
+    public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right)
+};
+
+} // namespace detail
+
+/*===========================================================================*/
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF
+#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY
+/*===========================================================================*/
+
+} // namespace bimaps
+} // namespace boost
+
+#endif // BOOST_BIMAP_VIEWS_VECTOR_MAP_VIEW_HPP
+
diff --git a/boost/bimap/views/vector_set_view.hpp b/boost/bimap/views/vector_set_view.hpp
new file mode 100644 (file)
index 0000000..f58c0e4
--- /dev/null
@@ -0,0 +1,279 @@
+// Boost.Bimap
+//
+// Copyright (c) 2006-2007 Matias Capeletto
+//
+// 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)
+
+/// \file views/vector_set_view.hpp
+/// \brief View of a side of a bimap that is signature compatible with std::vector.
+
+#ifndef BOOST_BIMAP_VIEWS_VECTOR_SET_VIEW_HPP
+#define BOOST_BIMAP_VIEWS_VECTOR_SET_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <boost/bimap/container_adaptor/vector_adaptor.hpp>
+#include <boost/bimap/container_adaptor/detail/comparison_adaptor.hpp>
+#include <boost/bimap/detail/set_view_base.hpp>
+
+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+/// \brief View of a bimap that is signature compatible with std::vector.
+/**
+
+This class uses container_adaptor and iterator_adaptor to wrapped a index of the
+multi_index bimap core so it can be used as a std::vector.
+
+See also const_set_view.
+                                                                                    **/
+
+template< class CoreIndex >
+class vector_set_view
+:
+    public BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR(
+        vector_adaptor,
+        CoreIndex,
+        reverse_iterator, const_reverse_iterator
+    ),
+
+    public ::boost::bimaps::detail::
+                set_view_base< vector_set_view< CoreIndex >, CoreIndex >
+{
+    BOOST_BIMAP_SET_VIEW_BASE_FRIEND(vector_set_view,CoreIndex)
+
+    typedef BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR(
+        vector_adaptor,
+        CoreIndex,
+        reverse_iterator, const_reverse_iterator
+
+    ) base_;
+
+    public:
+
+    vector_set_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) :
+        base_(c) {}
+
+    vector_set_view & operator=(const vector_set_view & v)
+    {
+        this->base() = v.base();
+        return *this;
+    }
+
+    BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(base_)
+
+    BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(base_)
+
+    // List operations
+
+    void splice(BOOST_DEDUCED_TYPENAME base_::iterator position, 
+                vector_set_view & x)
+    {
+        this->base().splice(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            x.base()
+        );
+    }
+
+    void splice(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                vector_set_view & x,
+                BOOST_DEDUCED_TYPENAME base_::iterator i)
+    {
+        this->base().splice(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            x.base(),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i)
+        );
+    }
+
+    void splice(BOOST_DEDUCED_TYPENAME base_::iterator position, 
+                vector_set_view & x,
+                BOOST_DEDUCED_TYPENAME base_::iterator first, 
+                BOOST_DEDUCED_TYPENAME base_::iterator last)
+    {
+        this->base().splice(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            x.base(),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last)
+        );
+    }
+
+    void remove(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
+                    BOOST_DEDUCED_TYPENAME base_::value_type >::param_type value)
+    {
+        this->base().remove(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::value_to_base>()(value)
+        );
+    }
+
+    template<typename Predicate>
+    void remove_if(Predicate pred)
+    {
+        this->base().remove_if(
+            ::boost::bimaps::container_adaptor::detail::unary_check_adaptor
+            <
+                Predicate,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( pred, this->template functor<
+                            BOOST_DEDUCED_TYPENAME base_::value_from_base>() )
+        );
+    }
+
+    void unique()
+    {
+        this->base().unique(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::equal_to<BOOST_DEDUCED_TYPENAME base_::value_type>,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >(
+                std::equal_to<BOOST_DEDUCED_TYPENAME base_::value_type>(),
+                this->template functor<
+                    BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+            )
+        );
+    }
+
+    template< class BinaryPredicate >
+    void unique(BinaryPredicate binary_pred)
+    {
+        this->base().unique(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                BinaryPredicate,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( binary_pred,
+               this->template functor<
+                    BOOST_DEDUCED_TYPENAME base_::value_from_base>() 
+            )
+        );
+    }
+
+    void merge(vector_set_view & x)
+    {
+        this->base().merge(x.base(),
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::less<BOOST_DEDUCED_TYPENAME base_::value_type>,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >(
+                std::less<BOOST_DEDUCED_TYPENAME base_::value_type>(),
+                this->template functor<
+                        BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+            )
+        );
+    }
+
+    template< class Compare >
+    void merge(vector_set_view & x, Compare comp)
+    {
+        this->base().merge(x.base(),
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                Compare,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( comp, this->template functor<
+                        BOOST_DEDUCED_TYPENAME base_::value_from_base>() )
+        );
+    }
+
+    void sort()
+    {
+        this->base().sort(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                std::less<BOOST_DEDUCED_TYPENAME base_::value_type>,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >(
+                std::less<BOOST_DEDUCED_TYPENAME base_::value_type>(),
+                this->template functor<
+                    BOOST_DEDUCED_TYPENAME base_::value_from_base>()
+            )
+        );
+    }
+
+    template< class Compare >
+    void sort(Compare comp)
+    {
+        this->base().sort(
+            ::boost::bimaps::container_adaptor::detail::comparison_adaptor
+            <
+                Compare,
+                BOOST_DEDUCED_TYPENAME base_::base_type::value_type,
+                BOOST_DEDUCED_TYPENAME base_::value_from_base
+
+            >( comp, this->template functor<
+                        BOOST_DEDUCED_TYPENAME base_::value_from_base>() )
+        );
+    }
+
+    void reverse()
+    {
+        this->base().reverse();
+    }
+
+    // Rearrange Operations
+
+    void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, 
+                  BOOST_DEDUCED_TYPENAME base_::iterator i)
+    {
+        this->base().relocate(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i)
+        );
+    }
+
+    void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position,
+                  BOOST_DEDUCED_TYPENAME base_::iterator first, 
+                  BOOST_DEDUCED_TYPENAME base_::iterator last)
+    {
+        this->base().relocate(
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first),
+            this->template functor<
+                BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last)
+        );
+    }
+
+};
+
+
+} // namespace views
+} // namespace bimaps
+} // namespace boost
+
+
+#endif // BOOST_BIMAP_VIEWS_VECTOR_SET_VIEW_HPP
+
diff --git a/boost/multi_index/composite_key.hpp b/boost/multi_index/composite_key.hpp
new file mode 100644 (file)
index 0000000..12e0605
--- /dev/null
@@ -0,0 +1,1315 @@
+/* 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_COMPOSITE_KEY_HPP
+#define BOOST_MULTI_INDEX_COMPOSITE_KEY_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/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>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
+#include <boost/preprocessor/list/at.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp> 
+#include <boost/static_assert.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <functional>
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+#include <boost/ref.hpp>
+#endif
+
+#if !defined(BOOST_NO_SFINAE)
+#include <boost/type_traits/is_convertible.hpp>
+#endif
+
+/* A composite key stores n key extractors and "computes" the
+ * result on a given value as a packed reference to the value and
+ * the composite key itself. Actual invocations to the component
+ * key extractors are lazily performed when executing an operation
+ * on composite_key results (equality, comparison, hashing.)
+ * As the other key extractors in Boost.MultiIndex, composite_key<T,...>
+ * is  overloaded to work on chained pointers to T and reference_wrappers
+ * of T.
+ */
+
+/* This user_definable macro limits the number of elements of a composite
+ * key; useful for shortening resulting symbol names (MSVC++ 6.0, for
+ * instance has problems coping with very long symbol names.)
+ * NB: This cannot exceed the maximum number of arguments of
+ * boost::tuple. In Boost 1.32, the limit is 10.
+ */
+
+#if !defined(BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE)
+#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
+#define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 5
+#else
+#define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 10
+#endif
+#endif
+
+/* maximum number of key extractors in a composite key */
+
+#if BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE<10 /* max length of a tuple */
+#define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE \
+  BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE
+#else
+#define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE 10
+#endif
+
+/* BOOST_PP_ENUM of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
+
+#define BOOST_MULTI_INDEX_CK_ENUM(macro,data)                                \
+  BOOST_PP_ENUM(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,macro,data)
+
+/* BOOST_PP_ENUM_PARAMS of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
+
+#define BOOST_MULTI_INDEX_CK_ENUM_PARAMS(param)                              \
+  BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,param)
+
+/* if n==0 ->   text0
+ * otherwise -> textn=tuples::null_type
+ */
+
+#define BOOST_MULTI_INDEX_CK_TEMPLATE_PARM(z,n,text)                         \
+  typename BOOST_PP_CAT(text,n) BOOST_PP_EXPR_IF(n,=tuples::null_type)
+
+/* const textn& kn=textn() */
+
+#define BOOST_MULTI_INDEX_CK_CTOR_ARG(z,n,text)                              \
+  const BOOST_PP_CAT(text,n)& BOOST_PP_CAT(k,n) = BOOST_PP_CAT(text,n)()
+
+/* typename list(0)<list(1),n>::type */
+
+#define BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N(z,n,list)                  \
+  BOOST_DEDUCED_TYPENAME BOOST_PP_LIST_AT(list,0)<                           \
+    BOOST_PP_LIST_AT(list,1),n                                               \
+  >::type
+
+namespace boost{
+
+template<class T> class reference_wrapper; /* fwd decl. */
+
+namespace multi_index{
+
+namespace detail{
+
+/* n-th key extractor of a composite key */
+
+template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)>
+struct nth_key_from_value
+{
+  typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
+  typedef typename prevent_eti<
+    tuples::element<N,key_extractor_tuple>,
+    typename mpl::eval_if_c<
+      N<tuples::length<key_extractor_tuple>::value,
+      tuples::element<N,key_extractor_tuple>,
+      mpl::identity<tuples::null_type>
+    >::type
+  >::type                                            type;
+};
+
+/* nth_composite_key_##name<CompositeKey,N>::type yields
+ * functor<nth_key_from_value<CompositeKey,N> >, or tuples::null_type
+ * if N exceeds the length of the composite key.
+ */
+
+#define BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(name,functor)         \
+template<typename KeyFromValue>                                              \
+struct BOOST_PP_CAT(key_,name)                                               \
+{                                                                            \
+  typedef functor<typename KeyFromValue::result_type> type;                  \
+};                                                                           \
+                                                                             \
+template<>                                                                   \
+struct BOOST_PP_CAT(key_,name)<tuples::null_type>                            \
+{                                                                            \
+  typedef tuples::null_type type;                                            \
+};                                                                           \
+                                                                             \
+template<typename CompositeKey,BOOST_MPL_AUX_NTTP_DECL(int, N)>              \
+struct BOOST_PP_CAT(nth_composite_key_,name)                                 \
+{                                                                            \
+  typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value;  \
+  typedef typename BOOST_PP_CAT(key_,name)<key_from_value>::type type;       \
+};
+
+/* nth_composite_key_equal_to
+ * nth_composite_key_less
+ * nth_composite_key_greater
+ * nth_composite_key_hash
+ */
+
+BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(equal_to,std::equal_to)
+BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(less,std::less)
+BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(greater,std::greater)
+BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(hash,boost::hash)
+
+/* used for defining equality and comparison ops of composite_key_result */
+
+#define BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO(z,n,text) text
+
+struct generic_operator_equal
+{
+  template<typename T,typename Q>
+  bool operator()(const T& x,const Q& y)const{return x==y;}
+};
+
+typedef tuple<
+  BOOST_MULTI_INDEX_CK_ENUM(
+    BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
+    detail::generic_operator_equal)>          generic_operator_equal_tuple;
+
+struct generic_operator_less
+{
+  template<typename T,typename Q>
+  bool operator()(const T& x,const Q& y)const{return x<y;}
+};
+
+typedef tuple<
+  BOOST_MULTI_INDEX_CK_ENUM(
+    BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
+    detail::generic_operator_less)>           generic_operator_less_tuple;
+
+/* Metaprogramming machinery for implementing equality, comparison and
+ * hashing operations of composite_key_result.
+ *
+ * equal_* checks for equality between composite_key_results and
+ * between those and tuples, accepting a tuple of basic equality functors.
+ * compare_* does lexicographical comparison.
+ * hash_* computes a combination of elementwise hash values.
+ */
+
+template
+<
+  typename KeyCons1,typename Value1,
+  typename KeyCons2, typename Value2,
+  typename EqualCons
+>
+struct equal_ckey_ckey; /* fwd decl. */
+
+template
+<
+  typename KeyCons1,typename Value1,
+  typename KeyCons2, typename Value2,
+  typename EqualCons
+>
+struct equal_ckey_ckey_terminal
+{
+  static bool compare(
+    const KeyCons1&,const Value1&,
+    const KeyCons2&,const Value2&,
+    const EqualCons&)
+  {
+    return true;
+  }
+};
+
+template
+<
+  typename KeyCons1,typename Value1,
+  typename KeyCons2, typename Value2,
+  typename EqualCons
+>
+struct equal_ckey_ckey_normal
+{
+  static bool compare(
+    const KeyCons1& c0,const Value1& v0,
+    const KeyCons2& c1,const Value2& v1,
+    const EqualCons& eq)
+  {
+    if(!eq.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return false;
+    return equal_ckey_ckey<
+      BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
+      BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
+      BOOST_DEDUCED_TYPENAME EqualCons::tail_type
+    >::compare(c0.get_tail(),v0,c1.get_tail(),v1,eq.get_tail());
+  }
+};
+
+template
+<
+  typename KeyCons1,typename Value1,
+  typename KeyCons2, typename Value2,
+  typename EqualCons
+>
+struct equal_ckey_ckey:
+  mpl::if_<
+    mpl::or_<
+      is_same<KeyCons1,tuples::null_type>,
+      is_same<KeyCons2,tuples::null_type>
+    >,
+    equal_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>,
+    equal_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>
+  >::type
+{
+};
+
+template
+<
+  typename KeyCons,typename Value,
+  typename ValCons,typename EqualCons
+>
+struct equal_ckey_cval; /* fwd decl. */
+
+template
+<
+  typename KeyCons,typename Value,
+  typename ValCons,typename EqualCons
+>
+struct equal_ckey_cval_terminal
+{
+  static bool compare(
+    const KeyCons&,const Value&,const ValCons&,const EqualCons&)
+  {
+    return true;
+  }
+
+  static bool compare(
+    const ValCons&,const KeyCons&,const Value&,const EqualCons&)
+  {
+    return true;
+  }
+};
+
+template
+<
+  typename KeyCons,typename Value,
+  typename ValCons,typename EqualCons
+>
+struct equal_ckey_cval_normal
+{
+  static bool compare(
+    const KeyCons& c,const Value& v,const ValCons& vc,
+    const EqualCons& eq)
+  {
+    if(!eq.get_head()(c.get_head()(v),vc.get_head()))return false;
+    return equal_ckey_cval<
+      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
+      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
+      BOOST_DEDUCED_TYPENAME EqualCons::tail_type
+    >::compare(c.get_tail(),v,vc.get_tail(),eq.get_tail());
+  }
+
+  static bool compare(
+    const ValCons& vc,const KeyCons& c,const Value& v,
+    const EqualCons& eq)
+  {
+    if(!eq.get_head()(vc.get_head(),c.get_head()(v)))return false;
+    return equal_ckey_cval<
+      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
+      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
+      BOOST_DEDUCED_TYPENAME EqualCons::tail_type
+    >::compare(vc.get_tail(),c.get_tail(),v,eq.get_tail());
+  }
+};
+
+template
+<
+  typename KeyCons,typename Value,
+  typename ValCons,typename EqualCons
+>
+struct equal_ckey_cval:
+  mpl::if_<
+    mpl::or_<
+      is_same<KeyCons,tuples::null_type>,
+      is_same<ValCons,tuples::null_type>
+    >,
+    equal_ckey_cval_terminal<KeyCons,Value,ValCons,EqualCons>,
+    equal_ckey_cval_normal<KeyCons,Value,ValCons,EqualCons>
+  >::type
+{
+};
+
+template
+<
+  typename KeyCons1,typename Value1,
+  typename KeyCons2, typename Value2,
+  typename CompareCons
+>
+struct compare_ckey_ckey; /* fwd decl. */
+
+template
+<
+  typename KeyCons1,typename Value1,
+  typename KeyCons2, typename Value2,
+  typename CompareCons
+>
+struct compare_ckey_ckey_terminal
+{
+  static bool compare(
+    const KeyCons1&,const Value1&,
+    const KeyCons2&,const Value2&,
+    const CompareCons&)
+  {
+    return false;
+  }
+};
+
+template
+<
+  typename KeyCons1,typename Value1,
+  typename KeyCons2, typename Value2,
+  typename CompareCons
+>
+struct compare_ckey_ckey_normal
+{
+  static bool compare(
+    const KeyCons1& c0,const Value1& v0,
+    const KeyCons2& c1,const Value2& v1,
+    const CompareCons& comp)
+  {
+    if(comp.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return true;
+    if(comp.get_head()(c1.get_head()(v1),c0.get_head()(v0)))return false;
+    return compare_ckey_ckey<
+      BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
+      BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
+      BOOST_DEDUCED_TYPENAME CompareCons::tail_type
+    >::compare(c0.get_tail(),v0,c1.get_tail(),v1,comp.get_tail());
+  }
+};
+
+template
+<
+  typename KeyCons1,typename Value1,
+  typename KeyCons2, typename Value2,
+  typename CompareCons
+>
+struct compare_ckey_ckey:
+  mpl::if_<
+    mpl::or_<
+      is_same<KeyCons1,tuples::null_type>,
+      is_same<KeyCons2,tuples::null_type>
+    >,
+    compare_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>,
+    compare_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>
+  >::type
+{
+};
+
+template
+<
+  typename KeyCons,typename Value,
+  typename ValCons,typename CompareCons
+>
+struct compare_ckey_cval; /* fwd decl. */
+
+template
+<
+  typename KeyCons,typename Value,
+  typename ValCons,typename CompareCons
+>
+struct compare_ckey_cval_terminal
+{
+  static bool compare(
+    const KeyCons&,const Value&,const ValCons&,const CompareCons&)
+  {
+    return false;
+  }
+
+  static bool compare(
+    const ValCons&,const KeyCons&,const Value&,const CompareCons&)
+  {
+    return false;
+  }
+};
+
+template
+<
+  typename KeyCons,typename Value,
+  typename ValCons,typename CompareCons
+>
+struct compare_ckey_cval_normal
+{
+  static bool compare(
+    const KeyCons& c,const Value& v,const ValCons& vc,
+    const CompareCons& comp)
+  {
+    if(comp.get_head()(c.get_head()(v),vc.get_head()))return true;
+    if(comp.get_head()(vc.get_head(),c.get_head()(v)))return false;
+    return compare_ckey_cval<
+      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
+      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
+      BOOST_DEDUCED_TYPENAME CompareCons::tail_type
+    >::compare(c.get_tail(),v,vc.get_tail(),comp.get_tail());
+  }
+
+  static bool compare(
+    const ValCons& vc,const KeyCons& c,const Value& v,
+    const CompareCons& comp)
+  {
+    if(comp.get_head()(vc.get_head(),c.get_head()(v)))return true;
+    if(comp.get_head()(c.get_head()(v),vc.get_head()))return false;
+    return compare_ckey_cval<
+      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
+      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
+      BOOST_DEDUCED_TYPENAME CompareCons::tail_type
+    >::compare(vc.get_tail(),c.get_tail(),v,comp.get_tail());
+  }
+};
+
+template
+<
+  typename KeyCons,typename Value,
+  typename ValCons,typename CompareCons
+>
+struct compare_ckey_cval:
+  mpl::if_<
+    mpl::or_<
+      is_same<KeyCons,tuples::null_type>,
+      is_same<ValCons,tuples::null_type>
+    >,
+    compare_ckey_cval_terminal<KeyCons,Value,ValCons,CompareCons>,
+    compare_ckey_cval_normal<KeyCons,Value,ValCons,CompareCons>
+  >::type
+{
+};
+
+template<typename KeyCons,typename Value,typename HashCons>
+struct hash_ckey; /* fwd decl. */
+
+template<typename KeyCons,typename Value,typename HashCons>
+struct hash_ckey_terminal
+{
+  static std::size_t hash(
+    const KeyCons&,const Value&,const HashCons&,std::size_t carry)
+  {
+    return carry;
+  }
+};
+
+template<typename KeyCons,typename Value,typename HashCons>
+struct hash_ckey_normal
+{
+  static std::size_t hash(
+    const KeyCons& c,const Value& v,const HashCons& h,std::size_t carry=0)
+  {
+    /* same hashing formula as boost::hash_combine */
+
+    carry^=h.get_head()(c.get_head()(v))+0x9e3779b9+(carry<<6)+(carry>>2);
+    return hash_ckey<
+      BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
+      BOOST_DEDUCED_TYPENAME HashCons::tail_type
+    >::hash(c.get_tail(),v,h.get_tail(),carry);
+  }
+};
+
+template<typename KeyCons,typename Value,typename HashCons>
+struct hash_ckey:
+  mpl::if_<
+    is_same<KeyCons,tuples::null_type>,
+    hash_ckey_terminal<KeyCons,Value,HashCons>,
+    hash_ckey_normal<KeyCons,Value,HashCons>
+  >::type
+{
+};
+
+template<typename ValCons,typename HashCons>
+struct hash_cval; /* fwd decl. */
+
+template<typename ValCons,typename HashCons>
+struct hash_cval_terminal
+{
+  static std::size_t hash(const ValCons&,const HashCons&,std::size_t carry)
+  {
+    return carry;
+  }
+};
+
+template<typename ValCons,typename HashCons>
+struct hash_cval_normal
+{
+  static std::size_t hash(
+    const ValCons& vc,const HashCons& h,std::size_t carry=0)
+  {
+    carry^=h.get_head()(vc.get_head())+0x9e3779b9+(carry<<6)+(carry>>2);
+    return hash_cval<
+      BOOST_DEDUCED_TYPENAME ValCons::tail_type,
+      BOOST_DEDUCED_TYPENAME HashCons::tail_type
+    >::hash(vc.get_tail(),h.get_tail(),carry);
+  }
+};
+
+template<typename ValCons,typename HashCons>
+struct hash_cval:
+  mpl::if_<
+    is_same<ValCons,tuples::null_type>,
+    hash_cval_terminal<ValCons,HashCons>,
+    hash_cval_normal<ValCons,HashCons>
+  >::type
+{
+};
+
+} /* namespace multi_index::detail */
+
+/* composite_key_result */
+
+template<typename CompositeKey>
+struct composite_key_result
+{
+  typedef CompositeKey                            composite_key_type;
+  typedef typename composite_key_type::value_type value_type;
+
+  composite_key_result(
+    const composite_key_type& composite_key_,const value_type& value_):
+    composite_key(composite_key_),value(value_)
+  {}
+
+  const composite_key_type& composite_key;
+  const value_type&         value;
+};
+
+/* composite_key */
+
+/* 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<
+  typename Value,
+  BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,KeyFromValue)
+>
+struct composite_key:
+  private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)>
+{
+private:
+  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)> super;
+
+public:
+  typedef super                               key_extractor_tuple;
+  typedef Value                               value_type;
+  typedef composite_key_result<composite_key> result_type;
+
+  composite_key(
+    BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,KeyFromValue)):
+    super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
+  {}
+
+  composite_key(const key_extractor_tuple& x):super(x){}
+
+  const key_extractor_tuple& key_extractors()const{return *this;}
+  key_extractor_tuple&       key_extractors(){return *this;}
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<const ChainedPtr&,const value_type&>,result_type>::type
+#else
+  result_type
+#endif
+
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  result_type operator()(const value_type& x)const
+  {
+    return result_type(*this,x);
+  }
+
+  result_type operator()(const reference_wrapper<const value_type>& x)const
+  {
+    return result_type(*this,x.get());
+  }
+
+  result_type operator()(const reference_wrapper<value_type>& x,int=0)const
+  {
+    return result_type(*this,x.get());
+  }
+};
+
+/* comparison operators */
+
+/* == */
+
+template<typename CompositeKey1,typename CompositeKey2>
+inline bool operator==(
+  const composite_key_result<CompositeKey1>& x,
+  const composite_key_result<CompositeKey2>& y)
+{
+  typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
+  typedef typename CompositeKey1::value_type          value_type1;
+  typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
+  typedef typename CompositeKey2::value_type          value_type2;
+
+  BOOST_STATIC_ASSERT(
+    tuples::length<key_extractor_tuple1>::value==
+    tuples::length<key_extractor_tuple2>::value);
+
+  return detail::equal_ckey_ckey<
+    key_extractor_tuple1,value_type1,
+    key_extractor_tuple2,value_type2,
+    detail::generic_operator_equal_tuple
+  >::compare(
+    x.composite_key.key_extractors(),x.value,
+    y.composite_key.key_extractors(),y.value,
+    detail::generic_operator_equal_tuple());
+}
+
+template<
+  typename CompositeKey,
+  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
+>
+inline bool operator==(
+  const composite_key_result<CompositeKey>& x,
+  const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
+{
+  typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
+  typedef typename CompositeKey::value_type              value_type;
+  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
+  
+  BOOST_STATIC_ASSERT(
+    tuples::length<key_extractor_tuple>::value==
+    tuples::length<key_tuple>::value);
+
+  return detail::equal_ckey_cval<
+    key_extractor_tuple,value_type,
+    key_tuple,detail::generic_operator_equal_tuple
+  >::compare(
+    x.composite_key.key_extractors(),x.value,
+    y,detail::generic_operator_equal_tuple());
+}
+
+template
+<
+  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
+  typename CompositeKey
+>
+inline bool operator==(
+  const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
+  const composite_key_result<CompositeKey>& y)
+{
+  typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
+  typedef typename CompositeKey::value_type              value_type;
+  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
+  
+  BOOST_STATIC_ASSERT(
+    tuples::length<key_extractor_tuple>::value==
+    tuples::length<key_tuple>::value);
+
+  return detail::equal_ckey_cval<
+    key_extractor_tuple,value_type,
+    key_tuple,detail::generic_operator_equal_tuple
+  >::compare(
+    x,y.composite_key.key_extractors(),
+    y.value,detail::generic_operator_equal_tuple());
+}
+
+/* < */
+
+template<typename CompositeKey1,typename CompositeKey2>
+inline bool operator<(
+  const composite_key_result<CompositeKey1>& x,
+  const composite_key_result<CompositeKey2>& y)
+{
+  typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
+  typedef typename CompositeKey1::value_type          value_type1;
+  typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
+  typedef typename CompositeKey2::value_type          value_type2;
+
+  return detail::compare_ckey_ckey<
+   key_extractor_tuple1,value_type1,
+   key_extractor_tuple2,value_type2,
+   detail::generic_operator_less_tuple
+  >::compare(
+    x.composite_key.key_extractors(),x.value,
+    y.composite_key.key_extractors(),y.value,
+    detail::generic_operator_less_tuple());
+}
+
+template
+<
+  typename CompositeKey,
+  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
+>
+inline bool operator<(
+  const composite_key_result<CompositeKey>& x,
+  const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
+{
+  typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
+  typedef typename CompositeKey::value_type              value_type;
+  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
+  
+  return detail::compare_ckey_cval<
+    key_extractor_tuple,value_type,
+    key_tuple,detail::generic_operator_less_tuple
+  >::compare(
+    x.composite_key.key_extractors(),x.value,
+    y,detail::generic_operator_less_tuple());
+}
+
+template
+<
+  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
+  typename CompositeKey
+>
+inline bool operator<(
+  const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
+  const composite_key_result<CompositeKey>& y)
+{
+  typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
+  typedef typename CompositeKey::value_type              value_type;
+  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
+  
+  return detail::compare_ckey_cval<
+    key_extractor_tuple,value_type,
+    key_tuple,detail::generic_operator_less_tuple
+  >::compare(
+    x,y.composite_key.key_extractors(),
+    y.value,detail::generic_operator_less_tuple());
+}
+
+/* rest of comparison operators */
+
+#define BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(t1,t2,a1,a2)                  \
+template<t1,t2> inline bool operator!=(const a1& x,const a2& y)              \
+{                                                                            \
+  return !(x==y);                                                            \
+}                                                                            \
+                                                                             \
+template<t1,t2> inline bool operator>(const a1& x,const a2& y)               \
+{                                                                            \
+  return y<x;                                                                \
+}                                                                            \
+                                                                             \
+template<t1,t2> inline bool operator>=(const a1& x,const a2& y)              \
+{                                                                            \
+  return !(x<y);                                                             \
+}                                                                            \
+                                                                             \
+template<t1,t2> inline bool operator<=(const a1& x,const a2& y)              \
+{                                                                            \
+  return !(y<x);                                                             \
+}
+
+BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
+  typename CompositeKey1,
+  typename CompositeKey2,
+  composite_key_result<CompositeKey1>,
+  composite_key_result<CompositeKey2>
+)
+
+BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
+  typename CompositeKey,
+  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
+  composite_key_result<CompositeKey>,
+  tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>
+)
+
+BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
+  BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
+  typename CompositeKey,
+  tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>,
+  composite_key_result<CompositeKey>
+)
+
+/* composite_key_equal_to */
+
+template
+<
+  BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Pred)
+>
+struct composite_key_equal_to:
+  private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)>
+{
+private:
+  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)> super;
+
+public:
+  typedef super key_eq_tuple;
+
+  composite_key_equal_to(
+    BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Pred)):
+    super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
+  {}
+
+  composite_key_equal_to(const key_eq_tuple& x):super(x){}
+
+  const key_eq_tuple& key_eqs()const{return *this;}
+  key_eq_tuple&       key_eqs(){return *this;}
+
+  template<typename CompositeKey1,typename CompositeKey2>
+  bool operator()(
+    const composite_key_result<CompositeKey1> & x,
+    const composite_key_result<CompositeKey2> & y)const
+  {
+    typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
+    typedef typename CompositeKey1::value_type          value_type1;
+    typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
+    typedef typename CompositeKey2::value_type          value_type2;
+
+    BOOST_STATIC_ASSERT(
+      tuples::length<key_extractor_tuple1>::value<=
+      tuples::length<key_eq_tuple>::value&&
+      tuples::length<key_extractor_tuple1>::value==
+      tuples::length<key_extractor_tuple2>::value);
+
+    return detail::equal_ckey_ckey<
+      key_extractor_tuple1,value_type1,
+      key_extractor_tuple2,value_type2,
+      key_eq_tuple
+    >::compare(
+      x.composite_key.key_extractors(),x.value,
+      y.composite_key.key_extractors(),y.value,
+      key_eqs());
+  }
+  
+  template
+  <
+    typename CompositeKey,
+    BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
+  >
+  bool operator()(
+    const composite_key_result<CompositeKey>& x,
+    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
+  {
+    typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
+    typedef typename CompositeKey::value_type              value_type;
+    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
+
+    BOOST_STATIC_ASSERT(
+      tuples::length<key_extractor_tuple>::value<=
+      tuples::length<key_eq_tuple>::value&&
+      tuples::length<key_extractor_tuple>::value==
+      tuples::length<key_tuple>::value);
+
+    return detail::equal_ckey_cval<
+      key_extractor_tuple,value_type,
+      key_tuple,key_eq_tuple
+    >::compare(x.composite_key.key_extractors(),x.value,y,key_eqs());
+  }
+
+  template
+  <
+    BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
+    typename CompositeKey
+  >
+  bool operator()(
+    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
+    const composite_key_result<CompositeKey>& y)const
+  {
+    typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
+    typedef typename CompositeKey::value_type              value_type;
+    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
+
+    BOOST_STATIC_ASSERT(
+      tuples::length<key_tuple>::value<=
+      tuples::length<key_eq_tuple>::value&&
+      tuples::length<key_tuple>::value==
+      tuples::length<key_extractor_tuple>::value);
+
+    return detail::equal_ckey_cval<
+      key_extractor_tuple,value_type,
+      key_tuple,key_eq_tuple
+    >::compare(x,y.composite_key.key_extractors(),y.value,key_eqs());
+  }
+};
+
+/* composite_key_compare */
+
+template
+<
+  BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Compare)
+>
+struct composite_key_compare:
+  private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)>
+{
+private:
+  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)> super;
+
+public:
+  typedef super key_comp_tuple;
+
+  composite_key_compare(
+    BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Compare)):
+    super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
+  {}
+
+  composite_key_compare(const key_comp_tuple& x):super(x){}
+
+  const key_comp_tuple& key_comps()const{return *this;}
+  key_comp_tuple&       key_comps(){return *this;}
+
+  template<typename CompositeKey1,typename CompositeKey2>
+  bool operator()(
+    const composite_key_result<CompositeKey1> & x,
+    const composite_key_result<CompositeKey2> & y)const
+  {
+    typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
+    typedef typename CompositeKey1::value_type          value_type1;
+    typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
+    typedef typename CompositeKey2::value_type          value_type2;
+
+    BOOST_STATIC_ASSERT(
+      tuples::length<key_extractor_tuple1>::value<=
+      tuples::length<key_comp_tuple>::value||
+      tuples::length<key_extractor_tuple2>::value<=
+      tuples::length<key_comp_tuple>::value);
+
+    return detail::compare_ckey_ckey<
+      key_extractor_tuple1,value_type1,
+      key_extractor_tuple2,value_type2,
+      key_comp_tuple
+    >::compare(
+      x.composite_key.key_extractors(),x.value,
+      y.composite_key.key_extractors(),y.value,
+      key_comps());
+  }
+  
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+  template<typename CompositeKey,typename Value>
+  bool operator()(
+    const composite_key_result<CompositeKey>& x,
+    const Value& y)const
+  {
+    return operator()(x,make_tuple(cref(y)));
+  }
+#endif
+
+  template
+  <
+    typename CompositeKey,
+    BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
+  >
+  bool operator()(
+    const composite_key_result<CompositeKey>& x,
+    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
+  {
+    typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
+    typedef typename CompositeKey::value_type              value_type;
+    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
+
+    BOOST_STATIC_ASSERT(
+      tuples::length<key_extractor_tuple>::value<=
+      tuples::length<key_comp_tuple>::value||
+      tuples::length<key_tuple>::value<=
+      tuples::length<key_comp_tuple>::value);
+
+    return detail::compare_ckey_cval<
+      key_extractor_tuple,value_type,
+      key_tuple,key_comp_tuple
+    >::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
+  }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+  template<typename Value,typename CompositeKey>
+  bool operator()(
+    const Value& x,
+    const composite_key_result<CompositeKey>& y)const
+  {
+    return operator()(make_tuple(cref(x)),y);
+  }
+#endif
+
+  template
+  <
+    BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
+    typename CompositeKey
+  >
+  bool operator()(
+    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
+    const composite_key_result<CompositeKey>& y)const
+  {
+    typedef typename CompositeKey::key_extractor_tuple     key_extractor_tuple;
+    typedef typename CompositeKey::value_type              value_type;
+    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
+
+    BOOST_STATIC_ASSERT(
+      tuples::length<key_tuple>::value<=
+      tuples::length<key_comp_tuple>::value||
+      tuples::length<key_extractor_tuple>::value<=
+      tuples::length<key_comp_tuple>::value);
+
+    return detail::compare_ckey_cval<
+      key_extractor_tuple,value_type,
+      key_tuple,key_comp_tuple
+    >::compare(x,y.composite_key.key_extractors(),y.value,key_comps());
+  }
+};
+
+/* composite_key_hash */
+
+template
+<
+  BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Hash)
+>
+struct composite_key_hash:
+  private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)>
+{
+private:
+  typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)> super;
+
+public:
+  typedef super key_hasher_tuple;
+
+  composite_key_hash(
+    BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Hash)):
+    super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
+  {}
+
+  composite_key_hash(const key_hasher_tuple& x):super(x){}
+
+  const key_hasher_tuple& key_hash_functions()const{return *this;}
+  key_hasher_tuple&       key_hash_functions(){return *this;}
+
+  template<typename CompositeKey>
+  std::size_t operator()(const composite_key_result<CompositeKey> & x)const
+  {
+    typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
+    typedef typename CompositeKey::value_type          value_type;
+
+    BOOST_STATIC_ASSERT(
+      tuples::length<key_extractor_tuple>::value==
+      tuples::length<key_hasher_tuple>::value);
+
+    return detail::hash_ckey<
+      key_extractor_tuple,value_type,
+      key_hasher_tuple
+    >::hash(x.composite_key.key_extractors(),x.value,key_hash_functions());
+  }
+  
+  template<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)>
+  std::size_t operator()(
+    const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x)const
+  {
+    typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
+
+    BOOST_STATIC_ASSERT(
+      tuples::length<key_tuple>::value==
+      tuples::length<key_hasher_tuple>::value);
+
+    return detail::hash_cval<
+      key_tuple,key_hasher_tuple
+    >::hash(x,key_hash_functions());
+  }
+};
+
+/* Instantiations of the former functors with "natural" basic components:
+ * composite_key_result_equal_to uses std::equal_to of the values.
+ * composite_key_result_less     uses std::less.
+ * composite_key_result_greater  uses std::greater.
+ * composite_key_result_hash     uses boost::hash.
+ */
+
+#define BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER                           \
+composite_key_equal_to<                                                      \
+    BOOST_MULTI_INDEX_CK_ENUM(                                               \
+      BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
+      /* the argument is a PP list */                                        \
+      (detail::nth_composite_key_equal_to,                                   \
+        (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
+          BOOST_PP_NIL)))                                                    \
+  >
+
+template<typename CompositeKeyResult>
+struct composite_key_result_equal_to:
+BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
+BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
+{
+private:
+  typedef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER super;
+
+public:
+  typedef CompositeKeyResult  first_argument_type;
+  typedef first_argument_type second_argument_type;
+  typedef bool                result_type;
+
+  using super::operator();
+};
+
+#define BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER                               \
+composite_key_compare<                                                       \
+    BOOST_MULTI_INDEX_CK_ENUM(                                               \
+      BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
+      /* the argument is a PP list */                                        \
+      (detail::nth_composite_key_less,                                       \
+        (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
+          BOOST_PP_NIL)))                                                    \
+  >
+
+template<typename CompositeKeyResult>
+struct composite_key_result_less:
+BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
+BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
+{
+private:
+  typedef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER super;
+
+public:
+  typedef CompositeKeyResult  first_argument_type;
+  typedef first_argument_type second_argument_type;
+  typedef bool                result_type;
+
+  using super::operator();
+};
+
+#define BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER                            \
+composite_key_compare<                                                       \
+    BOOST_MULTI_INDEX_CK_ENUM(                                               \
+      BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
+      /* the argument is a PP list */                                        \
+      (detail::nth_composite_key_greater,                                    \
+        (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
+          BOOST_PP_NIL)))                                                    \
+  >
+
+template<typename CompositeKeyResult>
+struct composite_key_result_greater:
+BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
+BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
+{
+private:
+  typedef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER super;
+
+public:
+  typedef CompositeKeyResult  first_argument_type;
+  typedef first_argument_type second_argument_type;
+  typedef bool                result_type;
+
+  using super::operator();
+};
+
+#define BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER                               \
+composite_key_hash<                                                          \
+    BOOST_MULTI_INDEX_CK_ENUM(                                               \
+      BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N,                             \
+      /* the argument is a PP list */                                        \
+      (detail::nth_composite_key_hash,                                       \
+        (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type,      \
+          BOOST_PP_NIL)))                                                    \
+  >
+
+template<typename CompositeKeyResult>
+struct composite_key_result_hash:
+BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
+BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
+{
+private:
+  typedef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER super;
+
+public:
+  typedef CompositeKeyResult argument_type;
+  typedef std::size_t        result_type;
+
+  using super::operator();
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+/* Specializations of std::equal_to, std::less, std::greater and boost::hash
+ * for composite_key_results enabling interoperation with tuples of values.
+ */
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+namespace std{
+
+template<typename CompositeKey>
+struct equal_to<boost::multi_index::composite_key_result<CompositeKey> >:
+  boost::multi_index::composite_key_result_equal_to<
+    boost::multi_index::composite_key_result<CompositeKey>
+  >
+{
+};
+
+template<typename CompositeKey>
+struct less<boost::multi_index::composite_key_result<CompositeKey> >:
+  boost::multi_index::composite_key_result_less<
+    boost::multi_index::composite_key_result<CompositeKey>
+  >
+{
+};
+
+template<typename CompositeKey>
+struct greater<boost::multi_index::composite_key_result<CompositeKey> >:
+  boost::multi_index::composite_key_result_greater<
+    boost::multi_index::composite_key_result<CompositeKey>
+  >
+{
+};
+
+} /* namespace std */
+
+namespace boost{
+
+template<typename CompositeKey>
+struct hash<boost::multi_index::composite_key_result<CompositeKey> >:
+  boost::multi_index::composite_key_result_hash<
+    boost::multi_index::composite_key_result<CompositeKey>
+  >
+{
+};
+
+} /* namespace boost */
+#else
+/* Lacking template partial specialization, std::equal_to, std::less and
+ * std::greater will still work for composite_key_results although without
+ * tuple interoperability. To achieve the same graceful degrading with
+ * boost::hash, we define the appropriate hash_value overload.
+ */
+
+namespace boost{
+
+#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+namespace multi_index{
+#endif
+
+template<typename CompositeKey>
+inline std::size_t hash_value(
+  const boost::multi_index::composite_key_result<CompositeKey>& x)
+{
+  boost::multi_index::composite_key_result_hash<
+    boost::multi_index::composite_key_result<CompositeKey> > h;
+  return h(x);
+}
+
+#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+} /* namespace multi_index */
+#endif
+
+} /* namespace boost */
+#endif
+
+#undef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
+#undef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
+#undef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
+#undef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
+#undef BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS
+#undef BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO
+#undef BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR
+#undef BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N
+#undef BOOST_MULTI_INDEX_CK_CTOR_ARG
+#undef BOOST_MULTI_INDEX_CK_TEMPLATE_PARM
+#undef BOOST_MULTI_INDEX_CK_ENUM_PARAMS
+#undef BOOST_MULTI_INDEX_CK_ENUM
+#undef BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE
+
+#endif
diff --git a/boost/multi_index/detail/access_specifier.hpp b/boost/multi_index/detail/access_specifier.hpp
new file mode 100644 (file)
index 0000000..5b44d25
--- /dev/null
@@ -0,0 +1,55 @@
+/* Copyright 2003-2006 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_DETAIL_ACCESS_SPECIFIER_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ACCESS_SPECIFIER_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+/* In those compilers that do not accept the member template friend syntax,
+ * some protected and private sections might need to be specified as
+ * public.
+ */
+
+#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+#define BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS public
+#define BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS public
+#else
+#define BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS protected
+#define BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS private
+#endif
+
+/* GCC does not correctly support in-class using declarations for template
+ * functions. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9810
+ * MSVC 7.1/8.0 seem to have a similar problem, though the conditions in
+ * which the error happens are not that simple. I have yet to isolate this
+ * into a snippet suitable for bug reporting.
+ * Sun Studio also has this problem, which might be related, from the
+ * information gathered at Sun forums, with a known issue notified at the
+ * internal bug report 6421933. The bug is present up to Studio Express 2,
+ * the latest preview version of the future Sun Studio 12. As of this writing
+ * (October 2006) it is not known whether a fix will finally make it into the
+ * official Sun Studio 12.
+ */
+
+#if BOOST_WORKAROUND(__GNUC__, <3)||\
+    BOOST_WORKAROUND(__GNUC__,==3)&&(__GNUC_MINOR__<4)||\
+    BOOST_WORKAROUND(BOOST_MSVC,==1310)||\
+    BOOST_WORKAROUND(BOOST_MSVC,==1400)||\
+    BOOST_WORKAROUND(__SUNPRO_CC,BOOST_TESTED_AT(0x590))
+#define BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS public
+#else
+#define BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS private
+#endif
+
+#endif
diff --git a/boost/multi_index/detail/adl_swap.hpp b/boost/multi_index/detail/adl_swap.hpp
new file mode 100644 (file)
index 0000000..0771b4b
--- /dev/null
@@ -0,0 +1,44 @@
+/* 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_DETAIL_ADL_SWAP_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ADL_SWAP_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 <algorithm>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<typename T>
+void adl_swap(T& x,T& y)
+{
+
+#if !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)
+  using std::swap;
+  swap(x,y);
+#else
+  std::swap(x,y);
+#endif
+
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/archive_constructed.hpp b/boost/multi_index/detail/archive_constructed.hpp
new file mode 100644 (file)
index 0000000..3ae6fca
--- /dev/null
@@ -0,0 +1,79 @@
+/* Copyright 2003-2005 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_DETAIL_ARCHIVE_CONSTRUCTED_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ARCHIVE_CONSTRUCTED_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/detail/no_exceptions_support.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/serialization/serialization.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp> 
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* constructs a stack-based object from a serialization archive */
+
+template<typename T>
+struct archive_constructed:private noncopyable
+{
+  template<class Archive>
+  archive_constructed(Archive& ar,const unsigned int version)
+  {
+    serialization::load_construct_data_adl(ar,&get(),version);
+    BOOST_TRY{
+      ar>>get();
+    }
+    BOOST_CATCH(...){
+      (&get())->~T();
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+  template<class Archive>
+  archive_constructed(const char* name,Archive& ar,const unsigned int version)
+  {
+    serialization::load_construct_data_adl(ar,&get(),version);
+    BOOST_TRY{
+      ar>>serialization::make_nvp(name,get());
+    }
+    BOOST_CATCH(...){
+      (&get())->~T();
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+  ~archive_constructed()
+  {
+    (&get())->~T();
+  }
+
+  T& get(){return *static_cast<T*>(static_cast<void*>(&space));}
+
+private:
+  typename aligned_storage<sizeof(T),alignment_of<T>::value>::type space;
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/auto_space.hpp b/boost/multi_index/detail/auto_space.hpp
new file mode 100644 (file)
index 0000000..4515caf
--- /dev/null
@@ -0,0 +1,95 @@
+/* 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_DETAIL_AUTO_SPACE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_AUTO_SPACE_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 <algorithm>
+#include <boost/detail/allocator_utilities.hpp>
+#include <boost/multi_index/detail/adl_swap.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
+#include <boost/noncopyable.hpp>
+#include <memory>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* auto_space provides uninitialized space suitably to store
+ * a given number of elements of a given type.
+ */
+
+/* NB: it is not clear whether using an allocator to handle
+ * zero-sized arrays of elements is conformant or not. GCC 3.3.1
+ * and prior fail here, other stdlibs handle the issue gracefully.
+ * To be on the safe side, the case n==0 is given special treatment.
+ * References:
+ *   GCC Bugzilla, "standard allocator crashes when deallocating segment
+ *    "of zero length", http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14176
+ *   C++ Standard Library Defect Report List (Revision 28), issue 199
+ *     "What does allocate(0) return?",
+ *     http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#199
+ */
+
+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_):pointer(0))
+  {}
+
+  ~auto_space()
+  {
+    if(n_)al_.deallocate(data_,n_);
+  }
+
+  Allocator get_allocator()const{return al_;}
+
+  pointer data()const{return data_;}
+
+  void swap(auto_space& x)
+  {
+    if(al_!=x.al_)adl_swap(al_,x.al_);
+    std::swap(n_,x.n_);
+    std::swap(data_,x.data_);
+  }
+    
+private:
+  typename boost::detail::allocator::rebind_to<
+    Allocator,T>::type                          al_;
+  std::size_t                                   n_;
+  pointer                                       data_;
+};
+
+template<typename T,typename Allocator>
+void swap(auto_space<T,Allocator>& x,auto_space<T,Allocator>& y)
+{
+  x.swap(y);
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/base_type.hpp b/boost/multi_index/detail/base_type.hpp
new file mode 100644 (file)
index 0000000..fd6e364
--- /dev/null
@@ -0,0 +1,87 @@
+/* Copyright 2003-2005 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_DETAIL_BASE_TYPE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_BASE_TYPE_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/detail/workaround.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/apply.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/multi_index/detail/index_base.hpp>
+#include <boost/multi_index/detail/is_index_list.hpp>
+#include <boost/multi_index/detail/msvc_index_specifier.hpp>
+#include <boost/static_assert.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* MPL machinery to construct a linear hierarchy of indices out of
+ * a index list.
+ */
+
+#if BOOST_WORKAROUND(BOOST_MSVC,<1310)
+struct index_applier
+{
+  template<typename IndexSpecifierMeta,typename SuperMeta>
+  struct apply:
+    msvc_index_specifier<IndexSpecifierMeta::type>::
+      template result_index_class<SuperMeta>
+  {
+  }; 
+};
+#else
+struct index_applier
+{
+  template<typename IndexSpecifierMeta,typename SuperMeta>
+  struct apply
+  {
+    typedef typename IndexSpecifierMeta::type            index_specifier;
+    typedef typename index_specifier::
+      BOOST_NESTED_TEMPLATE index_class<SuperMeta>::type type;
+  }; 
+};
+#endif
+
+template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
+struct nth_layer
+{
+  BOOST_STATIC_CONSTANT(int,length=mpl::size<IndexSpecifierList>::value);
+
+  typedef typename  mpl::eval_if_c<
+    N==length,
+    mpl::identity<index_base<Value,IndexSpecifierList,Allocator> >,
+    mpl::apply2<
+      index_applier,
+      mpl::at_c<IndexSpecifierList,N>,
+      nth_layer<N+1,Value,IndexSpecifierList,Allocator>
+    >
+  >::type type;
+};
+
+template<typename Value,typename IndexSpecifierList,typename Allocator>
+struct multi_index_base_type:nth_layer<0,Value,IndexSpecifierList,Allocator>
+{
+  BOOST_STATIC_ASSERT(detail::is_index_list<IndexSpecifierList>::value);
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/bidir_node_iterator.hpp b/boost/multi_index/detail/bidir_node_iterator.hpp
new file mode 100644 (file)
index 0000000..0ce1cee
--- /dev/null
@@ -0,0 +1,113 @@
+/* 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_DETAIL_BIDIR_NODE_ITERATOR_HPP
+#define BOOST_MULTI_INDEX_DETAIL_BIDIR_NODE_ITERATOR_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/operators.hpp>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/split_member.hpp>
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Iterator class for node-based indices with bidirectional
+ * iterators (ordered and sequenced indices.)
+ */
+
+template<typename Node,typename Derived=mpl::na>
+class bidir_node_iterator:
+  public bidirectional_iterator_helper<
+    bidir_node_iterator<Node,Derived>,
+    typename Node::value_type,
+    std::ptrdiff_t,
+    const typename Node::value_type*,
+    const typename Node::value_type&>
+{
+public:
+  bidir_node_iterator(){}
+  explicit bidir_node_iterator(Node* node_):node(node_){}
+
+  const typename Node::value_type& operator*()const
+  {
+    return node->value();
+  }
+
+  bidir_node_iterator& operator++()
+  {
+    Node::increment(node);
+    return *this;
+  }
+
+  bidir_node_iterator& operator--()
+  {
+    Node::decrement(node);
+    return *this;
+  }
+
+#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.
+   */
+
+  BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+  typedef typename Node::base_type node_base_type;
+
+  template<class Archive>
+  void save(Archive& ar,const unsigned int)const
+  {
+    node_base_type* bnode=node;
+    ar<<serialization::make_nvp("pointer",bnode);
+  }
+
+  template<class Archive>
+  void load(Archive& ar,const unsigned int)
+  {
+    node_base_type* bnode;
+    ar>>serialization::make_nvp("pointer",bnode);
+    node=static_cast<Node*>(bnode);
+  }
+#endif
+
+  /* get_node is not to be used by the user */
+
+  typedef Node node_type;
+
+  Node* get_node()const{return node;}
+
+private:
+  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 */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/bucket_array.hpp b/boost/multi_index/detail/bucket_array.hpp
new file mode 100644 (file)
index 0000000..1b0ffe7
--- /dev/null
@@ -0,0 +1,211 @@
+/* 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_DETAIL_BUCKET_ARRAY_HPP
+#define BOOST_MULTI_INDEX_DETAIL_BUCKET_ARRAY_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 <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>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/archive/archive_exception.hpp>
+#include <boost/serialization/access.hpp>
+#include <boost/throw_exception.hpp> 
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* bucket structure for use by hashed indices */
+
+class bucket_array_base:private noncopyable
+{
+protected:
+  inline static std::size_t next_prime(std::size_t n)
+  {
+    static const std::size_t prime_list[]={
+      53ul, 97ul, 193ul, 389ul, 769ul,
+      1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
+      49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
+      1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
+      50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
+      1610612741ul, 3221225473ul,
+
+#if ((((ULONG_MAX>>16)>>16)>>16)>>15)==0 /* unsigned long less than 64 bits */
+      4294967291ul
+#else
+      /* obtained with aid from
+       *   http://javaboutique.internet.com/prime_numb/
+       *   http://www.rsok.com/~jrm/next_ten_primes.html
+       * and verified with
+       *   http://www.alpertron.com.ar/ECM.HTM
+       */
+
+      6442450939ul, 12884901893ul, 25769803751ul, 51539607551ul,
+      103079215111ul, 206158430209ul, 412316860441ul, 824633720831ul,
+      1649267441651ul, 3298534883309ul, 6597069766657ul, 13194139533299ul,
+      26388279066623ul, 52776558133303ul, 105553116266489ul, 211106232532969ul,
+      422212465066001ul, 844424930131963ul, 1688849860263953ul,
+      3377699720527861ul, 6755399441055731ul, 13510798882111483ul,
+      27021597764222939ul, 54043195528445957ul, 108086391056891903ul,
+      216172782113783843ul, 432345564227567621ul, 864691128455135207ul,
+      1729382256910270481ul, 3458764513820540933ul, 6917529027641081903ul,
+      13835058055282163729ul, 18446744073709551557ul
+#endif
+
+    };
+    static const std::size_t prime_list_size=
+      sizeof(prime_list)/sizeof(prime_list[0]);
+
+    std::size_t const *bound=
+      std::lower_bound(prime_list,prime_list+prime_list_size,n);
+    if(bound==prime_list+prime_list_size)bound--;
+    return *bound;
+  }
+};
+
+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:
+  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)
+  {
+    clear();
+    end()->next()=end_;
+    end_->next()=end();
+  }
+
+  std::size_t size()const
+  {
+    return size_;
+  }
+
+  std::size_t position(std::size_t hash)const
+  {
+    return hash%size_;
+  }
+
+  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){
+      pointer x=at(n);
+      if(x->next()!=x)return n;
+    }
+  }
+
+  void clear()
+  {
+    for(pointer x=begin(),y=end();x!=y;++x)x->next()=x;
+  }
+
+  void swap(bucket_array& x)
+  {
+    std::swap(size_,x.size_);
+    spc.swap(x.spc);
+  }
+
+private:
+  std::size_t                          size_;
+  auto_space<node_impl_type,Allocator> spc;
+
+  pointer buckets()const
+  {
+    return spc.data();
+  }
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  friend class boost::serialization::access;
+  
+  /* bucket_arrays do not emit any kind of serialization info. They are
+   * fed to Boost.Serialization as hashed index iterators need to track
+   * them during serialization.
+   */
+
+  template<class Archive>
+  void serialize(Archive&,const unsigned int)
+  {
+  }
+#endif
+};
+
+template<typename Allocator>
+void swap(bucket_array<Allocator>& x,bucket_array<Allocator>& y)
+{
+  x.swap(y);
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+/* bucket_arrays never get constructed directly by Boost.Serialization,
+ * as archives are always fed pointers to previously existent
+ * arrays. So, if this is called it means we are dealing with a
+ * somehow invalid archive.
+ */
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+namespace serialization{
+#else
+namespace multi_index{
+namespace detail{
+#endif
+
+template<class Archive,typename Allocator>
+inline void load_construct_data(
+  Archive&,boost::multi_index::detail::bucket_array<Allocator>*,
+  const unsigned int)
+{
+  throw_exception(
+    archive::archive_exception(archive::archive_exception::other_exception));
+}
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+} /* namespace serialization */
+#else
+} /* namespace multi_index::detail */
+} /* namespace multi_index */
+#endif
+
+#endif
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/converter.hpp b/boost/multi_index/detail/converter.hpp
new file mode 100644 (file)
index 0000000..f4fb47b
--- /dev/null
@@ -0,0 +1,52 @@
+/* Copyright 2003-2005 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_DETAIL_CONVERTER_HPP
+#define BOOST_MULTI_INDEX_DETAIL_CONVERTER_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* converter offers means to access indices of a given multi_index_container
+ * and for convertibilty between index iterators, so providing a
+ * localized access point for get() and project() functions.
+ */
+
+template<typename MultiIndexContainer,typename Index>
+struct converter
+{
+  static const Index& index(const MultiIndexContainer& x){return x;}
+  static Index&       index(MultiIndexContainer& x){return x;}
+
+  static typename Index::const_iterator const_iterator(
+    const MultiIndexContainer& x,typename MultiIndexContainer::node_type* node)
+  {
+    return x.Index::make_iterator(node);
+  }
+
+  static typename Index::iterator iterator(
+    MultiIndexContainer& x,typename MultiIndexContainer::node_type* node)
+  {
+    return x.Index::make_iterator(node);
+  }
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/copy_map.hpp b/boost/multi_index/detail/copy_map.hpp
new file mode 100644 (file)
index 0000000..21ff51e
--- /dev/null
@@ -0,0 +1,140 @@
+/* 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_DETAIL_COPY_MAP_HPP
+#define BOOST_MULTI_INDEX_DETAIL_COPY_MAP_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 <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>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* copy_map is used as an auxiliary structure during copy_() operations.
+ * When a container with n nodes is replicated, node_map holds the pairings
+ * between original and copied nodes, and provides a fast way to find a
+ * copied node from an original one.
+ * The semantics of the class are not simple, and no attempt has been made
+ * to enforce it: multi_index_container handles it right. On the other hand,
+ * the const interface, which is the one provided to index implementations,
+ * only allows for:
+ *   - Enumeration of pairs of (original,copied) nodes (excluding the headers),
+ *   - fast retrieval of copied nodes (including the headers.)
+ */
+
+template <typename Node>
+struct copy_map_entry
+{
+  copy_map_entry(Node* f,Node* s):first(f),second(s){}
+
+  Node* first;
+  Node* second;
+
+  bool operator<(const copy_map_entry<Node>& x)const
+  {
+    return std::less<Node*>()(first,x.first);
+  }
+};
+
+template <typename Node,typename Allocator>
+class copy_map:private noncopyable
+{
+public:
+  typedef const copy_map_entry<Node>* const_iterator;
+
+  copy_map(
+    const Allocator& al,std::size_t size,Node* header_org,Node* header_cpy):
+    al_(al),size_(size),spc(al_,size_),n(0),
+    header_org_(header_org),header_cpy_(header_cpy),released(false)
+  {}
+
+  ~copy_map()
+  {
+    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);
+      }
+    }
+  }
+
+  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);
+    BOOST_TRY{
+      boost::detail::allocator::construct(
+        &(spc.data()+n)->second->value(),node->value());
+    }
+    BOOST_CATCH(...){
+      deallocate((spc.data()+n)->second);
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+    ++n;
+
+    if(n==size_)std::sort(&*spc.data(),&*spc.data()+size_);
+  }
+
+  Node* find(Node* node)const
+  {
+    if(node==header_org_)return header_cpy_;
+    return std::lower_bound(
+      begin(),end(),copy_map_entry<Node>(node,0))->second;
+  }
+
+  void release()
+  {
+    released=true;
+  }
+
+private:
+  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(static_cast<allocator_pointer>(node),1);
+  }
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/duplicates_iterator.hpp b/boost/multi_index/detail/duplicates_iterator.hpp
new file mode 100644 (file)
index 0000000..7cc126c
--- /dev/null
@@ -0,0 +1,120 @@
+/* Copyright 2003-2006 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_DETAIL_DUPLICATES_ITERATOR_HPP
+#define BOOST_MULTI_INDEX_DETAIL_DUPLICATES_ITERATOR_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 <cstddef>
+#include <iterator>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* duplicates_operator is given a range of ordered elements and
+ * passes only over those which are duplicated.
+ */
+
+template<typename Node,typename Predicate>
+class duplicates_iterator
+{
+public:
+  typedef typename Node::value_type        value_type;
+  typedef std::ptrdiff_t                   difference_type;
+  typedef const typename Node::value_type* pointer;
+  typedef const typename Node::value_type& reference;
+  typedef std::forward_iterator_tag        iterator_category;
+
+  duplicates_iterator(Node* node_,Node* end_,Predicate pred_):
+    node(node_),begin_chunk(0),end(end_),pred(pred_)
+  {
+    advance();
+  }
+
+  duplicates_iterator(Node* end_,Predicate pred_):
+    node(end_),begin_chunk(end_),end(end_),pred(pred_)
+  {
+  }
+
+  reference operator*()const
+  {
+    return node->value();
+  }
+
+  pointer operator->()const
+  {
+    return &node->value();
+  }
+
+  duplicates_iterator& operator++()
+  {
+    Node::increment(node);
+    sync();
+    return *this;
+  }
+
+  duplicates_iterator operator++(int)
+  {
+    duplicates_iterator tmp(*this);
+    ++(*this);
+    return tmp;
+  }
+
+  Node* get_node()const{return node;}
+
+private:
+  void sync()
+  {
+    if(node!=end&&pred(begin_chunk->value(),node->value()))advance();
+  }
+
+  void advance()
+  {
+    for(Node* node2=node;node!=end;node=node2){
+      Node::increment(node2);
+      if(node2!=end&&!pred(node->value(),node2->value()))break;
+    }
+    begin_chunk=node;
+  }
+
+  Node*     node;
+  Node*     begin_chunk;
+  Node*     end;
+  Predicate pred;
+};
+
+template<typename Node,typename Predicate>
+bool operator==(
+  const duplicates_iterator<Node,Predicate>& x,
+  const duplicates_iterator<Node,Predicate>& y)
+{
+  return x.get_node()==y.get_node();
+}
+
+template<typename Node,typename Predicate>
+bool operator!=(
+  const duplicates_iterator<Node,Predicate>& x,
+  const duplicates_iterator<Node,Predicate>& y)
+{
+  return !(x==y);
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/has_tag.hpp b/boost/multi_index/detail/has_tag.hpp
new file mode 100644 (file)
index 0000000..1037978
--- /dev/null
@@ -0,0 +1,42 @@
+/* Copyright 2003-2005 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_DETAIL_HAS_TAG_HPP
+#define BOOST_MULTI_INDEX_DETAIL_HAS_TAG_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/contains.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* determines whether an index type has a given tag in its tag list */
+
+template<typename Tag>
+struct has_tag
+{
+  template<typename Index>
+  struct apply:mpl::contains<BOOST_DEDUCED_TYPENAME Index::tag_list,Tag>
+  {
+  }; 
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/hash_index_args.hpp b/boost/multi_index/detail/hash_index_args.hpp
new file mode 100644 (file)
index 0000000..6211c8b
--- /dev/null
@@ -0,0 +1,105 @@
+/* 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_DETAIL_HASH_INDEX_ARGS_HPP
+#define BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_ARGS_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/functional/hash.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/multi_index/tag.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <functional>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Hashed index specifiers can be instantiated in two forms:
+ *
+ *   (hashed_unique|hashed_non_unique)<
+ *     KeyFromValue,
+ *     Hash=boost::hash<KeyFromValue::result_type>,
+ *     Pred=std::equal_to<KeyFromValue::result_type> >
+ *   (hashed_unique|hashed_non_unique)<
+ *     TagList,
+ *     KeyFromValue,
+ *     Hash=boost::hash<KeyFromValue::result_type>,
+ *     Pred=std::equal_to<KeyFromValue::result_type> >
+ *
+ * hashed_index_args implements the machinery to accept this
+ * argument-dependent polymorphism.
+ */
+
+template<typename KeyFromValue>
+struct index_args_default_hash
+{
+  typedef ::boost::hash<typename KeyFromValue::result_type> type;
+};
+
+template<typename KeyFromValue>
+struct index_args_default_pred
+{
+  typedef std::equal_to<typename KeyFromValue::result_type> type;
+};
+
+template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
+struct hashed_index_args
+{
+  typedef is_tag<Arg1> full_form;
+
+  typedef typename mpl::if_<
+    full_form,
+    Arg1,
+    tag< > >::type                                   tag_list_type;
+  typedef typename mpl::if_<
+    full_form,
+    Arg2,
+    Arg1>::type                                      key_from_value_type;
+  typedef typename mpl::if_<
+    full_form,
+    Arg3,
+    Arg2>::type                                      supplied_hash_type;
+  typedef typename mpl::eval_if<
+    mpl::is_na<supplied_hash_type>,
+    index_args_default_hash<key_from_value_type>,
+    mpl::identity<supplied_hash_type>
+  >::type                                            hash_type;
+  typedef typename mpl::if_<
+    full_form,
+    Arg4,
+    Arg3>::type                                      supplied_pred_type;
+  typedef typename mpl::eval_if<
+    mpl::is_na<supplied_pred_type>,
+    index_args_default_pred<key_from_value_type>,
+    mpl::identity<supplied_pred_type>
+  >::type                                            pred_type;
+
+  BOOST_STATIC_ASSERT(is_tag<tag_list_type>::value);
+  BOOST_STATIC_ASSERT(!mpl::is_na<key_from_value_type>::value);
+  BOOST_STATIC_ASSERT(!mpl::is_na<hash_type>::value);
+  BOOST_STATIC_ASSERT(!mpl::is_na<pred_type>::value);
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/hash_index_iterator.hpp b/boost/multi_index/detail/hash_index_iterator.hpp
new file mode 100644 (file)
index 0000000..1d62543
--- /dev/null
@@ -0,0 +1,111 @@
+/* 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_DETAIL_HASH_INDEX_ITERATOR_HPP
+#define BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_ITERATOR_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/operators.hpp>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/split_member.hpp>
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Iterator class for hashed indices.
+ */
+
+template<typename Node,typename BucketArray,typename Derived=mpl::na>
+class hashed_index_iterator:
+  public forward_iterator_helper<
+    hashed_index_iterator<Node,BucketArray,Derived>,
+    typename Node::value_type,
+    std::ptrdiff_t,
+    const typename Node::value_type*,
+    const typename Node::value_type&>
+{
+public:
+  hashed_index_iterator(){}
+  hashed_index_iterator(Node* node_,BucketArray* buckets_):
+    node(node_),buckets(buckets_)
+  {}
+
+  const typename Node::value_type& operator*()const
+  {
+    return node->value();
+  }
+
+  hashed_index_iterator& operator++()
+  {
+    Node::increment(node,buckets->begin(),buckets->end());
+    return *this;
+  }
+
+#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.
+   */
+  
+  BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+  typedef typename Node::base_type node_base_type;
+
+  template<class Archive>
+  void save(Archive& ar,const unsigned int)const
+  {
+    node_base_type* bnode=node;
+    ar<<serialization::make_nvp("pointer",bnode);
+    ar<<serialization::make_nvp("pointer",buckets);
+  }
+
+  template<class Archive>
+  void load(Archive& ar,const unsigned int)
+  {
+    node_base_type* bnode;
+    ar>>serialization::make_nvp("pointer",bnode);
+    node=static_cast<Node*>(bnode);
+    ar>>serialization::make_nvp("pointer",buckets);
+  }
+#endif
+
+  /* get_node is not to be used by the user */
+
+  typedef Node node_type;
+
+  Node* get_node()const{return node;}
+
+private:
+  Node*        node;
+  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 */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/hash_index_node.hpp b/boost/multi_index/detail/hash_index_node.hpp
new file mode 100644 (file)
index 0000000..93774c0
--- /dev/null
@@ -0,0 +1,165 @@
+/* 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_DETAIL_HASH_INDEX_NODE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_NODE_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/detail/allocator_utilities.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
+#include <functional>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* singly-linked node for use by hashed_index */
+
+template<typename Allocator>
+struct hashed_index_node_impl
+{
+  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(pointer& x,pointer bbegin,pointer bbend)
+  {
+    std::less_equal<pointer> leq;
+
+    x=x->next();
+    if(leq(bbegin,x)&&leq(x,bbend)){ /* bucket node */
+      do{
+        ++x;
+      }while(x->next()==x);
+      x=x->next();
+    }
+  }
+
+  static void link(pointer x,pointer pos)
+  {
+    x->next()=pos->next();
+    pos->next()=x;
+  };
+
+  static void unlink(pointer x)
+  {
+    pointer y=x->next();
+    while(y->next()!=x){y=y->next();}
+    y->next()=x->next();
+  }
+
+  static pointer prev(pointer x)
+  {
+    pointer y=x->next();
+    while(y->next()!=x){y=y->next();}
+    return y;
+  }
+
+  static void unlink_next(pointer x)
+  {
+    x->next()=x->next()->next();
+  }
+
+private:
+  pointer next_;
+};
+
+template<typename Super>
+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>
+{
+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 trampoline*>(&*x));
+  }
+
+  static void increment(
+    hashed_index_node*& x,impl_pointer bbegin,impl_pointer bend)
+  {
+    impl_pointer xi=x->impl();
+    trampoline::increment(xi,bbegin,bend);
+    x=from_impl(xi);
+  }
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/header_holder.hpp b/boost/multi_index/detail/header_holder.hpp
new file mode 100644 (file)
index 0000000..8bd1e5d
--- /dev/null
@@ -0,0 +1,50 @@
+/* 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_DETAIL_HEADER_HOLDER_HPP
+#define BOOST_MULTI_INDEX_DETAIL_HEADER_HOLDER_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/noncopyable.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* A utility class used to hold a pointer to the header node.
+ * The base from member idiom is used because index classes, which are
+ * superclasses of multi_index_container, need this header in construction
+ * time. The allocation is made by the allocator of the multi_index_container
+ * class --hence, this allocator needs also be stored resorting
+ * to the base from member trick.
+ */
+
+template<typename NodeTypePtr,typename Final>
+struct header_holder:private noncopyable
+{
+  header_holder():member(final().allocate_node()){}
+  ~header_holder(){final().deallocate_node(&*member);}
+
+  NodeTypePtr member;
+
+private:
+  Final& final(){return *static_cast<Final*>(this);}
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/index_base.hpp b/boost/multi_index/detail/index_base.hpp
new file mode 100644 (file)
index 0000000..6391968
--- /dev/null
@@ -0,0 +1,185 @@
+/* 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_DETAIL_INDEX_BASE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_INDEX_BASE_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/call_traits.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/multi_index/detail/copy_map.hpp>
+#include <boost/multi_index/detail/node_type.hpp>
+#include <boost/multi_index_container_fwd.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <utility>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/multi_index/detail/index_loader.hpp>
+#include <boost/multi_index/detail/index_saver.hpp>
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* The role of this class is threefold:
+ *   - tops the linear hierarchy of indices.
+ *   - terminates some cascading backbone function calls (insert_, etc.),
+ *   - grants access to the backbone functions of the final
+ *     multi_index_container class (for access restriction reasons, these
+ *     cannot be called directly from the index classes.)
+ */
+
+template<typename Value,typename IndexSpecifierList,typename Allocator>
+class index_base
+{
+protected:
+  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<
+    Value,IndexSpecifierList,Allocator>       final_type;
+  typedef tuples::null_type                   ctor_args_list;
+  typedef typename 
+    boost::detail::allocator::rebind_to<
+      Allocator,
+      typename Allocator::value_type>::type   final_allocator_type;
+  typedef mpl::vector0<>                      index_type_list;
+  typedef mpl::vector0<>                      iterator_type_list;
+  typedef mpl::vector0<>                      const_iterator_type_list;
+  typedef copy_map<
+    final_node_type,
+    final_allocator_type>                     copy_map_type;
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  typedef index_saver<
+    node_type,
+    final_allocator_type>                     index_saver_type;
+  typedef index_loader<
+    node_type,
+    final_node_type,
+    final_allocator_type>                     index_loader_type;
+#endif
+
+private:
+  typedef typename call_traits<Value>::param_type value_param_type;
+
+protected:
+  explicit index_base(const ctor_args_list&,const Allocator&){}
+
+  void copy_(
+    const index_base<Value,IndexSpecifierList,Allocator>&,const copy_map_type&)
+  {}
+
+  node_type* insert_(value_param_type v,node_type* x)
+  {
+    boost::detail::allocator::construct(&x->value(),v);
+    return x;
+  }
+
+  node_type* insert_(value_param_type v,node_type*,node_type* x)
+  {
+    boost::detail::allocator::construct(&x->value(),v);
+    return x;
+  }
+
+  void erase_(node_type* x)
+  {
+    boost::detail::allocator::destroy(&x->value());
+  }
+
+  void delete_node_(node_type* x)
+  {
+    boost::detail::allocator::destroy(&x->value());
+  }
+
+  void clear_(){}
+
+  void swap_(index_base<Value,IndexSpecifierList,Allocator>&){}
+
+  bool replace_(value_param_type v,node_type* x)
+  {
+    x->value()=v;
+    return true;
+  }
+
+  bool modify_(node_type*){return true;}
+
+  bool modify_rollback_(node_type*){return true;}
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  /* serialization */
+
+  template<typename Archive>
+  void save_(Archive&,const unsigned int,const index_saver_type&)const{}
+
+  template<typename Archive>
+  void load_(Archive&,const unsigned int,const index_loader_type&){}
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+  /* invariant stuff */
+
+  bool invariant_()const{return true;}
+#endif
+
+  /* access to backbone memfuns of Final class */
+
+  final_type&       final(){return *static_cast<final_type*>(this);}
+  const final_type& final()const{return *static_cast<const final_type*>(this);}
+
+  final_node_type* final_header()const{return final().header();}
+
+  bool        final_empty_()const{return final().empty_();}
+  std::size_t final_size_()const{return final().size_();}
+  std::size_t final_max_size_()const{return final().max_size_();}
+
+  std::pair<final_node_type*,bool> final_insert_(value_param_type x)
+    {return final().insert_(x);}
+  std::pair<final_node_type*,bool> final_insert_(
+    value_param_type x,final_node_type* position)
+    {return final().insert_(x,position);}
+
+  void final_erase_(final_node_type* x){final().erase_(x);}
+
+  void final_delete_node_(final_node_type* x){final().delete_node_(x);}
+  void final_delete_all_nodes_(){final().delete_all_nodes_();}
+  void final_clear_(){final().clear_();}
+
+  void final_swap_(final_type& x){final().swap_(x);}
+  bool final_replace_(
+    value_param_type k,final_node_type* x)
+    {return final().replace_(k,x);}
+
+  template<typename Modifier>
+  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
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/index_loader.hpp b/boost/multi_index/detail/index_loader.hpp
new file mode 100644 (file)
index 0000000..61fb2b0
--- /dev/null
@@ -0,0 +1,138 @@
+/* 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_DETAIL_INDEX_LOADER_HPP
+#define BOOST_MULTI_INDEX_DETAIL_INDEX_LOADER_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 <algorithm>
+#include <boost/archive/archive_exception.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/multi_index/detail/auto_space.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/throw_exception.hpp> 
+#include <cstddef>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Counterpart of index_saver (check index_saver.hpp for serialization
+ * details.)* multi_index_container is in charge of supplying the info about
+ * the base sequence, and each index can subsequently load itself using the
+ * const interface of index_loader.
+ */
+
+template<typename Node,typename FinalNode,typename Allocator>
+class index_loader:private noncopyable
+{
+public:
+  index_loader(const Allocator& al,std::size_t size):
+    spc(al,size),size_(size),n(0),sorted(false)
+  {
+  }
+
+  template<class Archive>
+  void add(Node* node,Archive& ar,const unsigned int)
+  {
+    ar>>serialization::make_nvp("position",*node);
+    entries()[n++]=node;
+  }
+
+  template<class Archive>
+  void add_track(Node* node,Archive& ar,const unsigned int)
+  {
+    ar>>serialization::make_nvp("position",*node);
+  }
+
+  /* A rearranger is passed two nodes, and is expected to
+   * reposition the second after the first.
+   * If the first node is 0, then the second should be moved
+   * to the beginning of the sequence.
+   */
+
+  template<typename Rearranger,class Archive>
+  void load(Rearranger r,Archive& ar,const unsigned int)const
+  {
+    FinalNode* prev=unchecked_load_node(ar);
+    if(!prev)return;
+
+    if(!sorted){
+      std::sort(entries(),entries()+size_);
+      sorted=true;
+    }
+
+    check_node(prev);
+
+    for(;;){
+      for(;;){
+        FinalNode* node=load_node(ar);
+        if(!node)break;
+
+        if(node==prev)prev=0;
+        r(prev,node);
+
+        prev=node;
+      }
+      prev=load_node(ar);
+      if(!prev)break;
+    }
+  }
+
+private:
+  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.
+   */
+
+  template<class Archive>
+  FinalNode* unchecked_load_node(Archive& ar)const
+  {
+    Node* node=0;
+    ar>>serialization::make_nvp("pointer",node);
+    return static_cast<FinalNode*>(node);
+  }
+
+  template<class Archive>
+  FinalNode* load_node(Archive& ar)const
+  {
+    Node* node=0;
+    ar>>serialization::make_nvp("pointer",node);
+    check_node(node);
+    return static_cast<FinalNode*>(node);
+  }
+
+  void check_node(Node* node)const
+  {
+    if(node!=0&&!std::binary_search(entries(),entries()+size_,node)){
+      throw_exception(
+        archive::archive_exception(
+          archive::archive_exception::other_exception));
+    }
+  }
+
+  auto_space<Node*,Allocator> spc;
+  std::size_t                 size_;
+  std::size_t                 n;
+  mutable bool                sorted;
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/index_matcher.hpp b/boost/multi_index/detail/index_matcher.hpp
new file mode 100644 (file)
index 0000000..23060b3
--- /dev/null
@@ -0,0 +1,248 @@
+/* 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_DETAIL_INDEX_MATCHER_HPP
+#define BOOST_MULTI_INDEX_DETAIL_INDEX_MATCHER_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 <algorithm>
+#include <boost/noncopyable.hpp>
+#include <boost/multi_index/detail/auto_space.hpp>
+#include <cstddef>
+#include <functional>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* index_matcher compares a sequence of elements against a
+ * base sequence, identifying those elements that belong to the
+ * longest subsequence which is ordered with respect to the base.
+ * For instance, if the base sequence is:
+ *
+ *   0 1 2 3 4 5 6 7 8 9
+ *
+ * and the compared sequence (not necesarilly the same length):
+ *
+ *   1 4 2 3 0 7 8 9
+ *
+ * the elements of the longest ordered subsequence are:
+ *
+ *   1 2 3 7 8 9
+ * 
+ * The algorithm for obtaining such a subsequence is called
+ * Patience Sorting, described in ch. 1 of:
+ *   Aldous, D., Diaconis, P.: "Longest increasing subsequences: from
+ *   patience sorting to the Baik-Deift-Johansson Theorem", Bulletin
+ *   of the American Mathematical Society, vol. 36, no 4, pp. 413-432,
+ *   July 1999.
+ *   http://www.ams.org/bull/1999-36-04/S0273-0979-99-00796-X/
+ *   S0273-0979-99-00796-X.pdf
+ *
+ * This implementation is not fully generic since it assumes that
+ * the sequences given are pointed to by index iterators (having a
+ * get_node() memfun.)
+ */
+
+namespace index_matcher{
+
+/* The algorithm stores the nodes of the base sequence and a number
+ * of "piles" that are dynamically updated during the calculation
+ * stage. From a logical point of view, nodes form an independent
+ * sequence from piles. They are stored together so as to minimize
+ * allocated memory.
+ */
+
+struct entry
+{
+  entry(void* node_,std::size_t pos_=0):node(node_),pos(pos_){}
+
+  /* node stuff */
+
+  void*       node;
+  std::size_t pos;
+  entry*      previous;
+  bool        ordered;
+
+  struct less_by_node
+  {
+    bool operator()(
+      const entry& x,const entry& y)const
+    {
+      return std::less<void*>()(x.node,y.node);
+    }
+  };
+
+  /* pile stuff */
+
+  std::size_t pile_top;
+  entry*      pile_top_entry;
+
+  struct less_by_pile_top
+  {
+    bool operator()(
+      const entry& x,const entry& y)const
+    {
+      return x.pile_top<y.pile_top;
+    }
+  };
+};
+
+/* common code operating on void *'s */
+
+template<typename Allocator>
+class algorithm_base:private noncopyable
+{
+protected:
+  algorithm_base(const Allocator& al,std::size_t size):
+    spc(al,size),size_(size),n(0),sorted(false)
+  {
+  }
+
+  void add(void* node)
+  {
+    entries()[n]=entry(node,n);
+    ++n;
+  }
+
+  void begin_algorithm()const
+  {
+    if(!sorted){
+      std::sort(entries(),entries()+size_,entry::less_by_node());
+      sorted=true;
+    }
+    num_piles=0;
+  }
+
+  void add_node_to_algorithm(void* node)const
+  {
+    entry* ent=
+      std::lower_bound(
+        entries(),entries()+size_,
+        entry(node),entry::less_by_node()); /* localize entry */
+    ent->ordered=false;
+    std::size_t n=ent->pos;                 /* get its position */
+
+    entry dummy(0);
+    dummy.pile_top=n;
+
+    entry* pile_ent=                        /* find the first available pile */
+      std::lower_bound(                     /* to stack the entry            */
+        entries(),entries()+num_piles,
+        dummy,entry::less_by_pile_top());
+
+    pile_ent->pile_top=n;                   /* stack the entry */
+    pile_ent->pile_top_entry=ent;        
+
+    /* if not the first pile, link entry to top of the preceding pile */
+    if(pile_ent>&entries()[0]){ 
+      ent->previous=(pile_ent-1)->pile_top_entry;
+    }
+
+    if(pile_ent==&entries()[num_piles]){    /* new pile? */
+      ++num_piles;
+    }
+  }
+
+  void finish_algorithm()const
+  {
+    if(num_piles>0){
+      /* Mark those elements which are in their correct position, i.e. those
+       * belonging to the longest increasing subsequence. These are those
+       * elements linked from the top of the last pile.
+       */
+
+      entry* ent=entries()[num_piles-1].pile_top_entry;
+      for(std::size_t n=num_piles;n--;){
+        ent->ordered=true;
+        ent=ent->previous;
+      }
+    }
+  }
+
+  bool is_ordered(void * node)const
+  {
+    return std::lower_bound(
+      entries(),entries()+size_,
+      entry(node),entry::less_by_node())->ordered;
+  }
+
+private:
+  entry* entries()const{return &*spc.data();}
+
+  auto_space<entry,Allocator> spc;
+  std::size_t                 size_;
+  std::size_t                 n;
+  mutable bool                sorted;
+  mutable std::size_t         num_piles;
+};
+
+/* The algorithm has three phases:
+ *   - Initialization, during which the nodes of the base sequence are added.
+ *   - Execution.
+ *   - Results querying, through the is_ordered memfun.
+ */
+
+template<typename Node,typename Allocator>
+class algorithm:private algorithm_base<Allocator>
+{
+  typedef algorithm_base<Allocator> super;
+
+public:
+  algorithm(const Allocator& al,std::size_t size):super(al,size){}
+
+  void add(Node* node)
+  {
+    super::add(node);
+  }
+
+  template<typename IndexIterator>
+  void execute(IndexIterator first,IndexIterator last)const
+  {
+    super::begin_algorithm();
+
+    for(IndexIterator it=first;it!=last;++it){
+      add_node_to_algorithm(get_node(it));
+    }
+
+    super::finish_algorithm();
+  }
+
+  bool is_ordered(Node* node)const
+  {
+    return super::is_ordered(node);
+  }
+
+private:
+  void add_node_to_algorithm(Node* node)const
+  {
+    super::add_node_to_algorithm(node);
+  }
+
+  template<typename IndexIterator>
+  static Node* get_node(IndexIterator it)
+  {
+    return static_cast<Node*>(it.get_node());
+  }
+};
+
+} /* namespace multi_index::detail::index_matcher */
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/index_node_base.hpp b/boost/multi_index/detail/index_node_base.hpp
new file mode 100644 (file)
index 0000000..42b45d1
--- /dev/null
@@ -0,0 +1,135 @@
+/* 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_DETAIL_INDEX_NODE_BASE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_INDEX_NODE_BASE_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/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp> 
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/archive/archive_exception.hpp>
+#include <boost/serialization/access.hpp>
+#include <boost/throw_exception.hpp> 
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* index_node_base tops the node hierarchy of multi_index_container. It holds
+ * the value of the element contained.
+ */
+
+template<typename Value>
+struct pod_value_holder
+{
+  typename aligned_storage<
+    sizeof(Value),
+    alignment_of<Value>::value
+  >::type                      space;
+};
+
+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()
+  {
+    return *static_cast<value_type*>(
+      static_cast<void*>(&this->space));
+  }
+
+  const value_type& value()const
+  {
+    return *static_cast<const value_type*>(
+      static_cast<const void*>(&this->space));
+  }
+
+  static index_node_base* from_value(const value_type* p)
+  {
+    return static_cast<index_node_base *>(
+      reinterpret_cast<pod_value_holder<Value>*>( /* std 9.2.17 */
+        const_cast<value_type*>(p))); 
+  }
+
+private:
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  friend class boost::serialization::access;
+  
+  /* nodes do not emit any kind of serialization info. They are
+   * fed to Boost.Serialization so that pointers to nodes are
+   * tracked correctly.
+   */
+
+  template<class Archive>
+  void serialize(Archive&,const unsigned int)
+  {
+  }
+#endif
+};
+
+template<typename Node,typename Value>
+Node* node_from_value(
+  const Value* p
+  BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
+{
+  typedef typename Node::allocator_type allocator_type;
+  return static_cast<Node*>(
+    index_node_base<Value,allocator_type>::from_value(p));
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+/* Index nodes never get constructed directly by Boost.Serialization,
+ * as archives are always fed pointers to previously existent
+ * nodes. So, if this is called it means we are dealing with a
+ * somehow invalid archive.
+ */
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+namespace serialization{
+#else
+namespace multi_index{
+namespace detail{
+#endif
+
+template<class Archive,typename Value,typename Allocator>
+inline void load_construct_data(
+  Archive&,boost::multi_index::detail::index_node_base<Value,Allocator>*,
+  const unsigned int)
+{
+  throw_exception(
+    archive::archive_exception(archive::archive_exception::other_exception));
+}
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+} /* namespace serialization */
+#else
+} /* namespace multi_index::detail */
+} /* namespace multi_index */
+#endif
+
+#endif
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/index_saver.hpp b/boost/multi_index/detail/index_saver.hpp
new file mode 100644 (file)
index 0000000..470e2b7
--- /dev/null
@@ -0,0 +1,135 @@
+/* Copyright 2003-2005 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_DETAIL_INDEX_SAVER_HPP
+#define BOOST_MULTI_INDEX_DETAIL_INDEX_SAVER_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/multi_index/detail/index_matcher.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <cstddef>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* index_saver accepts a base sequence of previously saved elements
+ * and saves a possibly reordered subsequence in an efficient manner,
+ * serializing only the information needed to rearrange the subsequence
+ * based on the original order of the base.
+ * multi_index_container is in charge of supplying the info about the
+ * base sequence, and each index can subsequently save itself using the
+ * const interface of index_saver.
+ */
+
+template<typename Node,typename Allocator>
+class index_saver:private noncopyable
+{
+public:
+  index_saver(const Allocator& al,std::size_t size):alg(al,size){}
+
+  template<class Archive>
+  void add(Node* node,Archive& ar,const unsigned int)
+  {
+    ar<<serialization::make_nvp("position",*node);
+    alg.add(node);
+  }
+
+  template<class Archive>
+  void add_track(Node* node,Archive& ar,const unsigned int)
+  {
+    ar<<serialization::make_nvp("position",*node);
+  }
+
+  template<typename IndexIterator,class Archive>
+  void save(
+    IndexIterator first,IndexIterator last,Archive& ar,
+    const unsigned int)const
+  {
+    /* calculate ordered positions */
+
+    alg.execute(first,last);
+
+    /* Given a consecutive subsequence of displaced elements
+     * x1,...,xn, the following information is serialized:
+     *
+     *   p0,p1,...,pn,0
+     *
+     * where pi is a pointer to xi and p0 is a pointer to the element
+     * preceding x1. Crealy, from this information is possible to
+     * restore the original order on loading time. If x1 is the first
+     * element in the sequence, the following is serialized instead:
+     *
+     *   p1,p1,...,pn,0
+     *
+     * For each subsequence of n elements, n+2 pointers are serialized.
+     * An optimization policy is applied: consider for instance the
+     * sequence
+     *
+     *   a,B,c,D
+     * 
+     * where B and D are displaced, but c is in its correct position.
+     * Applying the schema described above we would serialize 6 pointers:
+     *
+     *  p(a),p(B),0
+     *  p(c),p(D),0
+     * 
+     * but this can be reduced to 5 pointers by treating c as a displaced
+     * element:
+     *
+     *  p(a),p(B),p(c),p(D),0
+     */
+
+    std::size_t last_saved=3; /* distance to last pointer saved */
+    for(IndexIterator it=first,prev=first;it!=last;prev=it++,++last_saved){
+      if(!alg.is_ordered(get_node(it))){
+        if(last_saved>1)save_node(get_node(prev),ar);
+        save_node(get_node(it),ar);
+        last_saved=0;
+      }
+      else if(last_saved==2)save_node(null_node(),ar);
+    }
+    if(last_saved<=2)save_node(null_node(),ar);
+
+    /* marks the end of the serialization info for [first,last) */
+
+    save_node(null_node(),ar);
+  }
+
+private:
+  template<typename IndexIterator>
+  static Node* get_node(IndexIterator it)
+  {
+    return it.get_node();
+  }
+
+  static Node* null_node(){return 0;}
+
+  template<typename Archive>
+  static void save_node(Node* node,Archive& ar)
+  {
+    ar<<serialization::make_nvp("pointer",node);
+  }
+
+  index_matcher::algorithm<Node,Allocator> alg;
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/invariant_assert.hpp b/boost/multi_index/detail/invariant_assert.hpp
new file mode 100644 (file)
index 0000000..5f08dce
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright 2003-2005 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_DETAIL_INVARIANT_ASSERT_HPP
+#define BOOST_MULTI_INDEX_DETAIL_INVARIANT_ASSERT_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#if !defined(BOOST_MULTI_INDEX_INVARIANT_ASSERT)
+#include <boost/assert.hpp>
+#define BOOST_MULTI_INDEX_INVARIANT_ASSERT BOOST_ASSERT
+#endif
+
+#endif
diff --git a/boost/multi_index/detail/is_index_list.hpp b/boost/multi_index/detail/is_index_list.hpp
new file mode 100644 (file)
index 0000000..fd801da
--- /dev/null
@@ -0,0 +1,40 @@
+/* Copyright 2003-2005 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_DETAIL_IS_INDEX_LIST_HPP
+#define BOOST_MULTI_INDEX_DETAIL_IS_INDEX_LIST_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/empty.hpp>
+#include <boost/mpl/is_sequence.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<typename T>
+struct is_index_list
+{
+  BOOST_STATIC_CONSTANT(bool,mpl_sequence=mpl::is_sequence<T>::value);
+  BOOST_STATIC_CONSTANT(bool,non_empty=!mpl::empty<T>::value);
+  BOOST_STATIC_CONSTANT(bool,value=mpl_sequence&&non_empty);
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/iter_adaptor.hpp b/boost/multi_index/detail/iter_adaptor.hpp
new file mode 100644 (file)
index 0000000..521cfff
--- /dev/null
@@ -0,0 +1,325 @@
+/* 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_DETAIL_ITER_ADAPTOR_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_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/apply.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
+#include <boost/operators.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Poor man's version of boost::iterator_adaptor. Used instead of the
+ * original as compile times for the latter are significantly higher.
+ * The interface is not replicated exactly, only to the extent necessary
+ * 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:
+  template<class Class>
+    static typename Class::reference dereference(const Class& x)
+  {
+    return x.dereference();
+  }
+
+  template<class Class>
+  static bool equal(const Class& x,const Class& y)
+  {
+    return x.equal(y);
+  }
+
+  template<class Class>
+  static void increment(Class& x)
+  {
+    x.increment();
+  }
+
+  template<class Class>
+  static void decrement(Class& x)
+  {
+    x.decrement();
+  }
+
+  template<class Class>
+  static void advance(Class& x,typename Class::difference_type n)
+  {
+    x.advance(n);
+  }
+
+  template<class Class>
+  static typename Class::difference_type distance_to(
+    const Class& x,const Class& y)
+  {
+    return x.distance_to(y);
+  }
+};
+
+template<typename Category>
+struct iter_adaptor_selector;
+
+template<class Derived,class Base>
+class forward_iter_adaptor_base:
+  public forward_iterator_helper<
+    Derived,
+    typename Base::value_type,
+    typename Base::difference_type,
+    typename Base::pointer,
+    typename Base::reference>
+{
+public:
+  typedef typename Base::reference reference;
+
+  reference operator*()const
+  {
+    return iter_adaptor_access::dereference(final());
+  }
+
+  friend bool operator==(const Derived& x,const Derived& y)
+  {
+    return iter_adaptor_access::equal(x,y);
+  }
+
+  Derived& operator++()
+  {
+    iter_adaptor_access::increment(final());
+    return final();
+  }
+
+private:
+  Derived& final(){return *static_cast<Derived*>(this);}
+  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>
+{
+  template<class Derived,class Base>
+  struct apply
+  {
+    typedef forward_iter_adaptor_base<Derived,Base> type;
+  };
+};
+
+template<class Derived,class Base>
+class bidirectional_iter_adaptor_base:
+  public bidirectional_iterator_helper<
+    Derived,
+    typename Base::value_type,
+    typename Base::difference_type,
+    typename Base::pointer,
+    typename Base::reference>
+{
+public:
+  typedef typename Base::reference reference;
+
+  reference operator*()const
+  {
+    return iter_adaptor_access::dereference(final());
+  }
+
+  friend bool operator==(const Derived& x,const Derived& y)
+  {
+    return iter_adaptor_access::equal(x,y);
+  }
+
+  Derived& operator++()
+  {
+    iter_adaptor_access::increment(final());
+    return final();
+  }
+
+  Derived& operator--()
+  {
+    iter_adaptor_access::decrement(final());
+    return final();
+  }
+
+private:
+  Derived& final(){return *static_cast<Derived*>(this);}
+  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>
+{
+  template<class Derived,class Base>
+  struct apply
+  {
+    typedef bidirectional_iter_adaptor_base<Derived,Base> type;
+  };
+};
+
+template<class Derived,class Base>
+class random_access_iter_adaptor_base:
+  public random_access_iterator_helper<
+    Derived,
+    typename Base::value_type,
+    typename Base::difference_type,
+    typename Base::pointer,
+    typename Base::reference>
+{
+public:
+  typedef typename Base::reference       reference;
+  typedef typename Base::difference_type difference_type;
+
+  reference operator*()const
+  {
+    return iter_adaptor_access::dereference(final());
+  }
+
+  friend bool operator==(const Derived& x,const Derived& y)
+  {
+    return iter_adaptor_access::equal(x,y);
+  }
+
+  friend bool operator<(const Derived& x,const Derived& y)
+  {
+    return iter_adaptor_access::distance_to(x,y)>0;
+  }
+
+  Derived& operator++()
+  {
+    iter_adaptor_access::increment(final());
+    return final();
+  }
+
+  Derived& operator--()
+  {
+    iter_adaptor_access::decrement(final());
+    return final();
+  }
+
+  Derived& operator+=(difference_type n)
+  {
+    iter_adaptor_access::advance(final(),n);
+    return final();
+  }
+
+  Derived& operator-=(difference_type n)
+  {
+    iter_adaptor_access::advance(final(),-n);
+    return final();
+  }
+
+  friend difference_type operator-(const Derived& x,const Derived& y)
+  {
+    return iter_adaptor_access::distance_to(y,x);
+  }
+
+private:
+  Derived& final(){return *static_cast<Derived*>(this);}
+  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>
+{
+  template<class Derived,class Base>
+  struct apply
+  {
+    typedef random_access_iter_adaptor_base<Derived,Base> type;
+  };
+};
+
+template<class Derived,class Base>
+struct iter_adaptor_base
+{
+  typedef iter_adaptor_selector<
+    typename Base::iterator_category>        selector;
+  typedef typename prevent_eti<
+    selector,
+    typename mpl::apply2<
+      selector,Derived,Base>::type
+  >::type                                    type;
+};
+
+template<class Derived,class Base>
+class iter_adaptor:public iter_adaptor_base<Derived,Base>::type
+{
+protected:
+  iter_adaptor(){}
+  explicit iter_adaptor(const Base& b_):b(b_){}
+
+  const Base& base_reference()const{return b;}
+  Base&       base_reference(){return b;}
+
+private:
+  Base b;
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/modify_key_adaptor.hpp b/boost/multi_index/detail/modify_key_adaptor.hpp
new file mode 100644 (file)
index 0000000..7335a51
--- /dev/null
@@ -0,0 +1,49 @@
+/* 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_DETAIL_MODIFY_KEY_ADAPTOR_HPP
+#define BOOST_MULTI_INDEX_DETAIL_MODIFY_KEY_ADAPTOR_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Functional adaptor to resolve modify_key as a call to modify.
+ * Preferred over compose_f_gx and stuff cause it eliminates problems
+ * with references to references, dealing with function pointers, etc.
+ */
+
+template<typename Fun,typename Value,typename KeyFromValue>
+struct modify_key_adaptor
+{
+
+  modify_key_adaptor(Fun f_,KeyFromValue kfv_):f(f_),kfv(kfv_){}
+
+  void operator()(Value& x)
+  {
+    f(kfv(x));
+  }
+
+private:
+  Fun          f;
+  KeyFromValue kfv;
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/msvc_index_specifier.hpp b/boost/multi_index/detail/msvc_index_specifier.hpp
new file mode 100644 (file)
index 0000000..694e866
--- /dev/null
@@ -0,0 +1,69 @@
+/* Copyright 2003-2005 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_DETAIL_MSVC_INDEX_SPECIFIER_HPP
+#define BOOST_MULTI_INDEX_DETAIL_MSVC_INDEX_SPECIFIER_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/detail/workaround.hpp>
+
+#if BOOST_WORKAROUND(BOOST_MSVC,<1310)
+/* Workaround for a problem in MSVC with dependent template typedefs
+ * when accesing index specifiers.
+ * Modeled after <boost/mpl/aux_/msvc_dtw.hpp> (thanks, Aleksey!)
+ */
+
+#include <boost/mpl/aux_/msvc_never_true.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<typename IndexSpecifier>
+struct msvc_index_specifier
+{
+  template<bool> struct fake_index_type:IndexSpecifier{};
+  template<> struct fake_index_type<true>
+  {
+    template<typename Super>
+    struct node_class{};
+
+    template<typename Super>
+    struct index_class{};
+  };
+
+  template<typename Super>
+  struct result_node_class:
+    fake_index_type<mpl::aux::msvc_never_true<IndexSpecifier>::value>::
+      template node_class<Super>
+  {
+  };
+
+  template<typename Super>
+  struct result_index_class:
+    fake_index_type<mpl::aux::msvc_never_true<IndexSpecifier>::value>::
+      template index_class<Super>
+  {
+  };
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif /* workaround */
+
+#endif
diff --git a/boost/multi_index/detail/no_duplicate_tags.hpp b/boost/multi_index/detail/no_duplicate_tags.hpp
new file mode 100644 (file)
index 0000000..dbca6af
--- /dev/null
@@ -0,0 +1,97 @@
+/* Copyright 2003-2005 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_DETAIL_NO_DUPLICATE_TAGS_HPP
+#define BOOST_MULTI_INDEX_DETAIL_NO_DUPLICATE_TAGS_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/fold.hpp>
+#include <boost/mpl/set/set0.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* no_duplicate_tags check at compile-time that a tag list
+ * has no duplicate tags.
+ * The algorithm deserves some explanation: tags
+ * are sequentially inserted into a mpl::set if they were
+ * not already present. Due to the magic of mpl::set
+ * (mpl::has_key is contant time), this operation takes linear
+ * time, and even MSVC++ 6.5 handles it gracefully (other obvious
+ * solutions are quadratic.)
+ */
+
+struct duplicate_tag_mark{};
+
+struct duplicate_tag_marker
+{
+  template <typename MplSet,typename Tag>
+  struct apply
+  {
+    typedef mpl::s_item<
+      typename mpl::if_<mpl::has_key<MplSet,Tag>,duplicate_tag_mark,Tag>::type,
+      MplSet
+    > type;
+  };
+};
+
+template<typename TagList>
+struct no_duplicate_tags
+{
+  typedef typename mpl::fold<
+    TagList,
+    mpl::set0<>,
+    duplicate_tag_marker
+  >::type aux;
+  BOOST_STATIC_CONSTANT(
+    bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value));
+};
+
+/* Variant for an index list: duplication is checked
+ * across all the indices.
+ */
+
+struct duplicate_tag_list_marker
+{
+  template <typename MplSet,typename Index>
+  struct apply:mpl::fold<
+    BOOST_DEDUCED_TYPENAME Index::tag_list,
+    MplSet,
+    duplicate_tag_marker>
+  {
+  };
+};
+
+template<typename IndexList>
+struct no_duplicate_tags_in_index_list
+{
+  typedef typename mpl::fold<
+    IndexList,
+    mpl::set0<>,
+    duplicate_tag_list_marker
+  >::type aux;
+  BOOST_STATIC_CONSTANT(
+    bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value));
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/node_type.hpp b/boost/multi_index/detail/node_type.hpp
new file mode 100644 (file)
index 0000000..5e2ffa9
--- /dev/null
@@ -0,0 +1,79 @@
+/* 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_DETAIL_NODE_TYPE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_NODE_TYPE_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/detail/workaround.hpp>
+#include <boost/mpl/bind.hpp>
+#include <boost/mpl/reverse_iter_fold.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/multi_index_container_fwd.hpp>
+#include <boost/multi_index/detail/header_holder.hpp>
+#include <boost/multi_index/detail/index_node_base.hpp>
+#include <boost/multi_index/detail/is_index_list.hpp>
+#include <boost/multi_index/detail/msvc_index_specifier.hpp>
+#include <boost/static_assert.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* MPL machinery to construct the internal node type associated to an
+ * index list.
+ */
+
+#if BOOST_WORKAROUND(BOOST_MSVC,<1310)
+struct index_node_applier
+{
+  template<typename IndexSpecifierIterator,typename Super>
+  struct apply:
+    msvc_index_specifier< mpl::deref<IndexSpecifierIterator>::type >::
+      template result_node_class<Super>
+  {
+  }; 
+};
+#else
+struct index_node_applier
+{
+  template<typename IndexSpecifierIterator,typename Super>
+  struct apply
+  {
+    typedef typename mpl::deref<IndexSpecifierIterator>::type index_specifier;
+    typedef typename index_specifier::
+      BOOST_NESTED_TEMPLATE node_class<Super>::type type;
+  }; 
+};
+#endif
+
+template<typename Value,typename IndexSpecifierList,typename Allocator>
+struct multi_index_node_type
+{
+  BOOST_STATIC_ASSERT(detail::is_index_list<IndexSpecifierList>::value);
+
+  typedef typename mpl::reverse_iter_fold<
+    IndexSpecifierList,
+    index_node_base<Value,Allocator>,
+    mpl::bind2<index_node_applier,mpl::_2,mpl::_1>
+  >::type type;
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/ord_index_args.hpp b/boost/multi_index/detail/ord_index_args.hpp
new file mode 100644 (file)
index 0000000..86d5967
--- /dev/null
@@ -0,0 +1,83 @@
+/* Copyright 2003-2005 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_DETAIL_ORD_INDEX_ARGS_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_ARGS_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/aux_/na.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/multi_index/tag.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <functional>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Oredered index specifiers can be instantiated in two forms:
+ *
+ *   (ordered_unique|ordered_non_unique)<
+ *     KeyFromValue,Compare=std::less<KeyFromValue::result_type> >
+ *   (ordered_unique|ordered_non_unique)<
+ *     TagList,KeyFromValue,Compare=std::less<KeyFromValue::result_type> >
+ *
+ * index_args implements the machinery to accept this argument-dependent
+ * polymorphism.
+ */
+
+template<typename KeyFromValue>
+struct index_args_default_compare
+{
+  typedef std::less<typename KeyFromValue::result_type> type;
+};
+
+template<typename Arg1,typename Arg2,typename Arg3>
+struct ordered_index_args
+{
+  typedef is_tag<Arg1> full_form;
+
+  typedef typename mpl::if_<
+    full_form,
+    Arg1,
+    tag< > >::type                                   tag_list_type;
+  typedef typename mpl::if_<
+    full_form,
+    Arg2,
+    Arg1>::type                                      key_from_value_type;
+  typedef typename mpl::if_<
+    full_form,
+    Arg3,
+    Arg2>::type                                      supplied_compare_type;
+  typedef typename mpl::eval_if<
+    mpl::is_na<supplied_compare_type>,
+    index_args_default_compare<key_from_value_type>,
+    mpl::identity<supplied_compare_type>
+  >::type                                            compare_type;
+
+  BOOST_STATIC_ASSERT(is_tag<tag_list_type>::value);
+  BOOST_STATIC_ASSERT(!mpl::is_na<key_from_value_type>::value);
+  BOOST_STATIC_ASSERT(!mpl::is_na<compare_type>::value);
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/ord_index_node.hpp b/boost/multi_index/detail/ord_index_node.hpp
new file mode 100644 (file)
index 0000000..b4193d2
--- /dev/null
@@ -0,0 +1,650 @@
+/* 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.
+ *
+ * The internal implementation of red-black trees is based on that of SGI STL
+ * stl_tree.h file: 
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_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 <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{
+
+namespace multi_index{
+
+namespace detail{
+
+/* definition of red-black nodes for ordered_index */
+
+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 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_; 
+  pointer             parent_;
+  pointer             left_;
+  pointer             right_;
+};
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
+/* If ordered_index_node_impl has even alignment, we can use the least
+ * significant bit of one of the ordered_index_node_impl pointers to
+ * store color information. This typically reduces the size of
+ * ordered_index_node_impl by 25%.
+ */
+
+#if defined(BOOST_MSVC)
+/* This code casts pointers to an integer type that has been computed
+ * to be large enough to hold the pointer, however the metaprogramming
+ * logic is not always spotted by the VC++ code analyser that issues a
+ * long list of warnings.
+ */
+
+#pragma warning(push)
+#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_){}
+    
+    operator ordered_index_color()const
+    {
+      return ordered_index_color(*r&uintptr_type(1));
+    }
+    
+    color_ref& operator=(ordered_index_color c)
+    {
+      *r&=~uintptr_type(1);
+      *r|=uintptr_type(c);
+      return *this;
+    }
+    
+    color_ref& operator=(const color_ref& x)
+    {
+      return operator=(x.operator ordered_index_color());
+    }
+    
+  private:
+    uintptr_type* r;
+  };
+  
+  struct parent_ref
+  {
+    parent_ref(uintptr_type* r_):r(r_){}
+    
+    operator pointer()const
+    {
+      return (pointer)(void*)(*r&~uintptr_type(1));
+    }
+    
+    parent_ref& operator=(pointer p)
+    {
+      *r=((uintptr_type)(void*)p)|(*r&uintptr_type(1));
+      return *this;
+    }
+    
+    parent_ref& operator=(const parent_ref& x)
+    {
+      return operator=(x.operator pointer());
+    }
+
+    pointer operator->()const
+    {
+      return operator pointer();
+    }
+
+  private:
+    uintptr_type* r;
+  };
+  
+  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_);}
+  pointer    parent()const
+  {
+    return (pointer)(void*)(parentcolor_&~uintptr_type(1));
+  }
+
+  pointer& left(){return left_;}
+  pointer  left()const{return left_;}
+  pointer& right(){return right_;}
+  pointer  right()const{return right_;}
+
+private:
+  uintptr_type parentcolor_;
+  pointer      left_;
+  pointer      right_;
+};
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+#endif
+
+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<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<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(pointer& x)
+  {
+    if(x->right()!=pointer(0)){
+      x=x->right();
+      while(x->left()!=pointer(0))x=x->left();
+    }
+    else{
+      pointer y=x->parent();
+      while(x==y->right()){
+        x=y;
+        y=y->parent();
+      }
+      if(x->right()!=y)x=y;
+    }
+  }
+
+  static void decrement(pointer& x)
+  {
+    if(x->color()==red&&x->parent()->parent()==x){
+      x=x->right();
+    }
+    else if(x->left()!=pointer(0)){
+      pointer y=x->left();
+      while(y->right()!=pointer(0))y=y->right();
+      x=y;
+    }else{
+      pointer y=x->parent();
+      while(x==y->left()){
+        x=y;
+        y=y->parent();
+      }
+      x=y;
+    }
+  }
+
+  /* algorithmic stuff */
+
+  static void rotate_left(pointer x,parent_ref root)
+  {
+    pointer y=x->right();
+    x->right()=y->left();
+    if(y->left()!=pointer(0))y->left()->parent()=x;
+    y->parent()=x->parent();
+    
+    if(x==root)                    root=y;
+    else if(x==x->parent()->left())x->parent()->left()=y;
+    else                           x->parent()->right()=y;
+    y->left()=x;
+    x->parent()=y;
+  }
+
+  static pointer minimum(pointer x)
+  {
+    while(x->left()!=pointer(0))x=x->left();
+    return x;
+  }
+
+  static pointer maximum(pointer x)
+  {
+    while(x->right()!=pointer(0))x=x->right();
+    return x;
+  }
+
+  static void rotate_right(pointer x,parent_ref root)
+  {
+    pointer y=x->left();
+    x->left()=y->right();
+    if(y->right()!=pointer(0))y->right()->parent()=x;
+    y->parent()=x->parent();
+
+    if(x==root)                     root=y;
+    else if(x==x->parent()->right())x->parent()->right()=y;
+    else                            x->parent()->left()=y;
+    y->right()=x;
+    x->parent()=y;
+  }
+
+  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()){
+        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;
+          x=x->parent()->parent();
+        }
+        else{
+          if(x==x->parent()->right()){
+            x=x->parent();
+            rotate_left(x,root);
+          }
+          x->parent()->color()=black;
+          x->parent()->parent()->color()=red;
+          rotate_right(x->parent()->parent(),root);
+        }
+      }
+      else{
+        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;
+          x=x->parent()->parent();
+        }
+        else{
+          if(x==x->parent()->left()){
+            x=x->parent();
+            rotate_right(x,root);
+          }
+          x->parent()->color()=black;
+          x->parent()->parent()->color()=red;
+          rotate_left(x->parent()->parent(),root);
+        }
+      }
+    }
+    root->color()=black;
+  }
+
+  static void link(
+    pointer x,ordered_index_side side,pointer position,pointer header)
+  {
+    if(side==to_left){
+      position->left()=x;  /* also makes leftmost=x when parent==header */
+      if(position==header){
+        header->parent()=x;
+        header->right()=x;
+      }
+      else if(position==header->left()){
+        header->left()=x;  /* maintain leftmost pointing to min node */
+      }
+    }
+    else{
+      position->right()=x;
+      if(position==header->right()){
+        header->right()=x; /* maintain rightmost pointing to max node */
+      }
+    }
+    x->parent()=position;
+    x->left()=pointer(0);
+    x->right()=pointer(0);
+    ordered_index_node_impl::rebalance(x,header->parent());
+  }
+
+  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()==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()!=pointer(0))y=y->left();
+        x=y->right();
+      }
+    }
+    if(y!=z){
+      z->left()->parent()=y;   /* relink y in place of z. y is z's successor */
+      y->left()=z->left();
+      if(y!=z->right()){
+        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;
+      }
+      else{
+        x_parent=y;
+      }
+
+      if(root==z)                    root=y;
+      else if(z->parent()->left()==z)z->parent()->left()=y;
+      else                           z->parent()->right()=y;
+      y->parent()=z->parent();
+      ordered_index_color c=y->color();
+      y->color()=z->color();
+      z->color()=c;
+      y=z;                    /* y now points to node to be actually deleted */
+    }
+    else{                     /* y==z */
+      x_parent=y->parent();
+      if(x!=pointer(0))x->parent()=y->parent();   
+      if(root==z){
+        root=x;
+      }
+      else{
+        if(z->parent()->left()==z)z->parent()->left()=x;
+        else                      z->parent()->right()=x;
+      }
+      if(leftmost==z){
+        if(z->right()==pointer(0)){ /* z->left() must be null also */
+          leftmost=z->parent();
+        }
+        else{              
+          leftmost=minimum(x);      /* makes leftmost==header if z==root */
+        }
+      }
+      if(rightmost==z){
+        if(z->left()==pointer(0)){  /* z->right() must be null also */
+          rightmost=z->parent();
+        }
+        else{                   /* x==z->left() */
+          rightmost=maximum(x); /* makes rightmost==header if z==root */
+        }
+      }
+    }
+    if(y->color()!=red){
+      while(x!=root&&(x==pointer(0)|| x->color()==black)){
+        if(x==x_parent->left()){
+          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()==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()==pointer(0 )
+                || w->right()->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()!=pointer(0))w->right()->color()=black;
+            rotate_left(x_parent,root);
+            break;
+          }
+        } 
+        else{                   /* same as above,with right <-> 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()==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()==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()!=pointer(0))w->left()->color()=black;
+            rotate_right(x_parent,root);
+            break;
+          }
+        }
+      }
+      if(x!=pointer(0))x->color()=black;
+    }
+    return y;
+  }
+
+  static void restore(pointer x,pointer position,pointer header)
+  {
+    if(position->left()==pointer(0)||position->left()==header){
+      link(x,to_left,position,header);
+    }
+    else{
+      decrement(position);
+      link(x,to_right,position,header);
+    }
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+  /* invariant stuff */
+
+  static std::size_t black_count(pointer node,pointer root)
+  {
+    if(node==pointer(0))return 0;
+    std::size_t sum=0;
+    for(;;){
+      if(node->color()==black)++sum;
+      if(node==root)break;
+      node=node->parent();
+    } 
+    return sum;
+  }
+#endif
+};
+
+template<typename Super>
+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> trampoline;
+
+public:
+  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();}
+
+  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 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 trampoline*>(&*x));
+  }
+
+  /* interoperability with bidir_node_iterator */
+
+  static void increment(ordered_index_node*& x)
+  {
+    impl_pointer xi=x->impl();
+    trampoline::increment(xi);
+    x=from_impl(xi);
+  }
+
+  static void decrement(ordered_index_node*& x)
+  {
+    impl_pointer xi=x->impl();
+    trampoline::decrement(xi);
+    x=from_impl(xi);
+  }
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/ord_index_ops.hpp b/boost/multi_index/detail/ord_index_ops.hpp
new file mode 100644 (file)
index 0000000..52a7476
--- /dev/null
@@ -0,0 +1,147 @@
+/* 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.
+ *
+ * The internal implementation of red-black trees is based on that of SGI STL
+ * stl_tree.h file: 
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_OPS_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_OPS_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 <utility>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Common code for index memfuns having templatized and
+ * non-templatized versions.
+ */
+
+template<
+  typename Node,typename KeyFromValue,
+  typename CompatibleKey,typename CompatibleCompare
+>
+inline Node* ordered_index_find(
+  Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+  const CompatibleCompare& comp)
+{
+  Node* y0=y;
+
+  while (top){
+    if(!comp(key(top->value()),x)){
+      y=top;
+      top=Node::from_impl(top->left());
+    }
+    else top=Node::from_impl(top->right());
+  }
+    
+  return (y==y0||comp(x,key(y->value())))?y0:y;
+}
+
+template<
+  typename Node,typename KeyFromValue,
+  typename CompatibleKey,typename CompatibleCompare
+>
+inline Node* ordered_index_lower_bound(
+  Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+  const CompatibleCompare& comp)
+{
+  while(top){
+    if(!comp(key(top->value()),x)){
+      y=top;
+      top=Node::from_impl(top->left());
+    }
+    else top=Node::from_impl(top->right());
+  }
+
+  return y;
+}
+
+template<
+  typename Node,typename KeyFromValue,
+  typename CompatibleKey,typename CompatibleCompare
+>
+inline Node* ordered_index_upper_bound(
+  Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+  const CompatibleCompare& comp)
+{
+  while(top){
+    if(comp(x,key(top->value()))){
+      y=top;
+      top=Node::from_impl(top->left());
+    }
+    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 */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/prevent_eti.hpp b/boost/multi_index/detail/prevent_eti.hpp
new file mode 100644 (file)
index 0000000..39edf60
--- /dev/null
@@ -0,0 +1,60 @@
+/* Copyright 2003-2005 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_DETAIL_PREVENT_ETI_HPP
+#define BOOST_MULTI_INDEX_DETAIL_PREVENT_ETI_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/detail/workaround.hpp>
+
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/aux_/msvc_never_true.hpp>
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+/* See
+ * http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Effective_MPL
+ * Item 5.6, Beware of the 'early template instantiation' trap.
+ */
+
+template<typename Type,typename Construct>
+struct prevent_eti
+{
+  typedef typename mpl::if_<
+    mpl::aux::msvc_never_true<Type>,
+    mpl::integral_c<int,0>,
+    Construct
+  >::type type;
+};
+#else
+template<typename Type,typename Construct>
+struct prevent_eti
+{
+  typedef Construct type;
+};
+#endif
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/rnd_index_loader.hpp b/boost/multi_index/detail/rnd_index_loader.hpp
new file mode 100644 (file)
index 0000000..69ec8b7
--- /dev/null
@@ -0,0 +1,176 @@
+/* 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_DETAIL_RND_INDEX_LOADER_HPP
+#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_LOADER_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 <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>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* This class implements a serialization rearranger for random access
+ * indices. In order to achieve O(n) performance, the following strategy
+ * is followed: the nodes of the index are handled as if in a bidirectional
+ * list, where the next pointers are stored in the original
+ * random_access_index_ptr_array and the prev pointers are stored in
+ * an auxiliary array. Rearranging of nodes in such a bidirectional list
+ * is constant time. Once all the arrangements are performed (on destruction
+ * time) the list is traversed in reverse order and
+ * pointers are swapped and set accordingly so that they recover its
+ * original semantics ( *(node->up())==node ) while retaining the
+ * new order.
+ */
+
+template<typename Allocator>
+class random_access_index_loader_base:private noncopyable
+{
+protected:
+  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& ptrs_):
+    al(al_),
+    ptrs(ptrs_),
+    header(*ptrs.end()),
+    prev_spc(al,0),
+    preprocessed(false)
+  {}
+
+  ~random_access_index_loader_base()
+  {
+    if(preprocessed)
+    {
+      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_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));
+        }
+        next(n)=n;
+      }
+    }
+  }
+
+  void rearrange(node_impl_pointer position,node_impl_pointer x)
+  {
+    preprocess(); /* only incur this penalty if rearrange() is ever called */
+    if(position==node_impl_pointer(0))position=header;
+    next(prev(x))=next(x);
+    prev(next(x))=prev(x);
+    prev(x)=position;
+    next(x)=next(position);
+    next(prev(x))=prev(next(x))=x;
+  }
+
+private:
+  void preprocess()
+  {
+    if(!preprocessed){
+      /* get space for the auxiliary prev array */
+      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());
+
+      /* ptrs elements point to the next nodes */
+      std::rotate(&*ptrs.begin(),&*ptrs.begin()+1,&*ptrs.end()+1);
+
+      preprocessed=true;
+    }
+  }
+
+  std::size_t position(node_impl_pointer x)const
+  {
+    return (std::size_t)(x->up()-ptrs.begin());
+  }
+
+  node_impl_pointer& next_at(std::size_t n)const
+  {
+    return *ptrs.at(n);
+  }
+
+  node_impl_pointer& prev_at(std::size_t n)const
+  {
+    return *(prev_spc.data()+n);
+  }
+
+  node_impl_pointer& next(node_impl_pointer x)const
+  {
+    return *(x->up());
+  }
+
+  node_impl_pointer& prev(node_impl_pointer x)const
+  {
+    return prev_at(position(x));
+  }
+
+  Allocator                               al;
+  ptr_array&                              ptrs;
+  node_impl_pointer                       header;
+  auto_space<node_impl_pointer,Allocator> prev_spc;
+  bool                                    preprocessed;
+};
+
+template<typename Node,typename Allocator>
+class random_access_index_loader:
+  private random_access_index_loader_base<Allocator>
+{
+  typedef random_access_index_loader_base<Allocator> super;
+  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& ptrs_):
+    super(al_,ptrs_)
+  {}
+
+  void rearrange(Node* position,Node *x)
+  {
+    super::rearrange(position?position->impl():node_impl_pointer(0),x->impl());
+  }
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/rnd_index_node.hpp b/boost/multi_index/detail/rnd_index_node.hpp
new file mode 100644 (file)
index 0000000..45b1e79
--- /dev/null
@@ -0,0 +1,281 @@
+/* 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_DETAIL_RND_INDEX_NODE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_NODE_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 <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>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<typename Allocator>
+struct random_access_index_node_impl
+{
+  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(pointer& x)
+  {
+    x=*(x->up()+1);
+  }
+
+  static void decrement(pointer& x)
+  {
+    x=*(x->up()-1);
+  }
+
+  static void advance(pointer& x,std::ptrdiff_t n)
+  {
+    x=*(x->up()+n);
+  }
+
+  static std::ptrdiff_t distance(pointer x,pointer y)
+  {
+    return y->up()-x->up();
+  }
+
+  /* algorithmic stuff */
+
+  static void relocate(ptr_pointer pos,ptr_pointer x)
+  {
+    pointer n=*x;
+    if(x<pos){
+      extract(x,pos);
+      *(pos-1)=n;
+      n->up()=pos-1;
+    }
+    else{
+      while(x!=pos){
+        *x=*(x-1);
+        (*x)->up()=x;
+        --x;
+      }
+      *pos=n;
+      n->up()=pos;
+    }
+  };
+
+  static void relocate(ptr_pointer pos,ptr_pointer first,ptr_pointer last)
+  {
+    ptr_pointer begin,middle,end;
+    if(pos<first){
+      begin=pos;
+      middle=first;
+      end=last;
+    }
+    else{
+      begin=first;
+      middle=last;
+      end=pos;
+    }
+
+    std::ptrdiff_t n=end-begin;
+    std::ptrdiff_t m=middle-begin;
+    std::ptrdiff_t n_m=n-m;
+    std::ptrdiff_t p=math::gcd(n,m);
+
+    for(std::ptrdiff_t i=0;i<p;++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;
+          break;
+        }
+        else{
+          *(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;
+          break;
+        }
+        else{
+          *(begin+k)=*(begin+j);
+          (*(begin+k))->up()=begin+k;
+        }
+      }
+    }
+  };
+
+  static void extract(ptr_pointer x,ptr_pointer pend)
+  {
+    --pend;
+    while(x!=pend){
+      *x=*(x+1);
+      (*x)->up()=x;
+      ++x;
+    }
+  }
+
+  static void transfer(
+    ptr_pointer pbegin0,ptr_pointer pend0,ptr_pointer pbegin1)
+  {
+    while(pbegin0!=pend0){
+      *pbegin1=*pbegin0++;
+      (*pbegin1)->up()=pbegin1;
+      ++pbegin1;
+    }
+  }
+
+  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){
+      std::swap(*pbegin,*--pend);
+      (*pbegin)->up()=pbegin;
+      (*pend)->up()=pend;
+      ++pbegin;
+    }
+  }
+
+private:
+  ptr_pointer up_;
+};
+
+template<typename Super>
+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>
+{
+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();}
+
+  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 random_access_index_node* from_impl(impl_pointer x)
+  {
+    return static_cast<random_access_index_node*>(
+      static_cast<trampoline*>(&*x));
+  }
+
+  static const random_access_index_node* from_impl(const_impl_pointer x)
+  {
+    return static_cast<const random_access_index_node*>(
+      static_cast<const trampoline*>(&*x));
+  }
+
+  /* interoperability with rnd_node_iterator */
+
+  static void increment(random_access_index_node*& x)
+  {
+    impl_pointer xi=x->impl();
+    trampoline::increment(xi);
+    x=from_impl(xi);
+  }
+
+  static void decrement(random_access_index_node*& x)
+  {
+    impl_pointer xi=x->impl();
+    trampoline::decrement(xi);
+    x=from_impl(xi);
+  }
+
+  static void advance(random_access_index_node*& x,std::ptrdiff_t 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 trampoline::distance(x->impl(),y->impl());
+  }
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/rnd_index_ops.hpp b/boost/multi_index/detail/rnd_index_ops.hpp
new file mode 100644 (file)
index 0000000..93c6385
--- /dev/null
@@ -0,0 +1,206 @@
+/* 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_DETAIL_RND_INDEX_OPS_HPP
+#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_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 <algorithm>
+#include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
+#include <functional>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Common code for random_access_index memfuns having templatized and
+ * non-templatized versions.
+ */
+
+template<typename Node,typename Allocator,typename Predicate>
+Node* random_access_index_remove(
+  random_access_index_ptr_array<Allocator>& ptrs,Predicate pred
+  BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
+{
+  typedef typename Node::value_type value_type;
+  typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
+
+  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()))){
+      if(first!=res){
+        std::swap(*first,*res);
+        (*first)->up()=first;
+        (*res)->up()=res;
+      }
+      ++res;
+    }
+  }
+  return Node::from_impl(*res);
+}
+
+template<typename Node,typename Allocator,class BinaryPredicate>
+Node* random_access_index_unique(
+  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::impl_ptr_pointer impl_ptr_pointer;
+
+  impl_ptr_pointer first=ptrs.begin(),
+                   res=first,
+                   last=ptrs.end();
+  if(first!=last){
+    for(;++first!=last;){
+      if(!binary_pred(
+           const_cast<const value_type&>(Node::from_impl(*res)->value()),
+           const_cast<const value_type&>(Node::from_impl(*first)->value()))){
+        ++res;
+        if(first!=res){
+          std::swap(*first,*res);
+          (*first)->up()=first;
+          (*res)->up()=res;
+        }
+      }
+    }
+    ++res;
+  }
+  return Node::from_impl(*res);
+}
+
+template<typename Node,typename Allocator,typename Compare>
+void random_access_index_inplace_merge(
+  const Allocator& al,
+  random_access_index_ptr_array<Allocator>& ptrs,
+  BOOST_DEDUCED_TYPENAME Node::impl_ptr_pointer first1,Compare comp
+  BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
+{
+  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()),
+        const_cast<const value_type&>(Node::from_impl(*first0)->value()))){
+      *out++=*first1++;
+    }
+    else{
+      *out++=*first0++;
+    }
+  }
+  std::copy(&*first0,&*last0,&*out);
+  std::copy(&*first1,&*last1,&*out);
+
+  first1=ptrs.begin();
+  out=spc.data();
+  while(first1!=last1){
+    *first1=*out++;
+    (*first1)->up()=first1;
+    ++first1;
+  }
+}
+
+/* sorting */
+
+/* auxiliary stuff */
+
+template<typename Node,typename Compare>
+struct random_access_index_sort_compare:
+  std::binary_function<
+    typename Node::impl_pointer,
+    typename Node::impl_pointer,bool>
+{
+  random_access_index_sort_compare(Compare comp_=Compare()):comp(comp_){}
+
+  bool operator()(
+    typename Node::impl_pointer x,typename Node::impl_pointer y)const
+  {
+    typedef typename Node::value_type value_type;
+
+    return comp(
+      const_cast<const value_type&>(Node::from_impl(x)->value()),
+      const_cast<const value_type&>(Node::from_impl(y)->value()));
+  }
+
+private:
+  Compare comp;
+};
+
+template<typename Node,typename Allocator,class Compare>
+void random_access_index_sort(
+  const Allocator& al,
+  random_access_index_ptr_array<Allocator>& ptrs,
+  Compare comp
+  BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
+{
+  /* The implementation is extremely simple: an auxiliary
+   * array of pointers is sorted using stdlib facilities and
+   * then used to rearrange the index. This is suboptimal
+   * in space and time, but has some advantages over other
+   * possible approaches:
+   *   - Use std::stable_sort() directly on ptrs using some
+   *     special iterator in charge of maintaining pointers
+   *     and up() pointers in sync: we cannot guarantee
+   *     preservation of the container invariants in the face of
+   *     exceptions, if, for instance, std::stable_sort throws
+   *     when ptrs transitorily contains duplicate elements.
+   *   - Rewrite the internal algorithms of std::stable_sort
+   *     adapted for this case: besides being a fair amount of
+   *     work, making a stable sort compatible with Boost.MultiIndex
+   *     invariants (basically, no duplicates or missing elements
+   *     even if an exception is thrown) is complicated, error-prone
+   *     and possibly won't perform much better than the
+   *     solution adopted.
+   */
+
+  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;
+  
+  impl_ptr_pointer   first=ptrs.begin();
+  impl_ptr_pointer   last=ptrs.end();
+  auto_space<
+    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));
+
+  while(first!=last){
+    *first=*buf++;
+    (*first)->up()=first;
+    ++first;
+  }
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/rnd_index_ptr_array.hpp b/boost/multi_index/detail/rnd_index_ptr_array.hpp
new file mode 100644 (file)
index 0000000..6bb47d5
--- /dev/null
@@ -0,0 +1,143 @@
+/* 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_DETAIL_RND_INDEX_PTR_ARRAY_HPP
+#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_PTR_ARRAY_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 <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>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* pointer structure for use by random access indices */
+
+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 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):
+    size_(size),
+    capacity_(size),
+    spc(al,capacity_+1)
+  {
+    *end()=end_;
+    end_->up()=end();
+  }
+
+  std::size_t size()const{return size_;}
+  std::size_t capacity()const{return capacity_;}
+
+  void room_for_one()
+  {
+    if(size_==capacity_){
+      reserve(capacity_<=10?15:capacity_+capacity_/2);
+    }
+  }
+
+  void reserve(std::size_t c)
+  {
+    if(c>capacity_){
+      auto_space<value_type,Allocator> spc1(spc.get_allocator(),c+1);
+      node_impl_type::transfer(begin(),end()+1,spc1.data());
+      spc.swap(spc1);
+      capacity_=c;
+    }
+  }
+
+  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)
+  {
+    *(end()+1)=*end();
+    (*(end()+1))->up()=end()+1;
+    *end()=x;
+    (*end())->up()=end();
+    ++size_;
+  }
+
+  void erase(value_type x)
+  {
+    node_impl_type::extract(x->up(),end()+1);
+    --size_;
+  }
+
+  void clear()
+  {
+    *begin()=*end();
+    (*begin())->up()=begin();
+    size_=0;
+  }
+
+  void swap(random_access_index_ptr_array& x)
+  {
+    std::swap(size_,x.size_);
+    std::swap(capacity_,x.capacity_);
+    spc.swap(x.spc);
+  }
+
+private:
+  std::size_t                      size_;
+  std::size_t                      capacity_;
+  auto_space<value_type,Allocator> spc;
+
+  pointer ptrs()const
+  {
+    return spc.data();
+  }
+};
+
+template<typename Allocator>
+void swap(
+  random_access_index_ptr_array<Allocator>& x,
+  random_access_index_ptr_array<Allocator>& y)
+{
+  x.swap(y);
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/rnd_node_iterator.hpp b/boost/multi_index/detail/rnd_node_iterator.hpp
new file mode 100644 (file)
index 0000000..a41a0ff
--- /dev/null
@@ -0,0 +1,139 @@
+/* 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_DETAIL_RND_NODE_ITERATOR_HPP
+#define BOOST_MULTI_INDEX_DETAIL_RND_NODE_ITERATOR_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/operators.hpp>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/split_member.hpp>
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Iterator class for node-based indices with random access iterators. */
+
+template<typename Node,typename Derived=mpl::na>
+class rnd_node_iterator:
+  public random_access_iterator_helper<
+    rnd_node_iterator<Node,Derived>,
+    typename Node::value_type,
+    std::ptrdiff_t,
+    const typename Node::value_type*,
+    const typename Node::value_type&>
+{
+public:
+  rnd_node_iterator(){}
+  explicit rnd_node_iterator(Node* node_):node(node_){}
+
+  const typename Node::value_type& operator*()const
+  {
+    return node->value();
+  }
+
+  rnd_node_iterator& operator++()
+  {
+    Node::increment(node);
+    return *this;
+  }
+
+  rnd_node_iterator& operator--()
+  {
+    Node::decrement(node);
+    return *this;
+  }
+
+  rnd_node_iterator& operator+=(std::ptrdiff_t n)
+  {
+    Node::advance(node,n);
+    return *this;
+  }
+
+  rnd_node_iterator& operator-=(std::ptrdiff_t n)
+  {
+    Node::advance(node,-n);
+    return *this;
+  }
+
+#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.
+   */
+
+  BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+  typedef typename Node::base_type node_base_type;
+
+  template<class Archive>
+  void save(Archive& ar,const unsigned int)const
+  {
+    node_base_type* bnode=node;
+    ar<<serialization::make_nvp("pointer",bnode);
+  }
+
+  template<class Archive>
+  void load(Archive& ar,const unsigned int)
+  {
+    node_base_type* bnode;
+    ar>>serialization::make_nvp("pointer",bnode);
+    node=static_cast<Node*>(bnode);
+  }
+#endif
+
+  /* get_node is not to be used by the user */
+
+  typedef Node node_type;
+
+  Node* get_node()const{return node;}
+
+private:
+  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 */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/safe_ctr_proxy.hpp b/boost/multi_index/detail/safe_ctr_proxy.hpp
new file mode 100644 (file)
index 0000000..2f6f11a
--- /dev/null
@@ -0,0 +1,105 @@
+/* Copyright 2003-2006 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_DETAIL_SAFE_CTR_PROXY_HPP
+#define BOOST_MULTI_INDEX_DETAIL_SAFE_CTR_PROXY_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <boost/detail/workaround.hpp>
+
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+#include <boost/multi_index/detail/safe_mode.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* A safe iterator is instantiated in the form
+ * safe_iterator<Iterator,Container>: MSVC++ 6.0 has serious troubles with
+ * the resulting symbols names, given that index names (which stand for
+ * Container) are fairly long themselves. safe_ctr_proxy does not statically
+ * depend on Container, and provides the necessary methods (begin and end) to
+ * the safe mode framework via an abstract interface. With safe_ctr_proxy,
+ * instead of deriving from safe_container<Container> the following base class
+ * must be used:
+ *
+ *   safe_ctr_proxy_impl<Iterator,Container>
+ *
+ * where Iterator is the type of the *unsafe* iterator being wrapped.
+ * The corresponding safe iterator instantiation is then
+ * 
+ *   safe_iterator<Iterator,safe_ctr_proxy<Iterator> >,
+ *
+ * which does not include the name of Container.
+ */
+
+template<typename Iterator>
+class safe_ctr_proxy:
+  public safe_mode::safe_container<safe_ctr_proxy<Iterator> >
+{
+public:
+  typedef safe_mode::safe_iterator<Iterator,safe_ctr_proxy> iterator;
+  typedef iterator                                          const_iterator;
+
+  iterator       begin(){return begin_impl();}
+  const_iterator begin()const{return begin_impl();}
+  iterator       end(){return end_impl();}
+  const_iterator end()const{return end_impl();}
+
+protected:
+  virtual iterator       begin_impl()=0;
+  virtual const_iterator begin_impl()const=0;
+  virtual iterator       end_impl()=0;
+  virtual const_iterator end_impl()const=0;
+};
+
+template<typename Iterator,typename Container>
+class safe_ctr_proxy_impl:public safe_ctr_proxy<Iterator>
+{
+  typedef safe_ctr_proxy<Iterator> super;
+  typedef Container                container_type;
+
+public:
+  typedef typename super::iterator       iterator;
+  typedef typename super::const_iterator const_iterator;
+
+  virtual iterator       begin_impl(){return container().begin();}
+  virtual const_iterator begin_impl()const{return container().begin();}
+  virtual iterator       end_impl(){return container().end();}
+  virtual const_iterator end_impl()const{return container().end();}
+
+private:
+  container_type& container()
+  {
+    return *static_cast<container_type*>(this);
+  }
+  
+  const container_type& container()const
+  {
+    return *static_cast<const container_type*>(this);
+  }
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif /* workaround */
+
+#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
+
+#endif
diff --git a/boost/multi_index/detail/safe_mode.hpp b/boost/multi_index/detail/safe_mode.hpp
new file mode 100644 (file)
index 0000000..41885d0
--- /dev/null
@@ -0,0 +1,568 @@
+/* Copyright 2003-2006 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_DETAIL_SAFE_MODE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_SAFE_MODE_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+/* Safe mode machinery, in the spirit of Cay Hortmann's "Safe STL"
+ * (http://www.horstmann.com/safestl.html).
+ * In this mode, containers of type Container are derived from
+ * safe_container<Container>, and their corresponding iterators
+ * are wrapped with safe_iterator. These classes provide
+ * an internal record of which iterators are at a given moment associated
+ * to a given container, and properly mark the iterators as invalid
+ * when the container gets destroyed.
+ * Iterators are chained in a single attached list, whose header is
+ * kept by the container. More elaborate data structures would yield better
+ * performance, but I decided to keep complexity to a minimum since
+ * speed is not an issue here.
+ * Safe mode iterators automatically check that only proper operations
+ * are performed on them: for instance, an invalid iterator cannot be
+ * dereferenced. Additionally, a set of utilty macros and functions are
+ * provided that serve to implement preconditions and cooperate with
+ * the framework within the container.
+ * Iterators can also be unchecked, i.e. they do not have info about
+ * which container they belong in. This situation arises when the iterator
+ * is restored from a serialization archive: only information on the node
+ * is available, and it is not possible to determine to which container
+ * the iterator is associated to. The only sensible policy is to assume
+ * unchecked iterators are valid, though this can certainly generate false
+ * positive safe mode checks.
+ * This is not a full-fledged safe mode framework, and is only intended
+ * for use within the limits of Boost.MultiIndex.
+ */
+
+/* Assertion macros. These resolve to no-ops if
+ * !defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE).
+ */
+
+#if !defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#undef BOOST_MULTI_INDEX_SAFE_MODE_ASSERT
+#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) ((void)0)
+#else
+#if !defined(BOOST_MULTI_INDEX_SAFE_MODE_ASSERT)
+#include <boost/assert.hpp>
+#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) BOOST_ASSERT(expr)
+#endif
+#endif
+
+#define BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it)                           \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_valid_iterator(it),                                     \
+    safe_mode::invalid_iterator);
+
+#define BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(it)                 \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_dereferenceable_iterator(it),                           \
+    safe_mode::not_dereferenceable_iterator);
+
+#define BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(it)                   \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_incrementable_iterator(it),                             \
+    safe_mode::not_incrementable_iterator);
+
+#define BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(it)                   \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_decrementable_iterator(it),                             \
+    safe_mode::not_decrementable_iterator);
+
+#define BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,cont)                            \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_is_owner(it,cont),                                      \
+    safe_mode::not_owner);
+
+#define BOOST_MULTI_INDEX_CHECK_SAME_OWNER(it0,it1)                          \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_same_owner(it0,it1),                                    \
+    safe_mode::not_same_owner);
+
+#define BOOST_MULTI_INDEX_CHECK_VALID_RANGE(it0,it1)                         \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_valid_range(it0,it1),                                   \
+    safe_mode::invalid_range);
+
+#define BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(it,it0,it1)                    \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_outside_range(it,it0,it1),                              \
+    safe_mode::inside_range);
+
+#define BOOST_MULTI_INDEX_CHECK_IN_BOUNDS(it,n)                              \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_in_bounds(it,n),                                        \
+    safe_mode::out_of_bounds);
+
+#define BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(cont0,cont1)             \
+  BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(                                        \
+    safe_mode::check_different_container(cont0,cont1),                       \
+    safe_mode::same_container);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <algorithm>
+#include <boost/detail/iterator.hpp>
+#include <boost/multi_index/detail/access_specifier.hpp>
+#include <boost/multi_index/detail/iter_adaptor.hpp>
+#include <boost/multi_index/safe_mode_errors.hpp>
+#include <boost/noncopyable.hpp>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/serialization/split_member.hpp>
+#endif
+
+#if defined(BOOST_HAS_THREADS)
+#include <boost/detail/lightweight_mutex.hpp>
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace safe_mode{
+
+/* Checking routines. Assume the best for unchecked iterators
+ * (i.e. they pass the checking when there is not enough info
+ * to know.)
+ */
+
+template<typename Iterator>
+inline bool check_valid_iterator(const Iterator& it)
+{
+  return it.valid()||it.unchecked();
+}
+
+template<typename Iterator>
+inline bool check_dereferenceable_iterator(const Iterator& it)
+{
+  return it.valid()&&it!=it.owner()->end()||it.unchecked();
+}
+
+template<typename Iterator>
+inline bool check_incrementable_iterator(const Iterator& it)
+{
+  return it.valid()&&it!=it.owner()->end()||it.unchecked();
+}
+
+template<typename Iterator>
+inline bool check_decrementable_iterator(const Iterator& it)
+{
+  return it.valid()&&it!=it.owner()->begin()||it.unchecked();
+}
+
+template<typename Iterator>
+inline bool check_is_owner(
+  const Iterator& it,const typename Iterator::container_type& cont)
+{
+  return it.valid()&&it.owner()==&cont||it.unchecked();
+}
+
+template<typename Iterator>
+inline bool check_same_owner(const Iterator& it0,const Iterator& it1)
+{
+  return it0.valid()&&it1.valid()&&it0.owner()==it1.owner()||
+         it0.unchecked()||it1.unchecked();
+}
+
+template<typename Iterator>
+inline bool check_valid_range(const Iterator& it0,const Iterator& it1)
+{
+  if(!check_same_owner(it0,it1))return false;
+
+  if(it0.valid()){
+    Iterator last=it0.owner()->end();
+    if(it1==last)return true;
+
+    for(Iterator first=it0;first!=last;++first){
+      if(first==it1)return true;
+    }
+    return false;
+  }
+  return true;
+}
+
+template<typename Iterator>
+inline bool check_outside_range(
+  const Iterator& it,const Iterator& it0,const Iterator& it1)
+{
+  if(!check_same_owner(it0,it1))return false;
+
+  if(it0.valid()){
+    Iterator last=it0.owner()->end();
+    bool found=false;
+
+    Iterator first=it0;
+    for(;first!=last;++first){
+      if(first==it1)break;
+    
+      /* crucial that this check goes after previous break */
+    
+      if(first==it)found=true;
+    }
+    if(first!=it1)return false;
+    return !found;
+  }
+  return true;
+}
+
+template<typename Iterator,typename Difference>
+inline bool check_in_bounds(const Iterator& it,Difference n)
+{
+  if(it.unchecked())return true;
+  if(!it.valid())   return false;
+  if(n>0)           return it.owner()->end()-it>=n;
+  else              return it.owner()->begin()-it<=n;
+}
+
+template<typename Container>
+inline bool check_different_container(
+  const Container& cont0,const Container& cont1)
+{
+  return &cont0!=&cont1;
+}
+
+/* Invalidates all iterators equivalent to that given. Safe containers
+ * must call this when deleting elements: the safe mode framework cannot
+ * perform this operation automatically without outside help.
+ */
+
+template<typename Iterator>
+inline void detach_equivalent_iterators(Iterator& it)
+{
+  if(it.valid()){
+    Iterator *prev_,*next_;
+    for(
+      prev_=static_cast<Iterator*>(&it.cont->header);
+      (next_=static_cast<Iterator*>(prev_->next))!=0;){
+      if(next_!=&it&&*next_==it){
+        prev_->next=next_->next;
+        next_->cont=0;
+      }
+      else prev_=next_;
+    }
+    it.detach();
+  }
+}
+
+template<typename Container> class safe_container; /* fwd decl. */
+
+} /* namespace multi_index::safe_mode */
+
+namespace detail{
+
+class safe_container_base;                 /* fwd decl. */
+
+class safe_iterator_base
+{
+public:
+  bool valid()const{return cont!=0;}
+  bool unchecked()const{return unchecked_;}
+
+  inline void detach();
+
+  void uncheck()
+  {
+    detach();
+    unchecked_=true;
+  }
+
+protected:
+  safe_iterator_base():cont(0),next(0),unchecked_(false){}
+
+  explicit safe_iterator_base(safe_container_base* cont_):
+    unchecked_(false)
+  {
+    attach(cont_);
+  }
+
+  safe_iterator_base(const safe_iterator_base& it):
+    unchecked_(it.unchecked_)
+  {
+    attach(it.cont);
+  }
+
+  safe_iterator_base& operator=(const safe_iterator_base& it)
+  {
+    unchecked_=it.unchecked_;
+    safe_container_base* new_cont=it.cont;
+    if(cont!=new_cont){
+      detach();
+      attach(new_cont);
+    }
+    return *this;
+  }
+
+  ~safe_iterator_base()
+  {
+    detach();
+  }
+
+  const safe_container_base* owner()const{return cont;}
+
+BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
+  friend class safe_container_base;
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+  template<typename>          friend class safe_mode::safe_container;
+  template<typename Iterator> friend
+    void safe_mode::detach_equivalent_iterators(Iterator&);
+#endif
+
+  inline void attach(safe_container_base* cont_);
+
+  safe_container_base* cont;
+  safe_iterator_base*  next;
+  bool                 unchecked_;
+};
+
+class safe_container_base:private noncopyable
+{
+public:
+  safe_container_base(){}
+
+BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
+  friend class safe_iterator_base;
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+  template<typename Iterator> friend
+    void safe_mode::detach_equivalent_iterators(Iterator&);
+#endif
+
+  ~safe_container_base()
+  {
+    /* Detaches all remaining iterators, which by now will
+     * be those pointing to the end of the container.
+     */
+
+    for(safe_iterator_base* it=header.next;it;it=it->next)it->cont=0;
+    header.next=0;
+  }
+
+  void swap(safe_container_base& x)
+  {
+    for(safe_iterator_base* it0=header.next;it0;it0=it0->next)it0->cont=&x;
+    for(safe_iterator_base* it1=x.header.next;it1;it1=it1->next)it1->cont=this;
+    std::swap(header.cont,x.header.cont);
+    std::swap(header.next,x.header.next);
+  }
+
+  safe_iterator_base header;
+
+#if defined(BOOST_HAS_THREADS)
+  boost::detail::lightweight_mutex mutex;
+#endif
+};
+
+void safe_iterator_base::attach(safe_container_base* cont_)
+{
+  cont=cont_;
+  if(cont){
+#if defined(BOOST_HAS_THREADS)
+    boost::detail::lightweight_mutex::scoped_lock lock(cont->mutex);
+#endif
+
+    next=cont->header.next;
+    cont->header.next=this;
+  }
+}
+
+void safe_iterator_base::detach()
+{
+  if(cont){
+#if defined(BOOST_HAS_THREADS)
+    boost::detail::lightweight_mutex::scoped_lock lock(cont->mutex);
+#endif
+
+    safe_iterator_base *prev_,*next_;
+    for(prev_=&cont->header;(next_=prev_->next)!=this;prev_=next_){}
+    prev_->next=next;
+    cont=0;
+  }
+}
+
+} /* namespace multi_index::detail */
+
+namespace safe_mode{
+
+/* In order to enable safe mode on a container:
+ *   - The container must derive from safe_container<container_type>,
+ *   - iterators must be generated via safe_iterator, which adapts a
+ *     preexistent unsafe iterator class.
+ */
+template<typename Container>
+class safe_container;
+
+template<typename Iterator,typename Container>
+class safe_iterator:
+  public detail::iter_adaptor<safe_iterator<Iterator,Container>,Iterator>,
+  public detail::safe_iterator_base
+{
+  typedef detail::iter_adaptor<safe_iterator,Iterator> super;
+  typedef detail::safe_iterator_base                   safe_super;
+
+public:
+  typedef Container                                    container_type;
+  typedef typename Iterator::reference                 reference;
+  typedef typename Iterator::difference_type           difference_type;
+
+  safe_iterator(){}
+  explicit safe_iterator(safe_container<container_type>* cont_):
+    safe_super(cont_){}
+  template<typename T0>
+  safe_iterator(const T0& t0,safe_container<container_type>* cont_):
+    super(Iterator(t0)),safe_super(cont_){}
+  template<typename T0,typename T1>
+  safe_iterator(
+    const T0& t0,const T1& t1,safe_container<container_type>* cont_):
+    super(Iterator(t0,t1)),safe_super(cont_){}
+
+  safe_iterator& operator=(const safe_iterator& x)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
+    this->base_reference()=x.base_reference();
+    safe_super::operator=(x);
+    return *this;
+  }
+
+  const container_type* owner()const
+  {
+    return
+      static_cast<const container_type*>(
+        static_cast<const safe_container<container_type>*>(
+          this->safe_super::owner()));
+  }
+
+  /* get_node is not to be used by the user */
+
+  typedef typename Iterator::node_type node_type;
+
+  node_type* get_node()const{return this->base_reference().get_node();}
+
+private:
+  friend class boost::multi_index::detail::iter_adaptor_access;
+
+  reference dereference()const
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(*this);
+    return *(this->base_reference());
+  }
+
+  bool equal(const safe_iterator& x)const
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
+    BOOST_MULTI_INDEX_CHECK_SAME_OWNER(*this,x);
+    return this->base_reference()==x.base_reference();
+  }
+
+  void increment()
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
+    BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(*this);
+    ++(this->base_reference());
+  }
+
+  void decrement()
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
+    BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(*this);
+    --(this->base_reference());
+  }
+
+  void advance(difference_type n)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
+    BOOST_MULTI_INDEX_CHECK_IN_BOUNDS(*this,n);
+    this->base_reference()+=n;
+  }
+
+  difference_type distance_to(const safe_iterator& x)const
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
+    BOOST_MULTI_INDEX_CHECK_SAME_OWNER(*this,x);
+    return x.base_reference()-this->base_reference();
+  }
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  /* Serialization. Note that Iterator::save and Iterator:load
+   * are assumed to be defined and public: at first sight it seems
+   * like we could have resorted to the public serialization interface
+   * for doing the forwarding to the adapted iterator class:
+   *   ar<<base_reference();
+   *   ar>>base_reference();
+   * but this would cause incompatibilities if a saving
+   * program is in safe mode and the loading program is not, or
+   * viceversa --in safe mode, the archived iterator data is one layer
+   * deeper, this is especially relevant with XML archives.
+   * It'd be nice if Boost.Serialization provided some forwarding
+   * facility for use by adaptor classes.
+   */ 
+
+  friend class boost::serialization::access;
+
+  BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+  template<class Archive>
+  void save(Archive& ar,const unsigned int version)const
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
+    this->base_reference().save(ar,version);
+  }
+
+  template<class Archive>
+  void load(Archive& ar,const unsigned int version)
+  {
+    this->base_reference().load(ar,version);
+    safe_super::uncheck();
+  }
+#endif
+};
+
+template<typename Container>
+class safe_container:public detail::safe_container_base
+{
+  typedef detail::safe_container_base super;
+
+public:
+  void detach_dereferenceable_iterators()
+  {
+    typedef typename Container::iterator iterator;
+
+    iterator end_=static_cast<Container*>(this)->end();
+    iterator *prev_,*next_;
+    for(
+      prev_=static_cast<iterator*>(&this->header);
+      (next_=static_cast<iterator*>(prev_->next))!=0;){
+      if(*next_!=end_){
+        prev_->next=next_->next;
+        next_->cont=0;
+      }
+      else prev_=next_;
+    }
+  }
+
+  void swap(safe_container<Container>& x)
+  {
+    super::swap(x);
+  }
+};
+
+} /* namespace multi_index::safe_mode */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
+
+#endif
diff --git a/boost/multi_index/detail/scope_guard.hpp b/boost/multi_index/detail/scope_guard.hpp
new file mode 100644 (file)
index 0000000..5288c80
--- /dev/null
@@ -0,0 +1,277 @@
+/* Copyright 2003-2005 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_DETAIL_SCOPE_GUARD_HPP
+#define BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Until some official version of the ScopeGuard idiom makes it into Boost,
+ * we locally define our own. This is a merely reformated version of
+ * ScopeGuard.h as defined in:
+ *   Alexandrescu, A., Marginean, P.:"Generic<Programming>: Change the Way You
+ *     Write Exception-Safe Code - Forever", C/C++ Users Jornal, Dec 2000,
+ *     http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/
+ * with the following modifications:
+ *   - General pretty formatting (pretty to my taste at least.)
+ *   - Naming style changed to standard C++ library requirements.
+ *   - safe_execute does not feature a try-catch protection, so we can
+ *     use this even if BOOST_NO_EXCEPTIONS is defined.
+ *   - Added scope_guard_impl4 and obj_scope_guard_impl3, (Boost.MultiIndex
+ *     needs them). A better design would provide guards for many more
+ *     arguments through the Boost Preprocessor Library.
+ *   - Added scope_guard_impl_base::touch (see below.)
+ *   - Removed RefHolder and ByRef, whose functionality is provided
+ *     already by Boost.Ref.
+ *   - Removed static make_guard's and make_obj_guard's, so that the code
+ *     will work even if BOOST_NO_MEMBER_TEMPLATES is defined. This forces
+ *     us to move some private ctors to public, though.
+ *
+ * NB: CodeWarrior Pro 8 seems to have problems looking up safe_execute
+ * without an explicit qualification.
+ */
+
+class scope_guard_impl_base
+{
+public:
+  scope_guard_impl_base():dismissed_(false){}
+  void dismiss()const{dismissed_=true;}
+
+  /* This helps prevent some "unused variable" warnings under, for instance,
+   * GCC 3.2.
+   */
+  void touch()const{}
+
+protected:
+  ~scope_guard_impl_base(){}
+
+  scope_guard_impl_base(const scope_guard_impl_base& other):
+    dismissed_(other.dismissed_)
+  {
+    other.dismiss();
+  }
+
+  template<typename J>
+  static void safe_execute(J& j){if(!j.dismissed_)j.execute();}
+  
+  mutable bool dismissed_;
+
+private:
+  scope_guard_impl_base& operator=(const scope_guard_impl_base&);
+};
+
+typedef const scope_guard_impl_base& scope_guard;
+
+template<typename F>
+class scope_guard_impl0:public scope_guard_impl_base
+{
+public:
+  scope_guard_impl0(F fun):fun_(fun){}
+  ~scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);}
+  void execute(){fun_();}
+
+protected:
+
+  F fun_;
+};
+
+template<typename F> 
+inline scope_guard_impl0<F> make_guard(F fun)
+{
+  return scope_guard_impl0<F>(fun);
+}
+
+template<typename F,typename P1>
+class scope_guard_impl1:public scope_guard_impl_base
+{
+public:
+  scope_guard_impl1(F fun,P1 p1):fun_(fun),p1_(p1){}
+  ~scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);}
+  void execute(){fun_(p1_);}
+
+protected:
+  F        fun_;
+  const P1 p1_;
+};
+
+template<typename F,typename P1> 
+inline scope_guard_impl1<F,P1> make_guard(F fun,P1 p1)
+{
+  return scope_guard_impl1<F,P1>(fun,p1);
+}
+
+template<typename F,typename P1,typename P2>
+class scope_guard_impl2:public scope_guard_impl_base
+{
+public:
+  scope_guard_impl2(F fun,P1 p1,P2 p2):fun_(fun),p1_(p1),p2_(p2){}
+  ~scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);}
+  void execute(){fun_(p1_,p2_);}
+
+protected:
+  F        fun_;
+  const P1 p1_;
+  const P2 p2_;
+};
+
+template<typename F,typename P1,typename P2>
+inline scope_guard_impl2<F,P1,P2> make_guard(F fun,P1 p1,P2 p2)
+{
+  return scope_guard_impl2<F,P1,P2>(fun,p1,p2);
+}
+
+template<typename F,typename P1,typename P2,typename P3>
+class scope_guard_impl3:public scope_guard_impl_base
+{
+public:
+  scope_guard_impl3(F fun,P1 p1,P2 p2,P3 p3):fun_(fun),p1_(p1),p2_(p2),p3_(p3){}
+  ~scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);}
+  void execute(){fun_(p1_,p2_,p3_);}
+
+protected:
+  F        fun_;
+  const P1 p1_;
+  const P2 p2_;
+  const P3 p3_;
+};
+
+template<typename F,typename P1,typename P2,typename P3>
+inline scope_guard_impl3<F,P1,P2,P3> make_guard(F fun,P1 p1,P2 p2,P3 p3)
+{
+  return scope_guard_impl3<F,P1,P2,P3>(fun,p1,p2,p3);
+}
+
+template<typename F,typename P1,typename P2,typename P3,typename P4>
+class scope_guard_impl4:public scope_guard_impl_base
+{
+public:
+  scope_guard_impl4(F fun,P1 p1,P2 p2,P3 p3,P4 p4):
+    fun_(fun),p1_(p1),p2_(p2),p3_(p3),p4_(p4){}
+  ~scope_guard_impl4(){scope_guard_impl_base::safe_execute(*this);}
+  void execute(){fun_(p1_,p2_,p3_,p4_);}
+
+protected:
+  F        fun_;
+  const P1 p1_;
+  const P2 p2_;
+  const P3 p3_;
+  const P4 p4_;
+};
+
+template<typename F,typename P1,typename P2,typename P3,typename P4>
+inline scope_guard_impl4<F,P1,P2,P3,P4> make_guard(
+  F fun,P1 p1,P2 p2,P3 p3,P4 p4)
+{
+  return scope_guard_impl4<F,P1,P2,P3,P4>(fun,p1,p2,p3,p4);
+}
+
+template<class Obj,typename MemFun>
+class obj_scope_guard_impl0:public scope_guard_impl_base
+{
+public:
+  obj_scope_guard_impl0(Obj& obj,MemFun mem_fun):obj_(obj),mem_fun_(mem_fun){}
+  ~obj_scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);}
+  void execute(){(obj_.*mem_fun_)();}
+
+protected:
+  Obj&   obj_;
+  MemFun mem_fun_;
+};
+
+template<class Obj,typename MemFun>
+inline obj_scope_guard_impl0<Obj,MemFun> make_obj_guard(Obj& obj,MemFun mem_fun)
+{
+  return obj_scope_guard_impl0<Obj,MemFun>(obj,mem_fun);
+}
+
+template<class Obj,typename MemFun,typename P1>
+class obj_scope_guard_impl1:public scope_guard_impl_base
+{
+public:
+  obj_scope_guard_impl1(Obj& obj,MemFun mem_fun,P1 p1):
+    obj_(obj),mem_fun_(mem_fun),p1_(p1){}
+  ~obj_scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);}
+  void execute(){(obj_.*mem_fun_)(p1_);}
+
+protected:
+  Obj&     obj_;
+  MemFun   mem_fun_;
+  const P1 p1_;
+};
+
+template<class Obj,typename MemFun,typename P1>
+inline obj_scope_guard_impl1<Obj,MemFun,P1> make_obj_guard(
+  Obj& obj,MemFun mem_fun,P1 p1)
+{
+  return obj_scope_guard_impl1<Obj,MemFun,P1>(obj,mem_fun,p1);
+}
+
+template<class Obj,typename MemFun,typename P1,typename P2>
+class obj_scope_guard_impl2:public scope_guard_impl_base
+{
+public:
+  obj_scope_guard_impl2(Obj& obj,MemFun mem_fun,P1 p1,P2 p2):
+    obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2)
+  {}
+  ~obj_scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);}
+  void execute(){(obj_.*mem_fun_)(p1_,p2_);}
+
+protected:
+  Obj&     obj_;
+  MemFun   mem_fun_;
+  const P1 p1_;
+  const P2 p2_;
+};
+
+template<class Obj,typename MemFun,typename P1,typename P2>
+inline obj_scope_guard_impl2<Obj,MemFun,P1,P2>
+make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
+{
+  return obj_scope_guard_impl2<Obj,MemFun,P1,P2>(obj,mem_fun,p1,p2);
+}
+
+template<class Obj,typename MemFun,typename P1,typename P2,typename P3>
+class obj_scope_guard_impl3:public scope_guard_impl_base
+{
+public:
+  obj_scope_guard_impl3(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3):
+    obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2),p3_(p3)
+  {}
+  ~obj_scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);}
+  void execute(){(obj_.*mem_fun_)(p1_,p2_,p3_);}
+
+protected:
+  Obj&     obj_;
+  MemFun   mem_fun_;
+  const P1 p1_;
+  const P2 p2_;
+  const P3 p3_;
+};
+
+template<class Obj,typename MemFun,typename P1,typename P2,typename P3>
+inline obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>
+make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
+{
+  return obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>(obj,mem_fun,p1,p2,p3);
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/seq_index_node.hpp b/boost/multi_index/detail/seq_index_node.hpp
new file mode 100644 (file)
index 0000000..36803af
--- /dev/null
@@ -0,0 +1,223 @@
+/* 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_DETAIL_SEQ_INDEX_NODE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_NODE_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 <algorithm>
+#include <boost/detail/allocator_utilities.hpp>
+#include <boost/multi_index/detail/prevent_eti.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* doubly-linked node for use by sequenced_index */
+
+template<typename Allocator>
+struct sequenced_index_node_impl
+{
+  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(pointer& x){x=x->next();}
+  static void decrement(pointer& x){x=x->prior();}
+
+  /* algorithmic stuff */
+
+  static void link(pointer x,pointer header)
+  {
+    x->prior()=header->prior();
+    x->next()=header;
+    x->prior()->next()=x->next()->prior()=x;
+  };
+
+  static void unlink(pointer x)
+  {
+    x->prior()->next()=x->next();
+    x->next()->prior()=x->prior();
+  }
+
+  static void relink(pointer position,pointer x)
+  {
+    unlink(x);
+    x->prior()=position->prior();
+    x->next()=position;
+    x->prior()->next()=x->next()->prior()=x;
+  }
+
+  static void relink(pointer position,pointer x,pointer y)
+  {
+    /* position is assumed not to be in [x,y) */
+
+    if(x!=y){
+      pointer z=y->prior();
+      x->prior()->next()=y;
+      y->prior()=x->prior();
+      x->prior()=position->prior();
+      z->next()=position;
+      x->prior()->next()=x;
+      z->next()->prior()=z;
+    }
+  }
+
+  static void reverse(pointer header)
+  {
+    pointer x=header;
+    do{
+      pointer y=x->next();
+      std::swap(x->prior(),x->next());
+      x=y;
+    }while(x!=header);
+  }
+
+  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
+     * sequenced_index::swap.
+     */
+
+    if(x->next()!=x){
+      if(y->next()!=y){
+        std::swap(x->next(),y->next());
+        std::swap(x->prior(),y->prior());
+        x->next()->prior()=x->prior()->next()=x;
+        y->next()->prior()=y->prior()->next()=y;
+      }
+      else{
+        y->next()=x->next();
+        y->prior()=x->prior();
+        x->next()=x->prior()=x;
+        y->next()->prior()=y->prior()->next()=y;
+      }
+    }
+    else if(y->next()!=y){
+      x->next()=y->next();
+      x->prior()=y->prior();
+      y->next()=y->prior()=y;
+      x->next()->prior()=x->prior()->next()=x;
+    }
+  }
+
+private:
+  pointer prior_;
+  pointer next_;
+};
+
+template<typename Super>
+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>
+{
+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 trampoline*>(&*x));
+  }
+
+  /* interoperability with bidir_node_iterator */
+
+  static void increment(sequenced_index_node*& x)
+  {
+    impl_pointer xi=x->impl();
+    trampoline::increment(xi);
+    x=from_impl(xi);
+  }
+
+  static void decrement(sequenced_index_node*& x)
+  {
+    impl_pointer xi=x->impl();
+    trampoline::decrement(xi);
+    x=from_impl(xi);
+  }
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/seq_index_ops.hpp b/boost/multi_index/detail/seq_index_ops.hpp
new file mode 100644 (file)
index 0000000..2c0f213
--- /dev/null
@@ -0,0 +1,200 @@
+/* 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_DETAIL_SEQ_INDEX_OPS_HPP
+#define BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_OPS_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/detail/no_exceptions_support.hpp>
+#include <boost/multi_index/detail/seq_index_node.hpp>
+#include <boost/limits.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp> 
+#include <cstddef>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Common code for sequenced_index memfuns having templatized and
+ * non-templatized versions.
+ */
+
+template <typename SequencedIndex,typename Predicate>
+void sequenced_index_remove(SequencedIndex& x,Predicate pred)
+{
+  typedef typename SequencedIndex::iterator iterator;
+  iterator first=x.begin(),last=x.end();
+  while(first!=last){
+    if(pred(*first))x.erase(first++);
+    else ++first;
+  }
+}
+
+template <typename SequencedIndex,class BinaryPredicate>
+void sequenced_index_unique(SequencedIndex& x,BinaryPredicate binary_pred)
+{
+  typedef typename SequencedIndex::iterator iterator;
+  iterator first=x.begin();
+  iterator last=x.end();
+  if(first!=last){
+    for(iterator middle=first;++middle!=last;middle=first){
+      if(binary_pred(*middle,*first))x.erase(middle);
+      else first=middle;
+    }
+  }
+}
+
+template <typename SequencedIndex,typename Compare>
+void sequenced_index_merge(SequencedIndex& x,SequencedIndex& y,Compare comp)
+{
+  typedef typename SequencedIndex::iterator iterator;
+  if(&x!=&y){
+    iterator first0=x.begin(),last0=x.end();
+    iterator first1=y.begin(),last1=y.end();
+    while(first0!=last0&&first1!=last1){
+      if(comp(*first1,*first0))x.splice(first0,y,first1++);
+      else ++first0;
+    }
+    x.splice(last0,y,first1,last1);
+  }
+}
+
+/* sorting  */
+
+/* auxiliary stuff */
+
+template<typename Node,typename Compare>
+void sequenced_index_collate(
+  BOOST_DEDUCED_TYPENAME Node::impl_type* x,
+  BOOST_DEDUCED_TYPENAME Node::impl_type* y,
+  Compare comp
+  BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
+{
+  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())){
+      impl_pointer tmp=first1->next();
+      impl_type::relink(first0,first1);
+      first1=tmp;
+    }
+    else first0=first0->next();
+  }
+  impl_type::relink(last0,first1,last1);
+}
+
+/* Some versions of CGG require a bogus typename in counter_spc
+ * inside sequenced_index_sort if the following is defined
+ * also inside sequenced_index_sort.
+ */
+
+BOOST_STATIC_CONSTANT(
+  std::size_t,
+  sequenced_index_sort_max_fill=
+    (std::size_t)std::numeric_limits<std::size_t>::digits+1);
+
+template<typename Node,typename Compare>
+void sequenced_index_sort(Node* header,Compare comp)
+{
+  /* Musser's mergesort, see http://www.cs.rpi.edu/~musser/gp/List/lists1.html.
+   * The implementation is a little convoluted: in the original code
+   * counter elements and carry are std::lists: here we do not want
+   * to use multi_index instead, so we do things at a lower level, managing
+   * directly the internal node representation.
+   * Incidentally, the implementations I've seen of this algorithm (SGI,
+   * Dinkumware, STLPort) are not exception-safe: this is. Moreover, we do not
+   * use any dynamic storage.
+   */
+
+  if(header->next()==header->impl()||
+     header->next()->next()==header->impl())return;
+
+  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(
+      impl_type
+        [sequenced_index_sort_max_fill]),
+    alignment_of<
+      impl_type
+        [sequenced_index_sort_max_fill]
+    >::value
+  >::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()=static_cast<impl_pointer>(&carry);
+  counter[0].prior()=counter[0].next()=static_cast<impl_pointer>(&counter[0]);
+
+  BOOST_TRY{
+    while(header->next()!=header->impl()){
+      impl_type::relink(carry.next(),header->next());
+      std::size_t i=0;
+      while(i<fill&&counter[i].next()!=static_cast<impl_pointer>(&counter[i])){
+        sequenced_index_collate<Node>(&carry,&counter[i++],comp);
+      }
+      impl_type::swap(
+        static_cast<impl_pointer>(&carry),
+        static_cast<impl_pointer>(&counter[i]));
+      if(i==fill){
+        ++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);
+    }
+    impl_type::swap(
+      header->impl(),static_cast<impl_pointer>(&counter[fill-1]));
+  }
+  BOOST_CATCH(...)
+  {
+    impl_type::relink(
+      header->impl(),carry.next(),static_cast<impl_pointer>(&carry));
+    for(std::size_t i=0;i<=fill;++i){
+      impl_type::relink(
+        header->impl(),counter[i].next(),
+        static_cast<impl_pointer>(&counter[i]));
+    }
+    BOOST_RETHROW;
+  }
+  BOOST_CATCH_END
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/uintptr_type.hpp b/boost/multi_index/detail/uintptr_type.hpp
new file mode 100644 (file)
index 0000000..2c18180
--- /dev/null
@@ -0,0 +1,76 @@
+/* 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_DETAIL_UINTPTR_TYPE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_UINTPTR_TYPE_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/bool.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* has_uintptr_type is an MPL integral constant determining whether
+ * there exists an unsigned integral type with the same size as
+ * void *.
+ * uintptr_type is such a type if has_uintptr is true, or unsigned int
+ * otherwise.
+ * Note that uintptr_type is more restrictive than C99 uintptr_t,
+ * where an integral type with size greater than that of void *
+ * would be conformant.
+ */
+
+template<int N>struct uintptr_candidates;
+template<>struct uintptr_candidates<-1>{typedef unsigned int       type;};
+template<>struct uintptr_candidates<0> {typedef unsigned int       type;};
+template<>struct uintptr_candidates<1> {typedef unsigned short     type;};
+template<>struct uintptr_candidates<2> {typedef unsigned long      type;};
+
+#if defined(BOOST_HAS_LONG_LONG)
+template<>struct uintptr_candidates<3> {typedef unsigned long long type;};
+#else
+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:
+    sizeof(void*)==sizeof(uintptr_candidates<4>::type)?4:-1);
+
+  BOOST_STATIC_CONSTANT(bool,has_uintptr_type=(index>=0));
+
+  typedef uintptr_candidates<index>::type type;
+};
+
+typedef mpl::bool_<uintptr_aux::has_uintptr_type> has_uintptr_type;
+typedef uintptr_aux::type                         uintptr_type;
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/unbounded.hpp b/boost/multi_index/detail/unbounded.hpp
new file mode 100644 (file)
index 0000000..57b0215
--- /dev/null
@@ -0,0 +1,83 @@
+/* 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_DETAIL_UNBOUNDED_HPP
+#define BOOST_MULTI_INDEX_DETAIL_UNBOUNDED_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/detail/workaround.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+/* dummy type and variable for use in ordered_index::range() */
+
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+/* The default branch actually works for MSVC 6.0, but seems like
+ * 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
+/* 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
+
+/* 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 */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/detail/value_compare.hpp b/boost/multi_index/detail/value_compare.hpp
new file mode 100644 (file)
index 0000000..f392f85
--- /dev/null
@@ -0,0 +1,53 @@
+/* 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_DETAIL_VALUE_COMPARE_HPP
+#define BOOST_MULTI_INDEX_DETAIL_VALUE_COMPARE_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/call_traits.hpp>
+#include <functional>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<typename Value,typename KeyFromValue,typename Compare>
+struct value_comparison:std::binary_function<Value,Value,bool>
+{
+  value_comparison(
+    const KeyFromValue& key_=KeyFromValue(),const Compare& comp_=Compare()):
+    key(key_),comp(comp_)
+  {
+  }
+
+  bool operator()(
+    typename call_traits<Value>::param_type x,
+    typename call_traits<Value>::param_type y)const
+  {
+    return comp(key(x),key(y));
+  }
+
+private:
+  KeyFromValue key;
+  Compare      comp;
+};
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/global_fun.hpp b/boost/multi_index/global_fun.hpp
new file mode 100644 (file)
index 0000000..314d526
--- /dev/null
@@ -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
diff --git a/boost/multi_index/hashed_index.hpp b/boost/multi_index/hashed_index.hpp
new file mode 100644 (file)
index 0000000..456797a
--- /dev/null
@@ -0,0 +1,1167 @@
+/* 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_HASHED_INDEX_HPP
+#define BOOST_MULTI_INDEX_HASHED_INDEX_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 <algorithm>
+#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/limits.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/multi_index/detail/access_specifier.hpp>
+#include <boost/multi_index/detail/auto_space.hpp>
+#include <boost/multi_index/detail/bucket_array.hpp>
+#include <boost/multi_index/detail/hash_index_iterator.hpp>
+#include <boost/multi_index/detail/index_node_base.hpp>
+#include <boost/multi_index/detail/modify_key_adaptor.hpp>
+#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
+#include <boost/multi_index/detail/safe_mode.hpp>
+#include <boost/multi_index/detail/scope_guard.hpp>
+#include <boost/multi_index/hashed_index_fwd.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <cstddef>
+#include <functional>
+#include <utility>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/serialization/nvp.hpp>
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+#define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT                       \
+  detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
+    detail::make_obj_guard(*this,&hashed_index::check_invariant_);           \
+  BOOST_JOIN(check_invariant_,__LINE__).touch();
+#else
+#define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* hashed_index adds a layer of hashed indexing to a given Super */
+
+/* Most of the implementation of unique and non-unique indices is
+ * shared. We tell from one another on instantiation time by using
+ * these tags.
+ */
+
+struct hashed_unique_tag{};
+struct hashed_non_unique_tag{};
+
+template<
+  typename KeyFromValue,typename Hash,typename Pred,
+  typename SuperMeta,typename TagList,typename Category
+>
+class hashed_index:
+  BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  ,public safe_ctr_proxy_impl<
+    hashed_index_iterator<
+      hashed_index_node<typename SuperMeta::type::node_type>,
+      bucket_array<typename SuperMeta::type::final_allocator_type> >,
+    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
+#else
+  ,public safe_mode::safe_container<
+    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
+#endif
+#endif
+
+{ 
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
+ * lifetime of const references bound to temporaries --precisely what
+ * scopeguards are.
+ */
+
+#pragma parse_mfunc_templ off
+#endif
+
+  typedef typename SuperMeta::type                   super;
+
+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;
+
+public:
+  /* types */
+
+  typedef typename KeyFromValue::result_type         key_type;
+  typedef typename node_type::value_type             value_type;
+  typedef KeyFromValue                               key_from_value;
+  typedef Hash                                       hasher;
+  typedef Pred                                       key_equal;
+  typedef tuple<std::size_t,
+    key_from_value,hasher,key_equal>                 ctor_args;
+  typedef typename super::final_allocator_type       allocator_type;
+  typedef typename allocator_type::pointer           pointer;
+  typedef typename allocator_type::const_pointer     const_pointer;
+  typedef typename allocator_type::reference         reference;
+  typedef typename allocator_type::const_reference   const_reference;
+  typedef std::size_t                                size_type;      
+  typedef std::ptrdiff_t                             difference_type;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  typedef safe_mode::safe_iterator<
+    hashed_index_iterator<
+      node_type,bucket_array_type>,
+    safe_ctr_proxy<
+      hashed_index_iterator<
+        node_type,bucket_array_type> > >             iterator;
+#else
+  typedef safe_mode::safe_iterator<
+    hashed_index_iterator<
+      node_type,bucket_array_type>,
+    hashed_index>                                    iterator;
+#endif
+#else
+  typedef hashed_index_iterator<
+    node_type,bucket_array_type>                     iterator;
+#endif
+
+  typedef iterator                                   const_iterator;
+
+  typedef iterator                                   local_iterator;
+  typedef const_iterator                             const_local_iterator;
+  typedef TagList                                    tag_list;
+
+protected:
+  typedef typename super::final_node_type     final_node_type;
+  typedef tuples::cons<
+    ctor_args, 
+    typename super::ctor_args_list>           ctor_args_list;
+  typedef typename mpl::push_front<
+    typename super::index_type_list,
+    hashed_index>::type                       index_type_list;
+  typedef typename mpl::push_front<
+    typename super::iterator_type_list,
+    iterator>::type                           iterator_type_list;
+  typedef typename mpl::push_front<
+    typename super::const_iterator_type_list,
+    const_iterator>::type                     const_iterator_type_list;
+  typedef typename super::copy_map_type       copy_map_type;
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  typedef typename super::index_saver_type    index_saver_type;
+  typedef typename super::index_loader_type   index_loader_type;
+#endif
+
+private:
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  typedef safe_ctr_proxy_impl<
+    hashed_index_iterator<
+      node_type,bucket_array_type>,
+    hashed_index>                             safe_super;
+#else
+  typedef safe_mode::safe_container<
+    hashed_index>                             safe_super;
+#endif
+#endif
+
+  typedef typename call_traits<value_type>::param_type value_param_type;
+  typedef typename call_traits<
+    key_type>::param_type                              key_param_type;
+
+public:
+
+  /* construct/destroy/copy
+   * Default and copy ctors are in the protected section as indices are
+   * not supposed to be created on their own. No range ctor either.
+   */
+
+  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
+    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
+  {
+    this->final()=x.final();
+    return *this;
+  }
+
+  allocator_type get_allocator()const
+  {
+    return this->final().get_allocator();
+  }
+
+  /* size and capacity */
+
+  bool      empty()const{return this->final_empty_();}
+  size_type size()const{return this->final_size_();}
+  size_type max_size()const{return this->final_max_size_();}
+
+  /* iterators */
+
+  iterator begin()
+  {
+    return make_iterator(
+      node_type::from_impl(buckets.at(first_bucket)->next()));
+  }
+
+  const_iterator begin()const
+  {
+    return make_iterator(
+      node_type::from_impl(buckets.at(first_bucket)->next()));
+  }
+
+  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)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    std::pair<final_node_type*,bool> p=this->final_insert_(x);
+    return std::pair<iterator,bool>(make_iterator(p.first),p.second);
+  }
+
+  iterator insert(iterator position,value_param_type x)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    std::pair<final_node_type*,bool> p=this->final_insert_(
+      x,static_cast<final_node_type*>(position.get_node()));
+    return make_iterator(p.first);
+  }
+    
+  template<typename InputIterator>
+  void insert(InputIterator first,InputIterator last)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    iterator hint=end();
+    for(;first!=last;++first)hint=insert(hint,*first);
+  }
+
+  iterator erase(iterator position)
+  {
+    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;
+    this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
+    return position;
+  }
+
+  size_type erase(key_param_type k)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+
+    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{
+          node_impl_pointer z=y->next();
+          b=z!=x&&eq(
+            key(node_type::from_impl(y)->value()),
+            key(node_type::from_impl(z)->value()));
+          this->final_erase_(
+            static_cast<final_node_type*>(node_type::from_impl(y)));
+          y=z;
+          ++s;
+        }while(b);
+        break;
+      }
+      y=y->next();
+    }
+    return s;
+  }
+
+  iterator erase(iterator first,iterator last)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    while(first!=last){
+      first=erase(first);
+    }
+    return first;
+  }
+
+  bool replace(iterator position,value_param_type x)
+  {
+    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 this->final_replace_(
+      x,static_cast<final_node_type*>(position.get_node()));
+  }
+
+  template<typename Modifier>
+  bool modify(iterator position,Modifier mod)
+  {
+    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,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)
+  {
+    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));
+  }
+
+  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;
+    this->final_clear_();
+  }
+
+  void swap(hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    this->final_swap_(x.final());
+  }
+
+  /* observers */
+
+  key_from_value key_extractor()const{return key;}
+  hasher         hash_function()const{return hash;}
+  key_equal      key_eq()const{return eq;}
+  
+  /* lookup */
+
+  /* Internally, these ops rely on const_iterator being the same
+   * type as iterator.
+   */
+
+  template<typename CompatibleKey>
+  iterator find(const CompatibleKey& k)const
+  {
+    return find(k,hash,eq);
+  }
+
+  template<
+    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
+  >
+  iterator find(
+    const CompatibleKey& k,
+    const CompatibleHash& hash,const CompatiblePred& eq)const
+  {
+    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));
+      }
+      y=y->next();
+    }
+    return end();
+  }
+
+  template<typename CompatibleKey>
+  size_type count(const CompatibleKey& k)const
+  {
+    return count(k,hash,eq);
+  }
+
+  template<
+    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
+  >
+  size_type count(
+    const CompatibleKey& k,
+    const CompatibleHash& hash,const CompatiblePred& eq)const
+  {
+    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{
+          ++res;
+          y=y->next();
+        }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
+        break;
+      }
+      y=y->next();
+    }
+    return res;
+  }
+
+  template<typename CompatibleKey>
+  std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const
+  {
+    return equal_range(k,hash,eq);
+  }
+
+  template<
+    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
+  >
+  std::pair<iterator,iterator> equal_range(
+    const CompatibleKey& k,
+    const CompatibleHash& hash,const CompatiblePred& eq)const
+  {
+    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()))){
+        node_impl_pointer y0=y;
+        do{
+          y=y->next();
+        }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
+        if(y==x){
+          do{
+            ++y;
+          }while(y==y->next());
+          y=y->next();
+        }
+        return std::pair<iterator,iterator>(
+          make_iterator(node_type::from_impl(y0)),
+          make_iterator(node_type::from_impl(y)));
+      }
+      y=y->next();
+    }
+    return std::pair<iterator,iterator>(end(),end());
+  }
+
+  /* bucket interface */
+
+  size_type bucket_count()const{return buckets.size();}
+  size_type max_bucket_count()const{return static_cast<size_type>(-1);}
+
+  size_type bucket_size(size_type n)const
+  {
+    size_type         res=0;
+    node_impl_pointer x=buckets.at(n);
+    node_impl_pointer y=x->next();
+    while(y!=x){
+      ++res;
+      y=y->next();
+    }
+    return res;
+  }
+
+  size_type bucket(key_param_type k)const
+  {
+    return buckets.position(hash(k));
+  }
+
+  local_iterator begin(size_type n)
+  {
+    return const_cast<const hashed_index*>(this)->begin(n);
+  }
+
+  const_local_iterator begin(size_type n)const
+  {
+    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));
+  }
+
+  local_iterator end(size_type n)
+  {
+    return const_cast<const hashed_index*>(this)->end(n);
+  }
+
+  const_local_iterator end(size_type n)const
+  {
+    node_impl_pointer x=buckets.at(n);
+    if(x==x->next())return end();
+    do{
+      ++x;
+    }while(x==x->next());
+    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();}
+  float max_load_factor()const{return mlf;}
+  void  max_load_factor(float z){mlf=z;calculate_max_load();}
+
+  void rehash(size_type n)
+  {
+    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
+    if(size()<max_load&&n<=bucket_count())return;
+
+    size_type bc =(std::numeric_limits<size_type>::max)();
+    float     fbc=static_cast<float>(1+size()/mlf);
+    if(bc>fbc){
+      bc=static_cast<size_type>(fbc);
+      if(bc<n)bc=n;
+    }
+    unchecked_rehash(bc);
+  }
+
+BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
+  hashed_index(const ctor_args_list& args_list,const allocator_type& al):
+    super(args_list.get_tail(),al),
+    key(tuples::get<1>(args_list.get_head())),
+    hash(tuples::get<2>(args_list.get_head())),
+    eq(tuples::get<3>(args_list.get_head())),
+    buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
+    mlf(1.0),
+    first_bucket(buckets.size())
+  {
+    calculate_max_load();
+  }
+
+  hashed_index(
+    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
+    super(x),
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super(),
+#endif
+
+    key(x.key),
+    hash(x.hash),
+    eq(x.eq),
+    buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
+    mlf(x.mlf),
+    max_load(x.max_load),
+    first_bucket(x.first_bucket)
+  {
+    /* Copy ctor just takes the internal configuration objects from x. The rest
+     * is done in subsequent call to copy_().
+     */
+  }
+
+  ~hashed_index()
+  {
+    /* the container is guaranteed to be empty by now */
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  iterator make_iterator(node_type* node)
+  {
+    return iterator(node,&buckets,this);
+  }
+
+  const_iterator make_iterator(node_type* node)const
+  {
+    return const_iterator(
+      node,
+      &const_cast<bucket_array_type&>(buckets),
+      const_cast<hashed_index*>(this));
+  }
+#else
+  iterator make_iterator(node_type* node)
+  {
+    return iterator(node,&buckets);
+  }
+
+  const_iterator make_iterator(node_type* node)const
+  {
+    return const_iterator(node,&const_cast<bucket_array_type&>(buckets));
+  }
+#endif
+
+  void copy_(
+    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
+    const copy_map_type& map)
+  {
+    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){
+
+      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*>(
+            map.find(
+              static_cast<final_node_type*>(
+                node_type::from_impl(next_org))))->impl();
+        next_org=next_org->next();
+        cpy=cpy->next();
+      }
+      cpy->next()=begin_cpy;
+    }
+
+    super::copy_(x,map);
+  }
+
+  node_type* insert_(value_param_type v,node_type* x)
+  {
+    reserve(size()+1);
+
+    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));
+    if(res==x){
+      link(x,pos);
+      if(first_bucket>buc)first_bucket=buc;
+    }
+    return res;
+  }
+
+  node_type* insert_(value_param_type v,node_type* position,node_type* x)
+  {
+    reserve(size()+1);
+
+    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));
+    if(res==x){
+      link(x,pos);
+      if(first_bucket>buc)first_bucket=buc;
+    }
+    return res;
+  }
+
+  void erase_(node_type* x)
+  {
+    unlink(x);
+    first_bucket=buckets.first_nonempty(first_bucket);
+    super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    detach_iterators(x);
+#endif
+  }
+
+  void delete_all_nodes_()
+  {
+    for(node_impl_pointer x=buckets.begin(),x_end=buckets.end();
+        x!=x_end;++x){
+      node_impl_pointer y=x->next();
+      while(y!=x){
+        node_impl_pointer z=y->next();
+        this->final_delete_node_(
+          static_cast<final_node_type*>(node_type::from_impl(y)));
+        y=z;
+      }
+    }
+  }
+
+  void clear_()
+  {
+    super::clear_();
+    buckets.clear();
+    first_bucket=buckets.size();
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::detach_dereferenceable_iterators();
+#endif
+  }
+
+  void swap_(
+    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
+  {
+    std::swap(key,x.key);
+    std::swap(hash,x.hash);
+    std::swap(eq,x.eq);
+    buckets.swap(x.buckets);
+    std::swap(mlf,x.mlf);
+    std::swap(max_load,x.max_load);
+    std::swap(first_bucket,x.first_bucket);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::swap(x);
+#endif
+
+    super::swap_(x);
+  }
+
+  bool replace_(value_param_type v,node_type* x)
+  {
+    if(eq(key(v),key(x->value()))){
+      return super::replace_(v,x);
+    }
+
+    node_impl_pointer y=prev(x);
+    unlink_next(y);
+
+    BOOST_TRY{
+      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){
+          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
+  }
+
+  bool modify_(node_type* x)
+  {
+    unlink(x);
+
+    std::size_t       buc;
+    node_impl_pointer pos;
+    BOOST_TRY
+    {
+      buc=find_bucket(x->value());
+      pos=buckets.at(buc);
+      if(!link_point(x->value(),pos,Category())){
+        first_bucket=buckets.first_nonempty(first_bucket);
+        super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+        detach_iterators(x);
+#endif
+        return false;
+      }
+
+    }
+    BOOST_CATCH(...){
+      first_bucket=buckets.first_nonempty(first_bucket);
+      super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+      detach_iterators(x);
+#endif
+
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+
+    BOOST_TRY{
+      if(super::modify_(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;
+      }
+
+      first_bucket=buckets.first_nonempty(first_bucket);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+      detach_iterators(x);
+#endif
+      return false;
+    }
+    BOOST_CATCH(...){
+      first_bucket=buckets.first_nonempty(first_bucket);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+      detach_iterators(x);
+#endif
+
+      BOOST_RETHROW;
+    }
+    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 */
+
+  template<typename Archive>
+  void save_(
+    Archive& ar,const unsigned int version,const index_saver_type& sm)const
+  {
+    ar<<serialization::make_nvp("position",buckets);
+    super::save_(ar,version,sm);
+  }
+
+  template<typename Archive>
+  void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
+  {
+    ar>>serialization::make_nvp("position",buckets);
+    super::load_(ar,version,lm);
+  }
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+  /* invariant stuff */
+
+  bool invariant_()const
+  {
+    if(size()==0||begin()==end()){
+      if(size()!=0||begin()!=end())return false;
+    }
+    else{
+      size_type s0=0;
+      for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s0){}
+      if(s0!=size())return false;
+
+      size_type s1=0;
+      for(size_type buc=0;buc<bucket_count();++buc){
+        size_type ss1=0;
+        for(const_local_iterator it=begin(buc),it_end=end(buc);
+            it!=it_end;++it,++ss1){
+          if(find_bucket(*it)!=buc)return false;
+        }
+        if(ss1!=bucket_size(buc))return false;
+        s1+=ss1;
+      }
+      if(s1!=size())return false;
+    }
+
+    if(first_bucket!=buckets.first_nonempty(0))return false;
+
+    return super::invariant_();
+  }
+
+  /* This forwarding function eases things for the boost::mem_fn construct
+   * in BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT. Actually,
+   * final_check_invariant is already an inherited member function of index.
+   */
+  void check_invariant_()const{this->final_check_invariant_();}
+#endif
+
+private:
+  node_type* header()const{return this->final_header();}
+
+  std::size_t find_bucket(value_param_type v)const
+  {
+    return bucket(key(v));
+  }
+
+  bool link_point(
+    value_param_type v,node_impl_pointer& pos,hashed_unique_tag)
+  {
+    node_impl_pointer x=pos->next();
+    while(x!=pos){
+      if(eq(key(v),key(node_type::from_impl(x)->value()))){
+        pos=x;
+        return false;
+      }
+      x=x->next();
+    }
+    return true;
+  }
+
+  bool link_point(
+    value_param_type v,node_impl_pointer& pos,hashed_non_unique_tag)
+  {
+    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;
+        return true;
+      }
+      prev=x;
+      x=x->next();
+    }
+    return true;
+  }
+  
+  void link(node_type* x,node_impl_pointer pos)
+  {
+    node_impl_type::link(x->impl(),pos);
+  };
+
+  void link(node_impl_pointer x,node_impl_pointer pos)
+  {
+    node_impl_type::link(x,pos);
+  };
+
+  void unlink(node_type* x)
+  {
+    node_impl_type::unlink(x->impl());
+  };
+
+  static node_impl_pointer prev(node_type* x)
+  {
+    return node_impl_type::prev(x->impl());
+  }
+
+  static void unlink_next(node_impl_pointer x)
+  {
+    node_impl_type::unlink_next(x);
+  }
+
+  void calculate_max_load()
+  {
+    float fml=static_cast<float>(mlf*bucket_count());
+    max_load=(std::numeric_limits<size_type>::max)();
+    if(max_load>fml)max_load=static_cast<size_type>(fml);
+  }
+
+  void reserve(size_type n)
+  {
+    if(n>max_load){
+      size_type bc =(std::numeric_limits<size_type>::max)();
+      float     fbc=static_cast<float>(1+n/mlf);
+      if(bc>fbc)bc =static_cast<size_type>(fbc);
+      unchecked_rehash(bc);
+    }
+  }
+
+  void unchecked_rehash(size_type n)
+  {
+    bucket_array_type buckets1(get_allocator(),header()->impl(),n);
+    auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
+
+    std::size_t i=0;
+    node_impl_pointer x=buckets.begin();
+    node_impl_pointer x_end=buckets.end();
+    for(;x!=x_end;++x){
+      node_impl_pointer y=x->next();
+      while(y!=x){
+        hashes.data()[i++]=hash(key(node_type::from_impl(y)->value()));
+        y=y->next();
+      }
+    }
+
+    i=0;
+    x=buckets.begin();
+    for(;x!=x_end;++x){
+      node_impl_pointer y=x->next();
+      while(y!=x){
+        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;
+      }
+    }
+
+    buckets.swap(buckets1);
+    calculate_max_load();
+    first_bucket=buckets.first_nonempty(0);
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  void detach_iterators(node_type* x)
+  {
+    iterator it=make_iterator(x);
+    safe_mode::detach_equivalent_iterators(it);
+  }
+#endif
+
+  key_from_value               key;
+  hasher                       hash;
+  key_equal                    eq;
+  bucket_array_type            buckets;
+  float                        mlf;
+  size_type                    max_load;
+  std::size_t                  first_bucket;
+      
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+#pragma parse_mfunc_templ reset
+#endif
+};
+
+/*  specialized algorithms */
+
+template<
+  typename KeyFromValue,typename Hash,typename Pred,
+  typename SuperMeta,typename TagList,typename Category
+>
+void swap(
+  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
+  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
+{
+  x.swap(y);
+}
+
+} /* namespace multi_index::detail */
+
+/* hashed index specifiers */
+
+template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
+struct hashed_unique
+{
+  typedef typename detail::hashed_index_args<
+    Arg1,Arg2,Arg3,Arg4>                           index_args;
+  typedef typename index_args::tag_list_type::type tag_list_type;
+  typedef typename index_args::key_from_value_type key_from_value_type;
+  typedef typename index_args::hash_type           hash_type;
+  typedef typename index_args::pred_type           pred_type;
+
+  template<typename Super>
+  struct node_class
+  {
+    typedef detail::hashed_index_node<Super> type;
+  };
+
+  template<typename SuperMeta>
+  struct index_class
+  {
+    typedef detail::hashed_index<
+      key_from_value_type,hash_type,pred_type,
+      SuperMeta,tag_list_type,detail::hashed_unique_tag> type;
+  };
+};
+
+template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
+struct hashed_non_unique
+{
+  typedef typename detail::hashed_index_args<
+    Arg1,Arg2,Arg3,Arg4>                           index_args;
+  typedef typename index_args::tag_list_type::type tag_list_type;
+  typedef typename index_args::key_from_value_type key_from_value_type;
+  typedef typename index_args::hash_type           hash_type;
+  typedef typename index_args::pred_type           pred_type;
+
+  template<typename Super>
+  struct node_class
+  {
+    typedef detail::hashed_index_node<Super> type;
+  };
+
+  template<typename SuperMeta>
+  struct index_class
+  {
+    typedef detail::hashed_index<
+      key_from_value_type,hash_type,pred_type,
+      SuperMeta,tag_list_type,detail::hashed_non_unique_tag> type;
+  };
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
+
+#endif
diff --git a/boost/multi_index/hashed_index_fwd.hpp b/boost/multi_index/hashed_index_fwd.hpp
new file mode 100644 (file)
index 0000000..f436f68
--- /dev/null
@@ -0,0 +1,58 @@
+/* Copyright 2003-2005 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_HASHED_INDEX_FWD_HPP
+#define BOOST_MULTI_INDEX_HASHED_INDEX_FWD_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/multi_index/detail/hash_index_args.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<
+  typename KeyFromValue,typename Hash,typename Pred,
+  typename SuperMeta,typename TagList,typename Category
+>
+class hashed_index;
+
+template<
+  typename KeyFromValue,typename Hash,typename Pred,
+  typename SuperMeta,typename TagList,typename Category
+>
+void swap(
+  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
+  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y);
+
+} /* namespace multi_index::detail */
+
+/* hashed_index specifiers */
+
+template<
+  typename Arg1,typename Arg2=mpl::na,
+  typename Arg3=mpl::na,typename Arg4=mpl::na
+>
+struct hashed_unique;
+
+template<
+  typename Arg1,typename Arg2=mpl::na,
+  typename Arg3=mpl::na,typename Arg4=mpl::na
+>
+struct hashed_non_unique;
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/identity.hpp b/boost/multi_index/identity.hpp
new file mode 100644 (file)
index 0000000..b3c9568
--- /dev/null
@@ -0,0 +1,147 @@
+/* Copyright 2003-2006 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_IDENTITY_HPP
+#define BOOST_MULTI_INDEX_IDENTITY_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/multi_index/identity_fwd.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#if !defined(BOOST_NO_SFINAE)
+#include <boost/type_traits/is_convertible.hpp>
+#endif
+
+namespace boost{
+
+template<class Type> class reference_wrapper; /* fwd decl. */
+
+namespace multi_index{
+
+namespace detail{
+
+/* identity is a do-nothing key extractor that returns the [const] Type&
+ * object passed.
+ * Additionally, identity is overloaded to support referece_wrappers
+ * of Type and "chained pointers" to Type's. By chained pointer to Type we
+ * mean a  type  P such that, given a p of type P
+ *   *...n...*x is convertible to Type&, for some n>=1.
+ * Examples of chained pointers are raw and smart pointers, iterators and
+ * arbitrary combinations of these (vg. Type** or auto_ptr<Type*>.)
+ */
+
+/* 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<typename Type>
+struct const_identity_base
+{
+  typedef Type result_type;
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<is_convertible<const ChainedPtr&,Type&>,Type&>::type
+#else
+  Type&
+#endif 
+  
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  Type& operator()(Type& x)const
+  {
+    return x;
+  }
+
+  Type& operator()(const reference_wrapper<Type>& x)const
+  { 
+    return x.get();
+  }
+
+  Type& operator()(
+    const reference_wrapper<typename remove_const<Type>::type>& x,int=0)const
+  { 
+    return x.get();
+  }
+};
+
+template<typename Type>
+struct non_const_identity_base
+{
+  typedef Type result_type;
+
+  /* templatized for pointer-like types */
+  
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<const ChainedPtr&,const Type&>,Type&>::type
+#else
+  Type&
+#endif 
+    
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  const Type& operator()(const Type& x,int=0)const
+  {
+    return x;
+  }
+
+  Type& operator()(Type& x)const
+  {
+    return x;
+  }
+
+  const Type& operator()(const reference_wrapper<const Type>& x,int=0)const
+  { 
+    return x.get();
+  }
+
+  Type& operator()(const reference_wrapper<Type>& x)const
+  { 
+    return x.get();
+  }
+};
+
+} /* namespace multi_index::detail */
+
+template<class Type>
+struct identity:
+  mpl::if_c<
+    is_const<Type>::value,
+    detail::const_identity_base<Type>,detail::non_const_identity_base<Type>
+  >::type
+{
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/identity_fwd.hpp b/boost/multi_index/identity_fwd.hpp
new file mode 100644 (file)
index 0000000..91ba276
--- /dev/null
@@ -0,0 +1,26 @@
+/* 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_IDENTITY_FWD_HPP
+#define BOOST_MULTI_INDEX_IDENTITY_FWD_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+template<class Type> struct identity;
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/indexed_by.hpp b/boost/multi_index/indexed_by.hpp
new file mode 100644 (file)
index 0000000..acac93a
--- /dev/null
@@ -0,0 +1,72 @@
+/* Copyright 2003-2005 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_INDEXED_BY_HPP
+#define BOOST_MULTI_INDEX_INDEXED_BY_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/vector.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp> 
+
+/* An alias to mpl::vector used to hide MPL from the user.
+ * indexed_by contains the index specifiers for instantiation
+ * of a multi_index_container.
+ */
+
+/* This user_definable macro limits the number of elements of an index list;
+ * useful for shortening resulting symbol names (MSVC++ 6.0, for instance,
+ * has problems coping with very long symbol names.)
+ */
+
+#if !defined(BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE)
+#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
+#define BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE 5
+#else
+#define BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
+#endif
+#endif
+
+#if BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE<BOOST_MPL_LIMIT_VECTOR_SIZE
+#define BOOST_MULTI_INDEX_INDEXED_BY_SIZE \
+  BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE
+#else
+#define BOOST_MULTI_INDEX_INDEXED_BY_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
+#endif
+
+#define BOOST_MULTI_INDEX_INDEXED_BY_TEMPLATE_PARM(z,n,var) \
+  typename BOOST_PP_CAT(var,n) BOOST_PP_EXPR_IF(n,=mpl::na)
+
+namespace boost{
+
+namespace multi_index{
+
+template<
+  BOOST_PP_ENUM(
+    BOOST_MULTI_INDEX_INDEXED_BY_SIZE,
+    BOOST_MULTI_INDEX_INDEXED_BY_TEMPLATE_PARM,T)
+>
+struct indexed_by:
+  mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_INDEXED_BY_SIZE,T)>
+{
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#undef BOOST_MULTI_INDEX_INDEXED_BY_TEMPLATE_PARM
+#undef BOOST_MULTI_INDEX_INDEXED_BY_SIZE
+
+#endif
diff --git a/boost/multi_index/key_extractors.hpp b/boost/multi_index/key_extractors.hpp
new file mode 100644 (file)
index 0000000..0acb1aa
--- /dev/null
@@ -0,0 +1,22 @@
+/* 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_KEY_EXTRACTORS_HPP
+#define BOOST_MULTI_INDEX_KEY_EXTRACTORS_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#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>
+
+#endif
diff --git a/boost/multi_index/mem_fun.hpp b/boost/multi_index/mem_fun.hpp
new file mode 100644 (file)
index 0000000..f9257ec
--- /dev/null
@@ -0,0 +1,212 @@
+/* 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_MEM_FUN_HPP
+#define BOOST_MULTI_INDEX_MEM_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/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{
+
+/* mem_fun implements a read-only key extractor based on a given non-const
+ * member function of a class.
+ * const_mem_fun does the same for const member functions.
+ * Additionally, mem_fun  and const_mem_fun are overloaded to support
+ * referece_wrappers of T and "chained pointers" to T'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*>.)
+ */
+
+template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const>
+struct const_mem_fun
+{
+  typedef typename remove_reference<Type>::type result_type;
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<const ChainedPtr&,const Class&>,Type>::type
+#else
+  Type
+#endif
+
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  Type operator()(const Class& x)const
+  {
+    return (x.*PtrToMemberFunction)();
+  }
+
+  Type operator()(const reference_wrapper<const Class>& x)const
+  { 
+    return operator()(x.get());
+  }
+
+  Type operator()(const reference_wrapper<Class>& x)const
+  { 
+    return operator()(x.get());
+  }
+};
+
+template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()>
+struct mem_fun
+{
+  typedef typename remove_reference<Type>::type result_type;
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<ChainedPtr&,Class&>,Type>::type
+#else
+  Type
+#endif
+
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  Type operator()(Class& x)const
+  {
+    return (x.*PtrToMemberFunction)();
+  }
+
+  Type operator()(const reference_wrapper<Class>& x)const
+  { 
+    return operator()(x.get());
+  }
+};
+
+/* MSVC++ 6.0 has problems with const member functions as non-type template
+ * 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?
+ *     hl=en&lr=&ie=UTF-8&selm=ukwvg3O0BHA.1512%40tkmsftngp05
+ */
+
+template<
+  class Class,typename Type,
+  typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
+struct const_mem_fun_explicit
+{
+  typedef typename remove_reference<Type>::type result_type;
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<const ChainedPtr&,const Class&>,Type>::type
+#else
+  Type
+#endif
+
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  Type operator()(const Class& x)const
+  {
+    return (x.*PtrToMemberFunction)();
+  }
+
+  Type operator()(const reference_wrapper<const Class>& x)const
+  { 
+    return operator()(x.get());
+  }
+
+  Type operator()(const reference_wrapper<Class>& x)const
+  { 
+    return operator()(x.get());
+  }
+};
+
+template<
+  class Class,typename Type,
+  typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
+struct mem_fun_explicit
+{
+  typedef typename remove_reference<Type>::type result_type;
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<ChainedPtr&,Class&>,Type>::type
+#else
+  Type
+#endif
+
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  Type operator()(Class& x)const
+  {
+    return (x.*PtrToMemberFunction)();
+  }
+
+  Type operator()(const reference_wrapper<Class>& x)const
+  { 
+    return operator()(x.get());
+  }
+};
+
+/* BOOST_MULTI_INDEX_CONST_MEM_FUN and BOOST_MULTI_INDEX_MEM_FUN resolve to
+ * [const_]mem_fun_explicit for MSVC++ 6.0 and to [const_]mem_fun otherwise.
+ */
+
+#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
+
+#define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \
+::boost::multi_index::const_mem_fun_explicit<\
+  Class,Type,Type (Class::*)()const,&Class::MemberFunName >
+#define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \
+::boost::multi_index::mem_fun_explicit<\
+  Class,Type,Type (Class::*)(),&Class::MemberFunName >
+
+#else
+
+#define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \
+::boost::multi_index::const_mem_fun< Class,Type,&Class::MemberFunName >
+#define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \
+::boost::multi_index::mem_fun< Class,Type,&Class::MemberFunName >
+
+#endif
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/member.hpp b/boost/multi_index/member.hpp
new file mode 100644 (file)
index 0000000..0aff2dc
--- /dev/null
@@ -0,0 +1,269 @@
+/* Copyright 2003-2006 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_MEMBER_HPP
+#define BOOST_MULTI_INDEX_MEMBER_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/utility/enable_if.hpp>
+#include <cstddef>
+
+#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{
+
+/* member is a read/write key extractor for accessing a given
+ * member of a class.
+ * Additionally, member is overloaded to support referece_wrappers
+ * of T and "chained pointers" to T'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 Class,typename Type,Type Class::*PtrToMember>
+struct const_member_base
+{
+  typedef Type result_type;
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<const ChainedPtr&,const Class&>,Type&>::type
+#else
+  Type&
+#endif
+  
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  Type& operator()(const Class& x)const
+  {
+    return x.*PtrToMember;
+  }
+
+  Type& operator()(const reference_wrapper<const Class>& x)const
+  {
+    return operator()(x.get());
+  }
+
+  Type& operator()(const reference_wrapper<Class>& x,int=0)const
+  { 
+    return operator()(x.get());
+  }
+};
+
+template<class Class,typename Type,Type Class::*PtrToMember>
+struct non_const_member_base
+{
+  typedef Type result_type;
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<const ChainedPtr&,const Class&>,Type&>::type
+#else
+  Type&
+#endif
+
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  const Type& operator()(const Class& x,int=0)const
+  {
+    return x.*PtrToMember;
+  }
+
+  Type& operator()(Class& x)const
+  { 
+    return x.*PtrToMember;
+  }
+
+  const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
+  {
+    return operator()(x.get());
+  }
+
+  Type& operator()(const reference_wrapper<Class>& x)const
+  { 
+    return operator()(x.get());
+  }
+};
+
+} /* namespace multi_index::detail */
+
+template<class Class,typename Type,Type Class::*PtrToMember>
+struct member:
+  mpl::if_c<
+    is_const<Type>::value,
+    detail::const_member_base<Class,Type,PtrToMember>,
+    detail::non_const_member_base<Class,Type,PtrToMember>
+  >::type
+{
+};
+
+namespace detail{
+
+/* MSVC++ 6.0 does not support properly pointers to members as
+ * non-type template arguments, as reported in
+ *   http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
+ * A similar problem (though not identical) is shown by MSVC++ 7.0.
+ * We provide an alternative to member<> accepting offsets instead
+ * of pointers to members. This happens to work even for non-POD
+ * types (although the standard forbids use of offsetof on these),
+ * so it serves as a workaround in this compiler for all practical
+ * purposes.
+ * Surprisingly enough, other compilers, like Intel C++ 7.0/7.1 and
+ * Visual Age 6.0, have similar bugs. This replacement of member<>
+ * can be used for them too.
+ */
+
+template<class Class,typename Type,std::size_t OffsetOfMember>
+struct const_member_offset_base
+{
+  typedef Type result_type;
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<const ChainedPtr&,const Class&>,Type&>::type
+#else
+  Type&
+#endif 
+    
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  Type& operator()(const Class& x)const
+  {
+    return *static_cast<const Type*>(
+      static_cast<const void*>(
+        static_cast<const char*>(
+          static_cast<const void *>(&x))+OffsetOfMember));
+  }
+
+  Type& operator()(const reference_wrapper<const Class>& x)const
+  {
+    return operator()(x.get());
+  }
+
+  Type& operator()(const reference_wrapper<Class>& x,int=0)const
+  {
+    return operator()(x.get());
+  }
+};
+
+template<class Class,typename Type,std::size_t OffsetOfMember>
+struct non_const_member_offset_base
+{
+  typedef Type result_type;
+
+  template<typename ChainedPtr>
+
+#if !defined(BOOST_NO_SFINAE)
+  typename disable_if<
+    is_convertible<const ChainedPtr&,const Class&>,Type&>::type
+#else
+  Type&
+#endif 
+  
+  operator()(const ChainedPtr& x)const
+  {
+    return operator()(*x);
+  }
+
+  const Type& operator()(const Class& x,int=0)const
+  {
+    return *static_cast<const Type*>(
+      static_cast<const void*>(
+        static_cast<const char*>(
+          static_cast<const void *>(&x))+OffsetOfMember));
+  }
+
+  Type& operator()(Class& x)const
+  { 
+    return *static_cast<Type*>(
+      static_cast<void*>(
+        static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
+  }
+
+  const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
+  {
+    return operator()(x.get());
+  }
+
+  Type& operator()(const reference_wrapper<Class>& x)const
+  {
+    return operator()(x.get());
+  }
+};
+
+} /* namespace multi_index::detail */
+
+template<class Class,typename Type,std::size_t OffsetOfMember>
+struct member_offset:
+  mpl::if_c<
+    is_const<Type>::value,
+    detail::const_member_offset_base<Class,Type,OffsetOfMember>,
+    detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
+  >::type
+{
+};
+
+/* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
+ * and to member_offset as a workaround in those defective compilers for
+ * which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
+ */
+
+#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)
+#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
+::boost::multi_index::member_offset< Class,Type,offsetof(Class,MemberName) >
+#else
+#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
+::boost::multi_index::member< Class,Type,&Class::MemberName >
+#endif
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/ordered_index.hpp b/boost/multi_index/ordered_index.hpp
new file mode 100644 (file)
index 0000000..7f2538c
--- /dev/null
@@ -0,0 +1,1390 @@
+/* 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.
+ *
+ * The internal implementation of red-black trees is based on that of SGI STL
+ * stl_tree.h file: 
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef BOOST_MULTI_INDEX_ORDERED_INDEX_HPP
+#define BOOST_MULTI_INDEX_ORDERED_INDEX_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 <algorithm>
+#include <boost/call_traits.hpp>
+#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>
+#include <boost/multi_index/detail/index_node_base.hpp>
+#include <boost/multi_index/detail/modify_key_adaptor.hpp>
+#include <boost/multi_index/detail/ord_index_node.hpp>
+#include <boost/multi_index/detail/ord_index_ops.hpp>
+#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
+#include <boost/multi_index/detail/safe_mode.hpp>
+#include <boost/multi_index/detail/scope_guard.hpp>
+#include <boost/multi_index/detail/unbounded.hpp>
+#include <boost/multi_index/detail/value_compare.hpp>
+#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)
+#include <boost/archive/archive_exception.hpp>
+#include <boost/bind.hpp>
+#include <boost/multi_index/detail/duplicates_iterator.hpp>
+#include <boost/throw_exception.hpp> 
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT                          \
+  detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
+    detail::make_obj_guard(*this,&ordered_index::check_invariant_);          \
+  BOOST_JOIN(check_invariant_,__LINE__).touch();
+#else
+#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* ordered_index adds a layer of ordered indexing to a given Super */
+
+/* Most of the implementation of unique and non-unique indices is
+ * shared. We tell from one another on instantiation time by using
+ * these tags.
+ */
+
+struct ordered_unique_tag{};
+struct ordered_non_unique_tag{};
+
+template<
+  typename KeyFromValue,typename Compare,
+  typename SuperMeta,typename TagList,typename Category
+>
+class ordered_index:
+  BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  ,public safe_ctr_proxy_impl<
+    bidir_node_iterator<
+      ordered_index_node<typename SuperMeta::type::node_type> >,
+    ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category> >
+#else
+  ,public safe_mode::safe_container<
+    ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category> >
+#endif
+#endif
+
+{ 
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
+ * lifetime of const references bound to temporaries --precisely what
+ * scopeguards are.
+ */
+
+#pragma parse_mfunc_templ off
+#endif
+
+  typedef typename SuperMeta::type                   super;
+
+protected:
+  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 */
+
+  typedef typename KeyFromValue::result_type         key_type;
+  typedef typename node_type::value_type             value_type;
+  typedef KeyFromValue                               key_from_value;
+  typedef Compare                                    key_compare;
+  typedef value_comparison<
+    value_type,KeyFromValue,Compare>                 value_compare;
+  typedef tuple<key_from_value,key_compare>          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;
+#else
+  typedef safe_mode::safe_iterator<
+    bidir_node_iterator<node_type>,
+    ordered_index>                                   iterator;
+#endif
+#else
+  typedef bidir_node_iterator<node_type>             iterator;
+#endif
+
+  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 typename
+    boost::reverse_iterator<iterator>                reverse_iterator;
+  typedef typename
+    boost::reverse_iterator<const_iterator>          const_reverse_iterator;
+  typedef TagList                                    tag_list;
+
+protected:
+  typedef typename super::final_node_type            final_node_type;
+  typedef tuples::cons<
+    ctor_args, 
+    typename super::ctor_args_list>                  ctor_args_list;
+  typedef typename mpl::push_front<
+    typename super::index_type_list,
+    ordered_index>::type                             index_type_list;
+  typedef typename mpl::push_front<
+    typename super::iterator_type_list,
+    iterator>::type    iterator_type_list;
+  typedef typename mpl::push_front<
+    typename super::const_iterator_type_list,
+    const_iterator>::type                            const_iterator_type_list;
+  typedef typename super::copy_map_type              copy_map_type;
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  typedef typename super::index_saver_type           index_saver_type;
+  typedef typename super::index_loader_type          index_loader_type;
+#endif
+
+private:
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  typedef safe_ctr_proxy_impl<
+    bidir_node_iterator<node_type>,
+    ordered_index>                                   safe_super;
+#else
+  typedef safe_mode::safe_container<ordered_index>   safe_super;
+#endif
+#endif
+
+  typedef typename call_traits<
+    value_type>::param_type                          value_param_type;
+  typedef typename call_traits<
+    key_type>::param_type                            key_param_type;
+
+public:
+
+  /* construct/copy/destroy
+   * Default and copy ctors are in the protected section as indices are
+   * not supposed to be created on their own. No range ctor either.
+   */
+
+  ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& operator=(
+    const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
+  {
+    this->final()=x.final();
+    return *this;
+  }
+
+  allocator_type get_allocator()const
+  {
+    return this->final().get_allocator();
+  }
+
+  /* iterators */
+
+  iterator               begin(){return make_iterator(leftmost());}
+  const_iterator         begin()const{return make_iterator(leftmost());}
+  iterator               end(){return make_iterator(header());}
+  const_iterator         end()const{return make_iterator(header());}
+  reverse_iterator       rbegin(){return make_reverse_iterator(end());}
+  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_();}
+  size_type size()const{return this->final_size_();}
+  size_type max_size()const{return this->final_max_size_();}
+
+  /* modifiers */
+
+  std::pair<iterator,bool> insert(value_param_type x)
+  {
+    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+    std::pair<final_node_type*,bool> p=this->final_insert_(x);
+    return std::pair<iterator,bool>(make_iterator(p.first),p.second);
+  }
+
+  iterator insert(iterator position,value_param_type x)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+    std::pair<final_node_type*,bool> p=this->final_insert_(
+      x,static_cast<final_node_type*>(position.get_node()));
+    return make_iterator(p.first);
+  }
+    
+  template<typename InputIterator>
+  void insert(InputIterator first,InputIterator last)
+  {
+    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+    iterator hint=end();
+    for(;first!=last;++first)hint=insert(hint,*first);
+  }
+
+  iterator erase(iterator position)
+  {
+    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;
+    this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
+    return position;
+  }
+  
+  size_type erase(key_param_type x)
+  {
+    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+    std::pair<iterator,iterator> p=equal_range(x);
+    size_type s=0;
+    while(p.first!=p.second){
+      p.first=erase(p.first);
+      ++s;
+    }
+    return s;
+  }
+
+  iterator erase(iterator first,iterator last)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+    while(first!=last){
+      first=erase(first);
+    }
+    return first;
+  }
+
+  bool replace(iterator position,value_param_type x)
+  {
+    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 this->final_replace_(
+      x,static_cast<final_node_type*>(position.get_node()));
+  }
+
+  template<typename Modifier>
+  bool modify(iterator position,Modifier mod)
+  {
+    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,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)
+  {
+    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));
+  }
+
+  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;
+    this->final_swap_(x.final());
+  }
+
+  void clear()
+  {
+    BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+    this->final_clear_();
+  }
+
+  /* observers */
+
+  key_from_value key_extractor()const{return key;}
+  key_compare    key_comp()const{return comp;}
+  value_compare  value_comp()const{return value_compare(key,comp);}
+
+  /* set operations */
+
+  /* Internally, these ops rely on const_iterator being the same
+   * type as iterator.
+   */
+
+  template<typename CompatibleKey>
+  iterator find(const CompatibleKey& x)const
+  {
+    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(root(),header(),key,x,comp));
+  }
+
+  template<typename CompatibleKey>
+  size_type count(const CompatibleKey& x)const
+  {
+    return count(x,comp);
+  }
+
+  template<typename CompatibleKey,typename CompatibleCompare>
+  size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const
+  {
+    std::pair<iterator,iterator> p=equal_range(x,comp);
+    size_type n=std::distance(p.first,p.second);
+    return n;
+  }
+
+  template<typename CompatibleKey>
+  iterator lower_bound(const CompatibleKey& x)const
+  {
+    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(root(),header(),key,x,comp));
+  }
+
+  template<typename CompatibleKey>
+  iterator upper_bound(const CompatibleKey& x)const
+  {
+    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(root(),header(),key,x,comp));
+  }
+
+  template<typename CompatibleKey>
+  std::pair<iterator,iterator> equal_range(
+    const CompatibleKey& x)const
+  {
+    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>(
+      make_iterator(p.first),make_iterator(p.second));
+  }
+
+  /* range */
+
+  template<typename LowerBounder,typename UpperBounder>
+  std::pair<iterator,iterator>
+  range(LowerBounder lower,UpperBounder upper)const
+  {
+    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:
+  ordered_index(const ctor_args_list& args_list,const allocator_type& al):
+    super(args_list.get_tail(),al),
+    key(tuples::get<0>(args_list.get_head())),
+    comp(tuples::get<1>(args_list.get_head()))
+  {
+    empty_initialize();
+  }
+
+  ordered_index(
+    const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x):
+    super(x),
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super(),
+#endif
+
+    key(x.key),
+    comp(x.comp)
+  {
+    /* Copy ctor just takes the key and compare objects from x. The rest is
+     * done in subsequent call to copy_().
+     */
+  }
+
+  ~ordered_index()
+  {
+    /* the container is guaranteed to be empty by now */
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  iterator       make_iterator(node_type* node){return iterator(node,this);}
+  const_iterator make_iterator(node_type* node)const
+    {return const_iterator(node,const_cast<ordered_index*>(this));}
+#else
+  iterator       make_iterator(node_type* node){return iterator(node);}
+  const_iterator make_iterator(node_type* node)const
+                   {return const_iterator(node);}
+#endif
+
+  void copy_(
+    const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x,
+    const copy_map_type& map)
+  {
+    if(!x.root()){
+      empty_initialize();
+    }
+    else{
+      header()->color()=x.header()->color();
+
+      node_type* root_cpy=map.find(static_cast<final_node_type*>(x.root()));
+      header()->parent()=root_cpy->impl();
+
+      node_type* leftmost_cpy=map.find(
+        static_cast<final_node_type*>(x.leftmost()));
+      header()->left()=leftmost_cpy->impl();
+
+      node_type* rightmost_cpy=map.find(
+        static_cast<final_node_type*>(x.rightmost()));
+      header()->right()=rightmost_cpy->impl();
+
+      typedef typename copy_map_type::const_iterator copy_map_iterator;
+      for(copy_map_iterator it=map.begin(),it_end=map.end();it!=it_end;++it){
+        node_type* org=it->first;
+        node_type* cpy=it->second;
+
+        cpy->color()=org->color();
+
+        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)));
+          cpy->parent()=parent_cpy->impl();
+          if(parent_org->left()==org->impl()){
+            parent_cpy->left()=cpy->impl();
+          }
+          else if(parent_org->right()==org->impl()){
+            /* header() does not satisfy this nor the previous check */
+            parent_cpy->right()=cpy->impl();
+          }
+        }
+
+        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);
+      }
+    }
+    
+    super::copy_(x,map);
+  }
+
+  node_type* insert_(value_param_type v,node_type* x)
+  {
+    link_info inf;
+    if(!link_point(key(v),inf,Category())){
+      return node_type::from_impl(inf.pos);
+    }
+
+    node_type* res=static_cast<node_type*>(super::insert_(v,x));
+    if(res==x){
+      node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
+    }
+    return res;
+  }
+
+  node_type* insert_(value_param_type v,node_type* position,node_type* x)
+  {
+    link_info inf;
+    if(!hinted_link_point(key(v),position,inf,Category())){
+      return node_type::from_impl(inf.pos);
+    }
+
+    node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
+    if(res==x){
+      node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
+    }
+    return res;
+  }
+
+  void erase_(node_type* x)
+  {
+    node_impl_type::rebalance_for_erase(
+      x->impl(),header()->parent(),header()->left(),header()->right());
+    super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    detach_iterators(x);
+#endif
+  }
+
+  void delete_all_nodes_()
+  {
+    delete_all_nodes(root());
+  }
+
+  void clear_()
+  {
+    super::clear_();
+    empty_initialize();
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::detach_dereferenceable_iterators();
+#endif
+  }
+
+  void swap_(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
+  {
+    std::swap(key,x.key);
+    std::swap(comp,x.comp);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::swap(x);
+#endif
+
+    super::swap_(x);
+  }
+
+  bool replace_(value_param_type v,node_type* x)
+  {
+    if(in_place(v,x,Category())){
+      return super::replace_(v,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(v),inf,Category())&&super::replace_(v,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
+  }
+
+  bool modify_(node_type* x)
+  {
+    bool b;
+    BOOST_TRY{
+      b=in_place(x->value(),x,Category());
+    }
+    BOOST_CATCH(...){
+      erase_(x);
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+    if(!b){
+      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::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+          detach_iterators(x);
+#endif
+          return false;
+        }
+        node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
+      }
+      BOOST_CATCH(...){
+        super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+        detach_iterators(x);
+#endif
+
+        BOOST_RETHROW;
+      }
+      BOOST_CATCH_END
+    }
+
+    BOOST_TRY{
+      if(!super::modify_(x)){
+        node_impl_type::rebalance_for_erase(
+          x->impl(),header()->parent(),header()->left(),header()->right());
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+        detach_iterators(x);
+#endif
+
+        return false;
+      }
+      else return true;
+    }
+    BOOST_CATCH(...){
+      node_impl_type::rebalance_for_erase(
+        x->impl(),header()->parent(),header()->left(),header()->right());
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+      detach_iterators(x);
+#endif
+
+      BOOST_RETHROW;
+    }
+    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 */
+
+  template<typename Archive>
+  void save_(
+    Archive& ar,const unsigned int version,const index_saver_type& sm)const
+  {
+    save_(ar,version,sm,Category());
+  }
+
+  template<typename Archive>
+  void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
+  {
+    load_(ar,version,lm,Category());
+  }
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+  /* invariant stuff */
+
+  bool invariant_()const
+  {
+    if(size()==0||begin()==end()){
+      if(size()!=0||begin()!=end()||
+         header()->left()!=header()->impl()||
+         header()->right()!=header()->impl())return false;
+    }
+    else{
+      if((size_type)std::distance(begin(),end())!=size())return false;
+
+      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();
+        node_type* left_x=node_type::from_impl(x->left());
+        node_type* right_x=node_type::from_impl(x->right());
+
+        if(x->color()==red){
+          if((left_x&&left_x->color()==red)||
+             (right_x&&right_x->color()==red))return false;
+        }
+        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&&
+           node_impl_type::black_count(x->impl(),root()->impl())!=len)
+          return false;
+      }
+    
+      if(leftmost()->impl()!=node_impl_type::minimum(root()->impl()))
+        return false;
+      if(rightmost()->impl()!=node_impl_type::maximum(root()->impl()))
+        return false;
+    }
+
+    return super::invariant_();
+  }
+
+  
+  /* This forwarding function eases things for the boost::mem_fn construct
+   * in BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT. Actually,
+   * final_check_invariant is already an inherited member function of
+   * ordered_index.
+   */
+  void check_invariant_()const{this->final_check_invariant_();}
+#endif
+
+private:
+  node_type* header()const{return this->final_header();}
+  node_type* root()const{return node_type::from_impl(header()->parent());}
+  node_type* leftmost()const{return node_type::from_impl(header()->left());}
+  node_type* rightmost()const{return node_type::from_impl(header()->right());}
+
+  void empty_initialize()
+  {
+    header()->color()=red;
+    /* used to distinguish header() from root, in iterator.operator++ */
+    
+    header()->parent()=node_impl_pointer(0);
+    header()->left()=header()->impl();
+    header()->right()=header()->impl();
+  }
+
+  struct link_info
+  {
+    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)
+  {
+    node_type* y=header();
+    node_type* x=root();
+    bool c=true;
+    while(x){
+      y=x;
+      c=comp(k,key(x->value()));
+      x=node_type::from_impl(c?x->left():x->right());
+    }
+    node_type* yy=y;
+    if(c){
+      if(yy==leftmost()){
+        inf.side=to_left;
+        inf.pos=y->impl();
+        return true;
+      }
+      else node_type::decrement(yy);
+    }
+
+    if(comp(key(yy->value()),k)){
+      inf.side=c?to_left:to_right;
+      inf.pos=y->impl();
+      return true;
+    }
+    else{
+      inf.pos=yy->impl();
+      return false;
+    }
+  }
+
+  bool link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
+  {
+    node_type* y=header();
+    node_type* x=root();
+    bool c=true;
+    while (x){
+     y=x;
+     c=comp(k,key(x->value()));
+     x=node_type::from_impl(c?x->left():x->right());
+    }
+    inf.side=c?to_left:to_right;
+    inf.pos=y->impl();
+    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)
+  {
+    if(position->impl()==header()->left()){ 
+      if(size()>0&&comp(k,key(position->value()))){
+        inf.side=to_left;
+        inf.pos=position->impl();
+        return true;
+      }
+      else return link_point(k,inf,ordered_unique_tag());
+    } 
+    else if(position==header()){ 
+      if(comp(key(rightmost()->value()),k)){
+        inf.side=to_right;
+        inf.pos=rightmost()->impl();
+        return true;
+      }
+      else return link_point(k,inf,ordered_unique_tag());
+    } 
+    else{
+      node_type* before=position;
+      node_type::decrement(before);
+      if(comp(key(before->value()),k)&&comp(k,key(position->value()))){
+        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 link_point(k,inf,ordered_unique_tag());
+    }
+  }
+
+  bool hinted_link_point(
+    key_param_type k,node_type* position,link_info& inf,ordered_non_unique_tag)
+  {
+    if(position->impl()==header()->left()){ 
+      if(size()>0&&!comp(key(position->value()),k)){
+        inf.side=to_left;
+        inf.pos=position->impl();
+        return true;
+      }
+      else return lower_link_point(k,inf,ordered_non_unique_tag());
+    } 
+    else if(position==header()){
+      if(!comp(k,key(rightmost()->value()))){
+        inf.side=to_right;
+        inf.pos=rightmost()->impl();
+        return true;
+      }
+      else return link_point(k,inf,ordered_non_unique_tag());
+    } 
+    else{
+      node_type* before=position;
+      node_type::decrement(before);
+      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());
+    }
+  }
+
+  void delete_all_nodes(node_type* x)
+  {
+    if(!x)return;
+
+    delete_all_nodes(node_type::from_impl(x->left()));
+    delete_all_nodes(node_type::from_impl(x->right()));
+    this->final_delete_node_(static_cast<final_node_type*>(x));
+  }
+
+  bool in_place(value_param_type v,node_type* x,ordered_unique_tag)
+  {
+    node_type* y;
+    if(x!=leftmost()){
+      y=x;
+      node_type::decrement(y);
+      if(!comp(key(y->value()),key(v)))return false;
+    }
+
+    y=x;
+    node_type::increment(y);
+    return y==header()||comp(key(v),key(y->value()));
+  }
+
+  bool in_place(value_param_type v,node_type* x,ordered_non_unique_tag)
+  {
+    node_type* y;
+    if(x!=leftmost()){
+      y=x;
+      node_type::decrement(y);
+      if(comp(key(v),key(y->value())))return false;
+    }
+
+    y=x;
+    node_type::increment(y);
+    return y==header()||!comp(key(y->value()),key(v));
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  void detach_iterators(node_type* x)
+  {
+    iterator it=make_iterator(x);
+    safe_mode::detach_equivalent_iterators(it);
+  }
+#endif
+
+  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()))){
+        z=node_type::from_impl(z->right());
+      }
+      else if(!upper(key(z->value()))){
+        y=z;
+        z=node_type::from_impl(z->left());
+      }
+      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 std::pair<iterator,iterator>(make_iterator(y),make_iterator(y));
+  }
+
+  template<typename LowerBounder,typename UpperBounder>
+  std::pair<iterator,iterator>
+  range(LowerBounder,UpperBounder upper,lower_unbounded_tag)const
+  {
+    return std::pair<iterator,iterator>(
+      begin(),
+      make_iterator(upper_range(root(),header(),upper)));
+  }
+
+  template<typename LowerBounder,typename UpperBounder>
+  std::pair<iterator,iterator>
+  range(LowerBounder lower,UpperBounder,upper_unbounded_tag)const
+  {
+    return std::pair<iterator,iterator>(
+      make_iterator(lower_range(root(),header(),lower)),
+      end());
+  }
+
+  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 top=node_type::from_impl(top->right());
+    }
+
+    return y;
+  }
+
+  template<typename UpperBounder>
+  node_type * upper_range(node_type* top,node_type* y,UpperBounder upper)const
+  {
+    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)
+  template<typename Archive>
+  void save_(
+    Archive& ar,const unsigned int version,const index_saver_type& sm,
+    ordered_unique_tag)const
+  {
+    super::save_(ar,version,sm);
+  }
+
+  template<typename Archive>
+  void load_(
+    Archive& ar,const unsigned int version,const index_loader_type& lm,
+    ordered_unique_tag)
+  {
+    super::load_(ar,version,lm);
+  }
+
+  template<typename Archive>
+  void save_(
+    Archive& ar,const unsigned int version,const index_saver_type& sm,
+    ordered_non_unique_tag)const
+  {
+    typedef duplicates_iterator<node_type,value_compare> dup_iterator;
+
+    sm.save(
+      dup_iterator(begin().get_node(),end().get_node(),value_comp()),
+      dup_iterator(end().get_node(),value_comp()),
+      ar,version);
+    super::save_(ar,version,sm);
+  }
+
+  template<typename Archive>
+  void load_(
+    Archive& ar,const unsigned int version,const index_loader_type& lm,
+    ordered_non_unique_tag)
+  {
+    lm.load(
+      ::boost::bind(&ordered_index::rearranger,this,_1,_2),
+      ar,version);
+    super::load_(ar,version,lm);
+  }
+
+  void rearranger(node_type* position,node_type *x)
+  {
+    if(!position||comp(key(position->value()),key(x->value()))){
+      position=lower_bound(key(x->value())).get_node();
+    }
+    else if(comp(key(x->value()),key(position->value()))){
+      /* inconsistent rearrangement */
+      throw_exception(
+        archive::archive_exception(
+          archive::archive_exception::other_exception));
+    }
+    else node_type::increment(position);
+
+    if(position!=x){
+      node_impl_type::rebalance_for_erase(
+        x->impl(),header()->parent(),header()->left(),header()->right());
+      node_impl_type::restore(
+        x->impl(),position->impl(),header()->impl());
+    }
+  }
+#endif /* serialization */
+
+  key_from_value key;
+  key_compare    comp;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+#pragma parse_mfunc_templ reset
+#endif
+};
+
+/* comparison */
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator==(
+  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
+{
+  return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
+}
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator<(
+  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
+{
+  return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
+}
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator!=(
+  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
+{
+  return !(x==y);
+}
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator>(
+  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
+{
+  return y<x;
+}
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator>=(
+  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
+{
+  return !(x<y);
+}
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator<=(
+  const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
+{
+  return !(x>y);
+}
+
+/*  specialized algorithms */
+
+template<
+  typename KeyFromValue,typename Compare,
+  typename SuperMeta,typename TagList,typename Category
+>
+void swap(
+  ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x,
+  ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& y)
+{
+  x.swap(y);
+}
+
+} /* namespace multi_index::detail */
+
+/* ordered_index specifiers */
+
+template<typename Arg1,typename Arg2,typename Arg3>
+struct ordered_unique
+{
+  typedef typename detail::ordered_index_args<
+    Arg1,Arg2,Arg3>                                index_args;
+  typedef typename index_args::tag_list_type::type tag_list_type;
+  typedef typename index_args::key_from_value_type key_from_value_type;
+  typedef typename index_args::compare_type        compare_type;
+
+  template<typename Super>
+  struct node_class
+  {
+    typedef detail::ordered_index_node<Super> type;
+  };
+
+  template<typename SuperMeta>
+  struct index_class
+  {
+    typedef detail::ordered_index<
+      key_from_value_type,compare_type,
+      SuperMeta,tag_list_type,detail::ordered_unique_tag> type;
+  };
+};
+
+template<typename Arg1,typename Arg2,typename Arg3>
+struct ordered_non_unique
+{
+  typedef detail::ordered_index_args<
+    Arg1,Arg2,Arg3>                                index_args;
+  typedef typename index_args::tag_list_type::type tag_list_type;
+  typedef typename index_args::key_from_value_type key_from_value_type;
+  typedef typename index_args::compare_type        compare_type;
+
+  template<typename Super>
+  struct node_class
+  {
+    typedef detail::ordered_index_node<Super> type;
+  };
+
+  template<typename SuperMeta>
+  struct index_class
+  {
+    typedef detail::ordered_index<
+      key_from_value_type,compare_type,
+      SuperMeta,tag_list_type,detail::ordered_non_unique_tag> type;
+  };
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#undef BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
+
+#endif
diff --git a/boost/multi_index/ordered_index_fwd.hpp b/boost/multi_index/ordered_index_fwd.hpp
new file mode 100644 (file)
index 0000000..9ee6a0a
--- /dev/null
@@ -0,0 +1,124 @@
+/* Copyright 2003-2005 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_ORDERED_INDEX_FWD_HPP
+#define BOOST_MULTI_INDEX_ORDERED_INDEX_FWD_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/multi_index/detail/ord_index_args.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<
+  typename KeyFromValue,typename Compare,
+  typename SuperMeta,typename TagList,typename Category
+>
+class ordered_index;
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator==(
+  const ordered_index<
+    KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<
+    KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y);
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator<(
+  const ordered_index<
+    KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<
+    KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y);
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator!=(
+  const ordered_index<
+    KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<
+    KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y);
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator>(
+  const ordered_index<
+    KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<
+    KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y);
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator>=(
+  const ordered_index<
+    KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<
+    KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y);
+
+template<
+  typename KeyFromValue1,typename Compare1,
+  typename SuperMeta1,typename TagList1,typename Category1,
+  typename KeyFromValue2,typename Compare2,
+  typename SuperMeta2,typename TagList2,typename Category2
+>
+bool operator<=(
+  const ordered_index<
+    KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
+  const ordered_index<
+    KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y);
+
+template<
+  typename KeyFromValue,typename Compare,
+  typename SuperMeta,typename TagList,typename Category
+>
+void swap(
+  ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x,
+  ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& y);
+
+} /* namespace multi_index::detail */
+
+/* ordered_index specifiers */
+
+template<typename Arg1,typename Arg2=mpl::na,typename Arg3=mpl::na>
+struct ordered_unique;
+
+template<typename Arg1,typename Arg2=mpl::na,typename Arg3=mpl::na>
+struct ordered_non_unique;
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/random_access_index.hpp b/boost/multi_index/random_access_index.hpp
new file mode 100644 (file)
index 0000000..6f5a9ca
--- /dev/null
@@ -0,0 +1,1008 @@
+/* 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_RANDOM_ACCESS_INDEX_HPP
+#define BOOST_MULTI_INDEX_RANDOM_ACCESS_INDEX_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 <algorithm>
+#include <boost/call_traits.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/index_node_base.hpp>
+#include <boost/multi_index/detail/rnd_node_iterator.hpp>
+#include <boost/multi_index/detail/rnd_index_node.hpp>
+#include <boost/multi_index/detail/rnd_index_ops.hpp>
+#include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
+#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
+#include <boost/multi_index/detail/safe_mode.hpp>
+#include <boost/multi_index/detail/scope_guard.hpp>
+#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> 
+#include <utility>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/bind.hpp>
+#include <boost/multi_index/detail/rnd_index_loader.hpp>
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+#define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT                          \
+  detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
+    detail::make_obj_guard(*this,&random_access_index::check_invariant_);    \
+  BOOST_JOIN(check_invariant_,__LINE__).touch();
+#else
+#define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* random_access_index adds a layer of random access indexing
+ * to a given Super
+ */
+
+template<typename SuperMeta,typename TagList>
+class random_access_index:
+  BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  ,public safe_ctr_proxy_impl<
+    rnd_node_iterator<
+      random_access_index_node<typename SuperMeta::type::node_type> >,
+    random_access_index<SuperMeta,TagList> >
+#else
+  ,public safe_mode::safe_container<
+    random_access_index<SuperMeta,TagList> >
+#endif
+#endif
+
+{ 
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
+ * lifetime of const references bound to temporaries --precisely what
+ * scopeguards are.
+ */
+
+#pragma parse_mfunc_templ off
+#endif
+
+  typedef typename SuperMeta::type                 super;
+
+protected:
+  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 */
+
+  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<
+    rnd_node_iterator<node_type>,
+    safe_ctr_proxy<
+      rnd_node_iterator<node_type> > >             iterator;
+#else
+  typedef safe_mode::safe_iterator<
+    rnd_node_iterator<node_type>,
+    random_access_index>                           iterator;
+#endif
+#else
+  typedef rnd_node_iterator<node_type>             iterator;
+#endif
+
+  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 typename
+    boost::reverse_iterator<iterator>              reverse_iterator;
+  typedef typename
+    boost::reverse_iterator<const_iterator>        const_reverse_iterator;
+  typedef TagList                                  tag_list;
+
+protected:
+  typedef typename super::final_node_type     final_node_type;
+  typedef tuples::cons<
+    ctor_args, 
+    typename super::ctor_args_list>           ctor_args_list;
+  typedef typename mpl::push_front<
+    typename super::index_type_list,
+    random_access_index>::type                index_type_list;
+  typedef typename mpl::push_front<
+    typename super::iterator_type_list,
+    iterator>::type                           iterator_type_list;
+  typedef typename mpl::push_front<
+    typename super::const_iterator_type_list,
+    const_iterator>::type                     const_iterator_type_list;
+  typedef typename super::copy_map_type       copy_map_type;
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  typedef typename super::index_saver_type    index_saver_type;
+  typedef typename super::index_loader_type   index_loader_type;
+#endif
+
+private:
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  typedef safe_ctr_proxy_impl<
+    rnd_node_iterator<node_type>,
+    random_access_index>                      safe_super;
+#else
+  typedef safe_mode::safe_container<
+    random_access_index>                      safe_super;
+#endif
+#endif
+
+  typedef typename call_traits<
+    value_type>::param_type                   value_param_type;
+
+public:
+
+  /* construct/copy/destroy
+   * Default and copy ctors are in the protected section as indices are
+   * not supposed to be created on their own. No range ctor either.
+   */
+
+  random_access_index<SuperMeta,TagList>& operator=(
+    const random_access_index<SuperMeta,TagList>& x)
+  {
+    this->final()=x.final();
+    return *this;
+  }
+
+  template <class InputIterator>
+  void assign(InputIterator first,InputIterator last)
+  {
+    assign_iter(first,last,mpl::not_<is_integral<InputIterator> >());
+  }
+
+  void assign(size_type n,value_param_type value)
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    clear();
+    for(size_type i=0;i<n;++i)push_back(value);
+  }
+    
+  allocator_type get_allocator()const
+  {
+    return this->final().get_allocator();
+  }
+
+  /* iterators */
+
+  iterator               begin()
+    {return make_iterator(node_type::from_impl(*ptrs.begin()));}
+  const_iterator         begin()const
+    {return make_iterator(node_type::from_impl(*ptrs.begin()));}
+  iterator               end(){return make_iterator(header());}
+  const_iterator         end()const{return make_iterator(header());}
+  reverse_iterator       rbegin(){return make_reverse_iterator(end());}
+  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_();}
+  size_type size()const{return this->final_size_();}
+  size_type max_size()const{return this->final_max_size_();}
+  size_type capacity()const{return ptrs.capacity();}
+  void      reserve(size_type n){ptrs.reserve(n);}
+
+  void resize(size_type n,value_param_type x=value_type())
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    if(n>size())insert(end(),n-size(),x);
+    else if(n<size())erase(begin()+n,end());
+  }
+
+  /* access: no non-const versions provided as random_access_index
+   * handles const elements.
+   */
+
+  const_reference operator[](size_type n)const
+  {
+    BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(n<size(),safe_mode::out_of_bounds);
+    return node_type::from_impl(*ptrs.at(n))->value();
+  }
+
+  const_reference at(size_type n)const
+  {
+    if(n>=size())throw_exception(std::out_of_range("random access index"));
+    return node_type::from_impl(*ptrs.at(n))->value();
+  }
+
+  const_reference front()const{return operator[](0);}
+  const_reference back()const{return operator[](size()-1);}
+
+  /* modifiers */
+
+  std::pair<iterator,bool> push_front(value_param_type x)
+                             {return insert(begin(),x);}
+  void                     pop_front(){erase(begin());}
+  std::pair<iterator,bool> push_back(value_param_type x)
+                             {return insert(end(),x);}
+  void                     pop_back(){erase(--end());}
+
+  std::pair<iterator,bool> insert(iterator position,value_param_type x)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    std::pair<final_node_type*,bool> p=this->final_insert_(x);
+    if(p.second&&position.get_node()!=header()){
+      relocate(position.get_node(),p.first);
+    }
+    return std::pair<iterator,bool>(make_iterator(p.first),p.second);
+  }
+
+  void insert(iterator position,size_type n,value_param_type x)
+  {
+    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());
+  }
+  template<typename InputIterator>
+  void insert(iterator position,InputIterator first,InputIterator last)
+  {
+    insert_iter(position,first,last,mpl::not_<is_integral<InputIterator> >());
+  }
+
+  iterator erase(iterator position)
+  {
+    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;
+    this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
+    return position;
+  }
+  
+  iterator erase(iterator first,iterator last)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    difference_type n=last-first;
+    relocate(end(),first,last);
+    while(n--)pop_back();
+    return last;
+  }
+
+  bool replace(iterator position,value_param_type x)
+  {
+    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;
+    return this->final_replace_(
+      x,static_cast<final_node_type*>(position.get_node()));
+  }
+
+  template<typename Modifier>
+  bool modify(iterator position,Modifier mod)
+  {
+    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,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;
+    this->final_swap_(x.final());
+  }
+
+  void clear()
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    this->final_clear_();
+  }
+
+  /* list operations */
+
+  void splice(iterator position,random_access_index<SuperMeta,TagList>& x)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(*this,x);
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    iterator  first=x.begin(),last=x.end();
+    size_type n=0;
+    BOOST_TRY{
+      while(first!=last){
+        if(push_back(*first).second){
+          first=x.erase(first);
+          ++n;
+        }
+        else ++first;
+      }
+    }
+    BOOST_CATCH(...){
+      relocate(position,end()-n,end());
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+    relocate(position,end()-n,end());
+  }
+
+  void splice(
+    iterator position,random_access_index<SuperMeta,TagList>& x,iterator i)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x);
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    if(&x==this)relocate(position,i);
+    else{
+      if(insert(position,*i).second){
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    /* MSVC++ 6.0 optimizer has a hard time with safe mode, and the following
+     * workaround is needed. Left it for all compilers as it does no
+     * harm.
+     */
+        i.detach();
+        x.erase(x.make_iterator(i.get_node()));
+#else
+        x.erase(i);
+#endif
+
+      }
+    }
+  }
+
+  void splice(
+    iterator position,random_access_index<SuperMeta,TagList>& x,
+    iterator first,iterator last)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x);
+    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    if(&x==this)relocate(position,first,last);
+    else{
+      size_type n=0;
+      BOOST_TRY{
+        while(first!=last){
+          if(push_back(*first).second){
+            first=x.erase(first);
+            ++n;
+          }
+          else ++first;
+        }
+      }
+      BOOST_CATCH(...){
+        relocate(position,end()-n,end());
+        BOOST_RETHROW;
+      }
+      BOOST_CATCH_END
+      relocate(position,end()-n,end());
+    }
+  }
+
+  void remove(value_param_type value)
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    difference_type n=
+      end()-make_iterator(
+        random_access_index_remove<node_type>(
+          ptrs,std::bind2nd(std::equal_to<value_type>(),value)));
+    while(n--)pop_back();
+  }
+
+  template<typename Predicate>
+  void remove_if(Predicate pred)
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    difference_type n=
+      end()-make_iterator(random_access_index_remove<node_type>(ptrs,pred));
+    while(n--)pop_back();
+  }
+
+  void unique()
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    difference_type n=
+      end()-make_iterator(
+        random_access_index_unique<node_type>(
+          ptrs,std::equal_to<value_type>()));
+    while(n--)pop_back();
+  }
+
+  template <class BinaryPredicate>
+  void unique(BinaryPredicate binary_pred)
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    difference_type n=
+      end()-make_iterator(
+        random_access_index_unique<node_type>(ptrs,binary_pred));
+    while(n--)pop_back();
+  }
+
+  void merge(random_access_index<SuperMeta,TagList>& x)
+  {
+    if(this!=&x){
+      BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+      size_type s=size();
+      splice(end(),x);
+      random_access_index_inplace_merge<node_type>(
+        get_allocator(),ptrs,ptrs.at(s),std::less<value_type>());
+    }
+  }
+
+  template <typename Compare>
+  void merge(random_access_index<SuperMeta,TagList>& x,Compare comp)
+  {
+    if(this!=&x){
+      BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+      size_type s=size();
+      splice(end(),x);
+      random_access_index_inplace_merge<node_type>(
+        get_allocator(),ptrs,ptrs.at(s),comp);
+    }
+  }
+
+  void sort()
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    random_access_index_sort<node_type>(
+      get_allocator(),ptrs,std::less<value_type>());
+  }
+
+  template <typename Compare>
+  void sort(Compare comp)
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    random_access_index_sort<node_type>(
+      get_allocator(),ptrs,comp);
+  }
+
+  void reverse()
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    node_impl_type::reverse(ptrs.begin(),ptrs.end());
+  }
+
+  /* rearrange operations */
+
+  void relocate(iterator position,iterator i)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,*this);
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    if(position!=i)relocate(position.get_node(),i.get_node());
+  }
+
+  void relocate(iterator position,iterator first,iterator last)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+    BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last);
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    if(position!=last)relocate(
+      position.get_node(),first.get_node(),last.get_node());
+  }
+
+  template<typename InputIterator>
+  void rearrange(InputIterator first)
+  {
+    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
+    for(node_impl_ptr_pointer p0=ptrs.begin(),p0_end=ptrs.end();
+        p0!=p0_end;++first,++p0){
+      const value_type& v1=*first;
+      node_impl_ptr_pointer p1=node_from_value<node_type>(&v1)->up();
+
+      std::swap(*p0,*p1);
+      (*p0)->up()=p0;
+      (*p1)->up()=p1;
+    }
+  }
+    
+BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
+  random_access_index(
+    const ctor_args_list& args_list,const allocator_type& al):
+    super(args_list.get_tail(),al),
+    ptrs(al,header()->impl(),0)
+  {
+  }
+
+  random_access_index(const random_access_index<SuperMeta,TagList>& x):
+    super(x),
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super(),
+#endif
+
+    ptrs(x.get_allocator(),header()->impl(),x.size())
+  {
+    /* The actual copying takes place in subsequent call to copy_().
+     */
+  }
+
+  ~random_access_index()
+  {
+    /* the container is guaranteed to be empty by now */
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  iterator       make_iterator(node_type* node){return iterator(node,this);}
+  const_iterator make_iterator(node_type* node)const
+    {return const_iterator(node,const_cast<random_access_index*>(this));}
+#else
+  iterator       make_iterator(node_type* node){return iterator(node);}
+  const_iterator make_iterator(node_type* node)const
+                   {return const_iterator(node);}
+#endif
+
+  void copy_(
+    const random_access_index<SuperMeta,TagList>& x,const copy_map_type& map)
+  {
+    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*>(
+           map.find(
+             static_cast<final_node_type*>(
+               node_type::from_impl(*begin_org))))->impl();
+      (*begin_cpy)->up()=begin_cpy;
+    }
+
+    super::copy_(x,map);
+  }
+
+  node_type* insert_(value_param_type v,node_type* x)
+  {
+    ptrs.room_for_one();
+    node_type* res=static_cast<node_type*>(super::insert_(v,x));
+    if(res==x)ptrs.push_back(x->impl());
+    return res;
+  }
+
+  node_type* insert_(value_param_type v,node_type* position,node_type* x)
+  {
+    ptrs.room_for_one();
+    node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
+    if(res==x)ptrs.push_back(x->impl());
+    return res;
+  }
+
+  void erase_(node_type* x)
+  {
+    ptrs.erase(x->impl());
+    super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    detach_iterators(x);
+#endif
+  }
+
+  void delete_all_nodes_()
+  {
+    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)));
+    }
+  }
+
+  void clear_()
+  {
+    super::clear_();
+    ptrs.clear();
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::detach_dereferenceable_iterators();
+#endif
+  }
+
+  void swap_(random_access_index<SuperMeta,TagList>& x)
+  {
+    ptrs.swap(x.ptrs);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::swap(x);
+#endif
+
+    super::swap_(x);
+  }
+
+  bool replace_(value_param_type v,node_type* x)
+  {
+    return super::replace_(v,x);
+  }
+
+  bool modify_(node_type* x)
+  {
+    BOOST_TRY{
+      if(!super::modify_(x)){
+        ptrs.erase(x->impl());
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+        detach_iterators(x);
+#endif
+
+        return false;
+      }
+      else return true;
+    }
+    BOOST_CATCH(...){
+      ptrs.erase(x->impl());
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+      detach_iterators(x);
+#endif
+
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+  bool modify_rollback_(node_type* x)
+  {
+    return super::modify_rollback_(x);
+  }
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  /* serialization */
+
+  template<typename Archive>
+  void save_(
+    Archive& ar,const unsigned int version,const index_saver_type& sm)const
+  {
+    sm.save(begin(),end(),ar,version);
+    super::save_(ar,version,sm);
+  }
+
+  template<typename Archive>
+  void load_(
+    Archive& ar,const unsigned int version,const index_loader_type& lm)
+  {
+    {
+      typedef random_access_index_loader<node_type,allocator_type> loader;
+
+      loader ld(get_allocator(),ptrs);
+      lm.load(::boost::bind(&loader::rearrange,&ld,_1,_2),ar,version);
+    } /* exit scope so that ld frees its resources */
+    super::load_(ar,version,lm);
+  }
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+  /* invariant stuff */
+
+  bool invariant_()const
+  {
+    if(size()>capacity())return false;
+    if(size()==0||begin()==end()){
+      if(size()!=0||begin()!=end())return false;
+    }
+    else{
+      size_type s=0;
+      for(const_iterator it=begin(),it_end=end();;++it,++s){
+        if(*(it.get_node()->up())!=it.get_node()->impl())return false;
+        if(it==it_end)break;
+      }
+      if(s!=size())return false;
+    }
+
+    return super::invariant_();
+  }
+
+  /* This forwarding function eases things for the boost::mem_fn construct
+   * in BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT. Actually,
+   * final_check_invariant is already an inherited member function of index.
+   */
+  void check_invariant_()const{this->final_check_invariant_();}
+#endif
+
+private:
+  node_type* header()const{return this->final_header();}
+
+  static void relocate(node_type* position,node_type* x)
+  {
+    node_impl_type::relocate(position->up(),x->up());
+  }
+
+  static void relocate(node_type* position,node_type* first,node_type* last)
+  {
+    node_impl_type::relocate(
+      position->up(),first->up(),last->up());
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  void detach_iterators(node_type* x)
+  {
+    iterator it=make_iterator(x);
+    safe_mode::detach_equivalent_iterators(it);
+  }
+#endif
+
+  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)
+#pragma parse_mfunc_templ reset
+#endif
+};
+
+/* comparison */
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator==(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y)
+{
+  return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator<(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y)
+{
+  return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator!=(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y)
+{
+  return !(x==y);
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator>(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y)
+{
+  return y<x;
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator>=(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y)
+{
+  return !(x<y);
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator<=(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y)
+{
+  return !(x>y);
+}
+
+/*  specialized algorithms */
+
+template<typename SuperMeta,typename TagList>
+void swap(
+  random_access_index<SuperMeta,TagList>& x,
+  random_access_index<SuperMeta,TagList>& y)
+{
+  x.swap(y);
+}
+
+} /* namespace multi_index::detail */
+
+/* random access index specifier */
+
+template <typename TagList>
+struct random_access
+{
+  BOOST_STATIC_ASSERT(detail::is_tag<TagList>::value);
+
+  template<typename Super>
+  struct node_class
+  {
+    typedef detail::random_access_index_node<Super> type;
+  };
+
+  template<typename SuperMeta>
+  struct index_class
+  {
+    typedef detail::random_access_index<
+      SuperMeta,typename TagList::type>  type;
+  };
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#undef BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT
+
+#endif
diff --git a/boost/multi_index/random_access_index_fwd.hpp b/boost/multi_index/random_access_index_fwd.hpp
new file mode 100644 (file)
index 0000000..9e1be35
--- /dev/null
@@ -0,0 +1,91 @@
+/* Copyright 2003-2005 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_RANDOM_ACCESS_INDEX_FWD_HPP
+#define BOOST_MULTI_INDEX_RANDOM_ACCESS_INDEX_FWD_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/multi_index/tag.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<typename SuperMeta,typename TagList>
+class random_access_index;
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator==(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator<(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator!=(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator>(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator>=(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator<=(
+  const random_access_index<SuperMeta1,TagList1>& x,
+  const random_access_index<SuperMeta2,TagList2>& y);
+
+template<typename SuperMeta,typename TagList>
+void swap(
+  random_access_index<SuperMeta,TagList>& x,
+  random_access_index<SuperMeta,TagList>& y);
+
+} /* namespace multi_index::detail */
+
+/* index specifiers */
+
+template <typename TagList=tag<> >
+struct random_access;
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/safe_mode_errors.hpp b/boost/multi_index/safe_mode_errors.hpp
new file mode 100644 (file)
index 0000000..bfaf31b
--- /dev/null
@@ -0,0 +1,48 @@
+/* Copyright 2003-2006 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_SAFE_MODE_ERRORS_HPP
+#define BOOST_MULTI_INDEX_SAFE_MODE_ERRORS_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace safe_mode{
+
+/* Error codes for Boost.MultiIndex safe mode. These go in a separate
+ * header so that the user can include it when redefining
+ * BOOST_MULTI_INDEX_SAFE_MODE_ASSERT prior to the inclusion of
+ * any other header of Boost.MultiIndex.
+ */
+
+enum error_code
+{
+  invalid_iterator=0,
+  not_dereferenceable_iterator,
+  not_incrementable_iterator,
+  not_decrementable_iterator,
+  not_owner,
+  not_same_owner,
+  invalid_range,
+  inside_range,
+  out_of_bounds,
+  same_container
+};
+
+} /* namespace multi_index::safe_mode */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/sequenced_index.hpp b/boost/multi_index/sequenced_index.hpp
new file mode 100644 (file)
index 0000000..d0b4ec2
--- /dev/null
@@ -0,0 +1,922 @@
+/* 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_SEQUENCED_INDEX_HPP
+#define BOOST_MULTI_INDEX_SEQUENCED_INDEX_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/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>
+#include <boost/multi_index/detail/index_node_base.hpp>
+#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
+#include <boost/multi_index/detail/safe_mode.hpp>
+#include <boost/multi_index/detail/scope_guard.hpp>
+#include <boost/multi_index/detail/seq_index_node.hpp>
+#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>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/bind.hpp>
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+#define BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT                          \
+  detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
+    detail::make_obj_guard(*this,&sequenced_index::check_invariant_);        \
+  BOOST_JOIN(check_invariant_,__LINE__).touch();
+#else
+#define BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* sequenced_index adds a layer of sequenced indexing to a given Super */
+
+template<typename SuperMeta,typename TagList>
+class sequenced_index:
+  BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  ,public safe_ctr_proxy_impl<
+    bidir_node_iterator<
+      sequenced_index_node<typename SuperMeta::type::node_type> >,
+    sequenced_index<SuperMeta,TagList> >
+#else
+  ,public safe_mode::safe_container<
+    sequenced_index<SuperMeta,TagList> >
+#endif
+#endif
+
+{ 
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
+ * lifetime of const references bound to temporaries --precisely what
+ * scopeguards are.
+ */
+
+#pragma parse_mfunc_templ off
+#endif
+
+  typedef typename SuperMeta::type                    super;
+
+protected:
+  typedef sequenced_index_node<
+    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;
+
+#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;
+#else
+  typedef safe_mode::safe_iterator<
+    bidir_node_iterator<node_type>,
+    sequenced_index>                                  iterator;
+#endif
+#else
+  typedef bidir_node_iterator<node_type>              iterator;
+#endif
+
+  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 typename
+    boost::reverse_iterator<iterator>                 reverse_iterator;
+  typedef typename
+    boost::reverse_iterator<const_iterator>           const_reverse_iterator;
+  typedef TagList                                     tag_list;
+
+protected:
+  typedef typename super::final_node_type     final_node_type;
+  typedef tuples::cons<
+    ctor_args, 
+    typename super::ctor_args_list>           ctor_args_list;
+  typedef typename mpl::push_front<
+    typename super::index_type_list,
+    sequenced_index>::type                    index_type_list;
+  typedef typename mpl::push_front<
+    typename super::iterator_type_list,
+    iterator>::type                           iterator_type_list;
+  typedef typename mpl::push_front<
+    typename super::const_iterator_type_list,
+    const_iterator>::type                     const_iterator_type_list;
+  typedef typename super::copy_map_type       copy_map_type;
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  typedef typename super::index_saver_type    index_saver_type;
+  typedef typename super::index_loader_type   index_loader_type;
+#endif
+
+private:
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  typedef safe_ctr_proxy_impl<
+    bidir_node_iterator<node_type>,
+    sequenced_index>                          safe_super;
+#else
+  typedef safe_mode::safe_container<
+    sequenced_index>                          safe_super;
+#endif
+#endif
+
+  typedef typename call_traits<value_type>::param_type value_param_type;
+
+public:
+
+  /* construct/copy/destroy
+   * Default and copy ctors are in the protected section as indices are
+   * not supposed to be created on their own. No range ctor either.
+   */
+
+  sequenced_index<SuperMeta,TagList>& operator=(
+    const sequenced_index<SuperMeta,TagList>& x)
+  {
+    this->final()=x.final();
+    return *this;
+  }
+
+  template <class InputIterator>
+  void assign(InputIterator first,InputIterator last)
+  {
+    assign_iter(first,last,mpl::not_<is_integral<InputIterator> >());
+  }
+
+  void assign(size_type n,value_param_type value)
+  {
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    clear();
+    for(size_type i=0;i<n;++i)push_back(value);
+  }
+    
+  allocator_type get_allocator()const
+  {
+    return this->final().get_allocator();
+  }
+
+  /* iterators */
+
+  iterator               begin()
+    {return make_iterator(node_type::from_impl(header()->next()));}
+  const_iterator         begin()const
+    {return make_iterator(node_type::from_impl(header()->next()));}
+  iterator               end(){return make_iterator(header());}
+  const_iterator         end()const{return make_iterator(header());}
+  reverse_iterator       rbegin(){return make_reverse_iterator(end());}
+  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_();}
+  size_type size()const{return this->final_size_();}
+  size_type max_size()const{return this->final_max_size_();}
+
+  void resize(size_type n,value_param_type x=value_type())
+  {
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    if(n>size())insert(end(),n-size(),x);
+    else if(n<size()){
+      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());
+    }   
+  }
+
+  /* access: no non-const versions provided as sequenced_index
+   * handles const elements.
+   */
+
+  const_reference front()const{return *begin();}
+  const_reference back()const{return *--end();}
+
+  /* modifiers */
+
+  std::pair<iterator,bool> push_front(value_param_type x)
+                             {return insert(begin(),x);}
+  void                     pop_front(){erase(begin());}
+  std::pair<iterator,bool> push_back(value_param_type x)
+                             {return insert(end(),x);}
+  void                     pop_back(){erase(--end());}
+
+  std::pair<iterator,bool> insert(iterator position,value_param_type x)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    std::pair<final_node_type*,bool> p=this->final_insert_(x);
+    if(p.second&&position.get_node()!=header()){
+      relink(position.get_node(),p.first);
+    }
+    return std::pair<iterator,bool>(make_iterator(p.first),p.second);
+  }
+
+  void insert(iterator position,size_type n,value_param_type x)
+  {
+    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);
+  }
+  template<typename InputIterator>
+  void insert(iterator position,InputIterator first,InputIterator last)
+  {
+    insert_iter(position,first,last,mpl::not_<is_integral<InputIterator> >());
+  }
+
+  iterator erase(iterator position)
+  {
+    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;
+    this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
+    return position;
+  }
+  
+  iterator erase(iterator first,iterator last)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    while(first!=last){
+      first=erase(first);
+    }
+    return first;
+  }
+
+  bool replace(iterator position,value_param_type x)
+  {
+    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;
+    return this->final_replace_(
+      x,static_cast<final_node_type*>(position.get_node()));
+  }
+
+  template<typename Modifier>
+  bool modify(iterator position,Modifier mod)
+  {
+    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,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;
+    this->final_swap_(x.final());
+  }
+
+  void clear()
+  {
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    this->final_clear_();
+  }
+
+  /* list operations */
+
+  void splice(iterator position,sequenced_index<SuperMeta,TagList>& x)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(*this,x);
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    iterator first=x.begin(),last=x.end();
+    while(first!=last){
+      if(insert(position,*first).second)first=x.erase(first);
+      else ++first;
+    }
+  }
+
+  void splice(iterator position,sequenced_index<SuperMeta,TagList>& x,iterator i)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x);
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    if(&x==this){
+      if(position!=i)relink(position.get_node(),i.get_node());
+    }
+    else{
+      if(insert(position,*i).second){
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    /* MSVC++ 6.0 optimizer has a hard time with safe mode, and the following
+     * workaround is needed. Left it for all compilers as it does no
+     * harm.
+     */
+        i.detach();
+        x.erase(x.make_iterator(i.get_node()));
+#else
+        x.erase(i);
+#endif
+
+      }
+    }
+  }
+
+  void splice(
+    iterator position,sequenced_index<SuperMeta,TagList>& x,
+    iterator first,iterator last)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x);
+    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    if(&x==this){
+      BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last);
+      if(position!=last)relink(
+        position.get_node(),first.get_node(),last.get_node());
+    }
+    else{
+      while(first!=last){
+        if(insert(position,*first).second)first=x.erase(first);
+        else ++first;
+      }
+    }
+  }
+
+  void remove(value_param_type value)
+  {
+    sequenced_index_remove(
+      *this,std::bind2nd(std::equal_to<value_type>(),value));
+  }
+
+  template<typename Predicate>
+  void remove_if(Predicate pred)
+  {
+    sequenced_index_remove(*this,pred);
+  }
+
+  void unique()
+  {
+    sequenced_index_unique(*this,std::equal_to<value_type>());
+  }
+
+  template <class BinaryPredicate>
+  void unique(BinaryPredicate binary_pred)
+  {
+    sequenced_index_unique(*this,binary_pred);
+  }
+
+  void merge(sequenced_index<SuperMeta,TagList>& x)
+  {
+    sequenced_index_merge(*this,x,std::less<value_type>());
+  }
+
+  template <typename Compare>
+  void merge(sequenced_index<SuperMeta,TagList>& x,Compare comp)
+  {
+    sequenced_index_merge(*this,x,comp);
+  }
+
+  void sort()
+  {
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    sequenced_index_sort(header(),std::less<value_type>());
+  }
+
+  template <typename Compare>
+  void sort(Compare comp)
+  {
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    sequenced_index_sort(header(),comp);
+  }
+
+  void reverse()
+  {
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    node_impl_type::reverse(header()->impl());
+  }
+
+  /* rearrange operations */
+
+  void relocate(iterator position,iterator i)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
+    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,*this);
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    if(position!=i)relink(position.get_node(),i.get_node());
+  }
+
+  void relocate(iterator position,iterator first,iterator last)
+  {
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
+    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+    BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last);
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    if(position!=last)relink(
+      position.get_node(),first.get_node(),last.get_node());
+  }
+    
+  template<typename InputIterator>
+  void rearrange(InputIterator first)
+  {
+    BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
+    node_type* pos=header();
+    for(size_type s=size();s--;){
+      const value_type& v=*first++;
+      relink(pos,node_from_value<node_type>(&v));
+    }
+  }
+
+BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
+  sequenced_index(const ctor_args_list& args_list,const allocator_type& al):
+    super(args_list.get_tail(),al)
+  {
+    empty_initialize();
+  }
+
+  sequenced_index(const sequenced_index<SuperMeta,TagList>& x):
+    super(x)
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    ,safe_super()
+#endif
+
+  {
+    /* The actual copying takes place in subsequent call to copy_().
+     */
+  }
+
+  ~sequenced_index()
+  {
+    /* the container is guaranteed to be empty by now */
+  }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  iterator       make_iterator(node_type* node){return iterator(node,this);}
+  const_iterator make_iterator(node_type* node)const
+    {return const_iterator(node,const_cast<sequenced_index*>(this));}
+#else
+  iterator       make_iterator(node_type* node){return iterator(node);}
+  const_iterator make_iterator(node_type* node)const
+                   {return const_iterator(node);}
+#endif
+
+  void copy_(
+    const sequenced_index<SuperMeta,TagList>& x,const copy_map_type& map)
+  {
+    node_type* org=x.header();
+    node_type* cpy=header();
+    do{
+      node_type* next_org=node_type::from_impl(org->next());
+      node_type* next_cpy=map.find(static_cast<final_node_type*>(next_org));
+      cpy->next()=next_cpy->impl();
+      next_cpy->prior()=cpy->impl();
+      org=next_org;
+      cpy=next_cpy;
+    }while(org!=x.header());
+
+    super::copy_(x,map);
+  }
+
+  node_type* insert_(value_param_type v,node_type* x)
+  {
+    node_type* res=static_cast<node_type*>(super::insert_(v,x));
+    if(res==x)link(x);
+    return res;
+  }
+
+  node_type* insert_(value_param_type v,node_type* position,node_type* x)
+  {
+    node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
+    if(res==x)link(x);
+    return res;
+  }
+
+  void erase_(node_type* x)
+  {
+    unlink(x);
+    super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    detach_iterators(x);
+#endif
+  }
+
+  void delete_all_nodes_()
+  {
+    for(node_type* x=node_type::from_impl(header()->next());x!=header();){
+      node_type* y=node_type::from_impl(x->next());
+      this->final_delete_node_(static_cast<final_node_type*>(x));
+      x=y;
+    }
+  }
+
+  void clear_()
+  {
+    super::clear_();
+    empty_initialize();
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::detach_dereferenceable_iterators();
+#endif
+  }
+
+  void swap_(sequenced_index<SuperMeta,TagList>& x)
+  {
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+    safe_super::swap(x);
+#endif
+
+    super::swap_(x);
+  }
+
+  bool replace_(value_param_type v,node_type* x)
+  {
+    return super::replace_(v,x);
+  }
+
+  bool modify_(node_type* x)
+  {
+    BOOST_TRY{
+      if(!super::modify_(x)){
+        unlink(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+        detach_iterators(x);
+#endif
+
+        return false;
+      }
+      else return true;
+    }
+    BOOST_CATCH(...){
+      unlink(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+      detach_iterators(x);
+#endif
+
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+  bool modify_rollback_(node_type* x)
+  {
+    return super::modify_rollback_(x);
+  }
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  /* serialization */
+
+  template<typename Archive>
+  void save_(
+    Archive& ar,const unsigned int version,const index_saver_type& sm)const
+  {
+    sm.save(begin(),end(),ar,version);
+    super::save_(ar,version,sm);
+  }
+
+  template<typename Archive>
+  void load_(
+    Archive& ar,const unsigned int version,const index_loader_type& lm)
+  {
+    lm.load(
+      ::boost::bind(&sequenced_index::rearranger,this,_1,_2),
+      ar,version);
+    super::load_(ar,version,lm);
+  }
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+  /* invariant stuff */
+
+  bool invariant_()const
+  {
+    if(size()==0||begin()==end()){
+      if(size()!=0||begin()!=end()||
+         header()->next()!=header()->impl()||
+         header()->prior()!=header()->impl())return false;
+    }
+    else{
+      size_type s=0;
+      for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s){
+        if(it.get_node()->next()->prior()!=it.get_node()->impl())return false;
+        if(it.get_node()->prior()->next()!=it.get_node()->impl())return false;
+      }
+      if(s!=size())return false;
+    }
+
+    return super::invariant_();
+  }
+
+  /* This forwarding function eases things for the boost::mem_fn construct
+   * in BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT. Actually,
+   * final_check_invariant is already an inherited member function of index.
+   */
+  void check_invariant_()const{this->final_check_invariant_();}
+#endif
+
+private:
+  node_type* header()const{return this->final_header();}
+
+  void empty_initialize()
+  {
+    header()->prior()=header()->next()=header()->impl();
+  }
+
+  void link(node_type* x)
+  {
+    node_impl_type::link(x->impl(),header()->impl());
+  };
+
+  static void unlink(node_type* x)
+  {
+    node_impl_type::unlink(x->impl());
+  }
+
+  static void relink(node_type* position,node_type* x)
+  {
+    node_impl_type::relink(position->impl(),x->impl());
+  }
+
+  static void relink(node_type* position,node_type* first,node_type* last)
+  {
+    node_impl_type::relink(
+      position->impl(),first->impl(),last->impl());
+  }
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+  void rearranger(node_type* position,node_type *x)
+  {
+    if(!position)position=header();
+    node_type::increment(position);
+    if(position!=x)relink(position,x);
+  }
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  void detach_iterators(node_type* x)
+  {
+    iterator it=make_iterator(x);
+    safe_mode::detach_equivalent_iterators(it);
+  }
+#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
+#endif
+};
+
+/* comparison */
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator==(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y)
+{
+  return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator<(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y)
+{
+  return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator!=(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y)
+{
+  return !(x==y);
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator>(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y)
+{
+  return y<x;
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator>=(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y)
+{
+  return !(x<y);
+}
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator<=(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y)
+{
+  return !(x>y);
+}
+
+/*  specialized algorithms */
+
+template<typename SuperMeta,typename TagList>
+void swap(
+  sequenced_index<SuperMeta,TagList>& x,
+  sequenced_index<SuperMeta,TagList>& y)
+{
+  x.swap(y);
+}
+
+} /* namespace multi_index::detail */
+
+/* sequenced index specifier */
+
+template <typename TagList>
+struct sequenced
+{
+  BOOST_STATIC_ASSERT(detail::is_tag<TagList>::value);
+
+  template<typename Super>
+  struct node_class
+  {
+    typedef detail::sequenced_index_node<Super> type;
+  };
+
+  template<typename SuperMeta>
+  struct index_class
+  {
+    typedef detail::sequenced_index<SuperMeta,typename TagList::type> type;
+  };
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#undef BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT
+
+#endif
diff --git a/boost/multi_index/sequenced_index_fwd.hpp b/boost/multi_index/sequenced_index_fwd.hpp
new file mode 100644 (file)
index 0000000..221a149
--- /dev/null
@@ -0,0 +1,91 @@
+/* Copyright 2003-2005 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_SEQUENCED_INDEX_FWD_HPP
+#define BOOST_MULTI_INDEX_SEQUENCED_INDEX_FWD_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/multi_index/tag.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<typename SuperMeta,typename TagList>
+class sequenced_index;
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator==(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator<(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator!=(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator>(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator>=(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y);
+
+template<
+  typename SuperMeta1,typename TagList1,
+  typename SuperMeta2,typename TagList2
+>
+bool operator<=(
+  const sequenced_index<SuperMeta1,TagList1>& x,
+  const sequenced_index<SuperMeta2,TagList2>& y);
+
+template<typename SuperMeta,typename TagList>
+void swap(
+  sequenced_index<SuperMeta,TagList>& x,
+  sequenced_index<SuperMeta,TagList>& y);
+
+} /* namespace multi_index::detail */
+
+/* index specifiers */
+
+template <typename TagList=tag<> >
+struct sequenced;
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/multi_index/tag.hpp b/boost/multi_index/tag.hpp
new file mode 100644 (file)
index 0000000..57fb987
--- /dev/null
@@ -0,0 +1,92 @@
+/* Copyright 2003-2005 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_TAG_HPP
+#define BOOST_MULTI_INDEX_TAG_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/multi_index/detail/no_duplicate_tags.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/transform.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp> 
+#include <boost/preprocessor/repetition/enum_binary_params.hpp> 
+#include <boost/preprocessor/repetition/enum_params.hpp> 
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+
+/* A wrapper of mpl::vector used to hide MPL from the user.
+ * tag contains types used as tag names for indices in get() functions.
+ */
+
+/* This user_definable macro limits the number of elements of a tag;
+ * useful for shortening resulting symbol names (MSVC++ 6.0, for instance,
+ * has problems coping with very long symbol names.)
+ */
+
+#if !defined(BOOST_MULTI_INDEX_LIMIT_TAG_SIZE)
+#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
+#define BOOST_MULTI_INDEX_LIMIT_TAG_SIZE 3
+#else
+#define BOOST_MULTI_INDEX_LIMIT_TAG_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
+#endif
+#endif
+
+#if BOOST_MULTI_INDEX_LIMIT_TAG_SIZE<BOOST_MPL_LIMIT_VECTOR_SIZE
+#define BOOST_MULTI_INDEX_TAG_SIZE BOOST_MULTI_INDEX_LIMIT_TAG_SIZE
+#else
+#define BOOST_MULTI_INDEX_TAG_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+struct tag_marker{};
+
+template<typename T>
+struct is_tag
+{
+  BOOST_STATIC_CONSTANT(bool,value=(is_base_and_derived<tag_marker,T>::value));
+};
+
+} /* namespace multi_index::detail */
+
+template<
+  BOOST_PP_ENUM_BINARY_PARAMS(
+    BOOST_MULTI_INDEX_TAG_SIZE,
+    typename T,
+    =mpl::na BOOST_PP_INTERCEPT) 
+>
+struct tag:private detail::tag_marker
+{
+  /* The mpl::transform pass produces shorter symbols (without
+   * trailing mpl::na's.)
+   */
+
+  typedef typename mpl::transform<
+    mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_TAG_SIZE,T)>,
+    mpl::identity<mpl::_1>
+  >::type type;
+
+  BOOST_STATIC_ASSERT(detail::no_duplicate_tags<type>::value);
+};
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#undef BOOST_MULTI_INDEX_TAG_SIZE
+
+#endif
diff --git a/boost/multi_index_container.hpp b/boost/multi_index_container.hpp
new file mode 100644 (file)
index 0000000..11a6597
--- /dev/null
@@ -0,0 +1,1083 @@
+/* Multiply indexed container.
+ *
+ * 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_HPP
+#define BOOST_MULTI_INDEX_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 <algorithm>
+#include <boost/detail/allocator_utilities.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/mpl/find_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/multi_index_container_fwd.hpp>
+#include <boost/multi_index/detail/access_specifier.hpp>
+#include <boost/multi_index/detail/adl_swap.hpp>
+#include <boost/multi_index/detail/base_type.hpp>
+#include <boost/multi_index/detail/converter.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>
+#include <boost/multi_index/detail/prevent_eti.hpp>
+#include <boost/multi_index/detail/safe_mode.hpp>
+#include <boost/multi_index/detail/scope_guard.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/base_from_member.hpp>
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include <boost/multi_index/detail/archive_constructed.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/split_member.hpp>
+#include <boost/throw_exception.hpp> 
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+#include <boost/multi_index/detail/invariant_assert.hpp>
+#define BOOST_MULTI_INDEX_CHECK_INVARIANT                                    \
+  detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
+    detail::make_obj_guard(*this,&multi_index_container::check_invariant_);  \
+  BOOST_JOIN(check_invariant_,__LINE__).touch();
+#else
+#define BOOST_MULTI_INDEX_CHECK_INVARIANT
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+template<typename Value,typename IndexSpecifierList,typename Allocator>
+class multi_index_container:
+  private ::boost::base_from_member<
+    typename boost::detail::allocator::rebind_to<
+      Allocator,
+      typename detail::multi_index_node_type<
+        Value,IndexSpecifierList,Allocator>::type
+    >::type>,
+  BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
+    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
+{
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
+ * lifetime of const references bound to temporaries --precisely what
+ * scopeguards are.
+ */
+
+#pragma parse_mfunc_templ off
+#endif
+
+private:
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+  template <typename,typename,typename> friend class  detail::index_base;
+  template <typename,typename>          friend struct detail::header_holder;
+  template <typename,typename>          friend struct detail::converter;
+#endif
+
+  typedef typename detail::multi_index_base_type<
+      Value,IndexSpecifierList,Allocator>::type   super;
+  typedef typename
+  boost::detail::allocator::rebind_to<
+      Allocator,
+      typename super::node_type
+  >::type                                         node_allocator;
+  typedef ::boost::base_from_member<
+    node_allocator>                               bfm_allocator;
+  typedef detail::header_holder<
+    typename detail::prevent_eti<
+      Allocator,
+      node_allocator
+    >::type::pointer,
+    multi_index_container>                        bfm_header;
+
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+  /* see definition of index_type_list below */
+  typedef typename super::index_type_list         super_index_type_list;
+#endif
+
+public:
+  /* All types are inherited from super, a few are explicitly
+   * brought forward here to save us some typename's.
+   */
+
+  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
+   * or more), with errors ranging from corrupt exes to duplicate
+   * comdats. The following type hiding hack alleviates this condition;
+   * best results combined with type hiding of the indexed_by construct
+   * itself, as explained in the "Compiler specifics" section of
+   * the documentation.
+   */
+
+  struct index_type_list:super_index_type_list
+  {
+    typedef index_type_list                      type;
+    typedef typename super_index_type_list::back back;
+    typedef mpl::v_iter<type,0>                  begin;
+    typedef mpl::v_iter<
+      type,
+      mpl::size<super_index_type_list>::value>   end;
+  };
+#else
+  typedef typename super::index_type_list          index_type_list;
+#endif
+
+  typedef typename super::iterator_type_list       iterator_type_list;
+  typedef typename super::const_iterator_type_list const_iterator_type_list;
+  typedef typename super::value_type               value_type;
+  typedef typename super::final_allocator_type     allocator_type;
+  typedef typename super::iterator                 iterator;
+  typedef typename super::const_iterator           const_iterator;
+
+  BOOST_STATIC_ASSERT(
+    detail::no_duplicate_tags_in_index_list<index_type_list>::value);
+
+  /* global project() needs to see this publicly */
+
+  typedef typename super::node_type node_type;
+
+  /* construct/copy/destroy */
+
+  explicit multi_index_container(
+
+#if BOOST_WORKAROUND(__IBMCPP__,<=600)
+    /* VisualAge seems to have an ETI issue with the default values
+     * for arguments args_list and al.
+     */
+
+    const ctor_args_list& args_list=
+      typename mpl::identity<multi_index_container>::type::
+        ctor_args_list(),
+    const allocator_type& al=
+      typename mpl::identity<multi_index_container>::type::
+        allocator_type()):
+#else
+    const ctor_args_list& args_list=ctor_args_list(),
+    const allocator_type& al=allocator_type()):
+#endif
+
+    bfm_allocator(al),
+    super(args_list,bfm_allocator::member),
+    node_count(0)
+  {
+    BOOST_MULTI_INDEX_CHECK_INVARIANT;
+  }    
+
+  template<typename InputIterator>
+  multi_index_container(
+    InputIterator first,InputIterator last,
+
+#if BOOST_WORKAROUND(__IBMCPP__,<=600)
+    /* VisualAge seems to have an ETI issue with the default values
+     * for arguments args_list and al.
+     */
+
+    const ctor_args_list& args_list=
+      typename mpl::identity<multi_index_container>::type::
+        ctor_args_list(),
+    const allocator_type& al=
+      typename mpl::identity<multi_index_container>::type::
+        allocator_type()):
+#else
+    const ctor_args_list& args_list=ctor_args_list(),
+    const allocator_type& al=allocator_type()):
+#endif
+
+    bfm_allocator(al),
+    super(args_list,bfm_allocator::member),
+    node_count(0)
+  {
+    BOOST_MULTI_INDEX_CHECK_INVARIANT;
+    BOOST_TRY{
+      iterator hint=super::end();
+      for(;first!=last;++first){
+        hint=super::make_iterator(insert_(*first,hint.get_node()).first);
+      }
+    }
+    BOOST_CATCH(...){
+      clear_();
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+  multi_index_container(
+    const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
+    bfm_allocator(x.bfm_allocator::member),
+    bfm_header(),
+    super(x),
+    node_count(0)
+  {
+    copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
+    for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
+      map.clone(it.get_node());
+    }
+    super::copy_(x,map);
+    map.release();
+    node_count=x.size();
+
+    /* Not until this point are the indices required to be consistent,
+     * hence the position of the invariant checker.
+     */
+
+    BOOST_MULTI_INDEX_CHECK_INVARIANT;
+  }
+
+  ~multi_index_container()
+  {
+    delete_all_nodes_();
+  }
+
+  multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
+    const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
+  {
+    BOOST_MULTI_INDEX_CHECK_INVARIANT;
+    multi_index_container<Value,IndexSpecifierList,Allocator> tmp(x);
+    this->swap(tmp);
+    return *this;
+  }
+
+  allocator_type get_allocator()const
+  {
+    return allocator_type(bfm_allocator::member);
+  }
+
+  /* retrieval of indices by number */
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATES)
+  template<int N>
+  struct nth_index
+  {
+    BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
+    typedef typename mpl::at_c<index_type_list,N>::type type;
+  };
+
+  template<int N>
+  typename nth_index<N>::type& get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
+  {
+    BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
+    return *this;
+  }
+
+  template<int N>
+  const typename nth_index<N>::type& get(
+    BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
+  {
+    BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
+    return *this;
+  }
+#endif
+
+  /* retrieval of indices by tag */
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATES)
+  template<typename Tag>
+  struct index
+  {
+    typedef typename mpl::find_if<
+      index_type_list,
+      detail::has_tag<Tag>
+    >::type                                    iter;
+
+    BOOST_STATIC_CONSTANT(
+      bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
+    BOOST_STATIC_ASSERT(index_found);
+
+    typedef typename mpl::deref<iter>::type    type;
+  };
+
+  template<typename Tag>
+  typename index<Tag>::type& get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
+  {
+    return *this;
+  }
+
+  template<typename Tag>
+  const typename index<Tag>::type& get(
+    BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))const
+  {
+    return *this;
+  }
+#endif
+
+  /* projection of iterators by number */
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATES)
+  template<int N>
+  struct nth_index_iterator
+  {
+    typedef typename nth_index<N>::type::iterator type;
+  };
+
+  template<int N>
+  struct nth_index_const_iterator
+  {
+    typedef typename nth_index<N>::type::const_iterator type;
+  };
+
+  template<int N,typename IteratorType>
+  typename nth_index_iterator<N>::type project(
+    IteratorType it
+    BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
+  {
+    typedef typename nth_index<N>::type index;
+
+#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
+    BOOST_STATIC_ASSERT(
+      (mpl::contains<iterator_type_list,IteratorType>::value));
+#endif
+
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(
+      it,static_cast<typename IteratorType::container_type&>(*this));
+
+    return index::make_iterator(static_cast<node_type*>(it.get_node()));
+  }
+
+  template<int N,typename IteratorType>
+  typename nth_index_const_iterator<N>::type project(
+    IteratorType it
+    BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
+  {
+    typedef typename nth_index<N>::type index;
+
+#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
+    BOOST_STATIC_ASSERT((
+      mpl::contains<iterator_type_list,IteratorType>::value||
+      mpl::contains<const_iterator_type_list,IteratorType>::value));
+#endif
+
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(
+      it,static_cast<const typename IteratorType::container_type&>(*this));
+    return index::make_iterator(static_cast<node_type*>(it.get_node()));
+  }
+#endif
+
+  /* projection of iterators by tag */
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATES)
+  template<typename Tag>
+  struct index_iterator
+  {
+    typedef typename index<Tag>::type::iterator type;
+  };
+
+  template<typename Tag>
+  struct index_const_iterator
+  {
+    typedef typename index<Tag>::type::const_iterator type;
+  };
+
+  template<typename Tag,typename IteratorType>
+  typename index_iterator<Tag>::type project(
+    IteratorType it
+    BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
+  {
+    typedef typename index<Tag>::type index;
+
+#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
+    BOOST_STATIC_ASSERT(
+      (mpl::contains<iterator_type_list,IteratorType>::value));
+#endif
+
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(
+      it,static_cast<typename IteratorType::container_type&>(*this));
+    return index::make_iterator(static_cast<node_type*>(it.get_node()));
+  }
+
+  template<typename Tag,typename IteratorType>
+  typename index_const_iterator<Tag>::type project(
+    IteratorType it
+    BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))const
+  {
+    typedef typename index<Tag>::type index;
+
+#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
+    BOOST_STATIC_ASSERT((
+      mpl::contains<iterator_type_list,IteratorType>::value||
+      mpl::contains<const_iterator_type_list,IteratorType>::value));
+#endif
+
+    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
+    BOOST_MULTI_INDEX_CHECK_IS_OWNER(
+      it,static_cast<const typename IteratorType::container_type&>(*this));
+    return index::make_iterator(static_cast<node_type*>(it.get_node()));
+  }
+#endif
+
+BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
+  typedef typename super::copy_map_type copy_map_type;
+
+  node_type* header()const
+  {
+    return &*bfm_header::member;
+  }
+
+  node_type* allocate_node()
+  {
+    return &*bfm_allocator::member.allocate(1);
+  }
+
+  void deallocate_node(node_type* x)
+  {
+    typedef typename node_allocator::pointer node_pointer;
+    bfm_allocator::member.deallocate(static_cast<node_pointer>(x),1);
+  }
+
+  bool empty_()const
+  {
+    return node_count==0;
+  }
+
+  std::size_t size_()const
+  {
+    return node_count;
+  }
+
+  std::size_t max_size_()const
+  {
+    return static_cast<std::size_t >(-1);
+  }
+
+  std::pair<node_type*,bool> insert_(const Value& v)
+  {
+    node_type* x=allocate_node();
+    BOOST_TRY{
+      node_type* res=super::insert_(v,x);
+      if(res==x){
+        ++node_count;
+        return std::pair<node_type*,bool>(res,true);
+      }
+      else{
+        deallocate_node(x);
+        return std::pair<node_type*,bool>(res,false);
+      }
+    }
+    BOOST_CATCH(...){
+      deallocate_node(x);
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+  std::pair<node_type*,bool> insert_(const Value& v,node_type* position)
+  {
+    node_type* x=allocate_node();
+    BOOST_TRY{
+      node_type* res=super::insert_(v,position,x);
+      if(res==x){
+        ++node_count;
+        return std::pair<node_type*,bool>(res,true);
+      }
+      else{
+        deallocate_node(x);
+        return std::pair<node_type*,bool>(res,false);
+      }
+    }
+    BOOST_CATCH(...){
+      deallocate_node(x);
+      BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+  }
+
+  void erase_(node_type* x)
+  {
+    super::erase_(x);
+    deallocate_node(x);
+    --node_count;
+  }
+
+  void delete_node_(node_type* x)
+  {
+    super::delete_node_(x);
+    deallocate_node(x);
+  }
+
+  void delete_all_nodes_()
+  {
+    super::delete_all_nodes_();
+  }
+
+  void clear_()
+  {
+    delete_all_nodes_();
+    super::clear_();
+    node_count=0;
+  }
+
+  void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
+  {
+    if(bfm_allocator::member!=x.bfm_allocator::member){
+      detail::adl_swap(bfm_allocator::member,x.bfm_allocator::member);
+    }
+    std::swap(bfm_header::member,x.bfm_header::member);
+    super::swap_(x);
+    std::swap(node_count,x.node_count);
+  }
+
+  bool replace_(const Value& k,node_type* x)
+  {
+    return super::replace_(k,x);
+  }
+
+  template<typename Modifier>
+  bool modify_(Modifier& mod,node_type* x)
+  {
+    mod(const_cast<value_type&>(x->value()));
+
+    BOOST_TRY{
+      if(!super::modify_(x)){
+        deallocate_node(x);
+        --node_count;
+        return false;
+      }
+      else return true;
+    }
+    BOOST_CATCH(...){
+      deallocate_node(x);
+      --node_count;
+      BOOST_RETHROW;
+    }
+    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 */
+
+  friend class boost::serialization::access;
+
+  BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+  typedef typename super::index_saver_type        index_saver_type;
+  typedef typename super::index_loader_type       index_loader_type;
+
+  template<class Archive>
+  void save(Archive& ar,const unsigned int version)const
+  {
+    const std::size_t s=size_();
+    ar<<serialization::make_nvp("count",s);
+    index_saver_type sm(bfm_allocator::member,s);
+
+    for(iterator it=super::begin(),it_end=super::end();it!=it_end;++it){
+      ar<<serialization::make_nvp("item",*it);
+      sm.add(it.get_node(),ar,version);
+    }
+    sm.add_track(header(),ar,version);
+
+    super::save_(ar,version,sm);
+  }
+
+  template<class Archive>
+  void load(Archive& ar,const unsigned int version)
+  {
+    BOOST_MULTI_INDEX_CHECK_INVARIANT;
+
+    clear_(); 
+
+    std::size_t s;
+    ar>>serialization::make_nvp("count",s);
+    index_loader_type lm(bfm_allocator::member,s);
+
+    for(std::size_t n=0;n<s;++n){
+      detail::archive_constructed<Value> value("item",ar,version);
+      std::pair<node_type*,bool> p=insert_(
+        value.get(),super::end().get_node());
+      if(!p.second)throw_exception(
+        archive::archive_exception(
+          archive::archive_exception::other_exception));
+      ar.reset_object_address(&p.first->value(),&value.get());
+      lm.add(p.first,ar,version);
+    }
+    lm.add_track(header(),ar,version);
+
+    super::load_(ar,version,lm);
+  }
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+  /* invariant stuff */
+
+  bool invariant_()const
+  {
+    return super::invariant_();
+  }
+
+  void check_invariant_()const
+  {
+    BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
+  }
+#endif
+
+private:
+  std::size_t node_count;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+#pragma parse_mfunc_templ reset
+#endif
+};
+
+/* retrieval of indices by number */
+
+template<typename MultiIndexContainer,int N>
+struct nth_index
+{
+  BOOST_STATIC_CONSTANT(
+    int,
+    M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
+  BOOST_STATIC_ASSERT(N>=0&&N<M);
+  typedef typename mpl::at_c<
+    typename MultiIndexContainer::index_type_list,N>::type type;
+};
+
+template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
+typename nth_index<
+  multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
+get(
+  multi_index_container<Value,IndexSpecifierList,Allocator>& m
+  BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
+{
+  typedef multi_index_container<
+    Value,IndexSpecifierList,Allocator>    multi_index_type;
+  typedef typename nth_index<
+    multi_index_container<
+      Value,IndexSpecifierList,Allocator>,
+    N
+  >::type                                  index;
+
+  BOOST_STATIC_ASSERT(N>=0&&
+    N<
+    mpl::size<
+      BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
+    >::type::value);
+
+  return detail::converter<multi_index_type,index>::index(m);
+}
+
+template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
+const typename nth_index<
+  multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
+get(
+  const multi_index_container<Value,IndexSpecifierList,Allocator>& m
+  BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
+{
+  typedef multi_index_container<
+    Value,IndexSpecifierList,Allocator>    multi_index_type;
+  typedef typename nth_index<
+    multi_index_container<
+      Value,IndexSpecifierList,Allocator>,
+    N
+  >::type                                  index;
+
+  BOOST_STATIC_ASSERT(N>=0&&
+    N<
+    mpl::size<
+      BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
+    >::type::value);
+
+  return detail::converter<multi_index_type,index>::index(m);
+}
+
+/* retrieval of indices by tag */
+
+template<typename MultiIndexContainer,typename Tag>
+struct index
+{
+  typedef typename MultiIndexContainer::index_type_list index_type_list;
+
+  typedef typename mpl::find_if<
+    index_type_list,
+    detail::has_tag<Tag>
+  >::type                                      iter;
+
+  BOOST_STATIC_CONSTANT(
+    bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
+  BOOST_STATIC_ASSERT(index_found);
+
+  typedef typename mpl::deref<iter>::type       type;
+};
+
+template<
+  typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
+>
+typename ::boost::multi_index::index<
+  multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
+get(
+  multi_index_container<Value,IndexSpecifierList,Allocator>& m
+  BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
+{
+  typedef multi_index_container<
+    Value,IndexSpecifierList,Allocator>         multi_index_type;
+  typedef typename ::boost::multi_index::index<
+    multi_index_container<
+      Value,IndexSpecifierList,Allocator>,
+    Tag
+  >::type                                       index;
+
+  return detail::converter<multi_index_type,index>::index(m);
+}
+
+template<
+  typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
+>
+const typename ::boost::multi_index::index<
+  multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
+get(
+  const multi_index_container<Value,IndexSpecifierList,Allocator>& m
+  BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
+{
+  typedef multi_index_container<
+    Value,IndexSpecifierList,Allocator>         multi_index_type;
+  typedef typename ::boost::multi_index::index<
+    multi_index_container<
+      Value,IndexSpecifierList,Allocator>,
+    Tag
+  >::type                                       index;
+
+  return detail::converter<multi_index_type,index>::index(m);
+}
+
+/* projection of iterators by number */
+
+template<typename MultiIndexContainer,int N>
+struct nth_index_iterator
+{
+  typedef typename detail::prevent_eti<
+    nth_index<MultiIndexContainer,N>,
+    typename nth_index<MultiIndexContainer,N>::type>::type::iterator type;
+};
+
+template<typename MultiIndexContainer,int N>
+struct nth_index_const_iterator
+{
+  typedef typename detail::prevent_eti<
+    nth_index<MultiIndexContainer,N>,
+    typename nth_index<MultiIndexContainer,N>::type
+  >::type::const_iterator type;
+};
+
+template<
+  int N,typename IteratorType,
+  typename Value,typename IndexSpecifierList,typename Allocator>
+typename nth_index_iterator<
+  multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
+project(
+  multi_index_container<Value,IndexSpecifierList,Allocator>& m,
+  IteratorType it
+  BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
+{
+  typedef multi_index_container<
+    Value,IndexSpecifierList,Allocator>                multi_index_type;
+  typedef typename nth_index<multi_index_type,N>::type index;
+
+#if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&&  /* MSVC++ 6.0/7.0 fails */\
+    (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7  */
+  BOOST_STATIC_ASSERT((
+    mpl::contains<
+      BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
+      IteratorType>::value));
+#endif
+
+  BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  typedef detail::converter<
+    multi_index_type,
+    BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
+  BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
+#endif
+
+  return detail::converter<multi_index_type,index>::iterator(
+    m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
+}
+
+template<
+  int N,typename IteratorType,
+  typename Value,typename IndexSpecifierList,typename Allocator>
+typename nth_index_const_iterator<
+  multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
+project(
+  const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
+  IteratorType it
+  BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
+{
+  typedef multi_index_container<
+    Value,IndexSpecifierList,Allocator>                multi_index_type;
+  typedef typename nth_index<multi_index_type,N>::type index;
+
+#if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&&  /* MSVC++ 6.0/7.0 fails */\
+    (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7  */
+  BOOST_STATIC_ASSERT((
+    mpl::contains<
+      BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
+      IteratorType>::value||
+    mpl::contains<
+      BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
+      IteratorType>::value));
+#endif
+
+  BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  typedef detail::converter<
+    multi_index_type,
+    BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
+  BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
+#endif
+
+  return detail::converter<multi_index_type,index>::const_iterator(
+    m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
+}
+
+/* projection of iterators by tag */
+
+template<typename MultiIndexContainer,typename Tag>
+struct index_iterator
+{
+  typedef typename ::boost::multi_index::index<
+    MultiIndexContainer,Tag>::type::iterator    type;
+};
+
+template<typename MultiIndexContainer,typename Tag>
+struct index_const_iterator
+{
+  typedef typename ::boost::multi_index::index<
+    MultiIndexContainer,Tag>::type::const_iterator type;
+};
+
+template<
+  typename Tag,typename IteratorType,
+  typename Value,typename IndexSpecifierList,typename Allocator>
+typename index_iterator<
+  multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
+project(
+  multi_index_container<Value,IndexSpecifierList,Allocator>& m,
+  IteratorType it
+  BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
+{
+  typedef multi_index_container<
+    Value,IndexSpecifierList,Allocator>         multi_index_type;
+  typedef typename ::boost::multi_index::index<
+    multi_index_type,Tag>::type                 index;
+
+#if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&&  /* MSVC++ 6.0/7.0 fails */\
+    (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7  */
+  BOOST_STATIC_ASSERT((
+    mpl::contains<
+      BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
+      IteratorType>::value));
+#endif
+
+  BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  typedef detail::converter<
+    multi_index_type,
+    BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
+  BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
+#endif
+
+  return detail::converter<multi_index_type,index>::iterator(
+    m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
+}
+
+template<
+  typename Tag,typename IteratorType,
+  typename Value,typename IndexSpecifierList,typename Allocator>
+typename index_const_iterator<
+  multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
+project(
+  const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
+  IteratorType it
+  BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
+{
+  typedef multi_index_container<
+    Value,IndexSpecifierList,Allocator>         multi_index_type;
+  typedef typename ::boost::multi_index::index<
+    multi_index_type,Tag>::type                 index;
+
+#if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&&  /* MSVC++ 6.0/7.0 fails */\
+    (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7  */
+  BOOST_STATIC_ASSERT((
+    mpl::contains<
+      BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
+      IteratorType>::value||
+    mpl::contains<
+      BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
+      IteratorType>::value));
+#endif
+
+  BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+  typedef detail::converter<
+    multi_index_type,
+    BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
+  BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
+#endif
+
+  return detail::converter<multi_index_type,index>::const_iterator(
+    m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
+}
+
+/* Comparison. Simple forward to first index. */
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator==(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
+{
+  return get<0>(x)==get<0>(y);
+}
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator<(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
+{
+  return get<0>(x)<get<0>(y);
+}
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator!=(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
+{
+  return get<0>(x)!=get<0>(y);
+}
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator>(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
+{
+  return get<0>(x)>get<0>(y);
+}
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator>=(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
+{
+  return get<0>(x)>=get<0>(y);
+}
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator<=(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
+{
+  return get<0>(x)<=get<0>(y);
+}
+
+/*  specialized algorithms */
+
+template<typename Value,typename IndexSpecifierList,typename Allocator>
+void swap(
+  multi_index_container<Value,IndexSpecifierList,Allocator>& x,
+  multi_index_container<Value,IndexSpecifierList,Allocator>& y)
+{
+  x.swap(y);
+}
+
+} /* namespace multi_index */
+
+/* Associated global functions are promoted to namespace boost, except
+ * comparison operators and swap, which are meant to be Koenig looked-up.
+ */
+
+using multi_index::get;
+using multi_index::project;
+
+} /* namespace boost */
+
+#undef BOOST_MULTI_INDEX_CHECK_INVARIANT
+
+#endif
diff --git a/boost/multi_index_container_fwd.hpp b/boost/multi_index_container_fwd.hpp
new file mode 100644 (file)
index 0000000..6e377ed
--- /dev/null
@@ -0,0 +1,121 @@
+/* Copyright 2003-2005 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_FWD_HPP
+#define BOOST_MULTI_INDEX_FWD_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/multi_index/identity.hpp>
+#include <boost/multi_index/indexed_by.hpp>
+#include <boost/multi_index/ordered_index_fwd.hpp>
+#include <memory>
+
+namespace boost{
+
+namespace multi_index{
+
+/* Default value for IndexSpecifierList specifies a container
+ * equivalent to std::set<Value>.
+ */
+
+template<
+  typename Value,
+  typename IndexSpecifierList=indexed_by<ordered_unique<identity<Value> > >,
+  typename Allocator=std::allocator<Value> >
+class multi_index_container;
+
+template<typename MultiIndexContainer,int N>
+struct nth_index;
+
+template<typename MultiIndexContainer,typename Tag>
+struct index;
+
+template<typename MultiIndexContainer,int N>
+struct nth_index_iterator;
+
+template<typename MultiIndexContainer,int N>
+struct nth_index_const_iterator;
+
+template<typename MultiIndexContainer,typename Tag>
+struct index_iterator;
+
+template<typename MultiIndexContainer,typename Tag>
+struct index_const_iterator;
+
+/* get and project functions not fwd declared due to problems
+ * with dependent typenames
+ */
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator==(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator<(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator!=(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator>(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator>=(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
+
+template<
+  typename Value1,typename IndexSpecifierList1,typename Allocator1,
+  typename Value2,typename IndexSpecifierList2,typename Allocator2
+>
+bool operator<=(
+  const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
+  const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y);
+
+template<typename Value,typename IndexSpecifierList,typename Allocator>
+void swap(
+  multi_index_container<Value,IndexSpecifierList,Allocator>& x,
+  multi_index_container<Value,IndexSpecifierList,Allocator>& y);
+
+} /* namespace multi_index */
+
+/* multi_index_container, being the main type of this library, is promoted to
+ * namespace boost.
+ */
+
+using multi_index::multi_index_container;
+
+} /* namespace boost */
+
+#endif