// 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 <boost/config.hpp> | |
#include <stdexcept> | |
#include <utility> | |
#include <boost/throw_exception.hpp> | |
#include <boost/type_traits/is_const.hpp> | |
#include <boost/mpl/if.hpp> | |
#include <boost/bimap/relation/support/get_pair_functor.hpp> | |
#include <boost/bimap/relation/detail/to_mutable_relation_functor.hpp> | |
#include <boost/bimap/container_adaptor/support/iterator_facade_converters.hpp> | |
#include <boost/bimap/relation/support/data_extractor.hpp> | |
#include <boost/bimap/relation/support/opposite_tag.hpp> | |
#include <boost/bimap/relation/support/pair_type_by.hpp> | |
#include <boost/bimap/support/iterator_type_by.hpp> | |
#include <boost/bimap/support/key_type_by.hpp> | |
#include <boost/bimap/support/data_type_by.hpp> | |
#include <boost/bimap/support/value_type_by.hpp> | |
#include <boost/bimap/detail/modifier_adaptor.hpp> | |
#include <boost/bimap/detail/debug/static_error.hpp> | |
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<TAG>::type, \ | |
BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ | |
iterator_type_by<TAG,BIMAP>::type, \ | |
BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ | |
const_iterator_type_by<TAG,BIMAP>::type, \ | |
BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ | |
OTHER_ITER<TAG,BIMAP>::type, \ | |
BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ | |
CONST_OTHER_ITER<TAG,BIMAP>::type, \ | |
::boost::bimaps::container_adaptor::support::iterator_facade_to_base \ | |
< \ | |
BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ | |
iterator_type_by<TAG,BIMAP>::type, \ | |
BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ | |
const_iterator_type_by<TAG,BIMAP>::type \ | |
\ | |
>, \ | |
::boost::mpl::na, \ | |
::boost::mpl::na, \ | |
::boost::bimaps::relation::detail:: \ | |
pair_to_relation_functor<TAG,BOOST_DEDUCED_TYPENAME BIMAP::relation>, \ | |
::boost::bimaps::relation::support:: \ | |
get_pair_functor<TAG, BOOST_DEDUCED_TYPENAME BIMAP::relation > \ | |
> | |
/*===========================================================================*/ | |
#if defined(BOOST_MSVC) | |
/*===========================================================================*/ | |
#define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP) \ | |
typedef ::boost::bimaps::detail::map_view_base< \ | |
TYPE<TAG,BIMAP>,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>,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<Tag,BimapType>::type, | |
BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: | |
const_iterator_type_by<Tag,BimapType>::type | |
> iterator_to_base_; | |
typedef ::boost::bimaps::relation::detail:: | |
pair_to_relation_functor<Tag, | |
BOOST_DEDUCED_TYPENAME BimapType::relation> value_to_base_; | |
typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: | |
key_type_by<Tag,BimapType>::type key_type_; | |
typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: | |
data_type_by<Tag,BimapType>::type data_type_; | |
typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: | |
pair_type_by<Tag, | |
BOOST_DEDUCED_TYPENAME BimapType::relation>::type value_type_; | |
typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: | |
iterator_type_by<Tag,BimapType>::type iterator_; | |
public: | |
bool replace(iterator_ position, const value_type_ & x) | |
{ | |
return derived().base().replace( | |
derived().template functor<iterator_to_base_>()(position), | |
derived().template functor<value_to_base_>()(x) | |
); | |
} | |
template< class CompatibleKey > | |
bool replace_key(iterator_ position, const CompatibleKey & k) | |
{ | |
return derived().base().replace( | |
derived().template functor<iterator_to_base_>()(position), | |
derived().template functor<value_to_base_>()( | |
value_type_(k,position->second) | |
) | |
); | |
} | |
template< class CompatibleData > | |
bool replace_data(iterator_ position, const CompatibleData & d) | |
{ | |
return derived().base().replace( | |
derived().template functor<iterator_to_base_>()(position), | |
derived().template functor<value_to_base_>()( | |
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<iterator_to_base_>()(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<Tag,BimapType>::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<iterator_to_base_>()(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<Tag,BimapType>::type, | |
BOOST_DEDUCED_TYPENAME BimapType::relation | |
>::type data_extractor_; | |
return derived().base().modify( | |
derived().template functor<iterator_to_base_>()(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<Derived*>(this); | |
} | |
Derived const& derived() const | |
{ | |
return *static_cast<Derived const*>(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<Tag,BimapType>::type data_type_; | |
public: | |
template< class CompatibleKey > | |
data_type_ & at(const CompatibleKey& k) | |
{ | |
typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: | |
iterator_type_by<Tag,BimapType>::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<Tag,BimapType>::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<Tag,BimapType>::type iterator; | |
typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: | |
value_type_by<Tag,BimapType>::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<Derived*>(this); | |
} | |
Derived const& derived() const | |
{ | |
return *static_cast<Derived const*>(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<Tag,BimapType>::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<Tag,BimapType>::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<Derived*>(this); | |
} | |
Derived const& derived() const | |
{ | |
return *static_cast<Derived const*>(this); | |
} | |
}; | |
template< class Derived, class Tag, class BimapType> | |
struct unique_map_view_access | |
{ | |
private: | |
typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: | |
value_type_by<Tag,BimapType>::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<Derived,Tag,BimapType>, | |
mutable_data_unique_map_view_access<Derived,Tag,BimapType> | |
>::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 <class T> 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 |