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/structured_pair.hpp |
10 | /// \brief Defines the structured_pair class. |
11 | |
12 | #ifndef BOOST_BIMAP_RELATION_STRUCTURED_PAIR_HPP |
13 | #define BOOST_BIMAP_RELATION_STRUCTURED_PAIR_HPP |
14 | |
15 | #if defined(_MSC_VER) |
16 | #pragma once |
17 | #endif |
18 | |
19 | #include <boost/config.hpp> |
20 | |
21 | #include <utility> |
22 | |
23 | #include <boost/type_traits/remove_const.hpp> |
24 | |
25 | #include <boost/mpl/aux_/na.hpp> |
26 | |
27 | #include <boost/call_traits.hpp> |
28 | |
29 | #include <boost/utility/enable_if.hpp> |
30 | #include <boost/type_traits/is_same.hpp> |
31 | #include <boost/mpl/if.hpp> |
32 | #include <boost/mpl/vector.hpp> |
33 | |
34 | #include <boost/bimap/detail/debug/static_error.hpp> |
35 | #include <boost/bimap/relation/pair_layout.hpp> |
36 | #include <boost/bimap/relation/symmetrical_base.hpp> |
37 | #include <boost/bimap/relation/support/get.hpp> |
38 | #include <boost/bimap/tags/support/value_type_of.hpp> |
39 | |
40 | |
41 | |
42 | namespace boost { |
43 | namespace bimaps { |
44 | namespace relation { |
45 | |
46 | namespace detail { |
47 | |
48 | /// \brief Storage definition of the left view of a mutant relation. |
49 | /** |
50 | |
51 | See also storage_finder, mirror_storage. |
52 | **/ |
53 | |
54 | template< class FirstType, class SecondType > |
55 | class normal_storage : |
56 | public symmetrical_base<FirstType,SecondType> |
57 | { |
58 | typedef symmetrical_base<FirstType,SecondType> base_; |
59 | |
60 | public: |
61 | |
62 | typedef normal_storage storage_; |
63 | |
64 | typedef BOOST_DEDUCED_TYPENAME base_::left_value_type first_type; |
65 | typedef BOOST_DEDUCED_TYPENAME base_::right_value_type second_type; |
66 | |
67 | first_type first; |
68 | second_type second; |
69 | |
70 | normal_storage() {} |
71 | |
72 | normal_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits< |
73 | first_type >::param_type f, |
74 | BOOST_DEDUCED_TYPENAME ::boost::call_traits< |
75 | second_type>::param_type s) |
76 | |
77 | : first(f), second(s) {} |
78 | |
79 | BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left() { return first; } |
80 | const BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left()const { return first; } |
81 | BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right() { return second; } |
82 | const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return second; } |
83 | }; |
84 | |
85 | /// \brief Storage definition of the right view of a mutant relation. |
86 | /** |
87 | |
88 | See also storage_finder, normal_storage. |
89 | **/ |
90 | |
91 | template< class FirstType, class SecondType > |
92 | class mirror_storage : |
93 | public symmetrical_base<SecondType,FirstType> |
94 | { |
95 | typedef symmetrical_base<SecondType,FirstType> base_; |
96 | |
97 | public: |
98 | |
99 | typedef mirror_storage storage_; |
100 | |
101 | typedef BOOST_DEDUCED_TYPENAME base_::left_value_type second_type; |
102 | typedef BOOST_DEDUCED_TYPENAME base_::right_value_type first_type; |
103 | |
104 | second_type second; |
105 | first_type first; |
106 | |
107 | mirror_storage() {} |
108 | |
109 | mirror_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits<first_type >::param_type f, |
110 | BOOST_DEDUCED_TYPENAME ::boost::call_traits<second_type >::param_type s) |
111 | |
112 | : second(s), first(f) {} |
113 | |
114 | BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left() { return second; } |
115 | const BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left()const { return second; } |
116 | BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right() { return first; } |
117 | const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return first; } |
118 | }; |
119 | |
120 | /** \struct boost::bimaps::relation::storage_finder |
121 | \brief Obtain the a storage with the correct layout. |
122 | |
123 | \code |
124 | template< class FirstType, class SecondType, class Layout > |
125 | struct storage_finder |
126 | { |
127 | typedef {normal/mirror}_storage<FirstType,SecondType> type; |
128 | }; |
129 | \endcode |
130 | |
131 | See also normal_storage, mirror_storage. |
132 | **/ |
133 | |
134 | #ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES |
135 | |
136 | template |
137 | < |
138 | class FirstType, |
139 | class SecondType, |
140 | class Layout |
141 | > |
142 | struct storage_finder |
143 | { |
144 | typedef normal_storage<FirstType,SecondType> type; |
145 | }; |
146 | |
147 | template |
148 | < |
149 | class FirstType, |
150 | class SecondType |
151 | > |
152 | struct storage_finder<FirstType,SecondType,mirror_layout> |
153 | { |
154 | typedef mirror_storage<FirstType,SecondType> type; |
155 | }; |
156 | |
157 | #endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES |
158 | |
159 | |
160 | template< class TA, class TB, class Info, class Layout > |
161 | class pair_info_hook : |
162 | public ::boost::bimaps::relation::detail::storage_finder<TA,TB,Layout>::type |
163 | { |
164 | typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::storage_finder<TA,TB,Layout>::type base_; |
165 | |
166 | typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: |
167 | default_tagged<Info,member_at::info>::type tagged_info_type; |
168 | |
169 | public: |
170 | typedef BOOST_DEDUCED_TYPENAME tagged_info_type::value_type info_type; |
171 | typedef BOOST_DEDUCED_TYPENAME tagged_info_type::tag info_tag; |
172 | |
173 | info_type info; |
174 | |
175 | protected: |
176 | |
177 | pair_info_hook() {} |
178 | |
179 | pair_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits< |
180 | BOOST_DEDUCED_TYPENAME base_::first_type |
181 | >::param_type f, |
182 | BOOST_DEDUCED_TYPENAME ::boost::call_traits< |
183 | BOOST_DEDUCED_TYPENAME base_::second_type |
184 | >::param_type s, |
185 | BOOST_DEDUCED_TYPENAME ::boost::call_traits< |
186 | info_type |
187 | >::param_type i = info_type() ) |
188 | : base_(f,s), info(i) {} |
189 | |
190 | template< class Pair > |
191 | pair_info_hook( const Pair & p) : |
192 | base_(p.first,p.second), |
193 | info(p.info) {} |
194 | |
195 | template< class Pair > |
196 | void change_to( const Pair & p ) |
197 | { |
198 | base_::first = p.first ; |
199 | base_::second = p.second; |
200 | info = p.info ; |
201 | } |
202 | |
203 | void clear_info() |
204 | { |
205 | info = info_type(); |
206 | }; |
207 | }; |
208 | |
209 | template< class TA, class TB, class Layout> |
210 | class pair_info_hook<TA,TB,::boost::mpl::na,Layout> : |
211 | public ::boost::bimaps::relation::detail::storage_finder<TA,TB,Layout>::type |
212 | { |
213 | typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::storage_finder<TA,TB,Layout>::type base_; |
214 | |
215 | public: |
216 | typedef ::boost::mpl::na info_type; |
217 | typedef member_at::info info_tag; |
218 | |
219 | protected: |
220 | |
221 | pair_info_hook() {} |
222 | |
223 | pair_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits< |
224 | BOOST_DEDUCED_TYPENAME base_::first_type |
225 | >::param_type f, |
226 | BOOST_DEDUCED_TYPENAME ::boost::call_traits< |
227 | BOOST_DEDUCED_TYPENAME base_::second_type |
228 | >::param_type s) |
229 | |
230 | : base_(f,s) {} |
231 | |
232 | template< class Pair > |
233 | pair_info_hook( const Pair & p ) : |
234 | base_(p.first,p.second) {} |
235 | |
236 | template< class Pair > |
237 | void change_to( const Pair & p ) |
238 | { |
239 | base_::first = p.first ; |
240 | base_::second = p.second; |
241 | } |
242 | |
243 | void clear_info() {}; |
244 | }; |
245 | |
246 | |
247 | |
248 | } // namespace detail |
249 | |
250 | template< class TA, class TB, class Info, bool FM > |
251 | class mutant_relation; |
252 | |
253 | |
254 | /// \brief A std::pair signature compatible class that allows you to control |
255 | /// the internal structure of the data. |
256 | /** |
257 | This class allows you to specify the order in wich the two data types will be |
258 | in the layout of the class. |
259 | **/ |
260 | |
261 | template< class FirstType, class SecondType, class Info, class Layout = normal_layout > |
262 | class structured_pair : |
263 | |
264 | public ::boost::bimaps::relation::detail::pair_info_hook |
265 | < |
266 | FirstType, SecondType, |
267 | Info, |
268 | Layout |
269 | |
270 | > |
271 | |
272 | { |
273 | typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::pair_info_hook |
274 | < |
275 | FirstType, SecondType, |
276 | Info, |
277 | Layout |
278 | |
279 | > base_; |
280 | |
281 | public: |
282 | |
283 | typedef ::boost::mpl::vector3< |
284 | structured_pair< FirstType, SecondType, Info, normal_layout >, |
285 | structured_pair< FirstType, SecondType, Info, mirror_layout >, |
286 | BOOST_DEDUCED_TYPENAME ::boost::mpl::if_< |
287 | BOOST_DEDUCED_TYPENAME ::boost::is_same<Layout, normal_layout>::type, |
288 | mutant_relation< FirstType, SecondType, Info, true >, |
289 | mutant_relation< SecondType, FirstType, Info, true > |
290 | >::type |
291 | |
292 | > mutant_views; |
293 | |
294 | structured_pair() {} |
295 | |
296 | structured_pair(BOOST_DEDUCED_TYPENAME boost::call_traits< |
297 | BOOST_DEDUCED_TYPENAME base_::first_type >::param_type f, |
298 | BOOST_DEDUCED_TYPENAME boost::call_traits< |
299 | BOOST_DEDUCED_TYPENAME base_::second_type >::param_type s) |
300 | : base_(f,s) {} |
301 | |
302 | structured_pair(BOOST_DEDUCED_TYPENAME boost::call_traits< |
303 | BOOST_DEDUCED_TYPENAME base_::first_type >::param_type f, |
304 | BOOST_DEDUCED_TYPENAME boost::call_traits< |
305 | BOOST_DEDUCED_TYPENAME base_::second_type >::param_type s, |
306 | BOOST_DEDUCED_TYPENAME boost::call_traits< |
307 | BOOST_DEDUCED_TYPENAME base_::info_type >::param_type i) |
308 | : base_(f,s,i) {} |
309 | |
310 | template< class OtherLayout > |
311 | structured_pair( |
312 | const structured_pair<FirstType,SecondType,Info,OtherLayout> & p) |
313 | : base_(p) {} |
314 | |
315 | template< class OtherLayout > |
316 | structured_pair& operator=( |
317 | const structured_pair<FirstType,SecondType,OtherLayout> & p) |
318 | { |
319 | base_::change_to(p); |
320 | return *this; |
321 | } |
322 | |
323 | template< class First, class Second > |
324 | structured_pair(const std::pair<First,Second> & p) : |
325 | base_(p.first,p.second) |
326 | {} |
327 | |
328 | template< class First, class Second > |
329 | structured_pair& operator=(const std::pair<First,Second> & p) |
330 | { |
331 | base_::first = p.first; |
332 | base_::second = p.second; |
333 | base_::clear_info(); |
334 | return *this; |
335 | } |
336 | |
337 | template< class Tag > |
338 | const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: |
339 | result_of::get<Tag,const structured_pair>::type |
340 | get() const |
341 | { |
342 | return ::boost::bimaps::relation::support::get<Tag>(*this); |
343 | } |
344 | |
345 | template< class Tag > |
346 | BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: |
347 | result_of::get<Tag,structured_pair>::type |
348 | get() |
349 | { |
350 | return ::boost::bimaps::relation::support::get<Tag>(*this); |
351 | } |
352 | }; |
353 | |
354 | // structured_pair - structured_pair |
355 | |
356 | template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > |
357 | bool operator==(const structured_pair<FirstType,SecondType,Info,Layout1> & a, |
358 | const structured_pair<FirstType,SecondType,Info,Layout2> & b) |
359 | { |
360 | return ( ( a.first == b.first ) && |
361 | ( a.second == b.second ) ); |
362 | } |
363 | |
364 | template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > |
365 | bool operator!=(const structured_pair<FirstType,SecondType,Info,Layout1> & a, |
366 | const structured_pair<FirstType,SecondType,Info,Layout2> & b) |
367 | { |
368 | return ! ( a == b ); |
369 | } |
370 | |
371 | template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > |
372 | bool operator<(const structured_pair<FirstType,SecondType,Info,Layout1> & a, |
373 | const structured_pair<FirstType,SecondType,Info,Layout2> & b) |
374 | { |
375 | return ( ( a.first < b.first ) || |
376 | (( a.first == b.first ) && ( a.second < b.second ))); |
377 | } |
378 | |
379 | template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > |
380 | bool operator<=(const structured_pair<FirstType,SecondType,Info,Layout1> & a, |
381 | const structured_pair<FirstType,SecondType,Info,Layout2> & b) |
382 | { |
383 | return ( ( a.first < b.first ) || |
384 | (( a.first == b.first ) && ( a.second <= b.second ))); |
385 | } |
386 | |
387 | template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > |
388 | bool operator>(const structured_pair<FirstType,SecondType,Info,Layout1> & a, |
389 | const structured_pair<FirstType,SecondType,Info,Layout2> & b) |
390 | { |
391 | return ( ( a.first > b.first ) || |
392 | (( a.first == b.first ) && ( a.second > b.second ))); |
393 | } |
394 | |
395 | template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > |
396 | bool operator>=(const structured_pair<FirstType,SecondType,Info,Layout1> & a, |
397 | const structured_pair<FirstType,SecondType,Info,Layout2> & b) |
398 | { |
399 | return ( ( a.first > b.first ) || |
400 | (( a.first == b.first ) && ( a.second >= b.second ))); |
401 | } |
402 | |
403 | // structured_pair - std::pair |
404 | |
405 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
406 | bool operator==(const structured_pair<FirstType,SecondType,Info,Layout> & a, |
407 | const std::pair<F,S> & b) |
408 | { |
409 | return ( ( a.first == b.first ) && |
410 | ( a.second == b.second ) ); |
411 | } |
412 | |
413 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
414 | bool operator!=(const structured_pair<FirstType,SecondType,Info,Layout> & a, |
415 | const std::pair<F,S> & b) |
416 | { |
417 | return ! ( a == b ); |
418 | } |
419 | |
420 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
421 | bool operator<(const structured_pair<FirstType,SecondType,Info,Layout> & a, |
422 | const std::pair<F,S> & b) |
423 | { |
424 | return ( ( a.first < b.first ) || |
425 | (( a.first == b.first ) && ( a.second < b.second ))); |
426 | } |
427 | |
428 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
429 | bool operator<=(const structured_pair<FirstType,SecondType,Info,Layout> & a, |
430 | const std::pair<F,S> & b) |
431 | { |
432 | return ( ( a.first < b.first ) || |
433 | (( a.first == b.first ) && ( a.second <= b.second ))); |
434 | } |
435 | |
436 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
437 | bool operator>(const structured_pair<FirstType,SecondType,Info,Layout> & a, |
438 | const std::pair<F,S> & b) |
439 | { |
440 | return ( ( a.first > b.first ) || |
441 | (( a.first == b.first ) && ( a.second > b.second ))); |
442 | } |
443 | |
444 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
445 | bool operator>=(const structured_pair<FirstType,SecondType,Info,Layout> & a, |
446 | const std::pair<F,S> & b) |
447 | { |
448 | return ( ( a.first > b.first ) || |
449 | (( a.first == b.first ) && ( a.second >= b.second ))); |
450 | } |
451 | |
452 | // std::pair - sturctured_pair |
453 | |
454 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
455 | bool operator==(const std::pair<F,S> & a, |
456 | const structured_pair<FirstType,SecondType,Info,Layout> & b) |
457 | { |
458 | return ( ( a.first == b.first ) && |
459 | ( a.second == b.second ) ); |
460 | } |
461 | |
462 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
463 | bool operator!=(const std::pair<F,S> & a, |
464 | const structured_pair<FirstType,SecondType,Info,Layout> & b) |
465 | { |
466 | return ! ( a == b ); |
467 | } |
468 | |
469 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
470 | bool operator<(const std::pair<F,S> & a, |
471 | const structured_pair<FirstType,SecondType,Info,Layout> & b) |
472 | { |
473 | return ( ( a.first < b.first ) || |
474 | (( a.first == b.first ) && ( a.second < b.second ))); |
475 | } |
476 | |
477 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
478 | bool operator<=(const std::pair<F,S> & a, |
479 | const structured_pair<FirstType,SecondType,Info,Layout> & b) |
480 | { |
481 | return ( ( a.first < b.first ) || |
482 | (( a.first == b.first ) && ( a.second <= b.second ))); |
483 | } |
484 | |
485 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
486 | bool operator>(const std::pair<F,S> & a, |
487 | const structured_pair<FirstType,SecondType,Info,Layout> & b) |
488 | { |
489 | return ( ( a.first > b.first ) || |
490 | (( a.first == b.first ) && ( a.second > b.second ))); |
491 | } |
492 | |
493 | template< class FirstType, class SecondType, class Info, class Layout, class F, class S > |
494 | bool operator>=(const std::pair<F,S> & a, |
495 | const structured_pair<FirstType,SecondType,Info,Layout> & b) |
496 | { |
497 | return ( ( a.first > b.first ) || |
498 | (( a.first == b.first ) && ( a.second >= b.second ))); |
499 | } |
500 | |
501 | |
502 | namespace detail { |
503 | |
504 | template< class FirstType, class SecondType, class Info, class Layout> |
505 | structured_pair<FirstType,SecondType,Info,Layout> |
506 | copy_with_first_replaced(structured_pair<FirstType,SecondType,Info,Layout> const& p, |
507 | BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME |
508 | structured_pair<FirstType,SecondType,Info,Layout>::first_type> |
509 | ::param_type f) |
510 | { |
511 | return structured_pair<FirstType,SecondType,Info,Layout>(f,p.second,p.info); |
512 | } |
513 | |
514 | template< class FirstType, class SecondType, class Layout> |
515 | structured_pair<FirstType,SecondType,::boost::mpl::na,Layout> |
516 | copy_with_first_replaced(structured_pair<FirstType,SecondType,::boost::mpl::na,Layout> const& p, |
517 | BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME |
518 | structured_pair<FirstType,SecondType,::boost::mpl::na,Layout>::first_type> |
519 | ::param_type f) |
520 | { |
521 | return structured_pair<FirstType,SecondType,::boost::mpl::na,Layout>(f,p.second); |
522 | } |
523 | |
524 | template< class FirstType, class SecondType, class Info, class Layout> |
525 | structured_pair<FirstType,SecondType,Info,Layout> |
526 | copy_with_second_replaced(structured_pair<FirstType,SecondType,Info,Layout> const& p, |
527 | BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME |
528 | structured_pair<FirstType,SecondType,Info,Layout>::second_type> |
529 | ::param_type s) |
530 | { |
531 | return structured_pair<FirstType,SecondType,Info,Layout>(p.first,s,p.info); |
532 | } |
533 | |
534 | template< class FirstType, class SecondType, class Layout> |
535 | structured_pair<FirstType,SecondType,::boost::mpl::na,Layout> |
536 | copy_with_second_replaced(structured_pair<FirstType,SecondType,::boost::mpl::na,Layout> const& p, |
537 | BOOST_DEDUCED_TYPENAME ::boost::call_traits< BOOST_DEDUCED_TYPENAME |
538 | structured_pair<FirstType,SecondType,::boost::mpl::na,Layout>::second_type> |
539 | ::param_type s) |
540 | { |
541 | return structured_pair<FirstType,SecondType,::boost::mpl::na,Layout>(p.first,s); |
542 | } |
543 | |
544 | } // namespace detail |
545 | |
546 | |
547 | } // namespace relation |
548 | } // namespace bimaps |
549 | } // namespace boost |
550 | |
551 | #endif // BOOST_BIMAP_RELATION_STRUCTURED_PAIR_HPP |
552 | |
553 | |