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 | |
45 | namespace boost { |
46 | namespace bimaps { |
47 | namespace relation { |
48 | |
49 | namespace detail { |
50 | |
51 | // This class is included so structured_pair and mutant_relation share |
52 | // exactly the same class layout |
53 | |
54 | template< class LeftType, class RightType, bool force_mutable > |
55 | class 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 | |
98 | template< class TA, class TB, class Info, bool force_mutable > |
99 | class 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 | |
154 | template< class TA, class TB, bool force_mutable> |
155 | class 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 | /** |
204 | The mutant_relation is a mutant class. A mutant class can mutate |
205 | with zero overhead in other classes that are called views. |
206 | Each view has to be StorageCompatible with the base class |
207 | of the mutant. Note that all the views have the following |
208 | storage structure: |
209 | |
210 | \verbatim |
211 | __________ |
212 | | | |
213 | | TA | |
214 | |__________| |
215 | | | |
216 | | TB | |
217 | |__________| |
218 | |
219 | \endverbatim |
220 | |
221 | See also select_relation, standard_relation. |
222 | \ingroup relation_group |
223 | **/ |
224 | |
225 | |
226 | template< class TA, class TB, class Info = ::boost::mpl::na, bool force_mutable = false > |
227 | class 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 | |
366 | template< class FirstType, class SecondType, bool FM > |
367 | std::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 | |
378 | template< class FirstType, class SecondType, bool FM1, bool FM2 > |
379 | bool 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 | |
386 | template< class FirstType, class SecondType, bool FM1, bool FM2 > |
387 | bool 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 | |
393 | template< class FirstType, class SecondType, bool FM1, bool FM2 > |
394 | bool 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 | |
401 | template< class FirstType, class SecondType, bool FM1, bool FM2 > |
402 | bool 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 | |
409 | template< class FirstType, class SecondType, bool FM1, bool FM2 > |
410 | bool 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 | |
417 | template< class FirstType, class SecondType, bool FM1, bool FM2 > |
418 | bool 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 | |
425 | namespace detail { |
426 | |
427 | template< class TA, class TB, class Info, bool force_mutable> |
428 | mutant_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 | |
437 | template< class TA, class TB, bool force_mutable> |
438 | mutant_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 | |
447 | template< class TA, class TB, class Info, bool force_mutable> |
448 | mutant_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 | |
457 | template< class TA, class TB, bool force_mutable> |
458 | mutant_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 | |