From: g0dil Date: Fri, 18 Apr 2008 13:59:32 +0000 (+0000) Subject: Console: Implement enum registration and parsing/formatting X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=0eaf5340de8c2fbb02b1e0e13a797931e221dff3;p=senf.git Console: Implement enum registration and parsing/formatting 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 --- diff --git a/Console/Traits.cc b/Console/Traits.cc new file mode 100644 index 0000000..9207a13 --- /dev/null +++ b/Console/Traits.cc @@ -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 +// +// 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" + + +// 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: diff --git a/Console/Traits.cti b/Console/Traits.cti index e96392f..6e777ef 100644 --- a/Console/Traits.cti +++ b/Console/Traits.cti @@ -23,9 +23,11 @@ /** \file \brief Traits inline template implementation */ -//#include "Traits.ih" +#include "Traits.ih" // Custom includes +#include +#include #include "../Utils/TypeInfo.hh" #define prefix_ inline @@ -38,6 +40,12 @@ template prefix_ void senf::console::ReturnValueTraits::format(Type const & value, std::ostream & os) { + senf_console_format_value(value, os); +} + +template +prefix_ void senf::console::senf_console_format_value(Type const & value, std::ostream & os) +{ os << value; } @@ -48,6 +56,14 @@ template prefix_ void senf::console::ArgumentTraits:: parse(ParseCommandInfo::TokensRange const & tokens, Type & out) { + senf_console_parse_argument(tokens,out); +} + +template +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::description() template prefix_ std::string senf::console::ArgumentTraits::str(Type const & value) { - return boost::lexical_cast(value); + std::stringstream ss; + senf::console::ReturnValueTraits::format(value, ss); + return ss.str(); } ///////////////////////////////cti.e/////////////////////////////////////// diff --git a/Console/Traits.hh b/Console/Traits.hh index 8176fb0..779ef30 100644 --- a/Console/Traits.hh +++ b/Console/Traits.hh @@ -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 + 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 + 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 index 0000000..12fbb65 --- /dev/null +++ b/Console/Traits.ih @@ -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 +// +// 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 +#include +#include +#include +#include +#include "../Utils/singleton.hh" + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace senf { +namespace console { +namespace detail { + + typedef boost::bimap EnumTable; + + long parseEnum(EnumTable const & table, ParseCommandInfo::TokensRange const & tokens); + std::string formatEnum(EnumTable const & table, long value); + + template + struct EnumTraits : public senf::singleton< EnumTraits > + { + using senf::singleton< EnumTraits >::instance; + EnumTable table; + }; + +# define SENF_CONSOLE_REGISTER_ENUM_ELT(r,d,e) (BOOST_PP_STRINGIZE(e), static_cast(e)) + +# define SENF_CONSOLE_REGISTER_ENUM_(Type, Values) \ + void senf_console_init_enum_table(Type) \ + { \ + senf::console::detail::EnumTraits & traits ( \ + senf::console::detail::EnumTraits::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( \ + senf::console::detail::parseEnum( \ + senf::console::detail::EnumTraits::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::instance().table, \ + static_cast(value) ); \ + } + +}}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// 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: diff --git a/Console/Traits.test.cc b/Console/Traits.test.cc index 83f8af5..861d0f0 100644 --- a/Console/Traits.test.cc +++ b/Console/Traits.test.cc @@ -28,6 +28,10 @@ // Custom includes #include "Traits.hh" +#include "ParsedCommand.hh" +#include "Executor.hh" +#include "Parse.hh" +#include "ScopedDirectory.hh" #include "../Utils/auto_unit_test.hh" #include @@ -35,8 +39,45 @@ #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( 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( 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( boost::ref(executor), boost::ref(ss), _1 )), + senf::console::SyntaxErrorException ); + + BOOST_CHECK_THROW( + parser.parse("test/test Baz", + boost::bind( 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 index 0000000..51d726d --- /dev/null +++ b/boost/bimap.hpp @@ -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 + +namespace boost +{ + using ::boost::bimaps::bimap; +} + diff --git a/boost/bimap/bimap.hpp b/boost/bimap/bimap.hpp new file mode 100644 index 0000000..9af5cbf --- /dev/null +++ b/boost/bimap/bimap.hpp @@ -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 +#include +#include + +#define BOOST_BIMAP_DISABLE_SERIALIZATION +#define BOOST_MULTI_INDEX_DISABLE_SERIALIZATION + +#ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + #include +#endif // BOOST_BIMAP_DISABLE_SERIALIZATION + +// Boost.Bimap +#include +#include +#include +#include +#include + +#include +#include +#include + +/// \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 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 +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, + + // You can use bimap as a collection of relations + + public ::boost::bimaps::detail::bimap_core + ::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 + >::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 + >::type + > +{ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail:: + bimap_core 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::type left_map; + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail:: + right_map_view_type::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::type + project(IteratorType iter + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + return core.template project(iter.base()); + } + + template< class Tag, class IteratorType > + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type + project(IteratorType iter + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag)) const + { + return core.template project(iter.base()); + } + + template< class Tag > + struct map_by : + public ::boost::bimaps::support::map_type_by::type + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + map_type_by::type type; + + private: map_by() {} + }; + + template< class Tag > + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + map_type_by::type & + by(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + return ::boost::bimaps::support::map_by(*this); + } + + template< class Tag > + const BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + map_type_by::type & + by(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const + { + return ::boost::bimaps::support::map_by(*this); + } + + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + + // Serialization support + + private: + + friend class boost::serialization::access; + + template + 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 +#include +#include + +// 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 index 0000000..191a642 --- /dev/null +++ b/boost/bimap/container_adaptor/associative_container_adaptor.hpp @@ -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 + +#include + +#include +#include +#include +#include +#include +#include + +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, + // { + 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, + // { + 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()(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()(k) + ); + } + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::iterator find(const CompatibleKey & k) + { + return this->template functor() + ( + this->base().find( + this->template functor()(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()(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()(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()(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 index 0000000..8e78090 --- /dev/null +++ b/boost/bimap/container_adaptor/container_adaptor.hpp @@ -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 + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + +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, + // { + ::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, + // { + ::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, + // { + ::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, + // { + ::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()( base().begin() ); + } + + iterator end() + { + return this->template functor()( base().end() ); + } + + const_iterator begin() const + { + return this->template functor()( base().begin() ); + } + + const_iterator end() const + { + return this->template functor()( base().end() ); + } + + + iterator erase(iterator pos) + { + return this->template functor()( + base().erase(this->template functor()(pos)) + ); + } + + iterator erase(iterator first, iterator last) + { + return this->template functor()( + base().erase( + this->template functor()(first), + this->template functor()(last) + ) + ); + } + + void clear() + { + base().clear(); + } + + template< class InputIterator > + void insert(InputIterator iterBegin, InputIterator iterEnd) + { + for( ; iterBegin != iterEnd ; ++iterBegin ) + { + base().insert( this->template + functor()( *iterBegin ) + ); + } + } + + std::pair 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()(x) ) + ); + + return std::pair( this->template + functor()(r.first),r.second + ); + } + + iterator insert(iterator pos, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< value_type >::param_type x) + { + return this->template functor()( + base().insert( + this->template functor()(pos), + this->template functor()(x)) + ); + } + + void swap( container_adaptor & c ) + { + base().swap( c.base() ); + } + + // Access to functors ---------------------------------------------------- + + protected: + + template< class Functor > + Functor & functor() + { + return dwfb.template functor(); + } + + template< class Functor > + Functor const & functor() const + { + return dwfb.template 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 index 0000000..9051a46 --- /dev/null +++ b/boost/bimap/container_adaptor/detail/comparison_adaptor.hpp @@ -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 + +#include +#include + +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 +{ + comparison_adaptor( const Compare & comp, const Converter & conv) + : compare(comp), converter(conv) {} + + bool operator()( BOOST_DEDUCED_TYPENAME call_traits::param_type x, + BOOST_DEDUCED_TYPENAME call_traits::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 +{ + 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 +{ + unary_check_adaptor( const Compare & comp, const Converter & conv ) : + compare(comp), converter(conv) {} + + bool operator()( BOOST_DEDUCED_TYPENAME call_traits::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 index 0000000..fd8c435 --- /dev/null +++ b/boost/bimap/container_adaptor/detail/functor_bag.hpp @@ -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 + +#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 + +#include +#include + +#include +#include + +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::type d) + : data(d) {} + + template< class Functor > + Functor& functor() + { + return *(static_cast(this)); + } + + template< class Functor > + const Functor& functor() const + { + return *(static_cast(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 index 0000000..f6f5864 --- /dev/null +++ b/boost/bimap/container_adaptor/detail/identity_converters.hpp @@ -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 + +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 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 +{ + 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 & 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 index 0000000..3835b7c --- /dev/null +++ b/boost/bimap/container_adaptor/detail/key_extractor.hpp @@ -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. + +#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 + +#include + +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 index 0000000..6957045 --- /dev/null +++ b/boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp @@ -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 + +/*****************************************************************************/ +#define BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS \ + \ +template \ +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 index 0000000..310e2b4 --- /dev/null +++ b/boost/bimap/container_adaptor/list_adaptor.hpp @@ -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 + +#include +#include +#include +#include +#include +#include + +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() + (position), + x.base() + ); + } + + void splice(Iterator position, list_adaptor & x, Iterator i) + { + this->base().splice( + this->template functor() + (position), + x.base(), + this->template functor()(i) + ); + } + + void splice(Iterator position, list_adaptor & x, + Iterator first, Iterator last) + { + this->base().splice( + this->template functor() + (position), + x.base(), + this->template functor()(first), + this->template functor()(last) + ); + } + + void remove( + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type + >::param_type value + ) + { + this->base().remove( + this->template functor()(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() ) + ); + } + + 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_from_base + + >( + std::equal_to(), + this->template functor() + ) + ); + } + + 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() ) + ); + } + + 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_from_base + + >( + std::less(), + this->template functor() + ) + ); + } + + 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() ) + ); + } + + 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_from_base + + >( + std::less(), + this->template functor() + ) + ); + } + + 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() ) + ); + } + + 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 index 0000000..ff7a540 --- /dev/null +++ b/boost/bimap/container_adaptor/list_map_adaptor.hpp @@ -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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +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, + // { + 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, + // { + 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() ) + ); + } + + void unique() + { + this->base().unique( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::equal_to, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( + std::equal_to(), + this->template functor() + ) + ); + } + + 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() ) + ); + } + + void merge(list_map_adaptor & x) + { + this->base().merge(x.base(), + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( + std::less(), + this->template functor() + ) + ); + } + + 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() ) + ); + } + + void sort() + { + this->base().sort( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( + std::less(), + this->template functor() + ) + ); + } + + 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() ) + ); + } + +}; + + +} // 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 index 0000000..f1a6f64 --- /dev/null +++ b/boost/bimap/container_adaptor/map_adaptor.hpp @@ -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 + +#include +#include +#include +#include + +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()(k)]; + } + + template< class CompatibleKey > + data_type& at(const CompatibleKey & k) + { + return this->base(). + at(this->template functor()(k)); + } + + template< class CompatibleKey > + const data_type& at(const CompatibleKey & k) const + { + return this->base(). + at(this->template functor()(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 index 0000000..ad5edf2 --- /dev/null +++ b/boost/bimap/container_adaptor/multimap_adaptor.hpp @@ -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 + +#include +#include +#include +#include + +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 index 0000000..fe89d9a --- /dev/null +++ b/boost/bimap/container_adaptor/multiset_adaptor.hpp @@ -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 + +#include +#include +#include +#include + +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 index 0000000..6278844 --- /dev/null +++ b/boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include + +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, + // { + 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, + // { + 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() + ); + } + + 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() + ); + } + + 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()(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()(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()(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()(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 index 0000000..396635d --- /dev/null +++ b/boost/bimap/container_adaptor/sequence_container_adaptor.hpp @@ -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 + +#include + +#include +#include +#include +#include +#include +#include + +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, + // { + 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, + // { + 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()(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()(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()(x)); + } + + void pop_back() + { + this->base().pop_back(); + } + + std::pair + 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( + 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()(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 index 0000000..6c8dbf3 --- /dev/null +++ b/boost/bimap/container_adaptor/set_adaptor.hpp @@ -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 + +#include +#include +#include + +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 index 0000000..4bde159 --- /dev/null +++ b/boost/bimap/container_adaptor/support/iterator_facade_converters.hpp @@ -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 + +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 +{ + 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 index 0000000..937a0d8 --- /dev/null +++ b/boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp @@ -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 + +#include +#include +#include +#include +#include +#include + +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, + // { + 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, + // { + 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()(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 index 0000000..762a643 --- /dev/null +++ b/boost/bimap/container_adaptor/unordered_map_adaptor.hpp @@ -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 + +#include +#include +#include +#include + +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()(k)]; + } + + template< class CompatibleKey > + data_type& at(const CompatibleKey & k) + { + return this->base(). + at(this->template functor()(k)); + } + + template< class CompatibleKey > + const data_type& at(const CompatibleKey & k) const + { + return this->base(). + at(this->template functor()(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 index 0000000..be28b3a --- /dev/null +++ b/boost/bimap/container_adaptor/unordered_multimap_adaptor.hpp @@ -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 + +#include +#include +#include +#include + +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 index 0000000..1d8e4c9 --- /dev/null +++ b/boost/bimap/container_adaptor/unordered_multiset_adaptor.hpp @@ -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 + +#include +#include +#include +#include + +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 index 0000000..cf00b0f --- /dev/null +++ b/boost/bimap/container_adaptor/unordered_set_adaptor.hpp @@ -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 + +#include +#include +#include + +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 index 0000000..de6e391 --- /dev/null +++ b/boost/bimap/container_adaptor/vector_adaptor.hpp @@ -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 + +#include +#include +#include + +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()(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 index 0000000..9b0b9d3 --- /dev/null +++ b/boost/bimap/container_adaptor/vector_map_adaptor.hpp @@ -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 + +#include +#include +#include +#include +#include +#include + +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 index 0000000..247e93a --- /dev/null +++ b/boost/bimap/detail/bimap_core.hpp @@ -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 + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +// Boost.MultiIndex +#include +#include + +// Boost.Bimap +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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::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, + 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::other + + > core_type; + + // Core metadata + // -------------------------------------------------------------------- + public: + + typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index:: + index::type left_index; + + typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index:: + index::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 index 0000000..1f252e3 --- /dev/null +++ b/boost/bimap/detail/concept_tags.hpp @@ -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 + +#include +#include +#include + +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_ left_mutable_key; + typedef mpl::bool_ 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_ left_mutable_key; + typedef mpl::bool_ 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 index 0000000..3a8ed63 --- /dev/null +++ b/boost/bimap/detail/debug/static_error.hpp @@ -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 + +#include +#include + +// 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 index 0000000..01c899d --- /dev/null +++ b/boost/bimap/detail/generate_index_binder.hpp @@ -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 + +#include + + +/*===========================================================================*/ +#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 index 0000000..0ff4762 --- /dev/null +++ b/boost/bimap/detail/generate_relation_binder.hpp @@ -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 + +#include + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_RELATION_BINDER_0CP( \ + \ + SET_TYPE_OF \ + ) \ + \ + template< class Relation > \ + struct bind_to \ + { \ + typedef SET_TYPE_OF 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::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::type, \ + BOOST_DEDUCED_TYPENAME mpl::apply::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 index 0000000..925184c --- /dev/null +++ b/boost/bimap/detail/generate_view_binder.hpp @@ -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 + +#include + +/*===========================================================================*/ +#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 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 index 0000000..13d52c1 --- /dev/null +++ b/boost/bimap/detail/is_set_type_of.hpp @@ -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 + +#include +#include + +/** \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 index 0000000..3d22d73 --- /dev/null +++ b/boost/bimap/detail/manage_additional_parameters.hpp @@ -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 + +#include + +// Boost.MPL +#include +#include +#include +#include + +#include + +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 > : ::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 allocator; + typedef ::boost::mpl::na additional_info; + }; + + // (2) manage_additional_parameters + // + // 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 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 + // + // 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 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 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, + case_NNN, // (1) + BOOST_DEDUCED_TYPENAME mpl::if_ + < + ::boost::mpl::is_na, + BOOST_DEDUCED_TYPENAME mpl::if_ + < + is_set_type_of_relation, + case_SNN, // (3) + BOOST_DEDUCED_TYPENAME mpl::if_ + < + is_with_info, + case_HNN, // (5) + case_ANN // (2) + + >::type + + >::type, + BOOST_DEDUCED_TYPENAME mpl::if_ + < + ::boost::mpl::is_na, + BOOST_DEDUCED_TYPENAME mpl::if_ + < + is_with_info, + case_HAN, // (7) + BOOST_DEDUCED_TYPENAME mpl::if_ + < + is_with_info, + 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 index 0000000..d485e50 --- /dev/null +++ b/boost/bimap/detail/manage_bimap_key.hpp @@ -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 + +#include +#include + +#include + +#include + +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 index 0000000..7479937 --- /dev/null +++ b/boost/bimap/detail/map_view_base.hpp @@ -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 + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + iterator_type_by::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + const_iterator_type_by::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + OTHER_ITER::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + CONST_OTHER_ITER::type, \ + ::boost::bimaps::container_adaptor::support::iterator_facade_to_base \ + < \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + iterator_type_by::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + const_iterator_type_by::type \ + \ + >, \ + ::boost::mpl::na, \ + ::boost::mpl::na, \ + ::boost::bimaps::relation::detail:: \ + pair_to_relation_functor, \ + ::boost::bimaps::relation::support:: \ + get_pair_functor \ +> +/*===========================================================================*/ + + +#if defined(BOOST_MSVC) +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP) \ + typedef ::boost::bimaps::detail::map_view_base< \ + TYPE,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 >; +/*===========================================================================*/ +#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::type, + + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type + + > iterator_to_base_; + + typedef ::boost::bimaps::relation::detail:: + pair_to_relation_functor value_to_base_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + key_type_by::type key_type_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + data_type_by::type data_type_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + pair_type_by::type value_type_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type iterator_; + + public: + + bool replace(iterator_ position, const value_type_ & x) + { + return derived().base().replace( + derived().template functor()(position), + derived().template functor()(x) + ); + } + + template< class CompatibleKey > + bool replace_key(iterator_ position, const CompatibleKey & k) + { + return derived().base().replace( + derived().template functor()(position), + derived().template functor()( + value_type_(k,position->second) + ) + ); + } + + template< class CompatibleData > + bool replace_data(iterator_ position, const CompatibleData & d) + { + return derived().base().replace( + derived().template functor()(position), + derived().template functor()( + 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()(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::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()(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::type, + BOOST_DEDUCED_TYPENAME BimapType::relation + + >::type data_extractor_; + + return derived().base().modify( + + derived().template functor()(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(this); + } + + Derived const& derived() const + { + return *static_cast(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::type data_type_; + + public: + + template< class CompatibleKey > + data_type_ & at(const CompatibleKey& k) + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::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::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::type iterator; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + value_type_by::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(this); + } + + Derived const& derived() const + { + return *static_cast(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::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::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(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } +}; + + +template< class Derived, class Tag, class BimapType> +struct unique_map_view_access +{ + private: + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + value_type_by::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, + mutable_data_unique_map_view_access + + >::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 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 index 0000000..897cbe6 --- /dev/null +++ b/boost/bimap/detail/map_view_iterator.hpp @@ -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 +// #include +#include +#include +#include + +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::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::type +{ + typedef BOOST_DEDUCED_TYPENAME + map_view_iterator_base::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( + *const_cast( + &(*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::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::type +{ + typedef BOOST_DEDUCED_TYPENAME + const_map_view_iterator_base::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 i) + : base_(i.base()) {} + + BOOST_DEDUCED_TYPENAME base_::reference dereference() const + { + return ::boost::bimaps::relation::support::pair_by(*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 index 0000000..b170549 --- /dev/null +++ b/boost/bimap/detail/modifier_adaptor.hpp @@ -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 + +#include + +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, + 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, + 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 index 0000000..6801632 --- /dev/null +++ b/boost/bimap/detail/non_unique_views_helper.hpp @@ -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 + +/*===========================================================================*/ +#define BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS \ + \ +template \ +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 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( \ + 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 index 0000000..b867145 --- /dev/null +++ b/boost/bimap/detail/set_view_base.hpp @@ -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 + +#include +#include +#include +#include +#include +#include +#include + +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 +{ + 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(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::bimaps::detail:: + const_set_view_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 iterator_; + + public: + + bool replace(iterator_ position, + const value_type_ & x) + { + return derived().base().replace( + derived().template functor()(position),x + ); + } + + template< class CompatibleLeftType > + bool replace_left(iterator_ position, + const CompatibleLeftType & l) + { + return derived().base().replace( + derived().template functor()(position), + value_type_(l,position->right) + ); + } + + template< class CompatibleRightType > + bool replace_right(iterator_ position, + const CompatibleRightType & r) + { + return derived().base().replace( + derived().template functor()(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()(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()(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()(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(this); + } + + Derived const& derived() const + { + return *static_cast(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 index 0000000..93daa15 --- /dev/null +++ b/boost/bimap/detail/set_view_iterator.hpp @@ -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 +// #include +#include +#include +#include + +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::type +{ + typedef BOOST_DEDUCED_TYPENAME set_view_iterator_base::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::type +{ + typedef BOOST_DEDUCED_TYPENAME const_set_view_iterator_base::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 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 index 0000000..b669ee0 --- /dev/null +++ b/boost/bimap/detail/test/check_metadata.hpp @@ -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 + +#include +#include +#include + + +// 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 index 0000000..1d9a8e8 --- /dev/null +++ b/boost/bimap/detail/user_interface_config.hpp @@ -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 index 0000000..b3cfee3 --- /dev/null +++ b/boost/bimap/list_of.hpp @@ -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 + +#include + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +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 >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + list_of::index_bind + < + KeyExtractor, + Tag + + >::type, + + sequenced< tag, KeyExtractor > + + >::value +) + +typedef bimap +< + list_of, RightKeyType + +> bimap_with_left_type_as_list; + +BOOST_STATIC_ASSERT +( + is_same + < + list_of::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::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_ 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 +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_ left_mutable_key; + typedef mpl::bool_ 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 index 0000000..f99e330 --- /dev/null +++ b/boost/bimap/multiset_of.hpp @@ -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 + +#include + +#include +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +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 >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + compute_index_type + < + multiset_of, + KeyExtractor, + Tag + + >::type + , + ordered_nonunique< tag, KeyExtractor, KeyCompare > + + >::value +) + +typedef bimap +< + multiset_of, 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::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::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_ 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 +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_ left_mutable_key; + typedef mpl::bool_ 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 index 0000000..ae497e0 --- /dev/null +++ b/boost/bimap/property_map/set_support.hpp @@ -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 + +#include +#include +#include +#include + +#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 > +{ + typedef BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support::data_type_by::type value_type; + typedef BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support:: key_type_by::type key_type; + + typedef readable_property_map_tag category; +}; + + +template< class Tag, class Bimap > +const BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::data_type_by::type & + get(const ::boost::bimaps::views::map_view & m, + const BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support::key_type_by::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 index 0000000..2673ccc --- /dev/null +++ b/boost/bimap/property_map/unordered_set_support.hpp @@ -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 + +#include +#include +#include +#include + +#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 > +{ + typedef BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support::data_type_by::type value_type; + typedef BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support:: key_type_by::type key_type; + + typedef readable_property_map_tag category; +}; + + +template< class Tag, class Bimap > +const BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::data_type_by::type & + get(const ::boost::bimaps::views::unordered_map_view & m, + const BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support::key_type_by::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 index 0000000..a1e939f --- /dev/null +++ b/boost/bimap/relation/detail/access_builder.hpp @@ -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 + +#include +#include +#include +#include +#include +#include +#include + + +/****************************************************************************** + 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, \ + \ + BOOST_DEDUCED_TYPENAME call_traits::const_reference, \ + \ + BOOST_DEDUCED_TYPENAME call_traits::reference \ + \ + >::type type; \ + }; \ + \ + } +/*===========================================================================*/ + + + +/****************************************************************************** + BIMAP SYMMETRIC ACCESS IMPLEMENTATION +******************************************************************************* + +namespace detail { + +template< class Tag, class SymmetricType > +typename result_of::NAME::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::type + NAME( const SymmetricType & ); + +******************************************************************************/ + +/*===========================================================================*/ +#define BOOST_BIMAP_SYMMETRIC_ACCESS_INTERFACE_BUILDER( \ + \ + NAME \ + ) \ + \ + template< class Tag, class SymmetricType > \ + BOOST_DEDUCED_TYPENAME result_of::NAME::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 index 0000000..4ef6cae --- /dev/null +++ b/boost/bimap/relation/detail/metadata_access_builder.hpp @@ -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 + +#include +#include +#include +#include + + + +/****************************************************************************** + 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 index 0000000..e601ad3 --- /dev/null +++ b/boost/bimap/relation/detail/mutant.hpp @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include + +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 + )); + 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 + )); + 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 index 0000000..72f9925 --- /dev/null +++ b/boost/bimap/relation/detail/static_access_builder.hpp @@ -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 + +#include +#include +#include +#include + + + +/****************************************************************************** + 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 index 0000000..1e8b521 --- /dev/null +++ b/boost/bimap/relation/detail/to_mutable_relation_functor.hpp @@ -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 + +#include +#include +#include + +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::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 > +{ + typedef ::boost::bimaps::relation::mutant_relation Relation; + + Relation & + operator()( BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + pair_type_by::type & p ) const + { + return ::boost::bimaps::relation::detail::mutate(p); + } + + const Relation & + operator()( const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + pair_type_by::type & p) const + { + return ::boost::bimaps::relation::detail::mutate(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 > +{ + typedef ::boost::bimaps::relation::mutant_relation Relation; + + Relation & + operator()( BOOST_DEDUCED_TYPENAME Relation::above_view & r ) const + { + return ::boost::bimaps::relation::detail::mutate(r); + } + + const Relation & + operator()( const BOOST_DEDUCED_TYPENAME Relation::above_view & r ) const + { + return ::boost::bimaps::relation::detail::mutate(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 index 0000000..c39738f --- /dev/null +++ b/boost/bimap/relation/member_at.hpp @@ -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 + +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::type data = get(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 index 0000000..517557f --- /dev/null +++ b/boost/bimap/relation/mutant_relation.hpp @@ -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 + +#include +#include +#include +// #include + +#include + +#include + +// Boost.Bimap +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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 +{ + typedef symmetrical_base base_; + + typedef relation_storage storage_; + + public: + + typedef relation_storage 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 +{ + typedef ::boost::bimaps::relation::detail:: + relation_storage base_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + default_tagged::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 : + public ::boost::bimaps::relation::detail::relation_storage +{ + typedef ::boost::bimaps::relation::detail:: + relation_storage 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 +{ + typedef ::boost::bimaps::relation::detail:: + relation_info_hook 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 storage_base; + + /// Above view, non mutable view of the relation + + typedef mutant_relation 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 & rel) : + base_(rel) {} + + mutant_relation(const mutant_relation & rel) : + base_(rel) {} + + // Operators + + template< bool FM > + mutant_relation& operator=(const mutant_relation & 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(*this); + } + + const left_pair & get_left_pair() const + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + right_pair & get_right_pair() + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + const right_pair & get_right_pair() const + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + above_view & get_view() + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + const above_view & get_view() const + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + template< class Tag > + const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + result_of::get::type + get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const + { + return ::boost::bimaps::relation::support::get(*this); + } + + template< class Tag > + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + result_of::get::type + get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + return ::boost::bimaps::relation::support::get(*this); + } + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + + private: + friend class ::boost::serialization::access; + + template + 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 & 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 & a, + const detail::relation_storage & 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 & a, + const detail::relation_storage & b) +{ + return ! ( a == b ); +} + +template< class FirstType, class SecondType, bool FM1, bool FM2 > +bool operator<(const detail::relation_storage & a, + const detail::relation_storage & 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 & a, + const detail::relation_storage & 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 & a, + const detail::relation_storage & 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 & a, + const detail::relation_storage & 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 index 0000000..24368db --- /dev/null +++ b/boost/bimap/relation/pair_layout.hpp @@ -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 + +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 index 0000000..2325b3d --- /dev/null +++ b/boost/bimap/relation/structured_pair.hpp @@ -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 + +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + +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 +{ + typedef symmetrical_base 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 +{ + typedef symmetrical_base 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::param_type f, + BOOST_DEDUCED_TYPENAME ::boost::call_traits::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 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 type; +}; + +template +< + class FirstType, + class SecondType +> +struct storage_finder +{ + typedef mirror_storage 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::type +{ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::storage_finder::type base_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + default_tagged::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 : + public ::boost::bimaps::relation::detail::storage_finder::type +{ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::storage_finder::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::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 & p) + : base_(p) {} + + template< class OtherLayout > + structured_pair& operator=( + const structured_pair & p) + { + base_::change_to(p); + return *this; + } + + template< class First, class Second > + structured_pair(const std::pair & p) : + base_(p.first,p.second) + {} + + template< class First, class Second > + structured_pair& operator=(const std::pair & 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::type + get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const + { + return ::boost::bimaps::relation::support::get(*this); + } + + template< class Tag > + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + result_of::get::type + get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + return ::boost::bimaps::relation::support::get(*this); + } +}; + +// structured_pair - structured_pair + +template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > +bool operator==(const structured_pair & a, + const structured_pair & 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 & a, + const structured_pair & b) +{ + return ! ( a == b ); +} + +template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > +bool operator<(const structured_pair & a, + const structured_pair & 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 & a, + const structured_pair & 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 & a, + const structured_pair & 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 & a, + const structured_pair & 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 & a, + const std::pair & 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 & a, + const std::pair & b) +{ + return ! ( a == b ); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator<(const structured_pair & a, + const std::pair & 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 & a, + const std::pair & 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 & a, + const std::pair & 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 & a, + const std::pair & 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 & a, + const structured_pair & 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 & a, + const structured_pair & b) +{ + return ! ( a == b ); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator<(const std::pair & a, + const structured_pair & 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 & a, + const structured_pair & 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 & a, + const structured_pair & 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 & a, + const structured_pair & 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 index 0000000..b00c607 --- /dev/null +++ b/boost/bimap/relation/support/data_extractor.hpp @@ -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 + +#include + +/** \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 +{ + 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 +{ + 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::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 index 0000000..3a3afde --- /dev/null +++ b/boost/bimap/relation/support/get.hpp @@ -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(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 + +#include + +#include + +#include +#include +#include + +#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::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; + { + 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 index 0000000..5f37bf6 --- /dev/null +++ b/boost/bimap/relation/support/get_pair_functor.hpp @@ -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 + +#include + +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::type + operator()( Relation & r ) const + { + return pair_by(r); + } + + BOOST_DEDUCED_TYPENAME result_of::pair_by::type + operator()( const Relation & r ) const + { + return pair_by(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 index 0000000..b2b1b74 --- /dev/null +++ b/boost/bimap/relation/support/is_tag_of_member_at.hpp @@ -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 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 + +#include +#include + +#include +#include +#include + +/** \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::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::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::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::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::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 index 0000000..a8324ff --- /dev/null +++ b/boost/bimap/relation/support/member_with_tag.hpp @@ -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 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 + +#include +#include +#include +#include +#include +#include +#include + +/** \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 >, + 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 >, + 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 >, + 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 index 0000000..174bd98 --- /dev/null +++ b/boost/bimap/relation/support/opposite_tag.hpp @@ -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 + +#include + +/** \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 index 0000000..1ce25fb --- /dev/null +++ b/boost/bimap/relation/support/pair_by.hpp @@ -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(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 + +#include +#include + +#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::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; + { + 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 index 0000000..64f98d1 --- /dev/null +++ b/boost/bimap/relation/support/pair_type_by.hpp @@ -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 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 + +#include + +/** \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 index 0000000..9dc5761 --- /dev/null +++ b/boost/bimap/relation/support/value_type_of.hpp @@ -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 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 + +#include + +/** \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 index 0000000..ea787c3 --- /dev/null +++ b/boost/bimap/relation/symmetrical_base.hpp @@ -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 + +#include +#include + +// Boost.Bimap +#include +#include + +#include + + +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 index 0000000..b5a0c20 --- /dev/null +++ b/boost/bimap/set_of.hpp @@ -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 + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +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 >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + set_of::index_bind + < + KeyExtractor, + Tag + + >::type, + + ordered_unique< tag, KeyExtractor, KeyCompare > + + >::value +) + +typedef bimap +< + set_of, RightKeyType + +> bimap_with_left_type_as_set; + +BOOST_STATIC_ASSERT +( + is_same + < + set_of::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::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::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_ 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 +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_ left_mutable_key; + typedef mpl::bool_ 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 index 0000000..c6d2e2c --- /dev/null +++ b/boost/bimap/support/data_type_by.hpp @@ -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 + +#include + +/** \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 >::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 index 0000000..6d1cff3 --- /dev/null +++ b/boost/bimap/support/iterator_type_by.hpp @@ -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 + +#include +#include + +#include + +#include + +/** \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 + ::type::reverse_iterator type, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::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::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 + ::type::const_reverse_iterator type, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::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::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 + ::type::local_iterator type, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::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::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 + ::type::const_local_iterator type, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::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::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 index 0000000..0b4abb5 --- /dev/null +++ b/boost/bimap/support/key_type_by.hpp @@ -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 + +#include + +/** \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 index 0000000..cffa2c3 --- /dev/null +++ b/boost/bimap/support/lambda.hpp @@ -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 + +#include + +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 index 0000000..ac57f1b --- /dev/null +++ b/boost/bimap/support/map_by.hpp @@ -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(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 + +#include +#include + + +#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::type +Instead of using \c map_type_by::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::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; + { + 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 index 0000000..00b4d20 --- /dev/null +++ b/boost/bimap/support/map_type_by.hpp @@ -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 + +#include + +/** \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 index 0000000..a7ce6c0 --- /dev/null +++ b/boost/bimap/support/value_type_by.hpp @@ -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 + +#include + +/** \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 index 0000000..bb6aa60 --- /dev/null +++ b/boost/bimap/tags/support/apply_to_value_type.hpp @@ -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 + +#include +#include + +/** \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 > +{ + 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 index 0000000..4c02a65 --- /dev/null +++ b/boost/bimap/tags/support/default_tagged.hpp @@ -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 + +#include + +/** \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; +}; + +template< class Type, class OldTag, class NewTag > +struct default_tagged< tagged< Type, OldTag >, NewTag > +{ + typedef tagged 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 index 0000000..892b3b1 --- /dev/null +++ b/boost/bimap/tags/support/is_tagged.hpp @@ -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 + +#include +#include + +/** \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 index 0000000..55cd0fc --- /dev/null +++ b/boost/bimap/tags/support/overwrite_tagged.hpp @@ -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 + +#include + +/** \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; +}; + +template< class Type, class OldTag, class NewTag > +struct overwrite_tagged< tagged< Type, OldTag >, NewTag > +{ + typedef tagged 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 index 0000000..413703b --- /dev/null +++ b/boost/bimap/tags/support/tag_of.hpp @@ -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 + +#include +#include + +/** \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 index 0000000..a4ea828 --- /dev/null +++ b/boost/bimap/tags/support/value_type_of.hpp @@ -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 + +#include + +/** \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 index 0000000..ca2a24c --- /dev/null +++ b/boost/bimap/tags/tagged.hpp @@ -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 + +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 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, value_type_of >::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 index 0000000..a2aa241 --- /dev/null +++ b/boost/bimap/unconstrained_set_of.hpp @@ -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 + +#include + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include +#include + +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 >::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::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_ 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_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace detail { + +template +struct is_unconstrained_set_of : + ::boost::mpl::false_ {}; + +template +struct is_unconstrained_set_of< unconstrained_set_of > : + ::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 index 0000000..c41f202 --- /dev/null +++ b/boost/bimap/unordered_multiset_of.hpp @@ -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 + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +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 >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + compute_index_type + < + unordered_multiset_of, + KeyExtractor, + Tag + + >::type + , + hashed_nonunique< tag, KeyExtractor, HashFunctor, EqualKey > + + >::value +) + +typedef bimap +< + unordered_multiset_of, 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::type >, + class EqualKey = std::equal_to< BOOST_DEDUCED_TYPENAME + ::boost::bimaps::tags::support::value_type_of::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::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_ 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 +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_ left_mutable_key; + typedef mpl::bool_ 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 index 0000000..e39c231 --- /dev/null +++ b/boost/bimap/unordered_set_of.hpp @@ -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 + +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +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 >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + unordered_set_of::index_bind + < + KeyExtractor, + Tag + + >::type, + + hashed_unique< tag, KeyExtractor, HashFunctor, EqualKey > + + >::value +) + +typedef bimap +< + unordered_set_of, RightKeyType + +> bimap_with_left_type_as_unordered_set; + +BOOST_STATIC_ASSERT +( + is_same + < + unordered_set_of::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::type >, + class EqualKey = std::equal_to< BOOST_DEDUCED_TYPENAME + ::boost::bimaps::tags::support::value_type_of::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::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_ 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 +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_ left_mutable_key; + typedef mpl::bool_ 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 index 0000000..28e01ba --- /dev/null +++ b/boost/bimap/vector_of.hpp @@ -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 + +#include + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +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 >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + vector_of::index_bind + < + KeyExtractor, + Tag + + >::type, + + random_access< tag, KeyExtractor > + + >::value +) + +typedef bimap +< + vector_of, RightKeyType + +> bimap_with_left_type_as_vector; + +BOOST_STATIC_ASSERT +( + is_same + < + vector_of::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::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_ 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 +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_ left_mutable_key; + typedef mpl::bool_ 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 index 0000000..2a7d2b1 --- /dev/null +++ b/boost/bimap/views/list_map_view.hpp @@ -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 + +#include +#include +#include +#include +#include +#include + +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::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + reverse_iterator_type_by::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_reverse_iterator_type_by::type, + ::boost::bimaps::container_adaptor::support::iterator_facade_to_base + < + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type + + >, + ::boost::mpl::na, + ::boost::mpl::na, + ::boost::bimaps::relation::detail:: + pair_to_relation_functor, + ::boost::bimaps::relation::support:: + get_pair_functor, + + 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::type, + public ::boost::bimaps::detail:: + map_view_base< list_map_view,Tag,BimapType > + +{ + typedef BOOST_DEDUCED_TYPENAME list_map_view_base::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 > +{ + private: typedef ::boost::bimaps::views::list_map_view 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 > +{ + private: typedef ::boost::bimaps::views::list_map_view 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 index 0000000..4b5887f --- /dev/null +++ b/boost/bimap/views/list_set_view.hpp @@ -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 + +#include +#include + +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 index 0000000..245b5d6 --- /dev/null +++ b/boost/bimap/views/map_view.hpp @@ -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 + +#include +#include + +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 >, + public ::boost::bimaps::detail:: + unique_map_view_access< map_view, 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 + + >::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 > +{ + private: typedef ::boost::bimaps::views::map_view 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 > +{ + private: typedef ::boost::bimaps::views::map_view 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 index 0000000..4176949 --- /dev/null +++ b/boost/bimap/views/multimap_view.hpp @@ -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 + +#include +#include +#include +#include + +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 > + +{ + 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 > +{ + private: typedef ::boost::bimaps::views::multimap_view 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 > +{ + private: typedef ::boost::bimaps::views::multimap_view 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 index 0000000..c49230b --- /dev/null +++ b/boost/bimap/views/multiset_view.hpp @@ -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 + +#include +#include +#include +#include + +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 + 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 index 0000000..8a857af --- /dev/null +++ b/boost/bimap/views/set_view.hpp @@ -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 + +#include +#include + +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 + 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 index 0000000..da9b4b4 --- /dev/null +++ b/boost/bimap/views/unconstrained_map_view.hpp @@ -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 + +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 index 0000000..6b4a6e2 --- /dev/null +++ b/boost/bimap/views/unconstrained_set_view.hpp @@ -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 + +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 index 0000000..14813e2 --- /dev/null +++ b/boost/bimap/views/unordered_map_view.hpp @@ -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 + +#include + +#include +#include + +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 >, + public ::boost::bimaps::detail:: + unique_map_view_access< + unordered_map_view, 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 + + >::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 > +{ + private: typedef ::boost::bimaps::views::unordered_map_view 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 > +{ + private: typedef ::boost::bimaps::views::unordered_map_view 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 index 0000000..db22205 --- /dev/null +++ b/boost/bimap/views/unordered_multimap_view.hpp @@ -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 + +#include + +#include +#include +#include +#include + +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 > + +{ + 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 > +{ + private: typedef ::boost::bimaps::views::unordered_multimap_view 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 > +{ + private: typedef ::boost::bimaps::views::unordered_multimap_view 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 index 0000000..3a72e36 --- /dev/null +++ b/boost/bimap/views/unordered_multiset_view.hpp @@ -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 + +#include +#include +#include + +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 index 0000000..02187ae --- /dev/null +++ b/boost/bimap/views/unordered_set_view.hpp @@ -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 + +#include +#include + +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 index 0000000..1837c27 --- /dev/null +++ b/boost/bimap/views/vector_map_view.hpp @@ -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 + +#include +#include +#include +#include + +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 > +{ + 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_::base_type::value_type, + key_from_base_value + + >(std::equal_to(), + 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_::base_type::value_type, + key_from_base_value + + >( std::less(), + 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_::base_type::value_type, + key_from_base_value + + >( std::less(), + 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 > +{ + private: typedef ::boost::bimaps::views::vector_map_view 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 > +{ + private: typedef ::boost::bimaps::views::vector_map_view 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 index 0000000..f58c0e4 --- /dev/null +++ b/boost/bimap/views/vector_set_view.hpp @@ -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 + +#include +#include +#include + + +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 + 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_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( + std::equal_to(), + 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_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( + std::less(), + 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_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( + std::less(), + 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 index 0000000..12e0605 --- /dev/null +++ b/boost/multi_index/composite_key.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) +#include +#endif + +#if !defined(BOOST_NO_SFINAE) +#include +#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 + * 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)::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 reference_wrapper; /* fwd decl. */ + +namespace multi_index{ + +namespace detail{ + +/* n-th key extractor of a composite key */ + +template +struct nth_key_from_value +{ + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename prevent_eti< + tuples::element, + typename mpl::eval_if_c< + N::value, + tuples::element, + mpl::identity + >::type + >::type type; +}; + +/* nth_composite_key_##name::type yields + * functor >, 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 \ +struct BOOST_PP_CAT(key_,name) \ +{ \ + typedef functor type; \ +}; \ + \ +template<> \ +struct BOOST_PP_CAT(key_,name) \ +{ \ + typedef tuples::null_type type; \ +}; \ + \ +template \ +struct BOOST_PP_CAT(nth_composite_key_,name) \ +{ \ + typedef typename nth_key_from_value::type key_from_value; \ + typedef typename BOOST_PP_CAT(key_,name)::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 + 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 + bool operator()(const T& x,const Q& y)const{return x 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, + is_same + >, + equal_ckey_ckey_terminal, + equal_ckey_ckey_normal + >::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, + is_same + >, + equal_ckey_cval_terminal, + equal_ckey_cval_normal + >::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, + is_same + >, + compare_ckey_ckey_terminal, + compare_ckey_ckey_normal + >::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, + is_same + >, + compare_ckey_cval_terminal, + compare_ckey_cval_normal + >::type +{ +}; + +template +struct hash_ckey; /* fwd decl. */ + +template +struct hash_ckey_terminal +{ + static std::size_t hash( + const KeyCons&,const Value&,const HashCons&,std::size_t carry) + { + return carry; + } +}; + +template +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 +struct hash_ckey: + mpl::if_< + is_same, + hash_ckey_terminal, + hash_ckey_normal + >::type +{ +}; + +template +struct hash_cval; /* fwd decl. */ + +template +struct hash_cval_terminal +{ + static std::size_t hash(const ValCons&,const HashCons&,std::size_t carry) + { + return carry; + } +}; + +template +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 +struct hash_cval: + mpl::if_< + is_same, + hash_cval_terminal, + hash_cval_normal + >::type +{ +}; + +} /* namespace multi_index::detail */ + +/* composite_key_result */ + +template +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 +{ +private: + typedef tuple super; + +public: + typedef super key_extractor_tuple; + typedef Value value_type; + typedef composite_key_result 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 + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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& x)const + { + return result_type(*this,x.get()); + } + + result_type operator()(const reference_wrapper& x,int=0)const + { + return result_type(*this,x.get()); + } +}; + +/* comparison operators */ + +/* == */ + +template +inline bool operator==( + const composite_key_result& x, + const composite_key_result& 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::value== + tuples::length::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& x, + const tuple& y) +{ + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename CompositeKey::value_type value_type; + typedef tuple key_tuple; + + BOOST_STATIC_ASSERT( + tuples::length::value== + tuples::length::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& x, + const composite_key_result& y) +{ + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename CompositeKey::value_type value_type; + typedef tuple key_tuple; + + BOOST_STATIC_ASSERT( + tuples::length::value== + tuples::length::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 +inline bool operator<( + const composite_key_result& x, + const composite_key_result& 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& x, + const tuple& y) +{ + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename CompositeKey::value_type value_type; + typedef tuple 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& x, + const composite_key_result& y) +{ + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename CompositeKey::value_type value_type; + typedef tuple 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 inline bool operator!=(const a1& x,const a2& y) \ +{ \ + return !(x==y); \ +} \ + \ +template inline bool operator>(const a1& x,const a2& y) \ +{ \ + return y inline bool operator>=(const a1& x,const a2& y) \ +{ \ + return !(x inline bool operator<=(const a1& x,const a2& y) \ +{ \ + return !(y, + composite_key_result +) + +BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS( + typename CompositeKey, + BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value), + composite_key_result, + tuple +) + +BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS( + BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value), + typename CompositeKey, + tuple, + composite_key_result +) + +/* composite_key_equal_to */ + +template +< + BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Pred) +> +struct composite_key_equal_to: + private tuple +{ +private: + typedef tuple 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 + bool operator()( + const composite_key_result & x, + const composite_key_result & 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::value<= + tuples::length::value&& + tuples::length::value== + tuples::length::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& x, + const tuple& y)const + { + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename CompositeKey::value_type value_type; + typedef tuple key_tuple; + + BOOST_STATIC_ASSERT( + tuples::length::value<= + tuples::length::value&& + tuples::length::value== + tuples::length::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& x, + const composite_key_result& y)const + { + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename CompositeKey::value_type value_type; + typedef tuple key_tuple; + + BOOST_STATIC_ASSERT( + tuples::length::value<= + tuples::length::value&& + tuples::length::value== + tuples::length::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 +{ +private: + typedef tuple 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 + bool operator()( + const composite_key_result & x, + const composite_key_result & 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::value<= + tuples::length::value|| + tuples::length::value<= + tuples::length::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 + bool operator()( + const composite_key_result& 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& x, + const tuple& y)const + { + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename CompositeKey::value_type value_type; + typedef tuple key_tuple; + + BOOST_STATIC_ASSERT( + tuples::length::value<= + tuples::length::value|| + tuples::length::value<= + tuples::length::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 + bool operator()( + const Value& x, + const composite_key_result& 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& x, + const composite_key_result& y)const + { + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename CompositeKey::value_type value_type; + typedef tuple key_tuple; + + BOOST_STATIC_ASSERT( + tuples::length::value<= + tuples::length::value|| + tuples::length::value<= + tuples::length::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 +{ +private: + typedef tuple 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 + std::size_t operator()(const composite_key_result & x)const + { + typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple; + typedef typename CompositeKey::value_type value_type; + + BOOST_STATIC_ASSERT( + tuples::length::value== + tuples::length::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 + std::size_t operator()( + const tuple& x)const + { + typedef tuple key_tuple; + + BOOST_STATIC_ASSERT( + tuples::length::value== + tuples::length::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 +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 +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 +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 +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 +struct equal_to >: + boost::multi_index::composite_key_result_equal_to< + boost::multi_index::composite_key_result + > +{ +}; + +template +struct less >: + boost::multi_index::composite_key_result_less< + boost::multi_index::composite_key_result + > +{ +}; + +template +struct greater >: + boost::multi_index::composite_key_result_greater< + boost::multi_index::composite_key_result + > +{ +}; + +} /* namespace std */ + +namespace boost{ + +template +struct hash >: + boost::multi_index::composite_key_result_hash< + boost::multi_index::composite_key_result + > +{ +}; + +} /* 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 +inline std::size_t hash_value( + const boost::multi_index::composite_key_result& x) +{ + boost::multi_index::composite_key_result_hash< + boost::multi_index::composite_key_result > 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 index 0000000..5b44d25 --- /dev/null +++ b/boost/multi_index/detail/access_specifier.hpp @@ -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 +#include + +/* 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 index 0000000..0771b4b --- /dev/null +++ b/boost/multi_index/detail/adl_swap.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +template +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 index 0000000..3ae6fca --- /dev/null +++ b/boost/multi_index/detail/archive_constructed.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* constructs a stack-based object from a serialization archive */ + +template +struct archive_constructed:private noncopyable +{ + template + 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 + 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(static_cast(&space));} + +private: + typename aligned_storage::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 index 0000000..4515caf --- /dev/null +++ b/boost/multi_index/detail/auto_space.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include + +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 > +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 +void swap(auto_space& x,auto_space& 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 index 0000000..fd6e364 --- /dev/null +++ b/boost/multi_index/detail/base_type.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include + +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 + struct apply: + msvc_index_specifier:: + template result_index_class + { + }; +}; +#else +struct index_applier +{ + template + struct apply + { + typedef typename IndexSpecifierMeta::type index_specifier; + typedef typename index_specifier:: + BOOST_NESTED_TEMPLATE index_class::type type; + }; +}; +#endif + +template +struct nth_layer +{ + BOOST_STATIC_CONSTANT(int,length=mpl::size::value); + + typedef typename mpl::eval_if_c< + N==length, + mpl::identity >, + mpl::apply2< + index_applier, + mpl::at_c, + nth_layer + > + >::type type; +}; + +template +struct multi_index_base_type:nth_layer<0,Value,IndexSpecifierList,Allocator> +{ + BOOST_STATIC_ASSERT(detail::is_index_list::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 index 0000000..0ce1cee --- /dev/null +++ b/boost/multi_index/detail/bidir_node_iterator.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#include +#endif + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* Iterator class for node-based indices with bidirectional + * iterators (ordered and sequenced indices.) + */ + +template +class bidir_node_iterator: + public bidirectional_iterator_helper< + bidir_node_iterator, + 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 + void save(Archive& ar,const unsigned int)const + { + node_base_type* bnode=node; + ar< + void load(Archive& ar,const unsigned int) + { + node_base_type* bnode; + ar>>serialization::make_nvp("pointer",bnode); + node=static_cast(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 +bool operator==( + const bidir_node_iterator& x, + const bidir_node_iterator& 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 index 0000000..1b0ffe7 --- /dev/null +++ b/boost/multi_index/detail/bucket_array.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#include +#include +#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 +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 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 + void serialize(Archive&,const unsigned int) + { + } +#endif +}; + +template +void swap(bucket_array& x,bucket_array& 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 +inline void load_construct_data( + Archive&,boost::multi_index::detail::bucket_array*, + 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 index 0000000..f4fb47b --- /dev/null +++ b/boost/multi_index/detail/converter.hpp @@ -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 +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 index 0000000..21ff51e --- /dev/null +++ b/boost/multi_index/detail/copy_map.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include + +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 +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& x)const + { + return std::less()(first,x.first); + } +}; + +template +class copy_map:private noncopyable +{ +public: + typedef const copy_map_entry* 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;isecond->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,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,Allocator> spc; + std::size_t n; + Node* header_org_; + Node* header_cpy_; + bool released; + + void deallocate(Node* node) + { + al_.deallocate(static_cast(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 index 0000000..7cc126c --- /dev/null +++ b/boost/multi_index/detail/duplicates_iterator.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include + +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 +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 +bool operator==( + const duplicates_iterator& x, + const duplicates_iterator& y) +{ + return x.get_node()==y.get_node(); +} + +template +bool operator!=( + const duplicates_iterator& x, + const duplicates_iterator& 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 index 0000000..1037978 --- /dev/null +++ b/boost/multi_index/detail/has_tag.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* determines whether an index type has a given tag in its tag list */ + +template +struct has_tag +{ + template + struct apply:mpl::contains + { + }; +}; + +} /* 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 index 0000000..6211c8b --- /dev/null +++ b/boost/multi_index/detail/hash_index_args.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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, + * Pred=std::equal_to > + * (hashed_unique|hashed_non_unique)< + * TagList, + * KeyFromValue, + * Hash=boost::hash, + * Pred=std::equal_to > + * + * hashed_index_args implements the machinery to accept this + * argument-dependent polymorphism. + */ + +template +struct index_args_default_hash +{ + typedef ::boost::hash type; +}; + +template +struct index_args_default_pred +{ + typedef std::equal_to type; +}; + +template +struct hashed_index_args +{ + typedef is_tag 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, + index_args_default_hash, + mpl::identity + >::type hash_type; + typedef typename mpl::if_< + full_form, + Arg4, + Arg3>::type supplied_pred_type; + typedef typename mpl::eval_if< + mpl::is_na, + index_args_default_pred, + mpl::identity + >::type pred_type; + + BOOST_STATIC_ASSERT(is_tag::value); + BOOST_STATIC_ASSERT(!mpl::is_na::value); + BOOST_STATIC_ASSERT(!mpl::is_na::value); + BOOST_STATIC_ASSERT(!mpl::is_na::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 index 0000000..1d62543 --- /dev/null +++ b/boost/multi_index/detail/hash_index_iterator.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#include +#endif + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* Iterator class for hashed indices. + */ + +template +class hashed_index_iterator: + public forward_iterator_helper< + hashed_index_iterator, + 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 + void save(Archive& ar,const unsigned int)const + { + node_base_type* bnode=node; + ar< + void load(Archive& ar,const unsigned int) + { + node_base_type* bnode; + ar>>serialization::make_nvp("pointer",bnode); + node=static_cast(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 +bool operator==( + const hashed_index_iterator& x, + const hashed_index_iterator& 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 index 0000000..93774c0 --- /dev/null +++ b/boost/multi_index/detail/hash_index_node.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* singly-linked node for use by hashed_index */ + +template +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 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 +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 +struct hashed_index_node:Super,hashed_index_node_trampoline +{ +private: + typedef hashed_index_node_trampoline 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( + static_cast(static_cast(this))); + } + + const_impl_pointer impl()const + { + return static_cast( + static_cast(static_cast(this))); + } + + static hashed_index_node* from_impl(impl_pointer x) + { + return static_cast( + static_cast(&*x)); + } + + static const hashed_index_node* from_impl(const_impl_pointer x) + { + return static_cast( + static_cast(&*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 index 0000000..8bd1e5d --- /dev/null +++ b/boost/multi_index/detail/header_holder.hpp @@ -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 + +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 +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(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 index 0000000..6391968 --- /dev/null +++ b/boost/multi_index/detail/index_base.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#include +#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 +class index_base +{ +protected: + typedef index_node_base 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::param_type value_param_type; + +protected: + explicit index_base(const ctor_args_list&,const Allocator&){} + + void copy_( + const index_base&,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&){} + + 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 + void save_(Archive&,const unsigned int,const index_saver_type&)const{} + + template + 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(this);} + const final_type& final()const{return *static_cast(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_insert_(value_param_type x) + {return final().insert_(x);} + std::pair 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 + bool final_modify_(Modifier& mod,final_node_type* x) + {return final().modify_(mod,x);} + + template + 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 index 0000000..61fb2b0 --- /dev/null +++ b/boost/multi_index/detail/index_loader.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include + +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 +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 + void add(Node* node,Archive& ar,const unsigned int) + { + ar>>serialization::make_nvp("position",*node); + entries()[n++]=node; + } + + template + 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 + 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 + FinalNode* unchecked_load_node(Archive& ar)const + { + Node* node=0; + ar>>serialization::make_nvp("pointer",node); + return static_cast(node); + } + + template + FinalNode* load_node(Archive& ar)const + { + Node* node=0; + ar>>serialization::make_nvp("pointer",node); + check_node(node); + return static_cast(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 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 index 0000000..23060b3 --- /dev/null +++ b/boost/multi_index/detail/index_matcher.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include + +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()(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 +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 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 +class algorithm:private algorithm_base +{ + typedef algorithm_base super; + +public: + algorithm(const Allocator& al,std::size_t size):super(al,size){} + + void add(Node* node) + { + super::add(node); + } + + template + 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 + static Node* get_node(IndexIterator it) + { + return static_cast(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 index 0000000..42b45d1 --- /dev/null +++ b/boost/multi_index/detail/index_node_base.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#include +#include +#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 +struct pod_value_holder +{ + typename aligned_storage< + sizeof(Value), + alignment_of::value + >::type space; +}; + +template +struct index_node_base:private pod_value_holder +{ + typedef index_node_base base_type; /* used for serialization purposes */ + typedef Value value_type; + typedef Allocator allocator_type; + + value_type& value() + { + return *static_cast( + static_cast(&this->space)); + } + + const value_type& value()const + { + return *static_cast( + static_cast(&this->space)); + } + + static index_node_base* from_value(const value_type* p) + { + return static_cast( + reinterpret_cast*>( /* std 9.2.17 */ + const_cast(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 + void serialize(Archive&,const unsigned int) + { + } +#endif +}; + +template +Node* node_from_value( + const Value* p + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node)) +{ + typedef typename Node::allocator_type allocator_type; + return static_cast( + index_node_base::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 +inline void load_construct_data( + Archive&,boost::multi_index::detail::index_node_base*, + 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 index 0000000..470e2b7 --- /dev/null +++ b/boost/multi_index/detail/index_saver.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include + +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 +class index_saver:private noncopyable +{ +public: + index_saver(const Allocator& al,std::size_t size):alg(al,size){} + + template + void add(Node* node,Archive& ar,const unsigned int) + { + ar< + void add_track(Node* node,Archive& ar,const unsigned int) + { + ar< + 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 + static Node* get_node(IndexIterator it) + { + return it.get_node(); + } + + static Node* null_node(){return 0;} + + template + static void save_node(Node* node,Archive& ar) + { + ar< 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 index 0000000..5f08dce --- /dev/null +++ b/boost/multi_index/detail/invariant_assert.hpp @@ -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 +#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 index 0000000..fd801da --- /dev/null +++ b/boost/multi_index/detail/is_index_list.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +template +struct is_index_list +{ + BOOST_STATIC_CONSTANT(bool,mpl_sequence=mpl::is_sequence::value); + BOOST_STATIC_CONSTANT(bool,non_empty=!mpl::empty::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 index 0000000..521cfff --- /dev/null +++ b/boost/multi_index/detail/iter_adaptor.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include + +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 + static typename Class::reference dereference(const Class& x) + { + return x.dereference(); + } + + template + static bool equal(const Class& x,const Class& y) + { + return x.equal(y); + } + + template + static void increment(Class& x) + { + x.increment(); + } + + template + static void decrement(Class& x) + { + x.decrement(); + } + + template + static void advance(Class& x,typename Class::difference_type n) + { + x.advance(n); + } + + template + static typename Class::difference_type distance_to( + const Class& x,const Class& y) + { + return x.distance_to(y); + } +}; + +template +struct iter_adaptor_selector; + +template +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(this);} + const Derived& final()const{return *static_cast(this);} +}; + +template +bool operator==( + const forward_iter_adaptor_base& x, + const forward_iter_adaptor_base& y) +{ + return iter_adaptor_access::equal( + static_cast(x),static_cast(y)); +} + +template<> +struct iter_adaptor_selector +{ + template + struct apply + { + typedef forward_iter_adaptor_base type; + }; +}; + +template +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(this);} + const Derived& final()const{return *static_cast(this);} +}; + +template +bool operator==( + const bidirectional_iter_adaptor_base& x, + const bidirectional_iter_adaptor_base& y) +{ + return iter_adaptor_access::equal( + static_cast(x),static_cast(y)); +} + +template<> +struct iter_adaptor_selector +{ + template + struct apply + { + typedef bidirectional_iter_adaptor_base type; + }; +}; + +template +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(this);} + const Derived& final()const{return *static_cast(this);} +}; + +template +bool operator==( + const random_access_iter_adaptor_base& x, + const random_access_iter_adaptor_base& y) +{ + return iter_adaptor_access::equal( + static_cast(x),static_cast(y)); +} + +template +bool operator<( + const random_access_iter_adaptor_base& x, + const random_access_iter_adaptor_base& y) +{ + return iter_adaptor_access::distance_to( + static_cast(x),static_cast(y))>0; +} + +template +typename random_access_iter_adaptor_base::difference_type +operator-( + const random_access_iter_adaptor_base& x, + const random_access_iter_adaptor_base& y) +{ + return iter_adaptor_access::distance_to( + static_cast(y),static_cast(x)); +} + +template<> +struct iter_adaptor_selector +{ + template + struct apply + { + typedef random_access_iter_adaptor_base type; + }; +}; + +template +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 iter_adaptor:public iter_adaptor_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 index 0000000..7335a51 --- /dev/null +++ b/boost/multi_index/detail/modify_key_adaptor.hpp @@ -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 +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 index 0000000..694e866 --- /dev/null +++ b/boost/multi_index/detail/msvc_index_specifier.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +#if BOOST_WORKAROUND(BOOST_MSVC,<1310) +/* Workaround for a problem in MSVC with dependent template typedefs + * when accesing index specifiers. + * Modeled after (thanks, Aleksey!) + */ + +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +template +struct msvc_index_specifier +{ + template struct fake_index_type:IndexSpecifier{}; + template<> struct fake_index_type + { + template + struct node_class{}; + + template + struct index_class{}; + }; + + template + struct result_node_class: + fake_index_type::value>:: + template node_class + { + }; + + template + struct result_index_class: + fake_index_type::value>:: + template index_class + { + }; +}; + +} /* 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 index 0000000..dbca6af --- /dev/null +++ b/boost/multi_index/detail/no_duplicate_tags.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include + +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 + struct apply + { + typedef mpl::s_item< + typename mpl::if_,duplicate_tag_mark,Tag>::type, + MplSet + > type; + }; +}; + +template +struct no_duplicate_tags +{ + typedef typename mpl::fold< + TagList, + mpl::set0<>, + duplicate_tag_marker + >::type aux; + + BOOST_STATIC_CONSTANT( + bool,value=!(mpl::has_key::value)); +}; + +/* Variant for an index list: duplication is checked + * across all the indices. + */ + +struct duplicate_tag_list_marker +{ + template + struct apply:mpl::fold< + BOOST_DEDUCED_TYPENAME Index::tag_list, + MplSet, + duplicate_tag_marker> + { + }; +}; + +template +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::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 index 0000000..5e2ffa9 --- /dev/null +++ b/boost/multi_index/detail/node_type.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 + struct apply: + msvc_index_specifier< mpl::deref::type >:: + template result_node_class + { + }; +}; +#else +struct index_node_applier +{ + template + struct apply + { + typedef typename mpl::deref::type index_specifier; + typedef typename index_specifier:: + BOOST_NESTED_TEMPLATE node_class::type type; + }; +}; +#endif + +template +struct multi_index_node_type +{ + BOOST_STATIC_ASSERT(detail::is_index_list::value); + + typedef typename mpl::reverse_iter_fold< + IndexSpecifierList, + index_node_base, + mpl::bind2 + >::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 index 0000000..86d5967 --- /dev/null +++ b/boost/multi_index/detail/ord_index_args.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include + +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 > + * (ordered_unique|ordered_non_unique)< + * TagList,KeyFromValue,Compare=std::less > + * + * index_args implements the machinery to accept this argument-dependent + * polymorphism. + */ + +template +struct index_args_default_compare +{ + typedef std::less type; +}; + +template +struct ordered_index_args +{ + typedef is_tag 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, + index_args_default_compare, + mpl::identity + >::type compare_type; + + BOOST_STATIC_ASSERT(is_tag::value); + BOOST_STATIC_ASSERT(!mpl::is_na::value); + BOOST_STATIC_ASSERT(!mpl::is_na::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 index 0000000..b4193d2 --- /dev/null +++ b/boost/multi_index/detail/ord_index_node.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES) +#include +#include +#include +#include +#include +#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 +struct ordered_index_node_impl; /* fwd decl. */ + +template +struct ordered_index_node_std_base +{ + typedef typename prevent_eti< + Allocator, + typename boost::detail::allocator::rebind_to< + Allocator, + ordered_index_node_impl + >::type + >::type::pointer pointer; + typedef typename prevent_eti< + Allocator, + typename boost::detail::allocator::rebind_to< + Allocator, + ordered_index_node_impl + >::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 +struct ordered_index_node_compressed_base +{ + typedef ordered_index_node_impl* pointer; + typedef const ordered_index_node_impl* 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 +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 >::value%2)|| + !(is_same< + typename prevent_eti< + Allocator, + typename boost::detail::allocator::rebind_to< + Allocator, + ordered_index_node_impl + >::type + >::type::pointer, + ordered_index_node_impl*>::value), + ordered_index_node_std_base, + ordered_index_node_compressed_base + >::type +#else + ordered_index_node_std_base +#endif + +{}; + +template +struct ordered_index_node_impl:ordered_index_node_impl_base +{ +private: + typedef ordered_index_node_impl_base 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 +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 +struct ordered_index_node:Super,ordered_index_node_trampoline +{ +private: + typedef ordered_index_node_trampoline 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( + static_cast(static_cast(this))); + } + + const_impl_pointer impl()const + { + return static_cast( + static_cast(static_cast(this))); + } + + static ordered_index_node* from_impl(impl_pointer x) + { + return static_cast( + static_cast(&*x)); + } + + static const ordered_index_node* from_impl(const_impl_pointer x) + { + return static_cast( + static_cast(&*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 index 0000000..52a7476 --- /dev/null +++ b/boost/multi_index/detail/ord_index_ops.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +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 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( + 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(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 index 0000000..39edf60 --- /dev/null +++ b/boost/multi_index/detail/prevent_eti.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +#if BOOST_WORKAROUND(BOOST_MSVC,<1300) +#include +#include +#include +#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 +struct prevent_eti +{ + typedef typename mpl::if_< + mpl::aux::msvc_never_true, + mpl::integral_c, + Construct + >::type type; +}; +#else +template +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 index 0000000..69ec8b7 --- /dev/null +++ b/boost/multi_index/detail/rnd_index_loader.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include + +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 +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 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 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 prev_spc; + bool preprocessed; +}; + +template +class random_access_index_loader: + private random_access_index_loader_base +{ + typedef random_access_index_loader_base 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 index 0000000..45b1e79 --- /dev/null +++ b/boost/multi_index/detail/rnd_index_node.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +template +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(xup()=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(posup()=begin+j; + break; + } + else{ + *(begin+j)=*(begin+k); + (*(begin+j))->up()=begin+j; + } + + if(kup()=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;iup()=pbegin; + (*pend)->up()=pend; + ++pbegin; + } + } + +private: + ptr_pointer up_; +}; + +template +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 +struct random_access_index_node: + Super,random_access_index_node_trampoline +{ +private: + typedef random_access_index_node_trampoline 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( + static_cast(static_cast(this))); + } + + const_impl_pointer impl()const + { + return static_cast( + static_cast(static_cast(this))); + } + + static random_access_index_node* from_impl(impl_pointer x) + { + return static_cast( + static_cast(&*x)); + } + + static const random_access_index_node* from_impl(const_impl_pointer x) + { + return static_cast( + static_cast(&*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 index 0000000..93c6385 --- /dev/null +++ b/boost/multi_index/detail/rnd_index_ops.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* Common code for random_access_index memfuns having templatized and + * non-templatized versions. + */ + +template +Node* random_access_index_remove( + random_access_index_ptr_array& 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(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 +Node* random_access_index_unique( + random_access_index_ptr_array& 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(Node::from_impl(*res)->value()), + const_cast(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 +void random_access_index_inplace_merge( + const Allocator& al, + random_access_index_ptr_array& 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 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(Node::from_impl(*first1)->value()), + const_cast(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 +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(Node::from_impl(x)->value()), + const_cast(Node::from_impl(y)->value())); + } + +private: + Compare comp; +}; + +template +void random_access_index_sort( + const Allocator& al, + random_access_index_ptr_array& 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 index 0000000..6bb47d5 --- /dev/null +++ b/boost/multi_index/detail/rnd_index_ptr_array.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* pointer structure for use by random access indices */ + +template +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 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 spc; + + pointer ptrs()const + { + return spc.data(); + } +}; + +template +void swap( + random_access_index_ptr_array& x, + random_access_index_ptr_array& 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 index 0000000..a41a0ff --- /dev/null +++ b/boost/multi_index/detail/rnd_node_iterator.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#include +#endif + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* Iterator class for node-based indices with random access iterators. */ + +template +class rnd_node_iterator: + public random_access_iterator_helper< + rnd_node_iterator, + 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 + void save(Archive& ar,const unsigned int)const + { + node_base_type* bnode=node; + ar< + void load(Archive& ar,const unsigned int) + { + node_base_type* bnode; + ar>>serialization::make_nvp("pointer",bnode); + node=static_cast(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 +bool operator==( + const rnd_node_iterator& x, + const rnd_node_iterator& y) +{ + return x.get_node()==y.get_node(); +} + +template +bool operator<( + const rnd_node_iterator& x, + const rnd_node_iterator& y) +{ + return Node::distance(x.get_node(),y.get_node())>0; +} + +template +std::ptrdiff_t operator-( + const rnd_node_iterator& x, + const rnd_node_iterator& 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 index 0000000..2f6f11a --- /dev/null +++ b/boost/multi_index/detail/safe_ctr_proxy.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +#if BOOST_WORKAROUND(BOOST_MSVC,<1300) +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* A safe iterator is instantiated in the form + * safe_iterator: 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 the following base class + * must be used: + * + * safe_ctr_proxy_impl + * + * where Iterator is the type of the *unsafe* iterator being wrapped. + * The corresponding safe iterator instantiation is then + * + * safe_iterator >, + * + * which does not include the name of Container. + */ + +template +class safe_ctr_proxy: + public safe_mode::safe_container > +{ +public: + typedef safe_mode::safe_iterator 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 +class safe_ctr_proxy_impl:public safe_ctr_proxy +{ + typedef safe_ctr_proxy 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(this); + } + + const container_type& container()const + { + return *static_cast(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 index 0000000..41885d0 --- /dev/null +++ b/boost/multi_index/detail/safe_mode.hpp @@ -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, 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 +#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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#endif + +#if defined(BOOST_HAS_THREADS) +#include +#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 +inline bool check_valid_iterator(const Iterator& it) +{ + return it.valid()||it.unchecked(); +} + +template +inline bool check_dereferenceable_iterator(const Iterator& it) +{ + return it.valid()&&it!=it.owner()->end()||it.unchecked(); +} + +template +inline bool check_incrementable_iterator(const Iterator& it) +{ + return it.valid()&&it!=it.owner()->end()||it.unchecked(); +} + +template +inline bool check_decrementable_iterator(const Iterator& it) +{ + return it.valid()&&it!=it.owner()->begin()||it.unchecked(); +} + +template +inline bool check_is_owner( + const Iterator& it,const typename Iterator::container_type& cont) +{ + return it.valid()&&it.owner()==&cont||it.unchecked(); +} + +template +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 +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 +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 +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 +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 +inline void detach_equivalent_iterators(Iterator& it) +{ + if(it.valid()){ + Iterator *prev_,*next_; + for( + prev_=static_cast(&it.cont->header); + (next_=static_cast(prev_->next))!=0;){ + if(next_!=&it&&*next_==it){ + prev_->next=next_->next; + next_->cont=0; + } + else prev_=next_; + } + it.detach(); + } +} + +template 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 friend class safe_mode::safe_container; + template 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 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, + * - iterators must be generated via safe_iterator, which adapts a + * preexistent unsafe iterator class. + */ + +template +class safe_container; + +template +class safe_iterator: + public detail::iter_adaptor,Iterator>, + public detail::safe_iterator_base +{ + typedef detail::iter_adaptor 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* cont_): + safe_super(cont_){} + template + safe_iterator(const T0& t0,safe_container* cont_): + super(Iterator(t0)),safe_super(cont_){} + template + safe_iterator( + const T0& t0,const T1& t1,safe_container* 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( + static_cast*>( + 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(); + * 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 + void save(Archive& ar,const unsigned int version)const + { + BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this); + this->base_reference().save(ar,version); + } + + template + void load(Archive& ar,const unsigned int version) + { + this->base_reference().load(ar,version); + safe_super::uncheck(); + } +#endif +}; + +template +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(this)->end(); + iterator *prev_,*next_; + for( + prev_=static_cast(&this->header); + (next_=static_cast(prev_->next))!=0;){ + if(*next_!=end_){ + prev_->next=next_->next; + next_->cont=0; + } + else prev_=next_; + } + } + + void swap(safe_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 index 0000000..5288c80 --- /dev/null +++ b/boost/multi_index/detail/scope_guard.hpp @@ -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: 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 + 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 +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 +inline scope_guard_impl0 make_guard(F fun) +{ + return scope_guard_impl0(fun); +} + +template +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 +inline scope_guard_impl1 make_guard(F fun,P1 p1) +{ + return scope_guard_impl1(fun,p1); +} + +template +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 +inline scope_guard_impl2 make_guard(F fun,P1 p1,P2 p2) +{ + return scope_guard_impl2(fun,p1,p2); +} + +template +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 +inline scope_guard_impl3 make_guard(F fun,P1 p1,P2 p2,P3 p3) +{ + return scope_guard_impl3(fun,p1,p2,p3); +} + +template +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 +inline scope_guard_impl4 make_guard( + F fun,P1 p1,P2 p2,P3 p3,P4 p4) +{ + return scope_guard_impl4(fun,p1,p2,p3,p4); +} + +template +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 +inline obj_scope_guard_impl0 make_obj_guard(Obj& obj,MemFun mem_fun) +{ + return obj_scope_guard_impl0(obj,mem_fun); +} + +template +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 +inline obj_scope_guard_impl1 make_obj_guard( + Obj& obj,MemFun mem_fun,P1 p1) +{ + return obj_scope_guard_impl1(obj,mem_fun,p1); +} + +template +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 +inline obj_scope_guard_impl2 +make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2) +{ + return obj_scope_guard_impl2(obj,mem_fun,p1,p2); +} + +template +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 +inline obj_scope_guard_impl3 +make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3) +{ + return obj_scope_guard_impl3(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 index 0000000..36803af --- /dev/null +++ b/boost/multi_index/detail/seq_index_node.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* doubly-linked node for use by sequenced_index */ + +template +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 +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 +struct sequenced_index_node:Super,sequenced_index_node_trampoline +{ +private: + typedef sequenced_index_node_trampoline 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( + static_cast(static_cast(this))); + } + + const_impl_pointer impl()const + { + return static_cast( + static_cast(static_cast(this))); + } + + static sequenced_index_node* from_impl(impl_pointer x) + { + return static_cast( + static_cast(&*x)); + } + + static const sequenced_index_node* from_impl(const_impl_pointer x) + { + return static_cast( + static_cast(&*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 index 0000000..2c0f213 --- /dev/null +++ b/boost/multi_index/detail/seq_index_ops.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +/* Common code for sequenced_index memfuns having templatized and + * non-templatized versions. + */ + +template +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 +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 +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 +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::digits+1); + +template +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::value + >::type carry_spc_type; + carry_spc_type carry_spc; + impl_type& carry= + *static_cast(static_cast(&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(static_cast(&counter_spc)); + std::size_t fill=0; + + carry.prior()=carry.next()=static_cast(&carry); + counter[0].prior()=counter[0].next()=static_cast(&counter[0]); + + BOOST_TRY{ + while(header->next()!=header->impl()){ + impl_type::relink(carry.next(),header->next()); + std::size_t i=0; + while(i(&counter[i])){ + sequenced_index_collate(&carry,&counter[i++],comp); + } + impl_type::swap( + static_cast(&carry), + static_cast(&counter[i])); + if(i==fill){ + ++fill; + counter[fill].prior()=counter[fill].next()= + static_cast(&counter[fill]); + } + } + + for(std::size_t i=1;i(&counter[i],&counter[i-1],comp); + } + impl_type::swap( + header->impl(),static_cast(&counter[fill-1])); + } + BOOST_CATCH(...) + { + impl_type::relink( + header->impl(),carry.next(),static_cast(&carry)); + for(std::size_t i=0;i<=fill;++i){ + impl_type::relink( + header->impl(),counter[i].next(), + static_cast(&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 index 0000000..2c18180 --- /dev/null +++ b/boost/multi_index/detail/uintptr_type.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +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. + */ + +templatestruct 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::type type; +}; + +typedef mpl::bool_ 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 index 0000000..57b0215 --- /dev/null +++ b/boost/multi_index/detail/unbounded.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include + +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 index 0000000..f392f85 --- /dev/null +++ b/boost/multi_index/detail/value_compare.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +template +struct value_comparison:std::binary_function +{ + value_comparison( + const KeyFromValue& key_=KeyFromValue(),const Compare& comp_=Compare()): + key(key_),comp(comp_) + { + } + + bool operator()( + typename call_traits::param_type x, + typename call_traits::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 index 0000000..314d526 --- /dev/null +++ b/boost/multi_index/global_fun.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_SFINAE) +#include +#endif + +namespace boost{ + +template 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.) + */ + +/* 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 +struct const_ref_global_fun_base +{ + typedef typename remove_reference::type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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::type>& x)const + { + return operator()(x.get()); + } + + Type operator()( + const reference_wrapper< + typename remove_const< + typename remove_reference::type>::type>& x,int=0)const + { + return operator()(x.get()); + } +}; + +template +struct non_const_ref_global_fun_base +{ + typedef typename remove_reference::type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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::type>& x)const + { + return operator()(x.get()); + } +}; + +template +struct non_ref_global_fun_base +{ + typedef typename remove_reference::type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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& x)const + { + return operator()(x.get()); + } + + Type operator()( + const reference_wrapper< + typename remove_const::type>& x,int=0)const + { + return operator()(x.get()); + } +}; + +} /* namespace multi_index::detail */ + +template +struct global_fun: + mpl::if_c< + is_reference::value, + typename mpl::if_c< + is_const::type>::value, + detail::const_ref_global_fun_base, + detail::non_const_ref_global_fun_base + >::type, + detail::non_ref_global_fun_base + >::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 index 0000000..456797a --- /dev/null +++ b/boost/multi_index/hashed_index.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#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, + bucket_array >, + hashed_index > +#else + ,public safe_mode::safe_container< + hashed_index > +#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 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::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& operator=( + const hashed_index& 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(&x)); + } + + const_iterator iterator_to(const value_type& x)const + { + return make_iterator(node_from_value(&x)); + } + + /* modifiers */ + + std::pair insert(value_param_type x) + { + BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT; + std::pair p=this->final_insert_(x); + return std::pair(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 p=this->final_insert_( + x,static_cast(position.get_node())); + return make_iterator(p.first); + } + + template + 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(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(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(position.get_node())); + } + + template + 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(position.get_node())); + } + + template + 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(position.get_node())); + } + + template + 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(mod,key)); + } + + template + 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(mod,key), + modify_key_adaptor(back,key)); + } + + void clear() + { + BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT; + this->final_clear_(); + } + + void swap(hashed_index& 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 + 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 + 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 + std::pair equal_range(const CompatibleKey& k)const + { + return equal_range(k,hash,eq); + } + + template< + typename CompatibleKey,typename CompatibleHash,typename CompatiblePred + > + std::pair 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( + make_iterator(node_type::from_impl(y0)), + make_iterator(node_type::from_impl(y))); + } + y=y->next(); + } + return std::pair(end(),end()); + } + + /* bucket interface */ + + size_type bucket_count()const{return buckets.size();} + size_type max_bucket_count()const{return static_cast(-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(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(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(&x)); + } + + const_local_iterator local_iterator_to(const value_type& x)const + { + return make_iterator(node_from_value(&x)); + } + + /* hash policy */ + + float load_factor()const{return static_cast(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)(); + float fbc=static_cast(1+size()/mlf); + if(bc>fbc){ + bc=static_cast(fbc); + if(bc(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& 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(buckets), + const_cast(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(buckets)); + } +#endif + + void copy_( + const hashed_index& 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( + map.find( + static_cast( + 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(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(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(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& 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_bucketvalue()); + 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_bucketvalue()); + 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 + void save_( + Archive& ar,const unsigned int version,const index_saver_type& sm)const + { + ar< + 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;bucfinal_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(mlf*bucket_count()); + max_load=(std::numeric_limits::max)(); + if(max_load>fml)max_load=static_cast(fml); + } + + void reserve(size_type n) + { + if(n>max_load){ + size_type bc =(std::numeric_limits::max)(); + float fbc=static_cast(1+n/mlf); + if(bc>fbc)bc =static_cast(fbc); + unchecked_rehash(bc); + } + } + + void unchecked_rehash(size_type n) + { + bucket_array_type buckets1(get_allocator(),header()->impl(),n); + auto_space 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& x, + hashed_index& y) +{ + x.swap(y); +} + +} /* namespace multi_index::detail */ + +/* hashed index specifiers */ + +template +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 + struct node_class + { + typedef detail::hashed_index_node type; + }; + + template + 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 +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 + struct node_class + { + typedef detail::hashed_index_node type; + }; + + template + 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 index 0000000..f436f68 --- /dev/null +++ b/boost/multi_index/hashed_index_fwd.hpp @@ -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 + +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& x, + hashed_index& 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 index 0000000..b3c9568 --- /dev/null +++ b/boost/multi_index/identity.hpp @@ -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 +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_SFINAE) +#include +#endif + +namespace boost{ + +template 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.) + */ + +/* 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 +struct const_identity_base +{ + typedef Type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if,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& x)const + { + return x.get(); + } + + Type& operator()( + const reference_wrapper::type>& x,int=0)const + { + return x.get(); + } +}; + +template +struct non_const_identity_base +{ + typedef Type result_type; + + /* templatized for pointer-like types */ + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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& x,int=0)const + { + return x.get(); + } + + Type& operator()(const reference_wrapper& x)const + { + return x.get(); + } +}; + +} /* namespace multi_index::detail */ + +template +struct identity: + mpl::if_c< + is_const::value, + detail::const_identity_base,detail::non_const_identity_base + >::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 index 0000000..91ba276 --- /dev/null +++ b/boost/multi_index/identity_fwd.hpp @@ -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 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 index 0000000..acac93a --- /dev/null +++ b/boost/multi_index/indexed_by.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include + +/* 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 +struct indexed_by: + mpl::vector +{ +}; + +} /* 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 index 0000000..0acb1aa --- /dev/null +++ b/boost/multi_index/key_extractors.hpp @@ -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 +#include +#include +#include +#include + +#endif diff --git a/boost/multi_index/mem_fun.hpp b/boost/multi_index/mem_fun.hpp new file mode 100644 index 0000000..f9257ec --- /dev/null +++ b/boost/multi_index/mem_fun.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include + +#if !defined(BOOST_NO_SFINAE) +#include +#endif + +namespace boost{ + +template 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.) + */ + +template +struct const_mem_fun +{ + typedef typename remove_reference::type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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& x)const + { + return operator()(x.get()); + } + + Type operator()(const reference_wrapper& x)const + { + return operator()(x.get()); + } +}; + +template +struct mem_fun +{ + typedef typename remove_reference::type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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& 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 result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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& x)const + { + return operator()(x.get()); + } + + Type operator()(const reference_wrapper& x)const + { + return operator()(x.get()); + } +}; + +template< + class Class,typename Type, + typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction> +struct mem_fun_explicit +{ + typedef typename remove_reference::type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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& 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 index 0000000..0aff2dc --- /dev/null +++ b/boost/multi_index/member.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include + +#if !defined(BOOST_NO_SFINAE) +#include +#endif + +namespace boost{ + +template 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.) + */ + +/* 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 +struct const_member_base +{ + typedef Type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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& x)const + { + return operator()(x.get()); + } + + Type& operator()(const reference_wrapper& x,int=0)const + { + return operator()(x.get()); + } +}; + +template +struct non_const_member_base +{ + typedef Type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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& x,int=0)const + { + return operator()(x.get()); + } + + Type& operator()(const reference_wrapper& x)const + { + return operator()(x.get()); + } +}; + +} /* namespace multi_index::detail */ + +template +struct member: + mpl::if_c< + is_const::value, + detail::const_member_base, + detail::non_const_member_base + >::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 +struct const_member_offset_base +{ + typedef Type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,Type&>::type +#else + Type& +#endif + + operator()(const ChainedPtr& x)const + { + return operator()(*x); + } + + Type& operator()(const Class& x)const + { + return *static_cast( + static_cast( + static_cast( + static_cast(&x))+OffsetOfMember)); + } + + Type& operator()(const reference_wrapper& x)const + { + return operator()(x.get()); + } + + Type& operator()(const reference_wrapper& x,int=0)const + { + return operator()(x.get()); + } +}; + +template +struct non_const_member_offset_base +{ + typedef Type result_type; + + template + +#if !defined(BOOST_NO_SFINAE) + typename disable_if< + is_convertible,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( + static_cast( + static_cast( + static_cast(&x))+OffsetOfMember)); + } + + Type& operator()(Class& x)const + { + return *static_cast( + static_cast( + static_cast(static_cast(&x))+OffsetOfMember)); + } + + const Type& operator()(const reference_wrapper& x,int=0)const + { + return operator()(x.get()); + } + + Type& operator()(const reference_wrapper& x)const + { + return operator()(x.get()); + } +}; + +} /* namespace multi_index::detail */ + +template +struct member_offset: + mpl::if_c< + is_const::value, + detail::const_member_offset_base, + detail::non_const_member_offset_base + >::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 index 0000000..7f2538c --- /dev/null +++ b/boost/multi_index/ordered_index.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#include +#include +#include +#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 >, + ordered_index > +#else + ,public safe_mode::safe_container< + ordered_index > +#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 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, + safe_ctr_proxy< + bidir_node_iterator > > iterator; +#else + typedef safe_mode::safe_iterator< + bidir_node_iterator, + ordered_index> iterator; +#endif +#else + typedef bidir_node_iterator 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 reverse_iterator; + typedef typename + boost::reverse_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, + ordered_index> safe_super; +#else + typedef safe_mode::safe_container 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& operator=( + const ordered_index& 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(&x)); + } + + const_iterator iterator_to(const value_type& x)const + { + return make_iterator(node_from_value(&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 insert(value_param_type x) + { + BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT; + std::pair p=this->final_insert_(x); + return std::pair(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 p=this->final_insert_( + x,static_cast(position.get_node())); + return make_iterator(p.first); + } + + template + 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(position++.get_node())); + return position; + } + + size_type erase(key_param_type x) + { + BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT; + std::pair 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(position.get_node())); + } + + template + 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(position.get_node())); + } + + template + 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(position.get_node())); + } + + template + 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(mod,key)); + } + + template + 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(mod,key), + modify_key_adaptor(back,key)); + } + + void swap(ordered_index& 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 + iterator find(const CompatibleKey& x)const + { + return make_iterator(ordered_index_find(root(),header(),key,x,comp)); + } + + template + iterator find( + const CompatibleKey& x,const CompatibleCompare& comp)const + { + return make_iterator(ordered_index_find(root(),header(),key,x,comp)); + } + + template + size_type count(const CompatibleKey& x)const + { + return count(x,comp); + } + + template + size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const + { + std::pair p=equal_range(x,comp); + size_type n=std::distance(p.first,p.second); + return n; + } + + template + iterator lower_bound(const CompatibleKey& x)const + { + return make_iterator( + ordered_index_lower_bound(root(),header(),key,x,comp)); + } + + template + iterator lower_bound( + const CompatibleKey& x,const CompatibleCompare& comp)const + { + return make_iterator( + ordered_index_lower_bound(root(),header(),key,x,comp)); + } + + template + iterator upper_bound(const CompatibleKey& x)const + { + return make_iterator( + ordered_index_upper_bound(root(),header(),key,x,comp)); + } + + template + iterator upper_bound( + const CompatibleKey& x,const CompatibleCompare& comp)const + { + return make_iterator( + ordered_index_upper_bound(root(),header(),key,x,comp)); + } + + template + std::pair equal_range( + const CompatibleKey& x)const + { + std::pair p= + ordered_index_equal_range(root(),header(),key,x,comp); + return std::pair( + make_iterator(p.first),make_iterator(p.second)); + } + + template + std::pair equal_range( + const CompatibleKey& x,const CompatibleCompare& comp)const + { + std::pair p= + ordered_index_equal_range(root(),header(),key,x,comp); + return std::pair( + make_iterator(p.first),make_iterator(p.second)); + } + + /* range */ + + template + std::pair + range(LowerBounder lower,UpperBounder upper)const + { + typedef typename mpl::if_< + is_same, + BOOST_DEDUCED_TYPENAME mpl::if_< + is_same, + both_unbounded_tag, + lower_unbounded_tag + >::type, + BOOST_DEDUCED_TYPENAME mpl::if_< + is_same, + 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& 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(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& 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(x.root())); + header()->parent()=root_cpy->impl(); + + node_type* leftmost_cpy=map.find( + static_cast(x.leftmost())); + header()->left()=leftmost_cpy->impl(); + + node_type* rightmost_cpy=map.find( + static_cast(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(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(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(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& 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 + void save_( + Archive& ar,const unsigned int version,const index_saver_type& sm)const + { + save_(ar,version,sm,Category()); + } + + template + 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(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 + std::pair + 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( + 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(make_iterator(y),make_iterator(y)); + } + + template + std::pair + range(LowerBounder,UpperBounder upper,lower_unbounded_tag)const + { + return std::pair( + begin(), + make_iterator(upper_range(root(),header(),upper))); + } + + template + std::pair + range(LowerBounder lower,UpperBounder,upper_unbounded_tag)const + { + return std::pair( + make_iterator(lower_range(root(),header(),lower)), + end()); + } + + template + std::pair + range(LowerBounder,UpperBounder,both_unbounded_tag)const + { + return std::pair(begin(),end()); + } + + template + 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 + 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 + void save_( + Archive& ar,const unsigned int version,const index_saver_type& sm, + ordered_unique_tag)const + { + super::save_(ar,version,sm); + } + + template + void load_( + Archive& ar,const unsigned int version,const index_loader_type& lm, + ordered_unique_tag) + { + super::load_(ar,version,lm); + } + + template + void save_( + Archive& ar,const unsigned int version,const index_saver_type& sm, + ordered_non_unique_tag)const + { + typedef duplicates_iterator 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 + 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& x, + const ordered_index& 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& x, + const ordered_index& 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& x, + const ordered_index& 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& x, + const ordered_index& y) +{ + return y +bool operator>=( + const ordered_index& x, + const ordered_index& y) +{ + return !(x +bool operator<=( + const ordered_index& x, + const ordered_index& y) +{ + return !(x>y); +} + +/* specialized algorithms */ + +template< + typename KeyFromValue,typename Compare, + typename SuperMeta,typename TagList,typename Category +> +void swap( + ordered_index& x, + ordered_index& y) +{ + x.swap(y); +} + +} /* namespace multi_index::detail */ + +/* ordered_index specifiers */ + +template +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 + struct node_class + { + typedef detail::ordered_index_node type; + }; + + template + struct index_class + { + typedef detail::ordered_index< + key_from_value_type,compare_type, + SuperMeta,tag_list_type,detail::ordered_unique_tag> type; + }; +}; + +template +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 + struct node_class + { + typedef detail::ordered_index_node type; + }; + + template + 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 index 0000000..9ee6a0a --- /dev/null +++ b/boost/multi_index/ordered_index_fwd.hpp @@ -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 + +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& x, + ordered_index& y); + +} /* namespace multi_index::detail */ + +/* ordered_index specifiers */ + +template +struct ordered_unique; + +template +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 index 0000000..6f5a9ca --- /dev/null +++ b/boost/multi_index/random_access_index.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#include +#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 +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 >, + random_access_index > +#else + ,public safe_mode::safe_container< + random_access_index > +#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, + safe_ctr_proxy< + rnd_node_iterator > > iterator; +#else + typedef safe_mode::safe_iterator< + rnd_node_iterator, + random_access_index> iterator; +#endif +#else + typedef rnd_node_iterator 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 reverse_iterator; + typedef typename + boost::reverse_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, + 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& operator=( + const random_access_index& x) + { + this->final()=x.final(); + return *this; + } + + template + void assign(InputIterator first,InputIterator last) + { + assign_iter(first,last,mpl::not_ >()); + } + + void assign(size_type n,value_param_type value) + { + BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; + clear(); + for(size_type i=0;ifinal().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(&x)); + } + + const_iterator iterator_to(const value_type& x)const + { + return make_iterator(node_from_value(&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(nvalue(); + } + + 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 push_front(value_param_type x) + {return insert(begin(),x);} + void pop_front(){erase(begin());} + std::pair push_back(value_param_type x) + {return insert(end(),x);} + void pop_back(){erase(--end());} + + std::pair 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 p=this->final_insert_(x); + if(p.second&&position.get_node()!=header()){ + relocate(position.get_node(),p.first); + } + return std::pair(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 + void insert(iterator position,InputIterator first,InputIterator last) + { + insert_iter(position,first,last,mpl::not_ >()); + } + + 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(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(position.get_node())); + } + + template + 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(position.get_node())); + } + + template + 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(position.get_node())); + } + + void swap(random_access_index& 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& 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& 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& 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( + ptrs,std::bind2nd(std::equal_to(),value))); + while(n--)pop_back(); + } + + template + void remove_if(Predicate pred) + { + BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; + difference_type n= + end()-make_iterator(random_access_index_remove(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( + ptrs,std::equal_to())); + while(n--)pop_back(); + } + + template + void unique(BinaryPredicate binary_pred) + { + BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; + difference_type n= + end()-make_iterator( + random_access_index_unique(ptrs,binary_pred)); + while(n--)pop_back(); + } + + void merge(random_access_index& x) + { + if(this!=&x){ + BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; + size_type s=size(); + splice(end(),x); + random_access_index_inplace_merge( + get_allocator(),ptrs,ptrs.at(s),std::less()); + } + } + + template + void merge(random_access_index& 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( + get_allocator(),ptrs,ptrs.at(s),comp); + } + } + + void sort() + { + BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; + random_access_index_sort( + get_allocator(),ptrs,std::less()); + } + + template + void sort(Compare comp) + { + BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT; + random_access_index_sort( + 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 + 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(&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& 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(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& 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( + map.find( + static_cast( + 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(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(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(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& 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 + 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 + void load_( + Archive& ar,const unsigned int version,const index_loader_type& lm) + { + { + typedef random_access_index_loader 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 + 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 + 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& x, + const random_access_index& 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& x, + const random_access_index& 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& x, + const random_access_index& y) +{ + return !(x==y); +} + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator>( + const random_access_index& x, + const random_access_index& y) +{ + return y +bool operator>=( + const random_access_index& x, + const random_access_index& y) +{ + return !(x +bool operator<=( + const random_access_index& x, + const random_access_index& y) +{ + return !(x>y); +} + +/* specialized algorithms */ + +template +void swap( + random_access_index& x, + random_access_index& y) +{ + x.swap(y); +} + +} /* namespace multi_index::detail */ + +/* random access index specifier */ + +template +struct random_access +{ + BOOST_STATIC_ASSERT(detail::is_tag::value); + + template + struct node_class + { + typedef detail::random_access_index_node type; + }; + + template + 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 index 0000000..9e1be35 --- /dev/null +++ b/boost/multi_index/random_access_index_fwd.hpp @@ -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 + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +template +class random_access_index; + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator==( + const random_access_index& x, + const random_access_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator<( + const random_access_index& x, + const random_access_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator!=( + const random_access_index& x, + const random_access_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator>( + const random_access_index& x, + const random_access_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator>=( + const random_access_index& x, + const random_access_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator<=( + const random_access_index& x, + const random_access_index& y); + +template +void swap( + random_access_index& x, + random_access_index& y); + +} /* namespace multi_index::detail */ + +/* index specifiers */ + +template > +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 index 0000000..bfaf31b --- /dev/null +++ b/boost/multi_index/safe_mode_errors.hpp @@ -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 index 0000000..d0b4ec2 --- /dev/null +++ b/boost/multi_index/sequenced_index.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#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 +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 >, + sequenced_index > +#else + ,public safe_mode::safe_container< + sequenced_index > +#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, + safe_ctr_proxy< + bidir_node_iterator > > iterator; +#else + typedef safe_mode::safe_iterator< + bidir_node_iterator, + sequenced_index> iterator; +#endif +#else + typedef bidir_node_iterator 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 reverse_iterator; + typedef typename + boost::reverse_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, + sequenced_index> safe_super; +#else + typedef safe_mode::safe_container< + sequenced_index> safe_super; +#endif +#endif + + typedef typename call_traits::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& operator=( + const sequenced_index& x) + { + this->final()=x.final(); + return *this; + } + + template + void assign(InputIterator first,InputIterator last) + { + assign_iter(first,last,mpl::not_ >()); + } + + void assign(size_type n,value_param_type value) + { + BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT; + clear(); + for(size_type i=0;ifinal().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(&x)); + } + + const_iterator iterator_to(const value_type& x)const + { + return make_iterator(node_from_value(&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 push_front(value_param_type x) + {return insert(begin(),x);} + void pop_front(){erase(begin());} + std::pair push_back(value_param_type x) + {return insert(end(),x);} + void pop_back(){erase(--end());} + + std::pair 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 p=this->final_insert_(x); + if(p.second&&position.get_node()!=header()){ + relink(position.get_node(),p.first); + } + return std::pair(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 + void insert(iterator position,InputIterator first,InputIterator last) + { + insert_iter(position,first,last,mpl::not_ >()); + } + + 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(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(position.get_node())); + } + + template + 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(position.get_node())); + } + + template + 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(position.get_node())); + } + + void swap(sequenced_index& 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& 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& 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& 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)); + } + + template + void remove_if(Predicate pred) + { + sequenced_index_remove(*this,pred); + } + + void unique() + { + sequenced_index_unique(*this,std::equal_to()); + } + + template + void unique(BinaryPredicate binary_pred) + { + sequenced_index_unique(*this,binary_pred); + } + + void merge(sequenced_index& x) + { + sequenced_index_merge(*this,x,std::less()); + } + + template + void merge(sequenced_index& x,Compare comp) + { + sequenced_index_merge(*this,x,comp); + } + + void sort() + { + BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT; + sequenced_index_sort(header(),std::less()); + } + + template + 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 + 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(&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& 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(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& 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(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(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(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(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& 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 + 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 + 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 + 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 + 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 +bool operator==( + const sequenced_index& x, + const sequenced_index& 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& x, + const sequenced_index& 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& x, + const sequenced_index& y) +{ + return !(x==y); +} + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator>( + const sequenced_index& x, + const sequenced_index& y) +{ + return y +bool operator>=( + const sequenced_index& x, + const sequenced_index& y) +{ + return !(x +bool operator<=( + const sequenced_index& x, + const sequenced_index& y) +{ + return !(x>y); +} + +/* specialized algorithms */ + +template +void swap( + sequenced_index& x, + sequenced_index& y) +{ + x.swap(y); +} + +} /* namespace multi_index::detail */ + +/* sequenced index specifier */ + +template +struct sequenced +{ + BOOST_STATIC_ASSERT(detail::is_tag::value); + + template + struct node_class + { + typedef detail::sequenced_index_node type; + }; + + template + struct index_class + { + typedef detail::sequenced_index 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 index 0000000..221a149 --- /dev/null +++ b/boost/multi_index/sequenced_index_fwd.hpp @@ -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 + +namespace boost{ + +namespace multi_index{ + +namespace detail{ + +template +class sequenced_index; + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator==( + const sequenced_index& x, + const sequenced_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator<( + const sequenced_index& x, + const sequenced_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator!=( + const sequenced_index& x, + const sequenced_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator>( + const sequenced_index& x, + const sequenced_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator>=( + const sequenced_index& x, + const sequenced_index& y); + +template< + typename SuperMeta1,typename TagList1, + typename SuperMeta2,typename TagList2 +> +bool operator<=( + const sequenced_index& x, + const sequenced_index& y); + +template +void swap( + sequenced_index& x, + sequenced_index& y); + +} /* namespace multi_index::detail */ + +/* index specifiers */ + +template > +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 index 0000000..57fb987 --- /dev/null +++ b/boost/multi_index/tag.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 +struct is_tag +{ + BOOST_STATIC_CONSTANT(bool,value=(is_base_and_derived::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, + mpl::identity + >::type type; + + BOOST_STATIC_ASSERT(detail::no_duplicate_tags::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 index 0000000..11a6597 --- /dev/null +++ b/boost/multi_index_container.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) +#include +#include +#include +#include +#endif + +#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) +#include +#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 +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 >, + 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 friend class detail::index_base; + template friend struct detail::header_holder; + template 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 begin; + typedef mpl::v_iter< + type, + mpl::size::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::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::type:: + ctor_args_list(), + const allocator_type& al= + typename mpl::identity::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 + 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::type:: + ctor_args_list(), + const allocator_type& al= + typename mpl::identity::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& 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& operator=( + const multi_index_container& x) + { + BOOST_MULTI_INDEX_CHECK_INVARIANT; + multi_index_container 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 + struct nth_index + { + BOOST_STATIC_ASSERT(N>=0&&N::type::value); + typedef typename mpl::at_c::type type; + }; + + template + typename nth_index::type& get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N)) + { + BOOST_STATIC_ASSERT(N>=0&&N::type::value); + return *this; + } + + template + const typename nth_index::type& get( + BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const + { + BOOST_STATIC_ASSERT(N>=0&&N::type::value); + return *this; + } +#endif + + /* retrieval of indices by tag */ + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) + template + struct index + { + typedef typename mpl::find_if< + index_type_list, + detail::has_tag + >::type iter; + + BOOST_STATIC_CONSTANT( + bool,index_found=!(is_same::type >::value)); + BOOST_STATIC_ASSERT(index_found); + + typedef typename mpl::deref::type type; + }; + + template + typename index::type& get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + return *this; + } + + template + const typename index::type& get( + BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))const + { + return *this; + } +#endif + + /* projection of iterators by number */ + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) + template + struct nth_index_iterator + { + typedef typename nth_index::type::iterator type; + }; + + template + struct nth_index_const_iterator + { + typedef typename nth_index::type::const_iterator type; + }; + + template + typename nth_index_iterator::type project( + IteratorType it + BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N)) + { + typedef typename nth_index::type index; + +#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */ + BOOST_STATIC_ASSERT( + (mpl::contains::value)); +#endif + + BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it); + BOOST_MULTI_INDEX_CHECK_IS_OWNER( + it,static_cast(*this)); + + return index::make_iterator(static_cast(it.get_node())); + } + + template + typename nth_index_const_iterator::type project( + IteratorType it + BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const + { + typedef typename nth_index::type index; + +#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */ + BOOST_STATIC_ASSERT(( + mpl::contains::value|| + mpl::contains::value)); +#endif + + BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it); + BOOST_MULTI_INDEX_CHECK_IS_OWNER( + it,static_cast(*this)); + return index::make_iterator(static_cast(it.get_node())); + } +#endif + + /* projection of iterators by tag */ + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) + template + struct index_iterator + { + typedef typename index::type::iterator type; + }; + + template + struct index_const_iterator + { + typedef typename index::type::const_iterator type; + }; + + template + typename index_iterator::type project( + IteratorType it + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + typedef typename index::type index; + +#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */ + BOOST_STATIC_ASSERT( + (mpl::contains::value)); +#endif + + BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it); + BOOST_MULTI_INDEX_CHECK_IS_OWNER( + it,static_cast(*this)); + return index::make_iterator(static_cast(it.get_node())); + } + + template + typename index_const_iterator::type project( + IteratorType it + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))const + { + typedef typename index::type index; + +#if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */ + BOOST_STATIC_ASSERT(( + mpl::contains::value|| + mpl::contains::value)); +#endif + + BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it); + BOOST_MULTI_INDEX_CHECK_IS_OWNER( + it,static_cast(*this)); + return index::make_iterator(static_cast(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(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(-1); + } + + std::pair 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(res,true); + } + else{ + deallocate_node(x); + return std::pair(res,false); + } + } + BOOST_CATCH(...){ + deallocate_node(x); + BOOST_RETHROW; + } + BOOST_CATCH_END + } + + std::pair 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(res,true); + } + else{ + deallocate_node(x); + return std::pair(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& 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 + bool modify_(Modifier& mod,node_type* x) + { + mod(const_cast(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 + bool modify_(Modifier& mod,Rollback& back,node_type* x) + { + mod(const_cast(x->value())); + + bool b; + BOOST_TRY{ + b=super::modify_rollback_(x); + } + BOOST_CATCH(...){ + BOOST_TRY{ + back(const_cast(x->value())); + BOOST_RETHROW; + } + BOOST_CATCH(...){ + this->erase_(x); + BOOST_RETHROW; + } + BOOST_CATCH_END + } + BOOST_CATCH_END + + BOOST_TRY{ + if(!b){ + back(const_cast(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 + void save(Archive& ar,const unsigned int version)const + { + const std::size_t s=size_(); + ar< + 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 value("item",ar,version); + std::pair 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 +struct nth_index +{ + BOOST_STATIC_CONSTANT( + int, + M=mpl::size::type::value); + BOOST_STATIC_ASSERT(N>=0&&N::type type; +}; + +template +typename nth_index< + multi_index_container,N>::type& +get( + multi_index_container& 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::index(m); +} + +template +const typename nth_index< + multi_index_container,N>::type& +get( + const multi_index_container& 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::index(m); +} + +/* retrieval of indices by tag */ + +template +struct index +{ + typedef typename MultiIndexContainer::index_type_list index_type_list; + + typedef typename mpl::find_if< + index_type_list, + detail::has_tag + >::type iter; + + BOOST_STATIC_CONSTANT( + bool,index_found=!(is_same::type >::value)); + BOOST_STATIC_ASSERT(index_found); + + typedef typename mpl::deref::type type; +}; + +template< + typename Tag,typename Value,typename IndexSpecifierList,typename Allocator +> +typename ::boost::multi_index::index< + multi_index_container,Tag>::type& +get( + multi_index_container& 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::index(m); +} + +template< + typename Tag,typename Value,typename IndexSpecifierList,typename Allocator +> +const typename ::boost::multi_index::index< + multi_index_container,Tag>::type& +get( + const multi_index_container& 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::index(m); +} + +/* projection of iterators by number */ + +template +struct nth_index_iterator +{ + typedef typename detail::prevent_eti< + nth_index, + typename nth_index::type>::type::iterator type; +}; + +template +struct nth_index_const_iterator +{ + typedef typename detail::prevent_eti< + nth_index, + typename nth_index::type + >::type::const_iterator type; +}; + +template< + int N,typename IteratorType, + typename Value,typename IndexSpecifierList,typename Allocator> +typename nth_index_iterator< + multi_index_container,N>::type +project( + multi_index_container& 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::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::iterator( + m,static_cast(it.get_node())); +} + +template< + int N,typename IteratorType, + typename Value,typename IndexSpecifierList,typename Allocator> +typename nth_index_const_iterator< + multi_index_container,N>::type +project( + const multi_index_container& 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::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::const_iterator( + m,static_cast(it.get_node())); +} + +/* projection of iterators by tag */ + +template +struct index_iterator +{ + typedef typename ::boost::multi_index::index< + MultiIndexContainer,Tag>::type::iterator type; +}; + +template +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,Tag>::type +project( + multi_index_container& 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::iterator( + m,static_cast(it.get_node())); +} + +template< + typename Tag,typename IteratorType, + typename Value,typename IndexSpecifierList,typename Allocator> +typename index_const_iterator< + multi_index_container,Tag>::type +project( + const multi_index_container& 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::const_iterator( + m,static_cast(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& x, + const multi_index_container& 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& x, + const multi_index_container& y) +{ + return get<0>(x)(y); +} + +template< + typename Value1,typename IndexSpecifierList1,typename Allocator1, + typename Value2,typename IndexSpecifierList2,typename Allocator2 +> +bool operator!=( + const multi_index_container& x, + const multi_index_container& 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& x, + const multi_index_container& 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& x, + const multi_index_container& 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& x, + const multi_index_container& y) +{ + return get<0>(x)<=get<0>(y); +} + +/* specialized algorithms */ + +template +void swap( + multi_index_container& x, + multi_index_container& 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 index 0000000..6e377ed --- /dev/null +++ b/boost/multi_index_container_fwd.hpp @@ -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 /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include + +namespace boost{ + +namespace multi_index{ + +/* Default value for IndexSpecifierList specifies a container + * equivalent to std::set. + */ + +template< + typename Value, + typename IndexSpecifierList=indexed_by > >, + typename Allocator=std::allocator > +class multi_index_container; + +template +struct nth_index; + +template +struct index; + +template +struct nth_index_iterator; + +template +struct nth_index_const_iterator; + +template +struct index_iterator; + +template +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& x, + const multi_index_container& y); + +template< + typename Value1,typename IndexSpecifierList1,typename Allocator1, + typename Value2,typename IndexSpecifierList2,typename Allocator2 +> +bool operator<( + const multi_index_container& x, + const multi_index_container& y); + +template< + typename Value1,typename IndexSpecifierList1,typename Allocator1, + typename Value2,typename IndexSpecifierList2,typename Allocator2 +> +bool operator!=( + const multi_index_container& x, + const multi_index_container& y); + +template< + typename Value1,typename IndexSpecifierList1,typename Allocator1, + typename Value2,typename IndexSpecifierList2,typename Allocator2 +> +bool operator>( + const multi_index_container& x, + const multi_index_container& y); + +template< + typename Value1,typename IndexSpecifierList1,typename Allocator1, + typename Value2,typename IndexSpecifierList2,typename Allocator2 +> +bool operator>=( + const multi_index_container& x, + const multi_index_container& y); + +template< + typename Value1,typename IndexSpecifierList1,typename Allocator1, + typename Value2,typename IndexSpecifierList2,typename Allocator2 +> +bool operator<=( + const multi_index_container& x, + const multi_index_container& y); + +template +void swap( + multi_index_container& x, + multi_index_container& 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