1 /*-----------------------------------------------------------------------------+
2 Copyright (c) 2007-2011: 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_MAP_HPP_JOFA_070519
9 #define BOOST_ICL_MAP_HPP_JOFA_070519
11 #include <boost/icl/impl_config.hpp>
13 #if defined(ICL_USE_BOOST_MOVE_IMPLEMENTATION)
14 # include <boost/container/map.hpp>
15 # include <boost/container/set.hpp>
16 #elif defined(ICL_USE_STD_IMPLEMENTATION)
19 #else // Default for implementing containers
25 #include <boost/call_traits.hpp>
26 #include <boost/icl/detail/notate.hpp>
27 #include <boost/icl/detail/design_config.hpp>
28 #include <boost/icl/detail/concept_check.hpp>
29 #include <boost/icl/detail/on_absorbtion.hpp>
30 #include <boost/icl/type_traits/is_map.hpp>
31 #include <boost/icl/type_traits/absorbs_identities.hpp>
32 #include <boost/icl/type_traits/is_total.hpp>
33 #include <boost/icl/type_traits/is_element_container.hpp>
34 #include <boost/icl/type_traits/has_inverse.hpp>
36 #include <boost/icl/associative_element_container.hpp>
37 #include <boost/icl/functors.hpp>
38 #include <boost/icl/type_traits/to_string.hpp>
40 namespace boost{namespace icl
43 struct partial_absorber
45 enum { absorbs_identities = true };
46 enum { is_total = false };
50 inline std::string type_to_string<partial_absorber>::apply() { return "@0"; }
52 struct partial_enricher
54 enum { absorbs_identities = false };
55 enum { is_total = false };
59 inline std::string type_to_string<partial_enricher>::apply() { return "e0"; }
63 enum { absorbs_identities = true };
64 enum { is_total = true };
68 inline std::string type_to_string<total_absorber>::apply() { return "^0"; }
72 enum { absorbs_identities = false };
73 enum { is_total = true };
77 inline std::string type_to_string<total_enricher>::apply() { return "e^0"; }
81 /** \brief Addable, subractable and intersectable maps */
86 class Traits = icl::partial_absorber,
87 ICL_COMPARE Compare = ICL_COMPARE_INSTANCE(ICL_COMPARE_DEFAULT, DomainT),
88 ICL_COMBINE Combine = ICL_COMBINE_INSTANCE(icl::inplace_plus, CodomainT),
89 ICL_SECTION Section = ICL_SECTION_INSTANCE(icl::inter_section, CodomainT),
90 ICL_ALLOC Alloc = std::allocator
92 class map: private ICL_IMPL_SPACE::map<DomainT, CodomainT, ICL_COMPARE_DOMAIN(Compare,DomainT),
93 Alloc<std::pair<const DomainT, CodomainT> > >
96 typedef Alloc<typename std::pair<const DomainT, CodomainT> > allocator_type;
98 typedef typename icl::map<DomainT,CodomainT,Traits, Compare,Combine,Section,Alloc> type;
99 typedef typename ICL_IMPL_SPACE::map<DomainT, CodomainT, ICL_COMPARE_DOMAIN(Compare,DomainT),
100 allocator_type> base_type;
102 typedef Traits traits;
105 typedef DomainT domain_type;
106 typedef typename boost::call_traits<DomainT>::param_type domain_param;
107 typedef DomainT key_type;
108 typedef CodomainT codomain_type;
109 typedef CodomainT mapped_type;
110 typedef CodomainT data_type;
111 typedef std::pair<const DomainT, CodomainT> element_type;
112 typedef std::pair<const DomainT, CodomainT> value_type;
113 typedef ICL_COMPARE_DOMAIN(Compare,DomainT) domain_compare;
114 typedef ICL_COMBINE_CODOMAIN(Combine,CodomainT) codomain_combine;
115 typedef domain_compare key_compare;
116 typedef ICL_COMPARE_DOMAIN(Compare,element_type) element_compare;
117 typedef typename inverse<codomain_combine >::type inverse_codomain_combine;
118 typedef typename mpl::if_
119 <has_set_semantics<codomain_type>
120 , ICL_SECTION_CODOMAIN(Section,CodomainT)
122 >::type codomain_intersect;
123 typedef typename inverse<codomain_intersect>::type inverse_codomain_intersect;
124 typedef typename base_type::value_compare value_compare;
126 typedef typename ICL_IMPL_SPACE::set<DomainT, domain_compare, Alloc<DomainT> > set_type;
127 typedef set_type key_object_type;
130 BOOST_STATIC_CONSTANT(bool, _total = (Traits::is_total));
131 BOOST_STATIC_CONSTANT(bool, _absorbs = (Traits::absorbs_identities));
132 BOOST_STATIC_CONSTANT(bool,
133 total_invertible = (mpl::and_<is_total<type>, has_inverse<codomain_type> >::value));
135 typedef on_absorbtion<type,codomain_combine,Traits::absorbs_identities>
136 on_identity_absorbtion;
139 typedef typename base_type::pointer pointer;
140 typedef typename base_type::const_pointer const_pointer;
141 typedef typename base_type::reference reference;
142 typedef typename base_type::const_reference const_reference;
143 typedef typename base_type::iterator iterator;
144 typedef typename base_type::const_iterator const_iterator;
145 typedef typename base_type::size_type size_type;
146 typedef typename base_type::difference_type difference_type;
147 typedef typename base_type::reverse_iterator reverse_iterator;
148 typedef typename base_type::const_reverse_iterator const_reverse_iterator;
151 BOOST_STATIC_CONSTANT(bool,
152 is_total_invertible = ( Traits::is_total
153 && has_inverse<codomain_type>::value));
155 BOOST_STATIC_CONSTANT(int, fineness = 4);
158 //==========================================================================
159 //= Construct, copy, destruct
160 //==========================================================================
163 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
164 BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
165 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
166 BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
169 map(const key_compare& comp): base_type(comp){}
171 template <class InputIterator>
172 map(InputIterator first, InputIterator past)
173 : base_type(first,past){}
175 template <class InputIterator>
176 map(InputIterator first, InputIterator past, const key_compare& comp)
177 : base_type(first,past,comp)
183 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
184 BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
185 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
186 BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
189 explicit map(const element_type& key_value_pair): base_type::map()
191 insert(key_value_pair);
194 # ifndef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
195 //==========================================================================
197 //==========================================================================
200 : base_type(boost::move(src))
202 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
203 BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
204 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
205 BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
208 map& operator = (map src)
210 base_type::operator=(boost::move(src));
213 //==========================================================================
216 map& operator = (const map& src)
218 base_type::operator=(src);
222 # endif // BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
224 void swap(map& src) { base_type::swap(src); }
226 //==========================================================================
227 using base_type::empty;
228 using base_type::clear;
230 using base_type::begin;
231 using base_type::end;
232 using base_type::rbegin;
233 using base_type::rend;
235 using base_type::size;
236 using base_type::max_size;
238 using base_type::key_comp;
239 using base_type::value_comp;
241 using base_type::erase;
242 using base_type::find;
243 using base_type::count;
245 using base_type::lower_bound;
246 using base_type::upper_bound;
247 using base_type::equal_range;
249 using base_type::operator[];
252 //==========================================================================
254 //==========================================================================
256 template<class SubObject>
257 bool contains(const SubObject& sub)const
258 { return icl::contains(*this, sub); }
260 bool within(const map& super)const
261 { return icl::contains(super, *this); }
263 //==========================================================================
265 //==========================================================================
266 /** \c iterative_size() yields the number of elements that is visited
267 throu complete iteration. For interval sets \c iterative_size() is
268 different from \c size(). */
269 std::size_t iterative_size()const { return base_type::size(); }
271 //==========================================================================
273 //==========================================================================
275 /** Total select function. */
276 codomain_type operator()(const domain_type& key)const
278 const_iterator it = find(key);
279 return it==end() ? identity_element<codomain_type>::value()
283 //==========================================================================
285 //==========================================================================
286 /** \c add inserts \c value_pair into the map if it's key does
287 not exist in the map.
288 If \c value_pairs's key value exists in the map, it's data
289 value is added to the data value already found in the map. */
290 map& add(const value_type& value_pair)
292 return _add<codomain_combine>(value_pair);
295 /** \c add add \c value_pair into the map using \c prior as a hint to
296 insert \c value_pair after the position \c prior is pointing to. */
297 iterator add(iterator prior, const value_type& value_pair)
299 return _add<codomain_combine>(prior, value_pair);
302 //==========================================================================
304 //==========================================================================
305 /** If the \c value_pair's key value is in the map, it's data value is
306 subtraced from the data value stored in the map. */
307 map& subtract(const element_type& value_pair)
309 on_invertible<type, is_total_invertible>
310 ::subtract(*this, value_pair);
314 map& subtract(const domain_type& key)
316 icl::erase(*this, key);
320 //==========================================================================
321 //= Insertion, erasure
322 //==========================================================================
323 std::pair<iterator,bool> insert(const value_type& value_pair)
325 if(on_identity_absorbtion::is_absorbable(value_pair.second))
326 return std::pair<iterator,bool>(end(),true);
328 return base_type::insert(value_pair);
331 iterator insert(iterator prior, const value_type& value_pair)
333 if(on_identity_absorbtion::is_absorbable(value_pair.second))
336 return base_type::insert(prior, value_pair);
339 template<class Iterator>
340 iterator insert(Iterator first, Iterator last)
342 iterator prior = end(), it = first;
344 prior = this->insert(prior, *it++);
347 /** With <tt>key_value_pair = (k,v)</tt> set value \c v for key \c k */
348 map& set(const element_type& key_value_pair)
350 return icl::set_at(*this, key_value_pair);
353 /** erase \c key_value_pair from the map.
354 Erase only if, the exact value content \c val is stored for the given key. */
355 size_type erase(const element_type& key_value_pair)
357 return icl::erase(*this, key_value_pair);
360 //==========================================================================
362 //==========================================================================
363 /** The intersection of \c key_value_pair and \c *this map is added to \c section. */
364 void add_intersection(map& section, const element_type& key_value_pair)const
366 on_definedness<type, Traits::is_total>
367 ::add_intersection(section, *this, key_value_pair);
370 //==========================================================================
371 //= Symmetric difference
372 //==========================================================================
374 map& flip(const element_type& operand)
376 on_total_absorbable<type,_total,_absorbs>::flip(*this, operand);
381 template<class Combiner>
382 map& _add(const element_type& value_pair);
384 template<class Combiner>
385 iterator _add(iterator prior, const element_type& value_pair);
387 template<class Combiner>
388 map& _subtract(const element_type& value_pair);
390 template<class FragmentT>
391 void total_add_intersection(type& section, const FragmentT& fragment)const
394 section.add(fragment);
397 void partial_add_intersection(type& section, const element_type& operand)const
399 const_iterator it_ = find(operand.first);
402 section.template _add<codomain_combine >(*it_);
403 section.template _add<codomain_intersect>(operand);
409 //--------------------------------------------------------------------------
410 template<class Type, bool is_total_invertible>
411 struct on_invertible;
414 struct on_invertible<Type, true>
416 typedef typename Type::element_type element_type;
417 typedef typename Type::inverse_codomain_combine inverse_codomain_combine;
419 static void subtract(Type& object, const element_type& operand)
420 { object.template _add<inverse_codomain_combine>(operand); }
424 struct on_invertible<Type, false>
426 typedef typename Type::element_type element_type;
427 typedef typename Type::inverse_codomain_combine inverse_codomain_combine;
429 static void subtract(Type& object, const element_type& operand)
430 { object.template _subtract<inverse_codomain_combine>(operand); }
433 friend struct on_invertible<type, true>;
434 friend struct on_invertible<type, false>;
435 //--------------------------------------------------------------------------
437 //--------------------------------------------------------------------------
438 template<class Type, bool is_total>
439 struct on_definedness;
442 struct on_definedness<Type, true>
444 static void add_intersection(Type& section, const Type& object,
445 const element_type& operand)
446 { object.total_add_intersection(section, operand); }
450 struct on_definedness<Type, false>
452 static void add_intersection(Type& section, const Type& object,
453 const element_type& operand)
454 { object.partial_add_intersection(section, operand); }
457 friend struct on_definedness<type, true>;
458 friend struct on_definedness<type, false>;
459 //--------------------------------------------------------------------------
461 //--------------------------------------------------------------------------
462 template<class Type, bool has_set_semantics, bool absorbs_identities>
463 struct on_codomain_model;
466 struct on_codomain_model<Type, false, false>
467 { // !codomain_is_set, !absorbs_identities
468 static void subtract(Type&, typename Type::iterator it_,
469 const typename Type::codomain_type& )
470 { (*it_).second = identity_element<typename Type::codomain_type>::value(); }
474 struct on_codomain_model<Type, false, true>
475 { // !codomain_is_set, absorbs_identities
476 static void subtract(Type& object, typename Type::iterator it_,
477 const typename Type::codomain_type& )
478 { object.erase(it_); }
482 struct on_codomain_model<Type, true, false>
483 { // !codomain_is_set, !absorbs_identities
484 typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
485 static void subtract(Type&, typename Type::iterator it_,
486 const typename Type::codomain_type& co_value)
488 inverse_codomain_intersect()((*it_).second, co_value);
493 struct on_codomain_model<Type, true, true>
494 { // !codomain_is_set, absorbs_identities
495 typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
496 static void subtract(Type& object, typename Type::iterator it_,
497 const typename Type::codomain_type& co_value)
499 inverse_codomain_intersect()((*it_).second, co_value);
500 if((*it_).second == identity_element<codomain_type>::value())
504 //--------------------------------------------------------------------------
506 //--------------------------------------------------------------------------
507 template<class Type, bool is_total, bool absorbs_identities>
508 struct on_total_absorbable;
511 struct on_total_absorbable<Type, true, true>
513 typedef typename Type::element_type element_type;
514 static void flip(Type& object, const typename Type::element_type&)
515 { icl::clear(object); }
519 struct on_total_absorbable<Type, true, false>
521 typedef typename Type::element_type element_type;
522 typedef typename Type::codomain_type codomain_type;
524 static void flip(Type& object, const element_type& operand)
527 ICL_FORALL(typename Type, it_, object)
528 (*it_).second = identity_element<codomain_type>::value();
533 struct on_total_absorbable<Type, false, true>
534 { // !is_total, absorbs_identities
535 typedef typename Type::element_type element_type;
536 typedef typename Type::codomain_type codomain_type;
537 typedef typename Type::iterator iterator;
538 typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
540 static void flip(Type& object, const element_type& operand)
542 std::pair<iterator,bool> insertion = object.insert(operand);
543 if(!insertion.second)
544 on_codomain_model<Type, has_set_semantics<codomain_type>::value, true>
545 ::subtract(object, insertion.first, operand.second);
550 struct on_total_absorbable<Type, false, false>
551 { // !is_total !absorbs_identities
552 typedef typename Type::element_type element_type;
553 typedef typename Type::codomain_type codomain_type;
554 typedef typename Type::iterator iterator;
555 typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
557 static void flip(Type& object, const element_type& operand)
559 std::pair<iterator,bool> insertion = object.insert(operand);
560 if(!insertion.second)
561 on_codomain_model<Type, has_set_semantics<codomain_type>::value, false>
562 ::subtract(object, insertion.first, operand.second);
566 friend struct on_total_absorbable<type, true, true >;
567 friend struct on_total_absorbable<type, false, true >;
568 friend struct on_total_absorbable<type, true, false>;
569 friend struct on_total_absorbable<type, false, false>;
570 //--------------------------------------------------------------------------
575 //==============================================================================
576 //= Addition<ElementMap>
577 //==============================================================================
578 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
579 template <class Combiner>
580 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>&
581 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>
582 ::_add(const element_type& addend)
584 typedef typename on_absorbtion
585 <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
587 const codomain_type& co_val = addend.second;
588 if(on_absorbtion_::is_absorbable(co_val))
591 std::pair<iterator,bool> insertion
592 = base_type::insert(value_type(addend.first, version<Combiner>()(co_val)));
594 if(!insertion.second)
596 iterator it = insertion.first;
597 Combiner()((*it).second, co_val);
599 if(on_absorbtion_::is_absorbable((*it).second))
606 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
607 template <class Combiner>
608 typename map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>::iterator
609 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>
610 ::_add(iterator prior_, const value_type& addend)
612 typedef typename on_absorbtion
613 <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
615 const codomain_type& co_val = addend.second;
616 if(on_absorbtion_::is_absorbable(co_val))
620 = base_type::insert(prior_,
621 value_type(addend.first, Combiner::identity_element()));
622 Combiner()((*inserted_).second, addend.second);
624 if(on_absorbtion_::is_absorbable((*inserted_).second))
634 //==============================================================================
635 //= Subtraction<ElementMap>
636 //==============================================================================
637 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
638 template <class Combiner>
639 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>&
640 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>::_subtract(const value_type& minuend)
642 typedef typename on_absorbtion
643 <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
645 iterator it_ = find(minuend.first);
648 Combiner()((*it_).second, minuend.second);
649 if(on_absorbtion_::is_absorbable((*it_).second))
656 //-----------------------------------------------------------------------------
658 //-----------------------------------------------------------------------------
659 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
660 struct is_map<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
662 typedef is_map<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> > type;
663 BOOST_STATIC_CONSTANT(bool, value = true);
666 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
667 struct has_inverse<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
669 typedef has_inverse<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> > type;
670 BOOST_STATIC_CONSTANT(bool, value = (has_inverse<CodomainT>::value));
673 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
674 struct absorbs_identities<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
676 typedef absorbs_identities type;
677 BOOST_STATIC_CONSTANT(int, value = Traits::absorbs_identities);
680 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
681 struct is_total<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
683 typedef is_total type;
684 BOOST_STATIC_CONSTANT(int, value = Traits::is_total);
687 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
688 struct type_to_string<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
690 static std::string apply()
692 return "map<"+ type_to_string<DomainT>::apply() + ","
693 + type_to_string<CodomainT>::apply() + ","
694 + type_to_string<Traits>::apply() +">";
700 }} // namespace icl boost
702 #endif // BOOST_ICL_MAP_HPP_JOFA_070519