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 relation/mutant_relation.hpp Chris@16: /// \brief Defines the mutant_relation class Chris@16: Chris@16: #ifndef BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP Chris@16: #define BOOST_BIMAP_RELATION_MUTANT_RELATION_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: #include Chris@16: Chris@16: #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION Chris@16: #include Chris@16: #endif // BOOST_BIMAP_DISABLE_SERIALIZATION Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: // Boost.Bimap Chris@16: #include 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: Chris@16: namespace boost { Chris@16: namespace bimaps { Chris@16: namespace relation { Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: // This class is included so structured_pair and mutant_relation share Chris@16: // exactly the same class layout Chris@16: Chris@16: template< class LeftType, class RightType, bool force_mutable > Chris@16: class relation_storage : Chris@16: public symmetrical_base Chris@16: { Chris@16: typedef symmetrical_base base_; Chris@16: Chris@16: typedef relation_storage storage_; Chris@16: Chris@16: public: Chris@16: Chris@16: typedef relation_storage non_mutable_storage; Chris@16: Chris@16: typedef ::boost::mpl::vector2 Chris@16: < Chris@16: relation_storage< LeftType, RightType, true >, Chris@16: relation_storage< LeftType, RightType, false > Chris@16: Chris@16: > mutant_views; Chris@16: Chris@16: //@{ Chris@16: /// data Chris@16: BOOST_DEDUCED_TYPENAME base_::left_value_type left; Chris@16: BOOST_DEDUCED_TYPENAME base_::right_value_type right; Chris@16: //@} Chris@16: Chris@16: relation_storage() {} Chris@16: Chris@16: relation_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_::left_value_type Chris@16: >::param_type l, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_::right_value_type Chris@16: >::param_type r) Chris@16: Chris@16: : left(l), right(r) {} Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left() { return left; } Chris@16: const BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left()const { return left; } Chris@16: BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right() { return right; } Chris@16: const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return right; } Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: template< class TA, class TB, class Info, bool force_mutable > Chris@16: class relation_info_hook : public Chris@16: ::boost::bimaps::relation::detail::relation_storage Chris@16: { Chris@16: typedef ::boost::bimaps::relation::detail:: Chris@16: relation_storage base_; Chris@16: Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: Chris@16: default_tagged::type tagged_info_type; Chris@16: Chris@16: public: Chris@16: typedef BOOST_DEDUCED_TYPENAME tagged_info_type::value_type info_type; Chris@16: typedef BOOST_DEDUCED_TYPENAME tagged_info_type::tag info_tag; Chris@16: Chris@16: info_type info; Chris@16: Chris@16: protected: Chris@16: Chris@16: relation_info_hook() {} Chris@16: Chris@16: relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_::left_value_type Chris@16: >::param_type l, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_::right_value_type Chris@16: >::param_type r, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: info_type Chris@16: >::param_type i = info_type() ) Chris@16: Chris@16: : base_(l,r), info(i) {} Chris@16: Chris@16: template< class Relation > Chris@16: relation_info_hook( const Relation & rel ) : Chris@16: base_(rel.left,rel.right), Chris@16: info(rel.info) {} Chris@16: Chris@16: template< class Relation > Chris@16: void change_to( const Relation & rel ) Chris@16: { Chris@16: base_::left = rel.left ; Chris@16: base_::right = rel.right; Chris@16: info = rel.info ; Chris@16: } Chris@16: Chris@16: #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION Chris@16: template< class Archive > Chris@16: void serialize(Archive & ar, const unsigned int) Chris@16: { Chris@16: ar & ::boost::serialization::make_nvp("left" , base_::left ); Chris@16: ar & ::boost::serialization::make_nvp("right", base_::right); Chris@16: ar & ::boost::serialization::make_nvp("info" , info ); Chris@16: } Chris@16: #endif // BOOST_BIMAP_DISABLE_SERIALIZATION Chris@16: }; Chris@16: Chris@16: template< class TA, class TB, bool force_mutable> Chris@16: class relation_info_hook : Chris@16: public ::boost::bimaps::relation::detail::relation_storage Chris@16: { Chris@16: typedef ::boost::bimaps::relation::detail:: Chris@16: relation_storage base_; Chris@16: Chris@16: public: Chris@16: typedef ::boost::mpl::na info_type; Chris@16: typedef member_at::info info_tag; Chris@16: Chris@16: protected: Chris@16: Chris@16: relation_info_hook() {} Chris@16: Chris@16: relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_::left_value_type Chris@16: >::param_type l, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_::right_value_type Chris@16: >::param_type r) Chris@16: Chris@16: : base_(l,r) {} Chris@16: Chris@16: template< class Relation > Chris@16: relation_info_hook( const Relation & rel ) : Chris@16: base_(rel.left,rel.right) {} Chris@16: Chris@16: template< class Relation > Chris@16: void change_to( const Relation & rel ) Chris@16: { Chris@16: base_::left = rel.left ; Chris@16: base_::right = rel.right; Chris@16: } Chris@16: Chris@16: #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION Chris@16: template< class Archive > Chris@16: void serialize(Archive & ar, const unsigned int) Chris@16: { Chris@16: ar & ::boost::serialization::make_nvp("left" , base_::left ); Chris@16: ar & ::boost::serialization::make_nvp("right", base_::right); Chris@16: } Chris@16: #endif // BOOST_BIMAP_DISABLE_SERIALIZATION Chris@16: }; Chris@16: Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: /// \brief Abstraction of a related pair of values, that extends the std::pair class. Chris@16: /** Chris@16: The mutant_relation is a mutant class. A mutant class can mutate Chris@16: with zero overhead in other classes that are called views. Chris@16: Each view has to be StorageCompatible with the base class Chris@16: of the mutant. Note that all the views have the following Chris@16: storage structure: Chris@16: Chris@16: \verbatim Chris@16: __________ Chris@16: | | Chris@16: | TA | Chris@16: |__________| Chris@16: | | Chris@16: | TB | Chris@16: |__________| Chris@16: Chris@16: \endverbatim Chris@16: Chris@16: See also select_relation, standard_relation. Chris@16: \ingroup relation_group Chris@16: **/ Chris@16: Chris@16: Chris@16: template< class TA, class TB, class Info = ::boost::mpl::na, bool force_mutable = false > Chris@16: class mutant_relation : public Chris@16: ::boost::bimaps::relation::detail:: Chris@16: relation_info_hook Chris@16: { Chris@16: typedef ::boost::bimaps::relation::detail:: Chris@16: relation_info_hook base_; Chris@16: Chris@16: public: Chris@16: Chris@16: // We have to know the type of the base where the types are Chris@16: // defined because Boost.MultiIndex requires it. Chris@16: Chris@16: typedef ::boost::bimaps::relation::detail:: Chris@16: relation_storage storage_base; Chris@16: Chris@16: /// Above view, non mutable view of the relation Chris@16: Chris@16: typedef mutant_relation above_view; Chris@16: Chris@16: //@{ Chris@16: /// A signature compatible std::pair that is a view of the relation. Chris@16: Chris@16: typedef structured_pair< TA, TB, Info, normal_layout > left_pair; Chris@16: typedef structured_pair< TB, TA, Info, mirror_layout > right_pair; Chris@16: //@} Chris@16: Chris@16: typedef ::boost::mpl::vector4 Chris@16: < Chris@16: left_pair, Chris@16: right_pair, Chris@16: Chris@16: mutant_relation< TA, TB, Info, true >, Chris@16: mutant_relation< TA, TB, Info, false > Chris@16: Chris@16: > mutant_views; Chris@16: Chris@16: mutant_relation() {} Chris@16: Chris@16: mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_:: left_value_type Chris@16: >::param_type l, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_::right_value_type Chris@16: >::param_type r) : Chris@16: base_(l,r) {} Chris@16: Chris@16: mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_:: left_value_type Chris@16: >::param_type l, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_::right_value_type Chris@16: >::param_type r, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< Chris@16: BOOST_DEDUCED_TYPENAME base_::info_type Chris@16: >::param_type i) : Chris@16: base_(l,r,i) {} Chris@16: Chris@16: mutant_relation(const mutant_relation & rel) : Chris@16: base_(rel) {} Chris@16: Chris@16: mutant_relation(const mutant_relation & rel) : Chris@16: base_(rel) {} Chris@16: Chris@16: // Operators Chris@16: Chris@16: template< bool FM > Chris@16: mutant_relation& operator=(const mutant_relation & rel) Chris@16: { Chris@16: base_::change_to(rel); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // The following functions are redundant if you only consider this class. Chris@16: // They are included to make easier the construction of the get and the Chris@16: // pair_by metafunction. Remember that not all compiler supports the mutant Chris@16: // idiom. Chris@16: Chris@16: left_pair & get_left_pair() Chris@16: { Chris@16: return ::boost::bimaps::relation::detail::mutate(*this); Chris@16: } Chris@16: Chris@16: const left_pair & get_left_pair() const Chris@16: { Chris@16: return ::boost::bimaps::relation::detail::mutate(*this); Chris@16: } Chris@16: Chris@16: right_pair & get_right_pair() Chris@16: { Chris@16: return ::boost::bimaps::relation::detail::mutate(*this); Chris@16: } Chris@16: Chris@16: const right_pair & get_right_pair() const Chris@16: { Chris@16: return ::boost::bimaps::relation::detail::mutate(*this); Chris@16: } Chris@16: Chris@16: above_view & get_view() Chris@16: { Chris@16: return ::boost::bimaps::relation::detail::mutate(*this); Chris@16: } Chris@16: Chris@16: const above_view & get_view() const Chris@16: { Chris@16: return ::boost::bimaps::relation::detail::mutate(*this); Chris@16: } Chris@16: Chris@16: template< class Tag > Chris@16: const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: Chris@16: result_of::get::type Chris@101: get() const Chris@16: { Chris@16: return ::boost::bimaps::relation::support::get(*this); Chris@16: } Chris@16: Chris@16: template< class Tag > Chris@16: BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: Chris@16: result_of::get::type Chris@101: get() Chris@16: { Chris@16: return ::boost::bimaps::relation::support::get(*this); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION Chris@16: Chris@16: private: Chris@16: friend class ::boost::serialization::access; Chris@16: Chris@16: template Chris@16: void serialize(Archive & ar, const unsigned int version) Chris@16: { Chris@16: base_::serialize(ar,version); Chris@16: } Chris@16: Chris@16: #endif // BOOST_BIMAP_DISABLE_SERIALIZATION Chris@16: }; Chris@16: Chris@16: // hash value Chris@16: Chris@16: template< class FirstType, class SecondType, bool FM > Chris@16: std::size_t hash_value(const detail::relation_storage & r) Chris@16: { Chris@16: std::size_t seed = 0; Chris@16: ::boost::hash_combine(seed, r. left ); Chris@16: ::boost::hash_combine(seed, r.right ); Chris@16: Chris@16: return seed; Chris@16: } Chris@16: Chris@16: // mutant_relation - mutant_relation Chris@16: Chris@16: template< class FirstType, class SecondType, bool FM1, bool FM2 > Chris@16: bool operator==(const detail::relation_storage & a, Chris@16: const detail::relation_storage & b) Chris@16: { Chris@16: return ( ( a.left == b.left ) && Chris@16: ( a.right == b.right ) ); Chris@16: } Chris@16: Chris@16: template< class FirstType, class SecondType, bool FM1, bool FM2 > Chris@16: bool operator!=(const detail::relation_storage & a, Chris@16: const detail::relation_storage & b) Chris@16: { Chris@16: return ! ( a == b ); Chris@16: } Chris@16: Chris@16: template< class FirstType, class SecondType, bool FM1, bool FM2 > Chris@16: bool operator<(const detail::relation_storage & a, Chris@16: const detail::relation_storage & b) Chris@16: { Chris@16: return ( ( a.left < b.left ) || Chris@16: (( a.left == b.left ) && ( a.right < b.right ))); Chris@16: } Chris@16: Chris@16: template< class FirstType, class SecondType, bool FM1, bool FM2 > Chris@16: bool operator<=(const detail::relation_storage & a, Chris@16: const detail::relation_storage & b) Chris@16: { Chris@16: return ( ( a.left < b.left ) || Chris@16: (( a.left == b.left ) && ( a.right <= b.right ))); Chris@16: } Chris@16: Chris@16: template< class FirstType, class SecondType, bool FM1, bool FM2 > Chris@16: bool operator>(const detail::relation_storage & a, Chris@16: const detail::relation_storage & b) Chris@16: { Chris@16: return ( ( a.left > b.left ) || Chris@16: (( a.left == b.left ) && ( a.right > b.right ))); Chris@16: } Chris@16: Chris@16: template< class FirstType, class SecondType, bool FM1, bool FM2 > Chris@16: bool operator>=(const detail::relation_storage & a, Chris@16: const detail::relation_storage & b) Chris@16: { Chris@16: return ( ( a.left > b.left ) || Chris@16: (( a.left == b.left ) && ( a.right >= b.right ))); Chris@16: } Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template< class TA, class TB, class Info, bool force_mutable> Chris@16: mutant_relation Chris@16: copy_with_left_replaced(mutant_relation const& rel, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME Chris@16: mutant_relation::left_value_type> Chris@16: ::param_type l) Chris@16: { Chris@16: return mutant_relation(l,rel.right,rel.info); Chris@16: } Chris@16: Chris@16: template< class TA, class TB, bool force_mutable> Chris@16: mutant_relation Chris@16: copy_with_left_replaced(mutant_relation const& rel, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME Chris@16: mutant_relation::left_value_type> Chris@16: ::param_type l) Chris@16: { Chris@16: return mutant_relation(l,rel.right); Chris@16: } Chris@16: Chris@16: template< class TA, class TB, class Info, bool force_mutable> Chris@16: mutant_relation Chris@16: copy_with_right_replaced(mutant_relation const& rel, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME Chris@16: mutant_relation::right_value_type> Chris@16: ::param_type r) Chris@16: { Chris@16: return mutant_relation(rel.left,r,rel.info); Chris@16: } Chris@16: Chris@16: template< class TA, class TB, bool force_mutable> Chris@16: mutant_relation Chris@16: copy_with_right_replaced(mutant_relation const& rel, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME Chris@16: mutant_relation::right_value_type> Chris@16: ::param_type r) Chris@16: { Chris@16: return mutant_relation(rel.left,r); Chris@16: } Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: } // namespace relation Chris@16: } // namespace bimaps Chris@16: } // namespace boost Chris@16: Chris@16: Chris@16: #endif // BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP Chris@16: Chris@16: Chris@16: