3 // Copyright (c) 2006-2007 Matias Capeletto
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 /// \file relation/mutant_relation.hpp
10 /// \brief Defines the mutant_relation class
12 #ifndef BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP
13 #define BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP
15 #if defined(_MSC_VER) && (_MSC_VER>=1200)
19 #include <boost/config.hpp>
21 #include <boost/mpl/vector.hpp>
22 #include <boost/operators.hpp>
23 #include <boost/call_traits.hpp>
24 // #include <boost/serialization/nvp.hpp>
26 #include <boost/functional/hash/hash.hpp>
28 #include <boost/mpl/aux_/na.hpp>
31 #include <boost/bimap/tags/tagged.hpp>
32 #include <boost/bimap/tags/support/default_tagged.hpp>
33 #include <boost/bimap/tags/support/tag_of.hpp>
34 #include <boost/bimap/tags/support/value_type_of.hpp>
36 #include <boost/bimap/relation/member_at.hpp>
37 #include <boost/bimap/relation/detail/mutant.hpp>
38 #include <boost/bimap/relation/structured_pair.hpp>
39 #include <boost/bimap/relation/symmetrical_base.hpp>
40 #include <boost/bimap/relation/support/get.hpp>
48 // This class is included so structured_pair and mutant_relation share
49 // exactly the same class layout
51 template< class LeftType, class RightType, bool force_mutable >
52 class relation_storage :
53 public symmetrical_base<LeftType,RightType,force_mutable>
55 typedef symmetrical_base<LeftType,RightType,force_mutable> base_;
57 typedef relation_storage storage_;
61 typedef relation_storage<LeftType,RightType,false> non_mutable_storage;
63 typedef ::boost::mpl::vector2
65 relation_storage< LeftType, RightType, true >,
66 relation_storage< LeftType, RightType, false >
72 BOOST_DEDUCED_TYPENAME base_::left_value_type left;
73 BOOST_DEDUCED_TYPENAME base_::right_value_type right;
78 relation_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
79 BOOST_DEDUCED_TYPENAME base_::left_value_type
81 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
82 BOOST_DEDUCED_TYPENAME base_::right_value_type
85 : left(l), right(r) {}
87 BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left() { return left; }
88 const BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left()const { return left; }
89 BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right() { return right; }
90 const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return right; }
95 template< class TA, class TB, class Info, bool force_mutable >
96 class relation_info_hook : public
97 ::boost::bimaps::relation::detail::relation_storage<TA,TB,force_mutable>
99 typedef ::boost::bimaps::relation::detail::
100 relation_storage<TA,TB,force_mutable> base_;
102 typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
103 default_tagged<Info,member_at::info>::type tagged_info_type;
106 typedef BOOST_DEDUCED_TYPENAME tagged_info_type::value_type info_type;
107 typedef BOOST_DEDUCED_TYPENAME tagged_info_type::tag info_tag;
113 relation_info_hook() {}
115 relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
116 BOOST_DEDUCED_TYPENAME base_::left_value_type
118 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
119 BOOST_DEDUCED_TYPENAME base_::right_value_type
121 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
123 >::param_type i = info_type() )
125 : base_(l,r), info(i) {}
127 template< class Relation >
128 relation_info_hook( const Relation & rel ) :
129 base_(rel.left,rel.right),
132 template< class Relation >
133 void change_to( const Relation & rel )
135 base_::left = rel.left ;
136 base_::right = rel.right;
140 #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
141 template< class Archive >
142 void serialize(Archive & ar, const unsigned int version)
144 ar & ::boost::serialization::make_nvp("left" , base_::left );
145 ar & ::boost::serialization::make_nvp("right", base_::right);
146 ar & ::boost::serialization::make_nvp("info" , info );
148 #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
151 template< class TA, class TB, bool force_mutable>
152 class relation_info_hook<TA,TB,::boost::mpl::na,force_mutable> :
153 public ::boost::bimaps::relation::detail::relation_storage<TA,TB,force_mutable>
155 typedef ::boost::bimaps::relation::detail::
156 relation_storage<TA,TB,force_mutable> base_;
159 typedef ::boost::mpl::na info_type;
160 typedef member_at::info info_tag;
164 relation_info_hook() {}
166 relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
167 BOOST_DEDUCED_TYPENAME base_::left_value_type
169 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
170 BOOST_DEDUCED_TYPENAME base_::right_value_type
175 template< class Relation >
176 relation_info_hook( const Relation & rel ) :
177 base_(rel.left,rel.right) {}
179 template< class Relation >
180 void change_to( const Relation & rel )
182 base_::left = rel.left ;
183 base_::right = rel.right;
186 #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
187 template< class Archive >
188 void serialize(Archive & ar, const unsigned int version)
190 ar & ::boost::serialization::make_nvp("left" , base_::left );
191 ar & ::boost::serialization::make_nvp("right", base_::right);
193 #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
197 } // namespace detail
199 /// \brief Abstraction of a related pair of values, that extends the std::pair class.
201 The mutant_relation is a mutant class. A mutant class can mutate
202 with zero overhead in other classes that are called views.
203 Each view has to be StorageCompatible with the base class
204 of the mutant. Note that all the views have the following
218 See also select_relation, standard_relation.
219 \ingroup relation_group
223 template< class TA, class TB, class Info = ::boost::mpl::na, bool force_mutable = false >
224 class mutant_relation : public
225 ::boost::bimaps::relation::detail::
226 relation_info_hook<TA,TB,Info,force_mutable>
228 typedef ::boost::bimaps::relation::detail::
229 relation_info_hook<TA,TB,Info,force_mutable> base_;
233 // We have to know the type of the base where the types are
234 // defined because Boost.MultiIndex requires it.
236 typedef ::boost::bimaps::relation::detail::
237 relation_storage<TA,TB,force_mutable> storage_base;
239 /// Above view, non mutable view of the relation
241 typedef mutant_relation<TA,TB,Info,false> above_view;
244 /// A signature compatible std::pair that is a view of the relation.
246 typedef structured_pair< TA, TB, Info, normal_layout > left_pair;
247 typedef structured_pair< TB, TA, Info, mirror_layout > right_pair;
250 typedef ::boost::mpl::vector4
255 mutant_relation< TA, TB, Info, true >,
256 mutant_relation< TA, TB, Info, false >
262 mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
263 BOOST_DEDUCED_TYPENAME base_:: left_value_type
265 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
266 BOOST_DEDUCED_TYPENAME base_::right_value_type
270 mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
271 BOOST_DEDUCED_TYPENAME base_:: left_value_type
273 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
274 BOOST_DEDUCED_TYPENAME base_::right_value_type
276 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
277 BOOST_DEDUCED_TYPENAME base_::info_type
281 mutant_relation(const mutant_relation<TA,TB,Info,false> & rel) :
284 mutant_relation(const mutant_relation<TA,TB,Info,true> & rel) :
290 mutant_relation& operator=(const mutant_relation<TA,TB,Info,FM> & rel)
292 base_::change_to(rel);
296 // The following functions are redundant if you only consider this class.
297 // They are included to make easier the construction of the get and the
298 // pair_by metafunction. Remember that not all compiler supports the mutant
301 left_pair & get_left_pair()
303 return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
306 const left_pair & get_left_pair() const
308 return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
311 right_pair & get_right_pair()
313 return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
316 const right_pair & get_right_pair() const
318 return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
321 above_view & get_view()
323 return ::boost::bimaps::relation::detail::mutate<above_view>(*this);
326 const above_view & get_view() const
328 return ::boost::bimaps::relation::detail::mutate<above_view>(*this);
331 template< class Tag >
332 const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
333 result_of::get<Tag,const mutant_relation>::type
334 get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const
336 return ::boost::bimaps::relation::support::get<Tag>(*this);
339 template< class Tag >
340 BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
341 result_of::get<Tag,mutant_relation>::type
342 get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
344 return ::boost::bimaps::relation::support::get<Tag>(*this);
347 #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
350 friend class ::boost::serialization::access;
352 template<class Archive>
353 void serialize(Archive & ar, const unsigned int version)
355 base_::serialize(ar,version);
358 #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
363 template< class FirstType, class SecondType, bool FM >
364 std::size_t hash_value(const detail::relation_storage<FirstType,SecondType,FM> & r)
366 std::size_t seed = 0;
367 ::boost::hash_combine(seed, r. left );
368 ::boost::hash_combine(seed, r.right );
373 // mutant_relation - mutant_relation
375 template< class FirstType, class SecondType, bool FM1, bool FM2 >
376 bool operator==(const detail::relation_storage<FirstType,SecondType,FM1> & a,
377 const detail::relation_storage<FirstType,SecondType,FM2> & b)
379 return ( ( a.left == b.left ) &&
380 ( a.right == b.right ) );
383 template< class FirstType, class SecondType, bool FM1, bool FM2 >
384 bool operator!=(const detail::relation_storage<FirstType,SecondType,FM1> & a,
385 const detail::relation_storage<FirstType,SecondType,FM2> & b)
390 template< class FirstType, class SecondType, bool FM1, bool FM2 >
391 bool operator<(const detail::relation_storage<FirstType,SecondType,FM1> & a,
392 const detail::relation_storage<FirstType,SecondType,FM2> & b)
394 return ( ( a.left < b.left ) ||
395 (( a.left == b.left ) && ( a.right < b.right )));
398 template< class FirstType, class SecondType, bool FM1, bool FM2 >
399 bool operator<=(const detail::relation_storage<FirstType,SecondType,FM1> & a,
400 const detail::relation_storage<FirstType,SecondType,FM2> & b)
402 return ( ( a.left < b.left ) ||
403 (( a.left == b.left ) && ( a.right <= b.right )));
406 template< class FirstType, class SecondType, bool FM1, bool FM2 >
407 bool operator>(const detail::relation_storage<FirstType,SecondType,FM1> & a,
408 const detail::relation_storage<FirstType,SecondType,FM2> & b)
410 return ( ( a.left > b.left ) ||
411 (( a.left == b.left ) && ( a.right > b.right )));
414 template< class FirstType, class SecondType, bool FM1, bool FM2 >
415 bool operator>=(const detail::relation_storage<FirstType,SecondType,FM1> & a,
416 const detail::relation_storage<FirstType,SecondType,FM2> & b)
418 return ( ( a.left > b.left ) ||
419 (( a.left == b.left ) && ( a.right >= b.right )));
422 } // namespace relation
423 } // namespace bimaps
427 #endif // BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP