Add SCons configure checks
[senf.git] / boost_ext / boost / bimap / relation / mutant_relation.hpp
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) && (_MSC_VER>=1200)
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 // #include <boost/serialization/nvp.hpp>
25
26 #include <boost/functional/hash/hash.hpp>
27
28 #include <boost/mpl/aux_/na.hpp>
29
30 // Boost.Bimap
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>
35
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>
41
42 namespace boost {
43 namespace bimaps {
44 namespace relation {
45
46 namespace detail {
47
48 // This class is included so structured_pair and mutant_relation share
49 // exactly the same class layout
50
51 template< class LeftType, class RightType, bool force_mutable >
52 class relation_storage :
53     public symmetrical_base<LeftType,RightType,force_mutable>
54 {
55     typedef symmetrical_base<LeftType,RightType,force_mutable> base_;
56
57     typedef relation_storage storage_;
58
59     public:
60
61     typedef relation_storage<LeftType,RightType,false> non_mutable_storage;
62
63     typedef ::boost::mpl::vector2
64     <
65         relation_storage< LeftType, RightType, true  >,
66         relation_storage< LeftType, RightType, false >
67
68     > mutant_views;
69
70     //@{
71         /// data
72         BOOST_DEDUCED_TYPENAME base_::left_value_type  left;
73         BOOST_DEDUCED_TYPENAME base_::right_value_type right;
74     //@}
75
76     relation_storage() {}
77
78     relation_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
79                          BOOST_DEDUCED_TYPENAME base_::left_value_type
80                      >::param_type l,
81                      BOOST_DEDUCED_TYPENAME ::boost::call_traits<
82                         BOOST_DEDUCED_TYPENAME base_::right_value_type
83                      >::param_type r)
84
85         : left(l), right(r) {}
86
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; }
91 };
92
93
94
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>
98 {
99     typedef ::boost::bimaps::relation::detail::
100                 relation_storage<TA,TB,force_mutable> base_;
101
102     typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::
103         default_tagged<Info,member_at::info>::type tagged_info_type;
104
105     public:
106     typedef BOOST_DEDUCED_TYPENAME tagged_info_type::value_type info_type;
107     typedef BOOST_DEDUCED_TYPENAME tagged_info_type::tag        info_tag;
108
109     info_type info;
110
111     protected:
112
113     relation_info_hook() {}
114
115     relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
116                            BOOST_DEDUCED_TYPENAME base_::left_value_type
117                         >::param_type l,
118                         BOOST_DEDUCED_TYPENAME ::boost::call_traits<
119                             BOOST_DEDUCED_TYPENAME base_::right_value_type
120                         >::param_type r,
121                         BOOST_DEDUCED_TYPENAME ::boost::call_traits<
122                             info_type
123                         >::param_type i = info_type() )
124
125         : base_(l,r), info(i) {}
126
127     template< class Relation >
128     relation_info_hook( const Relation & rel ) :
129         base_(rel.left,rel.right),
130         info(rel.info) {}
131
132     template< class Relation >
133     void change_to( const Relation & rel )
134     {
135         base_::left  = rel.left ;
136         base_::right = rel.right;
137         info         = rel.info ;
138     }
139
140     #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
141     template< class Archive >
142     void serialize(Archive & ar, const unsigned int version)
143     {
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        );
147     }
148     #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
149 };
150
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>
154 {
155     typedef ::boost::bimaps::relation::detail::
156                 relation_storage<TA,TB,force_mutable> base_;
157
158     public:
159     typedef ::boost::mpl::na info_type;
160     typedef member_at::info info_tag;
161
162     protected:
163
164     relation_info_hook() {}
165
166     relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits<
167                            BOOST_DEDUCED_TYPENAME base_::left_value_type
168                         >::param_type l,
169                         BOOST_DEDUCED_TYPENAME ::boost::call_traits<
170                             BOOST_DEDUCED_TYPENAME base_::right_value_type
171                         >::param_type r)
172
173         : base_(l,r) {}
174
175     template< class Relation >
176     relation_info_hook( const Relation & rel ) :
177         base_(rel.left,rel.right) {}
178
179     template< class Relation >
180     void change_to( const Relation & rel )
181     {
182         base_::left  = rel.left ;
183         base_::right = rel.right;
184     }
185
186     #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
187     template< class Archive >
188     void serialize(Archive & ar, const unsigned int version)
189     {
190         ar & ::boost::serialization::make_nvp("left" , base_::left );
191         ar & ::boost::serialization::make_nvp("right", base_::right);
192     }
193     #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
194 };
195
196
197 } // namespace detail
198
199 /// \brief Abstraction of a related pair of values, that extends the std::pair class.
200 /**
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
205 storage structure:
206
207 \verbatim
208                         __________
209                        |          |
210                        |    TA    |
211                        |__________|
212                        |          |
213                        |    TB    |
214                        |__________|
215
216 \endverbatim
217
218 See also select_relation, standard_relation.
219 \ingroup relation_group
220                                                            **/
221
222
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>
227 {
228     typedef ::boost::bimaps::relation::detail::
229         relation_info_hook<TA,TB,Info,force_mutable> base_;
230
231     public:
232
233     // We have to know the type of the base where the types are
234     // defined because Boost.MultiIndex requires it.
235
236     typedef ::boost::bimaps::relation::detail::
237                 relation_storage<TA,TB,force_mutable> storage_base;
238
239     /// Above view, non mutable view of the relation
240
241     typedef mutant_relation<TA,TB,Info,false> above_view;
242
243     //@{
244         /// A signature compatible std::pair that is a view of the relation.
245
246         typedef structured_pair< TA, TB, Info, normal_layout >  left_pair;
247         typedef structured_pair< TB, TA, Info, mirror_layout > right_pair;
248     //@}
249
250     typedef ::boost::mpl::vector4
251     <
252          left_pair,
253         right_pair,
254
255         mutant_relation< TA, TB, Info, true  >,
256         mutant_relation< TA, TB, Info, false >
257
258     > mutant_views;
259
260     mutant_relation() {}
261
262     mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
263                         BOOST_DEDUCED_TYPENAME base_:: left_value_type
264                     >::param_type l,
265                     BOOST_DEDUCED_TYPENAME ::boost::call_traits<
266                         BOOST_DEDUCED_TYPENAME base_::right_value_type
267                     >::param_type r) :
268         base_(l,r) {}
269
270     mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits<
271                         BOOST_DEDUCED_TYPENAME base_:: left_value_type
272                     >::param_type l,
273                     BOOST_DEDUCED_TYPENAME ::boost::call_traits<
274                         BOOST_DEDUCED_TYPENAME base_::right_value_type
275                     >::param_type r,
276                     BOOST_DEDUCED_TYPENAME ::boost::call_traits<
277                         BOOST_DEDUCED_TYPENAME base_::info_type
278                     >::param_type i) :
279         base_(l,r,i) {}
280
281     mutant_relation(const mutant_relation<TA,TB,Info,false> & rel) :
282         base_(rel) {}
283
284     mutant_relation(const mutant_relation<TA,TB,Info,true> & rel) :
285         base_(rel) {}
286
287     // Operators
288
289     template< bool FM >
290     mutant_relation& operator=(const mutant_relation<TA,TB,Info,FM> & rel)
291     {
292         base_::change_to(rel);
293         return *this;
294     }
295
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
299     // idiom.
300
301     left_pair & get_left_pair()
302     {
303         return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
304     }
305
306     const left_pair & get_left_pair() const
307     {
308         return ::boost::bimaps::relation::detail::mutate<left_pair>(*this);
309     }
310
311     right_pair & get_right_pair()
312     {
313         return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
314     }
315
316     const right_pair & get_right_pair() const
317     {
318         return ::boost::bimaps::relation::detail::mutate<right_pair>(*this);
319     }
320
321     above_view & get_view()
322     {
323         return ::boost::bimaps::relation::detail::mutate<above_view>(*this);
324     }
325
326     const above_view & get_view() const
327     {
328         return ::boost::bimaps::relation::detail::mutate<above_view>(*this);
329     }
330
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
335     {
336         return ::boost::bimaps::relation::support::get<Tag>(*this);
337     }
338
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))
343     {
344         return ::boost::bimaps::relation::support::get<Tag>(*this);
345     }
346
347     #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION
348
349     private:
350     friend class ::boost::serialization::access;
351
352     template<class Archive>
353     void serialize(Archive & ar, const unsigned int version)
354     {
355         base_::serialize(ar,version);
356     }
357
358     #endif // BOOST_BIMAP_DISABLE_SERIALIZATION
359 };
360
361 // hash value
362
363 template< class FirstType, class SecondType, bool FM >
364 std::size_t hash_value(const detail::relation_storage<FirstType,SecondType,FM> & r)
365 {
366     std::size_t seed = 0;
367     ::boost::hash_combine(seed, r. left );
368     ::boost::hash_combine(seed, r.right );
369
370     return seed;
371 }
372
373 // mutant_relation - mutant_relation
374
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)
378 {
379     return ( ( a.left  == b.left  ) &&
380              ( a.right == b.right ) );
381 }
382
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)
386 {
387     return ! ( a == b );
388 }
389
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)
393 {
394     return (  ( a.left  <  b.left  ) ||
395              (( a.left == b.left ) && ( a.right < b.right )));
396 }
397
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)
401 {
402     return (  ( a.left  <  b.left  ) ||
403              (( a.left == b.left ) && ( a.right <= b.right )));
404 }
405
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)
409 {
410     return ( ( a.left  >  b.left  ) ||
411              (( a.left == b.left ) && ( a.right > b.right )));
412 }
413
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)
417 {
418     return ( ( a.left  >  b.left  ) ||
419              (( a.left == b.left ) && ( a.right >= b.right )));
420 }
421
422 } // namespace relation
423 } // namespace bimaps
424 } // namespace boost
425
426
427 #endif // BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP
428
429
430