// 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; // 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