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