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