element_map.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /*-----------------------------------------------------------------------------+
  2. Copyright (c) 2010-2010: Joachim Faulhaber
  3. +------------------------------------------------------------------------------+
  4. Distributed under the Boost Software License, Version 1.0.
  5. (See accompanying file LICENCE.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. +-----------------------------------------------------------------------------*/
  8. #ifndef BOOST_ICL_CONCEPT_ELEMENT_MAP_HPP_JOFA_100921
  9. #define BOOST_ICL_CONCEPT_ELEMENT_MAP_HPP_JOFA_100921
  10. #include <boost/mpl/and.hpp>
  11. #include <boost/mpl/not.hpp>
  12. #include <boost/icl/detail/on_absorbtion.hpp>
  13. #include <boost/icl/type_traits/unit_element.hpp>
  14. #include <boost/icl/type_traits/is_total.hpp>
  15. #include <boost/icl/type_traits/absorbs_identities.hpp>
  16. #include <boost/icl/type_traits/is_associative_element_container.hpp>
  17. #include <boost/icl/type_traits/is_combinable.hpp>
  18. #include <boost/icl/concept/map_value.hpp>
  19. #include <boost/icl/detail/map_algo.hpp>
  20. namespace boost{ namespace icl
  21. {
  22. //NOTE: Some forward declarations are needed by some compilers.
  23. template<class Type, class Predicate>
  24. typename enable_if<is_associative_element_container<Type>, Type>::type&
  25. erase_if(const Predicate& pred, Type& object);
  26. //==============================================================================
  27. //= Containedness<ElementMap>
  28. //==============================================================================
  29. //------------------------------------------------------------------------------
  30. //- bool within(c P&, c T&) T:{m} P:{b} fragment_types
  31. //------------------------------------------------------------------------------
  32. /** Checks if a key-value pair is in the map */
  33. template<class Type>
  34. typename enable_if<is_element_map<Type>, bool>::type
  35. within(const typename Type::element_type& value_pair, const Type& super)
  36. {
  37. typedef typename Type::const_iterator const_iterator;
  38. const_iterator found_ = super.find(value_pair.first);
  39. return found_ != super.end() && (*found_).second == value_pair.second;
  40. }
  41. //------------------------------------------------------------------------------
  42. //- bool contains(c T&, c P&) T:{m} P:{b} fragment_types
  43. //------------------------------------------------------------------------------
  44. template<class Type>
  45. typename enable_if<is_element_map<Type>, bool>::type
  46. contains(const Type& super, const typename Type::element_type& value_pair)
  47. {
  48. return icl::within(value_pair, super);
  49. }
  50. //==============================================================================
  51. //= Equivalences and Orderings<ElementMap>
  52. //==============================================================================
  53. /** Protonic equality is equality on all elements that do not carry an identity element as content. */
  54. template<class Type>
  55. inline typename enable_if<is_element_map<Type>, bool>::type
  56. is_distinct_equal(const Type& lhs, const Type& rhs)
  57. {
  58. return Map::lexicographical_distinct_equal(lhs, rhs);
  59. }
  60. //==============================================================================
  61. //= Addition<ElementMap>
  62. //==============================================================================
  63. /** \c add inserts \c value_pair into the map if it's key does
  64. not exist in the map.
  65. If \c value_pairs's key value exists in the map, it's data
  66. value is added to the data value already found in the map. */
  67. template <class Type>
  68. typename enable_if<is_element_map<Type>, Type>::type&
  69. add(Type& object, const typename Type::value_type& value_pair)
  70. {
  71. return object.add(value_pair);
  72. }
  73. /** \c add add \c value_pair into the map using \c prior as a hint to
  74. insert \c value_pair after the position \c prior is pointing to. */
  75. template <class Type>
  76. typename enable_if<is_element_map<Type>, typename Type::iterator>::type
  77. add(Type& object, typename Type::iterator prior,
  78. const typename Type::value_type& value_pair)
  79. {
  80. return object.add(prior, value_pair);
  81. }
  82. //==============================================================================
  83. //= Erasure
  84. //==============================================================================
  85. //------------------------------------------------------------------------------
  86. //- T& erase(T&, c P&) T:{m} P:{b} fragment_type
  87. //------------------------------------------------------------------------------
  88. template <class Type>
  89. typename enable_if<is_element_map<Type>, typename Type::size_type>::type
  90. erase(Type& object, const typename Type::element_type& value_pair)
  91. {
  92. typedef typename Type::size_type size_type;
  93. typedef typename Type::iterator iterator;
  94. typedef typename Type::on_identity_absorbtion on_identity_absorbtion;
  95. if(on_identity_absorbtion::is_absorbable(value_pair.second))
  96. return identity_element<size_type>::value();
  97. iterator it_ = object.find(value_pair.first);
  98. if(it_ != object.end() && value_pair.second == (*it_).second)
  99. {
  100. object.erase(it_);
  101. return unit_element<size_type>::value();
  102. }
  103. return identity_element<size_type>::value();
  104. }
  105. template<class Type>
  106. typename enable_if<is_element_map<Type>, Type>::type&
  107. erase(Type& object, const typename Type::set_type& erasure)
  108. {
  109. typedef typename Type::set_type set_type;
  110. ICL_const_FORALL(typename set_type, elem_, erasure)
  111. icl::erase(object, *elem_);
  112. return object;
  113. }
  114. //==============================================================================
  115. //= Subtraction
  116. //==============================================================================
  117. //------------------------------------------------------------------------------
  118. //- T& subtract(T&, c P&) T:{m} P:{b} fragment_type
  119. //------------------------------------------------------------------------------
  120. template <class Type>
  121. inline typename enable_if<is_element_map<Type>, Type>::type&
  122. subtract(Type& object, const typename Type::element_type& operand)
  123. {
  124. return object.subtract(operand);
  125. }
  126. //------------------------------------------------------------------------------
  127. //- T& subtract(T&, c P&) T:{m} P:{e} key_type
  128. //------------------------------------------------------------------------------
  129. template <class Type>
  130. typename enable_if<is_element_map<Type>, Type>::type&
  131. subtract(Type& object, const typename Type::domain_type& key_value)
  132. {
  133. return icl::erase(object, key_value);
  134. }
  135. //------------------------------------------------------------------------------
  136. //- T& subtract(T&, c P&) T:{m} P:{s} set key_type
  137. //------------------------------------------------------------------------------
  138. template <class Type>
  139. inline typename enable_if<is_element_map<Type>, Type>::type&
  140. operator -= (Type& object, const typename Type::set_type& operand)
  141. {
  142. typedef typename Type::set_type set_type;
  143. typedef typename set_type::const_iterator co_iterator;
  144. typedef typename Type::iterator iterator;
  145. co_iterator common_lwb_, common_upb_;
  146. if(!Set::common_range(common_lwb_, common_upb_, operand, object))
  147. return object;
  148. co_iterator it_ = common_lwb_;
  149. iterator common_;
  150. while(it_ != common_upb_)
  151. object.erase(*it_++);
  152. return object;
  153. }
  154. template <class Type>
  155. inline typename enable_if<is_element_map<Type>, Type>::type
  156. operator - (Type object, const typename Type::set_type& subtrahend)
  157. {
  158. return object -= subtrahend;
  159. }
  160. //==============================================================================
  161. //= Selective Update<ElementMap>
  162. //==============================================================================
  163. //------------------------------------------------------------------------------
  164. //- T& set_at(T&, c P&) T:{m} P:{b}
  165. //------------------------------------------------------------------------------
  166. template<class Type>
  167. inline typename enable_if<is_element_map<Type>, Type>::type&
  168. set_at(Type& object, const typename Type::element_type& operand)
  169. {
  170. typedef typename Type::iterator iterator;
  171. typedef typename Type::codomain_combine codomain_combine;
  172. typedef on_absorbtion<Type,codomain_combine,absorbs_identities<Type>::value>
  173. on_identity_absorbtion;
  174. if(!on_identity_absorbtion::is_absorbable(operand.second))
  175. {
  176. std::pair<iterator,bool> insertion = object.insert(operand);
  177. if(!insertion.second)
  178. insertion->second = operand.second;
  179. }
  180. return object;
  181. }
  182. //==============================================================================
  183. //= Intersection
  184. //==============================================================================
  185. template<class Type>
  186. inline typename enable_if<is_element_map<Type>, void>::type
  187. add_intersection(Type& section, const Type& object,
  188. const typename Type::element_type& operand)
  189. {
  190. object.add_intersection(section, operand);
  191. }
  192. template<class Type>
  193. inline typename enable_if<is_element_map<Type>, void>::type
  194. add_intersection(Type& section, const Type& object, const Type& operand)
  195. {
  196. ICL_const_FORALL(typename Type, it_, operand)
  197. icl::add_intersection(section, object, *it_);
  198. }
  199. //------------------------------------------------------------------------------
  200. //- T& op &=(T&, c P&) T:{m} P:{b m} fragment_types
  201. //------------------------------------------------------------------------------
  202. template<class Type>
  203. inline typename enable_if<mpl::and_<is_element_map<Type>, is_total<Type> >, Type>::type&
  204. operator &=(Type& object, const typename Type::element_type& operand)
  205. {
  206. object.add(operand);
  207. return object;
  208. }
  209. template<class Type>
  210. inline typename enable_if<mpl::and_<is_element_map<Type>, mpl::not_<is_total<Type> > >, Type>::type&
  211. operator &=(Type& object, const typename Type::element_type& operand)
  212. {
  213. Type section;
  214. icl::add_intersection(section, object, operand);
  215. object.swap(section);
  216. return object;
  217. }
  218. template<class Type>
  219. inline typename enable_if<is_element_map<Type>, Type>::type
  220. operator & (Type object, const typename Type::element_type& operand)
  221. {
  222. return object &= operand;
  223. }
  224. template<class Type>
  225. inline typename enable_if<is_element_map<Type>, Type>::type
  226. operator & (const typename Type::element_type& operand, Type object)
  227. {
  228. return object &= operand;
  229. }
  230. template<class Type>
  231. inline typename enable_if<mpl::and_<is_element_map<Type>, is_total<Type> >, Type>::type&
  232. operator &=(Type& object, const Type& operand)
  233. {
  234. object += operand;
  235. return object;
  236. }
  237. template<class Type>
  238. inline typename enable_if<mpl::and_<is_element_map<Type>, mpl::not_<is_total<Type> > >, Type>::type&
  239. operator &=(Type& object, const Type& operand)
  240. {
  241. Type section;
  242. icl::add_intersection(section, object, operand);
  243. object.swap(section);
  244. return object;
  245. }
  246. template<class Type>
  247. inline typename enable_if<is_element_map<Type>, Type>::type
  248. operator & (Type object, const typename Type::key_object_type& operand)
  249. {
  250. return object &= operand;
  251. }
  252. template<class Type>
  253. inline typename enable_if<is_element_map<Type>, Type>::type
  254. operator & (const typename Type::key_object_type& operand, Type object)
  255. {
  256. return object &= operand;
  257. }
  258. //==============================================================================
  259. //= Intersection<ElementMap> bool intersects(x,y)
  260. //==============================================================================
  261. template<class Type, class CoType>
  262. inline typename enable_if< mpl::and_< is_element_map<Type>
  263. , is_total<Type> >
  264. , bool>::type
  265. intersects(const Type&, const CoType&)
  266. {
  267. return true;
  268. }
  269. template<class Type>
  270. inline typename enable_if< mpl::and_< is_element_map<Type>
  271. , mpl::not_<is_total<Type> > >
  272. , bool>::type
  273. intersects(const Type& object, const typename Type::domain_type& operand)
  274. {
  275. return icl::contains(object, operand);
  276. }
  277. template<class Type>
  278. inline typename enable_if< mpl::and_< is_element_map<Type>
  279. , mpl::not_<is_total<Type> > >
  280. , bool>::type
  281. intersects(const Type& object, const typename Type::set_type& operand)
  282. {
  283. if(object.iterative_size() < operand.iterative_size())
  284. return Map::intersects(object, operand);
  285. else
  286. return Map::intersects(operand, object);
  287. }
  288. template<class Type>
  289. inline typename enable_if< mpl::and_< is_element_map<Type>
  290. , mpl::not_<is_total<Type> > >
  291. , bool>::type
  292. intersects(const Type& object, const typename Type::element_type& operand)
  293. {
  294. Type intersection;
  295. icl::add_intersection(intersection, object, operand);
  296. return !intersection.empty();
  297. }
  298. template<class Type>
  299. inline typename enable_if< mpl::and_< is_element_map<Type>
  300. , mpl::not_<is_total<Type> > >
  301. , bool>::type
  302. intersects(const Type& object, const Type& operand)
  303. {
  304. if(object.iterative_size() < operand.iterative_size())
  305. return Map::intersects(object, operand);
  306. else
  307. return Map::intersects(operand, object);
  308. }
  309. //==============================================================================
  310. //= Symmetric difference
  311. //==============================================================================
  312. template<class Type>
  313. inline typename enable_if<is_element_map<Type>, Type>::type&
  314. flip(Type& object, const typename Type::element_type& operand)
  315. {
  316. return object.flip(operand);
  317. }
  318. template<class Type, class CoType>
  319. inline typename enable_if< mpl::and_< is_element_map<Type>
  320. , is_total<Type>
  321. , absorbs_identities<Type> >
  322. , Type>::type&
  323. operator ^= (Type& object, const CoType&)
  324. {
  325. icl::clear(object);
  326. return object;
  327. }
  328. template<class Type>
  329. inline typename enable_if< mpl::and_< is_element_map<Type>
  330. , is_total<Type>
  331. , mpl::not_<absorbs_identities<Type> > >
  332. , Type>::type&
  333. operator ^= (Type& object, const typename Type::element_type& operand)
  334. {
  335. return object.flip(operand);
  336. }
  337. template<class Type>
  338. inline typename enable_if< mpl::and_< is_element_map<Type>
  339. , is_total<Type>
  340. , mpl::not_<absorbs_identities<Type> > >
  341. , Type>::type&
  342. operator ^= (Type& object, const Type& operand)
  343. {
  344. ICL_const_FORALL(typename Type, it_, operand)
  345. icl::flip(object, *it_);
  346. ICL_FORALL(typename Type, it2_, object)
  347. (*it2_).second = identity_element<typename Type::codomain_type>::value();
  348. return object;
  349. }
  350. template<class Type>
  351. inline typename enable_if< mpl::and_< is_element_map<Type>
  352. , mpl::not_<is_total<Type> > >
  353. , Type>::type&
  354. operator ^= (Type& object, const typename Type::element_type& operand)
  355. {
  356. return icl::flip(object, operand);
  357. }
  358. template<class Type>
  359. inline typename enable_if< mpl::and_< is_element_map<Type>
  360. , mpl::not_<is_total<Type> > >
  361. , Type>::type&
  362. operator ^= (Type& object, const Type& operand)
  363. {
  364. typedef typename Type::const_iterator const_iterator;
  365. const_iterator it_ = operand.begin();
  366. while(it_ != operand.end())
  367. icl::flip(object, *it_++);
  368. return object;
  369. }
  370. //==============================================================================
  371. //= Set selection
  372. //==============================================================================
  373. template<class Type>
  374. inline typename enable_if<is_element_map<Type>,
  375. typename Type::set_type>::type&
  376. domain(typename Type::set_type& domain_set, const Type& object)
  377. {
  378. typename Type::set_type::iterator prior_ = domain_set.end();
  379. typename Type::const_iterator it_ = object.begin();
  380. while(it_ != object.end())
  381. prior_ = domain_set.insert(prior_, (*it_++).first);
  382. return domain_set;
  383. }
  384. //==============================================================================
  385. //= Neutron absorbtion
  386. //==============================================================================
  387. template<class Type>
  388. inline typename enable_if<mpl::and_< is_element_map<Type>
  389. , absorbs_identities<Type> >, Type>::type&
  390. absorb_identities(Type& object)
  391. {
  392. typedef typename Type::element_type element_type;
  393. return icl::erase_if(content_is_identity_element<element_type>(), object);
  394. }
  395. template<class Type>
  396. inline typename enable_if<mpl::and_< is_element_map<Type>
  397. , mpl::not_<absorbs_identities<Type> > >
  398. , Type>::type&
  399. absorb_identities(Type&){}
  400. //==============================================================================
  401. //= Streaming<ElementMap>
  402. //==============================================================================
  403. template<class CharType, class CharTraits, class Type>
  404. inline typename enable_if<is_element_map<Type>, std::basic_ostream<CharType, CharTraits> >::type&
  405. operator << (std::basic_ostream<CharType, CharTraits>& stream, const Type& object)
  406. {
  407. stream << "{";
  408. ICL_const_FORALL(typename Type, it, object)
  409. stream << "(" << it->first << "->" << it->second << ")";
  410. return stream << "}";
  411. }
  412. }} // namespace boost icl
  413. #endif