// Boost.Bimap | |
// | |
// Copyright (c) 2006-2007 Matias Capeletto | |
// | |
// Distributed under the Boost Software License, Version 1.0. | |
// (See accompanying file LICENSE_1_0.txt or copy at | |
// http://www.boost.org/LICENSE_1_0.txt) | |
/// \file detail/bimap_core.hpp | |
/// \brief Bimap base definition. | |
#ifndef BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP | |
#define BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP | |
#if defined(_MSC_VER) && (_MSC_VER>=1200) | |
#pragma once | |
#endif | |
#include <boost/config.hpp> | |
#include <boost/mpl/placeholders.hpp> | |
#include <boost/mpl/push_front.hpp> | |
#include <boost/mpl/if.hpp> | |
#include <boost/mpl/and.hpp> | |
#include <boost/mpl/not.hpp> | |
#include <boost/mpl/vector.hpp> | |
#include <boost/type_traits/add_const.hpp> | |
#include <boost/type_traits/is_same.hpp> | |
#include <boost/concept_check.hpp> | |
// Boost.MultiIndex | |
#include <boost/multi_index_container.hpp> | |
#include <boost/multi_index/member.hpp> | |
// Boost.Bimap | |
#include <boost/bimap/relation/mutant_relation.hpp> | |
#include <boost/bimap/relation/member_at.hpp> | |
#include <boost/bimap/relation/support/data_extractor.hpp> | |
#include <boost/bimap/tags/support/default_tagged.hpp> | |
#include <boost/bimap/tags/tagged.hpp> | |
#include <boost/bimap/detail/manage_bimap_key.hpp> | |
#include <boost/bimap/detail/manage_additional_parameters.hpp> | |
#include <boost/bimap/detail/map_view_iterator.hpp> | |
#include <boost/bimap/detail/set_view_iterator.hpp> | |
#include <boost/bimap/set_of.hpp> | |
#include <boost/bimap/unconstrained_set_of.hpp> | |
namespace boost { | |
namespace bimaps { | |
/// \brief Library details | |
namespace detail { | |
#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES | |
template< class Type > | |
struct get_value_type | |
{ | |
typedef BOOST_DEDUCED_TYPENAME Type::value_type type; | |
}; | |
struct independent_index_tag {}; | |
#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES | |
/// \brief Base for the bimap class. | |
/** | |
See also bimap. | |
**/ | |
template< class LeftSetType, class RightSetType, class AP1, class AP2, class AP3 > | |
class bimap_core | |
{ | |
// Manage bimap key instantiation | |
// -------------------------------------------------------------------- | |
public: | |
typedef BOOST_DEDUCED_TYPENAME manage_bimap_key | |
< | |
LeftSetType | |
>::type left_set_type; | |
typedef BOOST_DEDUCED_TYPENAME manage_bimap_key | |
< | |
RightSetType | |
>::type right_set_type; | |
private: | |
typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::default_tagged | |
< | |
BOOST_DEDUCED_TYPENAME left_set_type::user_type, | |
::boost::bimaps::relation::member_at::left | |
>::type left_tagged_type; | |
typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::default_tagged | |
< | |
BOOST_DEDUCED_TYPENAME right_set_type::user_type, | |
::boost::bimaps::relation::member_at::right | |
>::type right_tagged_type; | |
public: | |
//@{ | |
typedef BOOST_DEDUCED_TYPENAME left_tagged_type::tag left_tag; | |
typedef BOOST_DEDUCED_TYPENAME right_tagged_type::tag right_tag; | |
//@} | |
//@{ | |
typedef BOOST_DEDUCED_TYPENAME left_set_type::value_type left_key_type; | |
typedef BOOST_DEDUCED_TYPENAME right_set_type::value_type right_key_type; | |
//@} | |
//@{ | |
typedef right_key_type left_data_type; | |
typedef left_key_type right_data_type; | |
//@} | |
// Manage the additional parameters | |
// -------------------------------------------------------------------- | |
private: | |
typedef BOOST_DEDUCED_TYPENAME manage_additional_parameters<AP1,AP2,AP3>::type parameters; | |
/// \brief Relation type stored by the bimap. | |
// -------------------------------------------------------------------- | |
public: | |
typedef ::boost::bimaps::relation::mutant_relation | |
< | |
::boost::bimaps::tags::tagged< | |
BOOST_DEDUCED_TYPENAME mpl::if_< | |
mpl::and_ | |
< | |
BOOST_DEDUCED_TYPENAME left_set_type::mutable_key, | |
BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation::left_mutable_key | |
>, | |
// { | |
left_key_type, | |
// } | |
// else | |
// { | |
BOOST_DEDUCED_TYPENAME ::boost::add_const< left_key_type >::type | |
// } | |
>::type, | |
left_tag | |
>, | |
::boost::bimaps::tags::tagged< | |
BOOST_DEDUCED_TYPENAME mpl::if_< | |
mpl::and_ | |
< | |
BOOST_DEDUCED_TYPENAME right_set_type::mutable_key, | |
BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation::right_mutable_key | |
>, | |
// { | |
right_key_type, | |
// } | |
// else | |
// { | |
BOOST_DEDUCED_TYPENAME ::boost::add_const< right_key_type >::type | |
// } | |
>::type, | |
right_tag | |
>, | |
// It is ::boost::mpl::na if no info_hook was included | |
BOOST_DEDUCED_TYPENAME parameters::additional_info, | |
// Force mutable keys | |
true | |
> relation; | |
//@{ | |
typedef BOOST_DEDUCED_TYPENAME relation::left_pair left_value_type; | |
typedef BOOST_DEDUCED_TYPENAME relation::right_pair right_value_type; | |
//@} | |
// Bind the member of the relation, so multi_index can manage them | |
// -------------------------------------------------------------------- | |
private: | |
typedef BOOST_DEDUCED_TYPENAME relation::storage_base relation_storage_base; | |
typedef BOOST_MULTI_INDEX_MEMBER(relation_storage_base, left_key_type, left) | |
left_member_extractor; | |
typedef BOOST_MULTI_INDEX_MEMBER(relation_storage_base,right_key_type,right) | |
right_member_extractor; | |
// The core indices are somewhat complicated to calculate, because they | |
// can be zero, one, two or three indices, depending on the use of | |
// {side}_based set type of relations and unconstrained_set_of and | |
// unconstrained_set_of_relation specifications. | |
typedef BOOST_DEDUCED_TYPENAME mpl::if_< | |
::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >, | |
// { | |
mpl::vector<>, | |
// } | |
// else | |
// { | |
mpl::vector | |
< | |
BOOST_DEDUCED_TYPENAME left_set_type:: | |
BOOST_NESTED_TEMPLATE index_bind | |
< | |
left_member_extractor, | |
left_tag | |
>::type | |
> | |
// } | |
>::type left_core_indices; | |
typedef BOOST_DEDUCED_TYPENAME mpl::if_< | |
::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >, | |
// { | |
left_core_indices, | |
// } | |
// else | |
// { | |
BOOST_DEDUCED_TYPENAME mpl::push_front | |
< | |
left_core_indices, | |
BOOST_DEDUCED_TYPENAME right_set_type:: | |
BOOST_NESTED_TEMPLATE index_bind | |
< | |
right_member_extractor, | |
right_tag | |
>::type | |
>::type | |
// } | |
>::type basic_core_indices; | |
// If it is based either on the left or on the right, then only the side | |
// indices are needed. But the set type of the relation can be completely | |
// diferent from the one used for the sides in wich case we have to add yet | |
// another index to the core. | |
// TODO | |
// If all the set types are unsconstrained there must be readable compile | |
// time error. | |
typedef BOOST_DEDUCED_TYPENAME mpl::if_< | |
is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, left_based >, | |
// { | |
::boost::bimaps::tags::tagged< left_set_type, left_tag >, | |
// } | |
/* else */ BOOST_DEDUCED_TYPENAME mpl::if_< | |
is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, right_based >, | |
// { | |
::boost::bimaps::tags::tagged< right_set_type, right_tag >, | |
// } | |
// else | |
// { | |
tags::tagged | |
< | |
BOOST_DEDUCED_TYPENAME parameters:: | |
set_type_of_relation::BOOST_NESTED_TEMPLATE bind_to | |
< | |
relation | |
>::type, | |
independent_index_tag | |
> | |
// } | |
>::type | |
>::type tagged_set_of_relation_type; | |
protected: | |
typedef BOOST_DEDUCED_TYPENAME tagged_set_of_relation_type::tag | |
relation_set_tag; | |
typedef BOOST_DEDUCED_TYPENAME tagged_set_of_relation_type::value_type | |
relation_set_type_of; | |
// Logic tags | |
// This is a necesary extra level of indirection to allow unconstrained | |
// sets to be plug in the design. The bimap constructors use this logic | |
// tags. | |
typedef BOOST_DEDUCED_TYPENAME mpl::if_< | |
::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >, | |
BOOST_DEDUCED_TYPENAME mpl::if_< | |
::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >, | |
independent_index_tag, | |
right_tag | |
>::type, | |
left_tag | |
>::type logic_left_tag; | |
typedef BOOST_DEDUCED_TYPENAME mpl::if_< | |
::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >, | |
BOOST_DEDUCED_TYPENAME mpl::if_< | |
::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >, | |
independent_index_tag, | |
left_tag | |
>::type, | |
right_tag | |
>::type logic_right_tag; | |
typedef BOOST_DEDUCED_TYPENAME mpl::if_< | |
is_same< relation_set_tag, independent_index_tag >, | |
BOOST_DEDUCED_TYPENAME mpl::if_< | |
::boost::bimaps::detail:: | |
is_unconstrained_set_of< relation_set_type_of >, | |
logic_left_tag, | |
independent_index_tag | |
>::type, | |
BOOST_DEDUCED_TYPENAME mpl::if_< | |
is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, left_based >, | |
logic_left_tag, | |
logic_right_tag | |
>::type | |
>::type logic_relation_set_tag; | |
private: | |
typedef BOOST_DEDUCED_TYPENAME mpl::if_< | |
mpl::and_< is_same< relation_set_tag, independent_index_tag >, | |
mpl::not_< | |
::boost::bimaps::detail:: | |
is_unconstrained_set_of< relation_set_type_of > | |
> | |
>, | |
// { | |
BOOST_DEDUCED_TYPENAME mpl::push_front | |
< | |
basic_core_indices, | |
BOOST_DEDUCED_TYPENAME relation_set_type_of:: | |
BOOST_NESTED_TEMPLATE index_bind | |
< | |
::boost::bimaps::relation::support::both_keys_extractor<relation>, | |
independent_index_tag | |
>::type | |
>::type, | |
// } | |
// else | |
// { | |
basic_core_indices | |
// } | |
>::type complete_core_indices; | |
struct core_indices : public complete_core_indices {}; | |
// Define the core using compute_index_type to translate the | |
// set type to an multi-index specification | |
// -------------------------------------------------------------------- | |
public: | |
typedef multi_index::multi_index_container | |
< | |
relation, | |
core_indices, | |
BOOST_DEDUCED_TYPENAME parameters::allocator:: | |
BOOST_NESTED_TEMPLATE rebind<relation>::other | |
> core_type; | |
// Core metadata | |
// -------------------------------------------------------------------- | |
public: | |
typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index:: | |
index<core_type, logic_left_tag>::type left_index; | |
typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index:: | |
index<core_type,logic_right_tag>::type right_index; | |
typedef BOOST_DEDUCED_TYPENAME left_index::iterator left_core_iterator; | |
typedef BOOST_DEDUCED_TYPENAME left_index::const_iterator left_core_const_iterator; | |
typedef BOOST_DEDUCED_TYPENAME right_index::iterator right_core_iterator; | |
typedef BOOST_DEDUCED_TYPENAME right_index::const_iterator right_core_const_iterator; | |
// Map by {side} iterator metadata | |
// -------------------------------------------------------------------- | |
public: | |
//@{ | |
typedef ::boost::bimaps::detail::map_view_iterator | |
< | |
left_tag, | |
relation, | |
left_core_iterator | |
> left_iterator; | |
typedef ::boost::bimaps::detail::map_view_iterator | |
< | |
right_tag, | |
relation, | |
right_core_iterator | |
> right_iterator; | |
//@} | |
//@{ | |
typedef ::boost::bimaps::detail::const_map_view_iterator | |
< | |
left_tag, | |
relation, | |
left_core_const_iterator | |
> left_const_iterator; | |
typedef ::boost::bimaps::detail::const_map_view_iterator | |
< | |
right_tag, | |
relation, | |
right_core_const_iterator | |
> right_const_iterator; | |
//@} | |
// Relation set view | |
typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index::index | |
< | |
core_type, logic_relation_set_tag | |
>::type relation_set_core_index; | |
typedef BOOST_DEDUCED_TYPENAME relation_set_type_of:: | |
BOOST_NESTED_TEMPLATE set_view_bind | |
< | |
relation_set_core_index | |
>::type relation_set; | |
public: | |
typedef bimap_core bimap_core_; | |
}; | |
// Two auxiliar metafunctions to compute the map view types | |
// The map view type can not be computed inside the bimap core because a | |
// they need the bimap core to be parsed first. | |
template< class BimapBaseType > | |
struct left_map_view_type | |
{ | |
typedef BOOST_DEDUCED_TYPENAME BimapBaseType::left_set_type left_set_type; | |
typedef BOOST_DEDUCED_TYPENAME | |
left_set_type::BOOST_NESTED_TEMPLATE map_view_bind< | |
BOOST_DEDUCED_TYPENAME BimapBaseType::left_tag, BimapBaseType | |
>::type type; | |
}; | |
template< class BimapBaseType > | |
struct right_map_view_type | |
{ | |
typedef BOOST_DEDUCED_TYPENAME BimapBaseType::right_set_type right_set_type; | |
typedef BOOST_DEDUCED_TYPENAME | |
right_set_type::BOOST_NESTED_TEMPLATE map_view_bind< | |
BOOST_DEDUCED_TYPENAME BimapBaseType::right_tag, BimapBaseType | |
>::type type; | |
}; | |
} // namespace detail | |
} // namespace bimaps | |
} // namespace boost | |
#endif // BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP |