• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
relation_storage()79     relation_storage() {}
80 
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)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 
get_left()90           BOOST_DEDUCED_TYPENAME base_:: left_value_type &  get_left()      { return left;  }
get_left() const91     const BOOST_DEDUCED_TYPENAME base_:: left_value_type &  get_left()const { return left;  }
get_right()92           BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()      { return right; }
get_right() const93     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 
relation_info_hook()116     relation_info_hook() {}
117 
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 ())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 >
relation_info_hook(const Relation & rel)131     relation_info_hook( const Relation & rel ) :
132         base_(rel.left,rel.right),
133         info(rel.info) {}
134 
135     template< class Relation >
change_to(const Relation & rel)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 >
serialize(Archive & ar,const unsigned int)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 
relation_info_hook()167     relation_info_hook() {}
168 
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)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 >
relation_info_hook(const Relation & rel)179     relation_info_hook( const Relation & rel ) :
180         base_(rel.left,rel.right) {}
181 
182     template< class Relation >
change_to(const Relation & rel)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 >
serialize(Archive & ar,const unsigned int)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 
mutant_relation()263     mutant_relation() {}
264 
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)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 
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)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 
mutant_relation(const mutant_relation<TA,TB,Info,false> & rel)284     mutant_relation(const mutant_relation<TA,TB,Info,false> & rel) :
285         base_(rel) {}
286 
mutant_relation(const mutant_relation<TA,TB,Info,true> & rel)287     mutant_relation(const mutant_relation<TA,TB,Info,true> & rel) :
288         base_(rel) {}
289 
290     // Operators
291 
292     template< bool FM >
operator =(const mutant_relation<TA,TB,Info,FM> & rel)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 
get_left_pair()304     left_pair & get_left_pair()
305     {
306         return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
307     }
308 
get_left_pair() const309     const left_pair & get_left_pair() const
310     {
311         return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
312     }
313 
get_right_pair()314     right_pair & get_right_pair()
315     {
316         return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
317     }
318 
get_right_pair() const319     const right_pair & get_right_pair() const
320     {
321         return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
322     }
323 
get_view()324     above_view & get_view()
325     {
326         return ::boost::bimaps::relation::detail::mutate<above_view>(*this);
327     }
328 
get_view() const329     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
get() const337     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
get()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>
serialize(Archive & ar,const unsigned int version)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 >
hash_value(const detail::relation_storage<FirstType,SecondType,FM> & r)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 >
operator ==(const detail::relation_storage<FirstType,SecondType,FM1> & a,const detail::relation_storage<FirstType,SecondType,FM2> & b)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 >
operator !=(const detail::relation_storage<FirstType,SecondType,FM1> & a,const detail::relation_storage<FirstType,SecondType,FM2> & b)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 >
operator <(const detail::relation_storage<FirstType,SecondType,FM1> & a,const detail::relation_storage<FirstType,SecondType,FM2> & b)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 >
operator <=(const detail::relation_storage<FirstType,SecondType,FM1> & a,const detail::relation_storage<FirstType,SecondType,FM2> & b)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 >
operator >(const detail::relation_storage<FirstType,SecondType,FM1> & a,const detail::relation_storage<FirstType,SecondType,FM2> & b)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 >
operator >=(const detail::relation_storage<FirstType,SecondType,FM1> & a,const detail::relation_storage<FirstType,SecondType,FM2> & b)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>
copy_with_left_replaced(mutant_relation<TA,TB,Info,force_mutable> const & rel,BOOST_DEDUCED_TYPENAME::boost::call_traits<BOOST_DEDUCED_TYPENAME mutant_relation<TA,TB,Info,force_mutable>::left_value_type>::param_type l)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>
copy_with_left_replaced(mutant_relation<TA,TB,::boost::mpl::na,force_mutable> const & rel,BOOST_DEDUCED_TYPENAME::boost::call_traits<BOOST_DEDUCED_TYPENAME mutant_relation<TA,TB,::boost::mpl::na,force_mutable>::left_value_type>::param_type l)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>
copy_with_right_replaced(mutant_relation<TA,TB,Info,force_mutable> const & rel,BOOST_DEDUCED_TYPENAME::boost::call_traits<BOOST_DEDUCED_TYPENAME mutant_relation<TA,TB,Info,force_mutable>::right_value_type>::param_type r)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>
copy_with_right_replaced(mutant_relation<TA,TB,::boost::mpl::na,force_mutable> const & rel,BOOST_DEDUCED_TYPENAME::boost::call_traits<BOOST_DEDUCED_TYPENAME mutant_relation<TA,TB,::boost::mpl::na,force_mutable>::right_value_type>::param_type r)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