element_associator.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  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_ASSOCIATOR_HPP_JOFA_100921
  9. #define BOOST_ICL_CONCEPT_ELEMENT_ASSOCIATOR_HPP_JOFA_100921
  10. #include <boost/config.hpp>
  11. #include <boost/icl/type_traits/is_associative_element_container.hpp>
  12. #include <boost/icl/type_traits/is_key_container_of.hpp>
  13. #include <boost/icl/type_traits/is_combinable.hpp>
  14. #include <boost/icl/detail/subset_comparer.hpp>
  15. #include <boost/icl/concept/element_set.hpp>
  16. #include <boost/icl/concept/element_map.hpp>
  17. namespace boost{ namespace icl
  18. {
  19. //==============================================================================
  20. //= Size
  21. //==============================================================================
  22. template<class Type>
  23. typename enable_if<is_element_container<Type>, std::size_t>::type
  24. iterative_size(const Type& object)
  25. {
  26. return object.size();
  27. }
  28. template<class Type>
  29. typename enable_if<is_associative_element_container<Type>, typename Type::size_type>::type
  30. size(const Type& object)
  31. {
  32. return icl::iterative_size(object);
  33. }
  34. template<class Type>
  35. typename enable_if<is_associative_element_container<Type>, typename Type::size_type>::type
  36. cardinality(const Type& object)
  37. {
  38. return icl::iterative_size(object);
  39. }
  40. //==============================================================================
  41. //= Containedness<ElementSet|ElementMap>
  42. //==============================================================================
  43. //------------------------------------------------------------------------------
  44. //- bool within(c P&, c T&) T:{s}|{m} P:{e}|{i} fragment_types|key_types
  45. //------------------------------------------------------------------------------
  46. /** Checks if a key is in the associative container */
  47. template<class Type>
  48. typename enable_if<is_associative_element_container<Type>, bool>::type
  49. within(const typename Type::key_type& key, const Type& super)
  50. {
  51. return !(super.find(key) == super.end());
  52. }
  53. //------------------------------------------------------------------------------
  54. //- bool within(c P&, c T&) T:{s}|{m} P:{s'} fragment_types|key_types
  55. //------------------------------------------------------------------------------
  56. template<class SubT, class SuperT>
  57. typename enable_if<mpl::and_< is_associative_element_container<SuperT>
  58. , is_key_container_of<SubT, SuperT> >,
  59. bool>::type
  60. within(const SubT& sub, const SuperT& super)
  61. {
  62. if(icl::is_empty(sub)) return true;
  63. if(icl::is_empty(super)) return false;
  64. if(icl::size(super) < icl::size(sub)) return false;
  65. typename SubT::const_iterator common_lwb_;
  66. typename SubT::const_iterator common_upb_;
  67. if(!Set::common_range(common_lwb_, common_upb_, sub, super))
  68. return false;
  69. typename SubT::const_iterator sub_ = sub.begin();
  70. typename SuperT::const_iterator super_;
  71. while(sub_ != sub.end())
  72. {
  73. super_ = super.find(key_value<SubT>(sub_));
  74. if(super_ == super.end())
  75. return false;
  76. else if(!co_equal(sub_, super_, &sub, &super))
  77. return false;
  78. ++sub_;
  79. }
  80. return true;
  81. }
  82. //------------------------------------------------------------------------------
  83. //- bool contains(c T&, c P&) T:{s}|{m} P:{e}|{i} fragment_types|key_types
  84. //------------------------------------------------------------------------------
  85. template<class Type>
  86. typename enable_if<is_associative_element_container<Type>, bool>::type
  87. contains(const Type& super, const typename Type::key_type& key)
  88. {
  89. return icl::within(key, super);
  90. }
  91. //------------------------------------------------------------------------------
  92. //- bool contains(c T&, c P&) T:{s}|{m} P:{s'} fragment_types|key_types
  93. //------------------------------------------------------------------------------
  94. template<class SubT, class SuperT>
  95. typename enable_if<mpl::and_< is_associative_element_container<SuperT>
  96. , is_key_container_of<SubT, SuperT> >,
  97. bool>::type
  98. contains(const SuperT& super, const SubT& sub)
  99. {
  100. return icl::within(sub, super);
  101. }
  102. //==============================================================================
  103. //= Equivalences and Orderings
  104. //==============================================================================
  105. #ifdef BOOST_MSVC
  106. #pragma warning(push)
  107. #pragma warning(disable:4996) //'std::equal': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
  108. #endif // I do guarantee here that I am using the parameters correctly :)
  109. /** Standard equality, which is lexicographical equality of the sets
  110. as sequences, that are given by their Compare order. */
  111. template<class Type>
  112. inline typename enable_if<is_associative_element_container<Type>, bool>::type
  113. operator == (const Type& left, const Type& right)
  114. {
  115. return left.size() == right.size()
  116. && std::equal(left.begin(), left.end(), right.begin());
  117. }
  118. #ifdef BOOST_MSVC
  119. #pragma warning(pop)
  120. #endif
  121. template<class Type>
  122. inline typename enable_if<is_associative_element_container<Type>, bool>::type
  123. is_element_equal(const Type& left, const Type& right)
  124. { return left == right; }
  125. /* Strict weak less ordering which is given by the Compare order */
  126. template<class Type>
  127. inline typename enable_if<is_associative_element_container<Type>, bool>::type
  128. operator < (const Type& left, const Type& right)
  129. {
  130. return std::lexicographical_compare(
  131. left.begin(), left.end(), right.begin(), right.end(),
  132. typename Type::element_compare()
  133. );
  134. }
  135. template<class LeftT, class RightT>
  136. typename enable_if<is_concept_equivalent<is_element_container,LeftT, RightT>,
  137. int>::type
  138. inclusion_compare(const LeftT& left, const RightT& right)
  139. {
  140. return Set::subset_compare(left, right,
  141. left.begin(), left.end(),
  142. right.begin(), right.end());
  143. }
  144. //==============================================================================
  145. //= Addition
  146. //==============================================================================
  147. template <class Type>
  148. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  149. operator += (Type& object, const typename Type::value_type& operand)
  150. {
  151. return icl::add(object, operand);
  152. }
  153. template <class Type>
  154. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  155. operator + (Type object, const typename Type::value_type& operand)
  156. {
  157. return object += operand;
  158. }
  159. template <class Type>
  160. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  161. operator + (const typename Type::value_type& operand, Type object)
  162. {
  163. return object += operand;
  164. }
  165. template <class Type>
  166. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  167. operator += (Type& object, const Type& operand)
  168. {
  169. if(&object == &operand)
  170. return object;
  171. typename Type::iterator prior_ = object.end();
  172. ICL_const_FORALL(typename Type, it_, operand)
  173. prior_ = icl::add(object, prior_, *it_);
  174. return object;
  175. }
  176. template <class Type>
  177. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  178. operator + (Type object, const Type& operand)
  179. {
  180. return object += operand;
  181. }
  182. //==============================================================================
  183. template <class Type>
  184. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  185. operator |= (Type& object, const typename Type::value_type& operand)
  186. {
  187. return icl::add(object, operand);
  188. }
  189. template <class Type>
  190. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  191. operator | (Type object, const typename Type::value_type& operand)
  192. {
  193. return object += operand;
  194. }
  195. template <class Type>
  196. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  197. operator | (const typename Type::value_type& operand, Type object)
  198. {
  199. return object += operand;
  200. }
  201. template <class Type>
  202. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  203. operator |= (Type& object, const Type& operand)
  204. {
  205. return object += operand;
  206. }
  207. template <class Type>
  208. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  209. operator | (Type object, const Type& operand)
  210. {
  211. return object += operand;
  212. }
  213. //==============================================================================
  214. //= Insertion
  215. //==============================================================================
  216. //------------------------------------------------------------------------------
  217. //- V insert(T&, c P&) T:{s}|{m} P:{e}|{b} fragment_type
  218. //------------------------------------------------------------------------------
  219. template<class Type>
  220. typename enable_if<is_associative_element_container<Type>,
  221. std::pair<typename Type::iterator,bool> >::type
  222. insert(Type& object, const typename Type::value_type& operand)
  223. {
  224. return object.insert(operand);
  225. }
  226. template<class Type>
  227. typename enable_if<is_associative_element_container<Type>,
  228. typename Type::iterator>::type
  229. insert(Type& object, typename Type::iterator prior,
  230. const typename Type::value_type& operand)
  231. {
  232. return object.insert(prior, operand);
  233. }
  234. //------------------------------------------------------------------------------
  235. //- T insert(T&, c T&) T:{s m} map fragment_type
  236. //------------------------------------------------------------------------------
  237. template<class Type>
  238. typename enable_if<is_associative_element_container<Type>, Type>::type&
  239. insert(Type& object, const Type& addend)
  240. {
  241. typedef typename Type::iterator iterator;
  242. iterator prior_ = object.end();
  243. ICL_const_FORALL(typename Type, elem_, addend)
  244. icl::insert(object, prior_, *elem_);
  245. return object;
  246. }
  247. //==============================================================================
  248. //= Erasure
  249. //==============================================================================
  250. template<class Type>
  251. typename enable_if<is_associative_element_container<Type>, typename Type::size_type>::type
  252. erase(Type& object, const typename Type::key_type& key_value)
  253. {
  254. typedef typename Type::size_type size_type;
  255. typename Type::iterator it_ = object.find(key_value);
  256. if(it_ != object.end())
  257. {
  258. object.erase(it_);
  259. return unit_element<size_type>::value();
  260. }
  261. return identity_element<size_type>::value();
  262. }
  263. template<class Type>
  264. typename enable_if<is_associative_element_container<Type>, Type>::type&
  265. erase(Type& object, const Type& erasure)
  266. {
  267. ICL_const_FORALL(typename Type, elem_, erasure)
  268. icl::erase(object, *elem_);
  269. return object;
  270. }
  271. //==============================================================================
  272. //= Subtraction<ElementSet|ElementMap>
  273. //==============================================================================
  274. template <class Type>
  275. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  276. operator -= (Type& object, const typename Type::value_type& operand)
  277. {
  278. return icl::subtract(object, operand);
  279. }
  280. template <class Type>
  281. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  282. operator - (Type object, const typename Type::value_type& operand)
  283. {
  284. return object -= operand;
  285. }
  286. template <class Type>
  287. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  288. operator -= (Type& object, const Type& subtrahend)
  289. {
  290. ICL_const_FORALL(typename Type, it_, subtrahend)
  291. icl::subtract(object, *it_);
  292. return object;
  293. }
  294. template <class Type>
  295. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  296. operator - (Type object, const Type& subtrahend)
  297. {
  298. return object -= subtrahend;
  299. }
  300. //==============================================================================
  301. //= Intersection
  302. //==============================================================================
  303. //------------------------------------------------------------------------------
  304. //- void add_intersection(T&, c T&, c P&) T:{s}{m} P:{e}{e} key_type
  305. //------------------------------------------------------------------------------
  306. template<class Type>
  307. inline typename enable_if<is_associative_element_container<Type>, void>::type
  308. add_intersection(Type& section, const Type& object,
  309. const typename Type::key_type& operand)
  310. {
  311. typedef typename Type::const_iterator const_iterator;
  312. const_iterator it_ = object.find(operand);
  313. if(it_ != object.end())
  314. icl::add(section, *it_);
  315. }
  316. //------------------------------------------------------------------------------
  317. //- void add_intersection(T&, c T&, c P&) T:{s}{m} P:{s}{s} set key_type
  318. //------------------------------------------------------------------------------
  319. template<class Type>
  320. inline typename enable_if<is_associative_element_container<Type>, void>::type
  321. add_intersection(Type& section, const Type& object,
  322. const typename key_container_type_of<Type>::type& operand)
  323. {
  324. typedef typename key_container_type_of<Type>::type key_container_type;
  325. typedef typename key_container_type::const_iterator const_iterator;
  326. const_iterator common_lwb_, common_upb_;
  327. if(!Set::common_range(common_lwb_, common_upb_, operand, object))
  328. return;
  329. const_iterator sec_ = common_lwb_;
  330. while(sec_ != common_upb_)
  331. add_intersection(section, object, *sec_++);
  332. }
  333. //------------------------------------------------------------------------------
  334. //- Intersection<ElementMap|ElementSet>
  335. //------------------------------------------------------------------------------
  336. template<class Type>
  337. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  338. operator &= (Type& object, const typename Type::key_type& operand)
  339. {
  340. Type section;
  341. add_intersection(section, object, operand);
  342. object.swap(section);
  343. return object;
  344. }
  345. template<class Type>
  346. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  347. operator & (Type object, const typename Type::key_type& operand)
  348. {
  349. return object &= operand;
  350. }
  351. template<class Type>
  352. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  353. operator & (const typename Type::key_type& operand, Type object)
  354. {
  355. return object &= operand;
  356. }
  357. template<class Type>
  358. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  359. operator &= (Type& object, const typename key_container_type_of<Type>::type& operand)
  360. {
  361. Type section;
  362. add_intersection(section, object, operand);
  363. object.swap(section);
  364. return object;
  365. }
  366. template<class Type>
  367. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  368. operator & (Type object, const Type& operand)
  369. {
  370. return object &= operand;
  371. }
  372. //------------------------------------------------------------------------------
  373. template<class Type, class CoType>
  374. inline typename enable_if<is_associative_element_container<Type>, bool>::type
  375. disjoint(const Type& left, const Type& right)
  376. {
  377. return !intersects(left, right);
  378. }
  379. //==============================================================================
  380. //= Symmetric difference<ElementSet|ElementMap>
  381. //==============================================================================
  382. template<class Type>
  383. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  384. operator ^ (Type object, const typename Type::value_type& operand)
  385. {
  386. return icl::flip(object, operand);
  387. }
  388. template<class Type>
  389. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  390. operator ^ (const typename Type::value_type& operand, Type object)
  391. {
  392. return icl::flip(object, operand);
  393. }
  394. template<class Type>
  395. inline typename enable_if<is_associative_element_container<Type>, Type>::type
  396. operator ^ (Type object, const Type& operand)
  397. {
  398. return object ^= operand;
  399. }
  400. //==============================================================================
  401. //= Manipulation by predicates
  402. //==============================================================================
  403. template<class Type, class Predicate>
  404. typename enable_if<is_associative_element_container<Type>, Type>::type&
  405. erase_if(const Predicate& pred, Type& object)
  406. {
  407. typename Type::iterator it_ = object.begin();
  408. while(it_ != object.end())
  409. if(pred(*it_))
  410. icl::erase(object, it_++);
  411. else ++it_;
  412. return object;
  413. }
  414. template<class Type, class Predicate>
  415. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  416. add_if(const Predicate& pred, Type& object, const Type& src)
  417. {
  418. typename Type::const_iterator it_ = src.begin();
  419. while(it_ != src.end())
  420. if(pred(*it_))
  421. icl::add(object, *it_++);
  422. return object;
  423. }
  424. template<class Type, class Predicate>
  425. inline typename enable_if<is_associative_element_container<Type>, Type>::type&
  426. assign_if(const Predicate& pred, Type& object, const Type& src)
  427. {
  428. icl::clear(object);
  429. return add_if(object, src, pred);
  430. }
  431. }} // namespace boost icl
  432. #endif