mutant_relation.hpp 15 KB

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