1// Boost.Bimap
2//
3// Copyright (c) 2006-2007 Matias Capeletto
4//
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)
8
9/// \file relation/mutant_relation.hpp
10/// \brief Defines the mutant_relation class
11
12#ifndef BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP
13#define BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP
14
15#if defined(_MSC_VER)
16#pragma once
17#endif
18
19#include <boost/config.hpp>
20
21#include <boost/mpl/vector.hpp>
22#include <boost/operators.hpp>
23#include <boost/call_traits.hpp>
24
25#ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
26 #include <boost/serialization/nvp.hpp>
27#endif // BOOST_BIMAP_DISABLE_SERIALIZATION
28
29#include <boost/functional/hash/hash.hpp>
30
31#include <boost/mpl/aux_/na.hpp>
32
33// Boost.Bimap
34#include <boost/bimap/tags/tagged.hpp>
35#include <boost/bimap/tags/support/default_tagged.hpp>
36#include <boost/bimap/tags/support/tag_of.hpp>
37#include <boost/bimap/tags/support/value_type_of.hpp>
38
39#include <boost/bimap/relation/member_at.hpp>
40#include <boost/bimap/relation/detail/mutant.hpp>
41#include <boost/bimap/relation/structured_pair.hpp>
42#include <boost/bimap/relation/symmetrical_base.hpp>
43#include <boost/bimap/relation/support/get.hpp>
44
45namespace boost {
46namespace bimaps {
47namespace relation {
48
49namespace detail {
50
51// This class is included so structured_pair and mutant_relation share
52// exactly the same class layout
53
54template< class LeftType, class RightType, bool force_mutable >
55class relation_storage :
56 public symmetrical_base<LeftType,RightType,force_mutable>
57{
58 typedef symmetrical_base<LeftType,RightType,force_mutable> base_;
59
60 typedef relation_storage storage_;
61
62 public:
63
64 typedef relation_storage<LeftType,RightType,false> non_mutable_storage;
65
66 typedef ::boost::mpl::vector2
67 <
68 relation_storage< LeftType, RightType, true >,
69 relation_storage< LeftType, RightType, false >
70
71 > mutant_views;
72
73 //@{
74 /// data
75 BOOST_DEDUCED_TYPENAME base_::left_value_type left;
76 BOOST_DEDUCED_TYPENAME base_::right_value_type right;
77 //@}
78
79 relation_storage() {}
80
81 relation_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
82 BOOST_DEDUCED_TYPENAME base_::left_value_type
83 >::param_type l,
84 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
85 BOOST_DEDUCED_TYPENAME base_::right_value_type
86 >::param_type r)
87
88 : left(l), right(r) {}
89
90 BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left() { return left; }
91 const BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left()const { return left; }
92 BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right() { return right; }
93 const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return right; }
94};
95
96
97
98template< class TA, class TB, class Info, bool force_mutable >
99class relation_info_hook : public
100 ::boost::bimaps::relation::detail::relation_storage<TA,TB,force_mutable>
101{
102 typedef ::boost::bimaps::relation::detail::
103 relation_storage<TA,TB,force_mutable> base_;
104
105 typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
106 default_tagged<Info,member_at::info>::type tagged_info_type;
107
108 public:
109 typedef BOOST_DEDUCED_TYPENAME tagged_info_type::value_type info_type;
110 typedef BOOST_DEDUCED_TYPENAME tagged_info_type::tag info_tag;
111
112 info_type info;
113
114 protected:
115
116 relation_info_hook() {}
117
118 relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
119 BOOST_DEDUCED_TYPENAME base_::left_value_type
120 >::param_type l,
121 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
122 BOOST_DEDUCED_TYPENAME base_::right_value_type
123 >::param_type r,
124 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
125 info_type
126 >::param_type i = info_type() )
127
128 : base_(l,r), info(i) {}
129
130 template< class Relation >
131 relation_info_hook( const Relation & rel ) :
132 base_(rel.left,rel.right),
133 info(rel.info) {}
134
135 template< class Relation >
136 void change_to( const Relation & rel )
137 {
138 base_::left = rel.left ;
139 base_::right = rel.right;
140 info = rel.info ;
141 }
142
143 #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
144 template< class Archive >
145 void serialize(Archive & ar, const unsigned int)
146 {
147 ar & ::boost::serialization::make_nvp("left" , base_::left );
148 ar & ::boost::serialization::make_nvp("right", base_::right);
149 ar & ::boost::serialization::make_nvp("info" , info );
150 }
151 #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
152};
153
154template< class TA, class TB, bool force_mutable>
155class relation_info_hook<TA,TB,::boost::mpl::na,force_mutable> :
156 public ::boost::bimaps::relation::detail::relation_storage<TA,TB,force_mutable>
157{
158 typedef ::boost::bimaps::relation::detail::
159 relation_storage<TA,TB,force_mutable> base_;
160
161 public:
162 typedef ::boost::mpl::na info_type;
163 typedef member_at::info info_tag;
164
165 protected:
166
167 relation_info_hook() {}
168
169 relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
170 BOOST_DEDUCED_TYPENAME base_::left_value_type
171 >::param_type l,
172 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
173 BOOST_DEDUCED_TYPENAME base_::right_value_type
174 >::param_type r)
175
176 : base_(l,r) {}
177
178 template< class Relation >
179 relation_info_hook( const Relation & rel ) :
180 base_(rel.left,rel.right) {}
181
182 template< class Relation >
183 void change_to( const Relation & rel )
184 {
185 base_::left = rel.left ;
186 base_::right = rel.right;
187 }
188
189 #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
190 template< class Archive >
191 void serialize(Archive & ar, const unsigned int)
192 {
193 ar & ::boost::serialization::make_nvp("left" , base_::left );
194 ar & ::boost::serialization::make_nvp("right", base_::right);
195 }
196 #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
197};
198
199
200} // namespace detail
201
202/// \brief Abstraction of a related pair of values, that extends the std::pair class.
203/**
204The mutant_relation is a mutant class. A mutant class can mutate
205with zero overhead in other classes that are called views.
206Each view has to be StorageCompatible with the base class
207of the mutant. Note that all the views have the following
208storage structure:
209
210\verbatim
211 __________
212 | |
213 | TA |
214 |__________|
215 | |
216 | TB |
217 |__________|
218
219\endverbatim
220
221See also select_relation, standard_relation.
222\ingroup relation_group
223 **/
224
225
226template< class TA, class TB, class Info = ::boost::mpl::na, bool force_mutable = false >
227class mutant_relation : public
228 ::boost::bimaps::relation::detail::
229 relation_info_hook<TA,TB,Info,force_mutable>
230{
231 typedef ::boost::bimaps::relation::detail::
232 relation_info_hook<TA,TB,Info,force_mutable> base_;
233
234 public:
235
236 // We have to know the type of the base where the types are
237 // defined because Boost.MultiIndex requires it.
238
239 typedef ::boost::bimaps::relation::detail::
240 relation_storage<TA,TB,force_mutable> storage_base;
241
242 /// Above view, non mutable view of the relation
243
244 typedef mutant_relation<TA,TB,Info,false> above_view;
245
246 //@{
247 /// A signature compatible std::pair that is a view of the relation.
248
249 typedef structured_pair< TA, TB, Info, normal_layout > left_pair;
250 typedef structured_pair< TB, TA, Info, mirror_layout > right_pair;
251 //@}
252
253 typedef ::boost::mpl::vector4
254 <
255 left_pair,
256 right_pair,
257
258 mutant_relation< TA, TB, Info, true >,
259 mutant_relation< TA, TB, Info, false >
260
261 > mutant_views;
262
263 mutant_relation() {}
264
265 mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
266 BOOST_DEDUCED_TYPENAME base_:: left_value_type
267 >::param_type l,
268 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
269 BOOST_DEDUCED_TYPENAME base_::right_value_type
270 >::param_type r) :
271 base_(l,r) {}
272
273 mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
274 BOOST_DEDUCED_TYPENAME base_:: left_value_type
275 >::param_type l,
276 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
277 BOOST_DEDUCED_TYPENAME base_::right_value_type
278 >::param_type r,
279 BOOST_DEDUCED_TYPENAME ::boost::call_traits<
280 BOOST_DEDUCED_TYPENAME base_::info_type
281 >::param_type i) :
282 base_(l,r,i) {}
283
284 mutant_relation(const mutant_relation<TA,TB,Info,false> & rel) :
285 base_(rel) {}
286
287 mutant_relation(const mutant_relation<TA,TB,Info,true> & rel) :
288 base_(rel) {}
289
290 // Operators
291
292 template< bool FM >
293 mutant_relation& operator=(const mutant_relation<TA,TB,Info,FM> & rel)
294 {
295 base_::change_to(rel);
296 return *this;
297 }
298
299 // The following functions are redundant if you only consider this class.
300 // They are included to make easier the construction of the get and the
301 // pair_by metafunction. Remember that not all compiler supports the mutant
302 // idiom.
303
304 left_pair & get_left_pair()
305 {
306 return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
307 }
308
309 const left_pair & get_left_pair() const
310 {
311 return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
312 }
313
314 right_pair & get_right_pair()
315 {
316 return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
317 }
318
319 const right_pair & get_right_pair() const
320 {
321 return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
322 }
323
324 above_view & get_view()
325 {
326 return ::boost::bimaps::relation::detail::mutate<above_view>(*this);
327 }
328
329 const above_view & get_view() const
330 {
331 return ::boost::bimaps::relation::detail::mutate<above_view>(*this);
332 }
333
334 template< class Tag >
335 const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
336 result_of::get<Tag,const mutant_relation>::type
337 get() const
338 {
339 return ::boost::bimaps::relation::support::get<Tag>(*this);
340 }
341
342 template< class Tag >
343 BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
344 result_of::get<Tag,mutant_relation>::type
345 get()
346 {
347 return ::boost::bimaps::relation::support::get<Tag>(*this);
348 }
349
350 #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
351
352 private:
353 friend class ::boost::serialization::access;
354
355 template<class Archive>
356 void serialize(Archive & ar, const unsigned int version)
357 {
358 base_::serialize(ar,version);
359 }
360
361 #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
362};
363
364// hash value
365
366template< class FirstType, class SecondType, bool FM >
367std::size_t hash_value(const detail::relation_storage<FirstType,SecondType,FM> & r)
368{
369 std::size_t seed = 0;
370 ::boost::hash_combine(seed, r. left );
371 ::boost::hash_combine(seed, r.right );
372
373 return seed;
374}
375
376// mutant_relation - mutant_relation
377
378template< class FirstType, class SecondType, bool FM1, bool FM2 >
379bool operator==(const detail::relation_storage<FirstType,SecondType,FM1> & a,
380 const detail::relation_storage<FirstType,SecondType,FM2> & b)
381{
382 return ( ( a.left == b.left ) &&
383 ( a.right == b.right ) );
384}
385
386template< class FirstType, class SecondType, bool FM1, bool FM2 >
387bool operator!=(const detail::relation_storage<FirstType,SecondType,FM1> & a,
388 const detail::relation_storage<FirstType,SecondType,FM2> & b)
389{
390 return ! ( a == b );
391}
392
393template< class FirstType, class SecondType, bool FM1, bool FM2 >
394bool operator<(const detail::relation_storage<FirstType,SecondType,FM1> & a,
395 const detail::relation_storage<FirstType,SecondType,FM2> & b)
396{
397 return ( ( a.left < b.left ) ||
398 (( a.left == b.left ) && ( a.right < b.right )));
399}
400
401template< class FirstType, class SecondType, bool FM1, bool FM2 >
402bool operator<=(const detail::relation_storage<FirstType,SecondType,FM1> & a,
403 const detail::relation_storage<FirstType,SecondType,FM2> & b)
404{
405 return ( ( a.left < b.left ) ||
406 (( a.left == b.left ) && ( a.right <= b.right )));
407}
408
409template< class FirstType, class SecondType, bool FM1, bool FM2 >
410bool operator>(const detail::relation_storage<FirstType,SecondType,FM1> & a,
411 const detail::relation_storage<FirstType,SecondType,FM2> & b)
412{
413 return ( ( a.left > b.left ) ||
414 (( a.left == b.left ) && ( a.right > b.right )));
415}
416
417template< class FirstType, class SecondType, bool FM1, bool FM2 >
418bool operator>=(const detail::relation_storage<FirstType,SecondType,FM1> & a,
419 const detail::relation_storage<FirstType,SecondType,FM2> & b)
420{
421 return ( ( a.left > b.left ) ||
422 (( a.left == b.left ) && ( a.right >= b.right )));
423}
424
425namespace detail {
426
427template< class TA, class TB, class Info, bool force_mutable>
428mutant_relation<TA,TB,Info,force_mutable>
429 copy_with_left_replaced(mutant_relation<TA,TB,Info,force_mutable> const& rel,
430 BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME
431 mutant_relation<TA,TB,Info,force_mutable>::left_value_type>
432 ::param_type l)
433{
434 return mutant_relation<TA,TB,Info,force_mutable>(l,rel.right,rel.info);
435}
436
437template< class TA, class TB, bool force_mutable>
438mutant_relation<TA,TB,::boost::mpl::na,force_mutable>
439 copy_with_left_replaced(mutant_relation<TA,TB,::boost::mpl::na,force_mutable> const& rel,
440 BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME
441 mutant_relation<TA,TB,::boost::mpl::na,force_mutable>::left_value_type>
442 ::param_type l)
443{
444 return mutant_relation<TA,TB,::boost::mpl::na,force_mutable>(l,rel.right);
445}
446
447template< class TA, class TB, class Info, bool force_mutable>
448mutant_relation<TA,TB,Info,force_mutable>
449 copy_with_right_replaced(mutant_relation<TA,TB,Info,force_mutable> const& rel,
450 BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME
451 mutant_relation<TA,TB,Info,force_mutable>::right_value_type>
452 ::param_type r)
453{
454 return mutant_relation<TA,TB,Info,force_mutable>(rel.left,r,rel.info);
455}
456
457template< class TA, class TB, bool force_mutable>
458mutant_relation<TA,TB,::boost::mpl::na,force_mutable>
459 copy_with_right_replaced(mutant_relation<TA,TB,::boost::mpl::na,force_mutable> const& rel,
460 BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME
461 mutant_relation<TA,TB,::boost::mpl::na,force_mutable>::right_value_type>
462 ::param_type r)
463{
464 return mutant_relation<TA,TB,::boost::mpl::na,force_mutable>(rel.left,r);
465}
466
467} // namespace detail
468
469} // namespace relation
470} // namespace bimaps
471} // namespace boost
472
473
474#endif // BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP
475
476
477
478

source code of boost/boost/bimap/relation/mutant_relation.hpp