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