Chris@16: // Boost.Bimap Chris@16: // Chris@16: // Copyright (c) 2006-2007 Matias Capeletto Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: /// \file detail/map_view_base.hpp Chris@16: /// \brief Helper base for the construction of the bimap views types. Chris@16: Chris@16: #ifndef BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP Chris@16: #define BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: //#include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace bimaps { Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: Chris@16: // The next macro can be converted in a metafunctor to gain code robustness. Chris@16: /*===========================================================================*/ Chris@16: #define BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( \ Chris@16: CONTAINER_ADAPTOR, TAG, BIMAP, OTHER_ITER, CONST_OTHER_ITER \ Chris@16: ) \ Chris@16: ::boost::bimaps::container_adaptor::CONTAINER_ADAPTOR \ Chris@16: < \ Chris@16: BOOST_DEDUCED_TYPENAME BIMAP::core_type:: \ Chris@16: BOOST_NESTED_TEMPLATE index::type, \ Chris@16: ::boost::bimaps::detail:: map_view_iterator, \ Chris@16: ::boost::bimaps::detail::const_map_view_iterator, \ Chris@16: ::boost::bimaps::detail:: OTHER_ITER, \ Chris@16: ::boost::bimaps::detail::CONST_OTHER_ITER, \ Chris@16: ::boost::bimaps::container_adaptor::support::iterator_facade_to_base \ Chris@16: < \ Chris@16: ::boost::bimaps::detail:: map_view_iterator, \ Chris@16: ::boost::bimaps::detail::const_map_view_iterator \ Chris@16: >, \ Chris@16: ::boost::mpl::na, \ Chris@16: ::boost::mpl::na, \ Chris@16: ::boost::bimaps::relation::detail:: \ Chris@16: pair_to_relation_functor, \ Chris@16: ::boost::bimaps::relation::support:: \ Chris@16: get_pair_functor \ Chris@16: > Chris@16: /*===========================================================================*/ Chris@16: Chris@16: Chris@16: #if defined(BOOST_MSVC) Chris@16: /*===========================================================================*/ Chris@16: #define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP) \ Chris@16: typedef ::boost::bimaps::detail::map_view_base< \ Chris@16: TYPE,TAG,BIMAP > friend_map_view_base; \ Chris@16: friend class friend_map_view_base; Chris@16: /*===========================================================================*/ Chris@16: #else Chris@16: /*===========================================================================*/ Chris@16: #define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP) \ Chris@16: friend class ::boost::bimaps::detail::map_view_base< \ Chris@16: TYPE,TAG,BIMAP >; Chris@16: /*===========================================================================*/ Chris@16: #endif Chris@16: Chris@16: Chris@16: /// \brief Common base for map views. Chris@16: Chris@16: template< class Derived, class Tag, class BimapType> Chris@16: class map_view_base Chris@16: { Chris@16: typedef ::boost::bimaps::container_adaptor::support:: Chris@16: iterator_facade_to_base< Chris@16: ::boost::bimaps::detail:: map_view_iterator, Chris@16: ::boost::bimaps::detail::const_map_view_iterator Chris@16: > iterator_to_base_; Chris@16: Chris@16: typedef ::boost::bimaps::relation::detail:: Chris@16: pair_to_relation_functor value_to_base_; Chris@16: Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: Chris@16: key_type_by::type key_type_; Chris@16: Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: Chris@16: data_type_by::type data_type_; Chris@16: Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: Chris@16: pair_type_by::type value_type_; Chris@16: Chris@16: typedef Chris@16: ::boost::bimaps::detail::map_view_iterator iterator_; Chris@16: Chris@16: public: Chris@16: Chris@16: bool replace(iterator_ position, const value_type_ & x) Chris@16: { Chris@16: return derived().base().replace( Chris@16: derived().template functor()(position), Chris@16: derived().template functor()(x) Chris@16: ); Chris@16: } Chris@16: Chris@16: template< class CompatibleKey > Chris@16: bool replace_key(iterator_ position, const CompatibleKey & k) Chris@16: { Chris@16: return derived().base().replace( Chris@16: derived().template functor()(position), Chris@16: derived().template functor()( Chris@16: ::boost::bimaps::relation::detail:: Chris@16: copy_with_first_replaced(*position,k) Chris@16: ) Chris@16: ); Chris@16: } Chris@16: Chris@16: template< class CompatibleData > Chris@16: bool replace_data(iterator_ position, const CompatibleData & d) Chris@16: { Chris@16: return derived().base().replace( Chris@16: derived().template functor()(position), Chris@16: derived().template functor()( Chris@16: ::boost::bimaps::relation::detail:: Chris@16: copy_with_second_replaced(*position,d) Chris@16: ) Chris@16: ); Chris@16: } Chris@16: Chris@16: /* This function may be provided in the future Chris@16: Chris@16: template< class Modifier > Chris@16: bool modify(iterator_ position, Modifier mod) Chris@16: { Chris@16: return derived().base().modify( Chris@16: Chris@16: derived().template functor()(position), Chris@16: Chris@16: ::boost::bimaps::detail::relation_modifier_adaptor Chris@16: < Chris@16: Modifier, Chris@16: BOOST_DEDUCED_TYPENAME BimapType::relation, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: Chris@16: data_extractor Chris@16: < Chris@16: Tag, BOOST_DEDUCED_TYPENAME BimapType::relation Chris@16: Chris@16: >::type, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: Chris@16: data_extractor Chris@16: < Chris@16: BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: Chris@16: opossite_tag::type, Chris@16: BOOST_DEDUCED_TYPENAME BimapType::relation Chris@16: Chris@16: >::type Chris@16: Chris@16: >(mod) Chris@16: ); Chris@16: } Chris@16: */ Chris@16: Chris@16: template< class Modifier > Chris@16: bool modify_key(iterator_ position, Modifier mod) Chris@16: { Chris@16: return derived().base().modify_key( Chris@16: derived().template functor()(position), mod Chris@16: ); Chris@16: } Chris@16: Chris@16: template< class Modifier > Chris@16: bool modify_data(iterator_ position, Modifier mod) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: Chris@16: data_extractor Chris@16: < Chris@16: BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: Chris@16: opossite_tag::type, Chris@16: BOOST_DEDUCED_TYPENAME BimapType::relation Chris@16: Chris@16: >::type data_extractor_; Chris@16: Chris@16: return derived().base().modify( Chris@16: Chris@16: derived().template functor()(position), Chris@16: Chris@16: // this may be replaced later by Chris@16: // ::boost::bind( mod, ::boost::bind(data_extractor_(),_1) ) Chris@16: Chris@16: ::boost::bimaps::detail::unary_modifier_adaptor Chris@16: < Chris@16: Modifier, Chris@16: BOOST_DEDUCED_TYPENAME BimapType::relation, Chris@16: data_extractor_ Chris@16: Chris@16: >(mod) Chris@16: ); Chris@16: } Chris@16: Chris@16: protected: Chris@16: Chris@16: typedef map_view_base map_view_base_; Chris@16: Chris@16: private: Chris@16: Chris@16: // Curiously Recurring Template interface. Chris@16: Chris@16: Derived& derived() Chris@16: { Chris@16: return *static_cast(this); Chris@16: } Chris@16: Chris@16: Derived const& derived() const Chris@16: { Chris@16: return *static_cast(this); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: Chris@16: template< class Derived, class Tag, class BimapType> Chris@16: class mutable_data_unique_map_view_access Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: Chris@16: data_type_by::type data_type_; Chris@16: Chris@16: public: Chris@16: Chris@16: template< class CompatibleKey > Chris@16: data_type_ & at(const CompatibleKey& k) Chris@16: { Chris@16: typedef ::boost::bimaps::detail:: Chris@16: map_view_iterator iterator; Chris@16: Chris@16: iterator iter = derived().find(k); Chris@16: if( iter == derived().end() ) Chris@16: { Chris@16: ::boost::throw_exception( Chris@16: std::out_of_range("bimap<>: invalid key") Chris@16: ); Chris@16: } Chris@16: return iter->second; Chris@16: } Chris@16: Chris@16: template< class CompatibleKey > Chris@16: const data_type_ & at(const CompatibleKey& k) const Chris@16: { Chris@16: typedef ::boost::bimaps::detail:: Chris@16: const_map_view_iterator const_iterator; Chris@16: Chris@16: const_iterator iter = derived().find(k); Chris@16: if( iter == derived().end() ) Chris@16: { Chris@16: ::boost::throw_exception( Chris@16: std::out_of_range("bimap<>: invalid key") Chris@16: ); Chris@16: } Chris@16: return iter->second; Chris@16: } Chris@16: Chris@16: template< class CompatibleKey > Chris@16: data_type_ & operator[](const CompatibleKey& k) Chris@16: { Chris@16: typedef ::boost::bimaps::detail:: Chris@16: map_view_iterator iterator; Chris@16: Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: Chris@16: value_type_by::type value_type; Chris@16: Chris@16: iterator iter = derived().find(k); Chris@16: if( iter == derived().end() ) Chris@16: { Chris@16: iter = derived().insert( value_type(k,data_type_()) ).first; Chris@16: } Chris@16: return iter->second; Chris@16: } Chris@16: Chris@16: protected: Chris@16: Chris@16: typedef mutable_data_unique_map_view_access Chris@16: mutable_data_unique_map_view_access_; Chris@16: Chris@16: private: Chris@16: Chris@16: // Curiously Recurring Template interface. Chris@16: Chris@16: Derived& derived() Chris@16: { Chris@16: return *static_cast(this); Chris@16: } Chris@16: Chris@16: Derived const& derived() const Chris@16: { Chris@16: return *static_cast(this); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template< class Derived, class Tag, class BimapType> Chris@16: class non_mutable_data_unique_map_view_access Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: Chris@16: data_type_by::type data_type_; Chris@16: Chris@16: public: Chris@16: Chris@16: template< class CompatibleKey > Chris@16: const data_type_ & at(const CompatibleKey& k) const Chris@16: { Chris@16: typedef ::boost::bimaps::detail:: Chris@16: const_map_view_iterator const_iterator; Chris@16: Chris@16: const_iterator iter = derived().find(k); Chris@16: if( iter == derived().end() ) Chris@16: { Chris@16: ::boost::throw_exception( Chris@16: std::out_of_range("bimap<>: invalid key") Chris@16: ); Chris@16: } Chris@16: return iter->second; Chris@16: } Chris@16: Chris@16: template< class CompatibleKey > Chris@16: data_type_ & operator[](const CompatibleKey&) Chris@16: { Chris@16: BOOST_BIMAP_STATIC_ERROR( OPERATOR_BRACKET_IS_NOT_SUPPORTED, (Derived)); Chris@16: } Chris@16: Chris@16: protected: Chris@16: Chris@16: typedef non_mutable_data_unique_map_view_access Chris@16: non_mutable_data_unique_map_view_access_; Chris@16: Chris@16: private: Chris@16: Chris@16: // Curiously Recurring Template interface. Chris@16: Chris@16: Derived& derived() Chris@16: { Chris@16: return *static_cast(this); Chris@16: } Chris@16: Chris@16: Derived const& derived() const Chris@16: { Chris@16: return *static_cast(this); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template< class Derived, class Tag, class BimapType> Chris@16: struct unique_map_view_access Chris@16: { Chris@16: private: Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: Chris@16: value_type_by::type value_type; Chris@16: Chris@16: public: Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_ Chris@16: < Chris@16: typename ::boost::is_const< Chris@16: BOOST_DEDUCED_TYPENAME value_type::second_type >::type, Chris@16: Chris@16: non_mutable_data_unique_map_view_access, Chris@16: mutable_data_unique_map_view_access Chris@16: Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // Map views specialize the following structs to provide to the bimap class Chris@16: // the extra side typedefs (i.e. left_local_iterator for unordered_maps, Chris@16: // right_range_type for maps) Chris@16: Chris@16: template< class MapView > Chris@16: struct left_map_view_extra_typedefs {}; Chris@16: Chris@16: template< class MapView > Chris@16: struct right_map_view_extra_typedefs {}; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: // This function is already part of Boost.Lambda. Chris@16: // They may be moved to Boost.Utility. Chris@16: Chris@16: template inline const T& make_const(const T& t) { return t; } Chris@16: Chris@16: } // namespace bimaps Chris@16: } // namespace boost Chris@16: Chris@16: Chris@16: // The following macros avoids code duplication in map views Chris@16: // Maybe this can be changed in the future using a scheme similar to Chris@16: // the one used with map_view_base. Chris@16: Chris@16: /*===========================================================================*/ Chris@16: #define BOOST_BIMAP_MAP_VIEW_RANGE_IMPLEMENTATION(BASE) \ Chris@16: \ Chris@16: typedef std::pair< \ Chris@16: BOOST_DEDUCED_TYPENAME base_::iterator, \ Chris@16: BOOST_DEDUCED_TYPENAME base_::iterator> range_type; \ Chris@16: \ Chris@16: typedef std::pair< \ Chris@16: BOOST_DEDUCED_TYPENAME base_::const_iterator, \ Chris@16: BOOST_DEDUCED_TYPENAME base_::const_iterator> const_range_type; \ Chris@16: \ Chris@16: \ Chris@16: template< class LowerBounder, class UpperBounder> \ Chris@16: range_type range(LowerBounder lower,UpperBounder upper) \ Chris@16: { \ Chris@16: std::pair< \ Chris@16: \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::base_type::iterator, \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::base_type::iterator \ Chris@16: \ Chris@16: > r( this->base().range(lower,upper) ); \ Chris@16: \ Chris@16: return range_type( \ Chris@16: this->template functor< \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \ Chris@16: >() ( r.first ), \ Chris@16: this->template functor< \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \ Chris@16: >() ( r.second ) \ Chris@16: ); \ Chris@16: } \ Chris@16: \ Chris@16: template< class LowerBounder, class UpperBounder> \ Chris@16: const_range_type range(LowerBounder lower,UpperBounder upper) const \ Chris@16: { \ Chris@16: std::pair< \ Chris@16: \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::base_type::const_iterator, \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::base_type::const_iterator \ Chris@16: \ Chris@16: > r( this->base().range(lower,upper) ); \ Chris@16: \ Chris@16: return const_range_type( \ Chris@16: this->template functor< \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \ Chris@16: >() ( r.first ), \ Chris@16: this->template functor< \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \ Chris@16: >() ( r.second ) \ Chris@16: ); \ Chris@16: } Chris@16: /*===========================================================================*/ Chris@16: Chris@16: Chris@16: /*===========================================================================*/ Chris@16: #define BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(BASE) \ Chris@16: \ Chris@16: template< class InputIterator > \ Chris@16: void assign(InputIterator first,InputIterator last) \ Chris@16: { \ Chris@16: this->clear(); \ Chris@16: this->insert(this->end(),first,last); \ Chris@16: } \ Chris@16: \ Chris@16: void assign(BOOST_DEDUCED_TYPENAME BASE::size_type n, \ Chris@16: const BOOST_DEDUCED_TYPENAME BASE::value_type& v) \ Chris@16: { \ Chris@16: this->clear(); \ Chris@16: for(BOOST_DEDUCED_TYPENAME BASE::size_type i = 0 ; i < n ; ++i) \ Chris@16: { \ Chris@16: this->push_back(v); \ Chris@16: } \ Chris@16: } Chris@16: /*===========================================================================*/ Chris@16: Chris@16: Chris@16: /*===========================================================================*/ Chris@16: #define BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(BASE) \ Chris@16: \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::reference front() \ Chris@16: { \ Chris@16: return this->template functor< \ Chris@16: BOOST_DEDUCED_TYPENAME base_::value_from_base>() \ Chris@16: ( \ Chris@16: const_cast \ Chris@16: < \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::base_type::value_type & \ Chris@16: \ Chris@16: > ( this->base().front() ) \ Chris@16: ); \ Chris@16: } \ Chris@16: \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::reference back() \ Chris@16: { \ Chris@16: return this->template functor< \ Chris@16: BOOST_DEDUCED_TYPENAME base_::value_from_base>() \ Chris@16: ( \ Chris@16: const_cast \ Chris@16: < \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::base_type::value_type & \ Chris@16: \ Chris@16: >( this->base().back() ) \ Chris@16: ); \ Chris@16: } \ Chris@16: \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::const_reference front() const \ Chris@16: { \ Chris@16: return this->template functor< \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::value_from_base>() \ Chris@16: ( \ Chris@16: this->base().front() \ Chris@16: ); \ Chris@16: } \ Chris@16: \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::const_reference back() const \ Chris@16: { \ Chris@16: return this->template functor< \ Chris@16: BOOST_DEDUCED_TYPENAME BASE::value_from_base>() \ Chris@16: ( \ Chris@16: this->base().back() \ Chris@16: ); \ Chris@16: } Chris@16: /*===========================================================================*/ Chris@16: Chris@16: Chris@16: #endif // BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP