File indexing completed on 2025-01-18 09:38:23
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_ICL_MAP_HPP_JOFA_070519
0009 #define BOOST_ICL_MAP_HPP_JOFA_070519
0010
0011 #include <boost/icl/impl_config.hpp>
0012
0013 #if defined(ICL_USE_BOOST_MOVE_IMPLEMENTATION)
0014 # include <boost/container/map.hpp>
0015 # include <boost/container/set.hpp>
0016 #elif defined(ICL_USE_STD_IMPLEMENTATION)
0017 # include <map>
0018 # include <set>
0019 #else
0020 # include <map>
0021 # include <set>
0022 #endif
0023
0024 #include <string>
0025 #include <boost/call_traits.hpp>
0026 #include <boost/icl/detail/notate.hpp>
0027 #include <boost/icl/detail/design_config.hpp>
0028 #include <boost/icl/detail/concept_check.hpp>
0029 #include <boost/icl/detail/on_absorbtion.hpp>
0030 #include <boost/icl/type_traits/is_map.hpp>
0031 #include <boost/icl/type_traits/absorbs_identities.hpp>
0032 #include <boost/icl/type_traits/is_total.hpp>
0033 #include <boost/icl/type_traits/is_element_container.hpp>
0034 #include <boost/icl/type_traits/has_inverse.hpp>
0035
0036 #include <boost/icl/associative_element_container.hpp>
0037 #include <boost/icl/functors.hpp>
0038 #include <boost/icl/type_traits/to_string.hpp>
0039
0040 namespace boost{namespace icl
0041 {
0042
0043 struct partial_absorber
0044 {
0045 enum { absorbs_identities = true };
0046 enum { is_total = false };
0047 };
0048
0049 template<>
0050 inline std::string type_to_string<partial_absorber>::apply() { return "@0"; }
0051
0052 struct partial_enricher
0053 {
0054 enum { absorbs_identities = false };
0055 enum { is_total = false };
0056 };
0057
0058 template<>
0059 inline std::string type_to_string<partial_enricher>::apply() { return "e0"; }
0060
0061 struct total_absorber
0062 {
0063 enum { absorbs_identities = true };
0064 enum { is_total = true };
0065 };
0066
0067 template<>
0068 inline std::string type_to_string<total_absorber>::apply() { return "^0"; }
0069
0070 struct total_enricher
0071 {
0072 enum { absorbs_identities = false };
0073 enum { is_total = true };
0074 };
0075
0076 template<>
0077 inline std::string type_to_string<total_enricher>::apply() { return "e^0"; }
0078
0079
0080
0081
0082 template
0083 <
0084 typename DomainT,
0085 typename CodomainT,
0086 class Traits = icl::partial_absorber,
0087 ICL_COMPARE Compare = ICL_COMPARE_INSTANCE(ICL_COMPARE_DEFAULT, DomainT),
0088 ICL_COMBINE Combine = ICL_COMBINE_INSTANCE(icl::inplace_plus, CodomainT),
0089 ICL_SECTION Section = ICL_SECTION_INSTANCE(icl::inter_section, CodomainT),
0090 ICL_ALLOC Alloc = std::allocator
0091 >
0092 class map: private ICL_IMPL_SPACE::map<DomainT, CodomainT, ICL_COMPARE_DOMAIN(Compare,DomainT),
0093 Alloc<std::pair<const DomainT, CodomainT> > >
0094 {
0095 public:
0096 typedef Alloc<typename std::pair<const DomainT, CodomainT> > allocator_type;
0097
0098 typedef typename icl::map<DomainT,CodomainT,Traits, Compare,Combine,Section,Alloc> type;
0099 typedef typename ICL_IMPL_SPACE::map<DomainT, CodomainT, ICL_COMPARE_DOMAIN(Compare,DomainT),
0100 allocator_type> base_type;
0101
0102 typedef Traits traits;
0103
0104 public:
0105 typedef DomainT domain_type;
0106 typedef typename boost::call_traits<DomainT>::param_type domain_param;
0107 typedef DomainT key_type;
0108 typedef CodomainT codomain_type;
0109 typedef CodomainT mapped_type;
0110 typedef CodomainT data_type;
0111 typedef std::pair<const DomainT, CodomainT> element_type;
0112 typedef std::pair<const DomainT, CodomainT> value_type;
0113 typedef ICL_COMPARE_DOMAIN(Compare,DomainT) domain_compare;
0114 typedef ICL_COMBINE_CODOMAIN(Combine,CodomainT) codomain_combine;
0115 typedef domain_compare key_compare;
0116 typedef ICL_COMPARE_DOMAIN(Compare,element_type) element_compare;
0117 typedef typename inverse<codomain_combine >::type inverse_codomain_combine;
0118 typedef typename mpl::if_
0119 <has_set_semantics<codomain_type>
0120 , ICL_SECTION_CODOMAIN(Section,CodomainT)
0121 , codomain_combine
0122 >::type codomain_intersect;
0123 typedef typename inverse<codomain_intersect>::type inverse_codomain_intersect;
0124 typedef typename base_type::value_compare value_compare;
0125
0126 typedef typename ICL_IMPL_SPACE::set<DomainT, domain_compare, Alloc<DomainT> > set_type;
0127 typedef set_type key_object_type;
0128
0129
0130 BOOST_STATIC_CONSTANT(bool, _total = (Traits::is_total));
0131 BOOST_STATIC_CONSTANT(bool, _absorbs = (Traits::absorbs_identities));
0132 BOOST_STATIC_CONSTANT(bool,
0133 total_invertible = (mpl::and_<is_total<type>, has_inverse<codomain_type> >::value));
0134
0135 typedef on_absorbtion<type,codomain_combine,Traits::absorbs_identities>
0136 on_identity_absorbtion;
0137
0138 public:
0139 typedef typename base_type::pointer pointer;
0140 typedef typename base_type::const_pointer const_pointer;
0141 typedef typename base_type::reference reference;
0142 typedef typename base_type::const_reference const_reference;
0143 typedef typename base_type::iterator iterator;
0144 typedef typename base_type::const_iterator const_iterator;
0145 typedef typename base_type::size_type size_type;
0146 typedef typename base_type::difference_type difference_type;
0147 typedef typename base_type::reverse_iterator reverse_iterator;
0148 typedef typename base_type::const_reverse_iterator const_reverse_iterator;
0149
0150 public:
0151 BOOST_STATIC_CONSTANT(bool,
0152 is_total_invertible = ( Traits::is_total
0153 && has_inverse<codomain_type>::value));
0154
0155 BOOST_STATIC_CONSTANT(int, fineness = 4);
0156
0157 public:
0158
0159
0160
0161 map()
0162 {
0163 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
0164 BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
0165 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
0166 BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
0167 }
0168
0169 map(const key_compare& comp): base_type(comp){}
0170
0171 template <class InputIterator>
0172 map(InputIterator first, InputIterator past)
0173 : base_type(first,past){}
0174
0175 template <class InputIterator>
0176 map(InputIterator first, InputIterator past, const key_compare& comp)
0177 : base_type(first,past,comp)
0178 {}
0179
0180 map(const map& src)
0181 : base_type(src)
0182 {
0183 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
0184 BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
0185 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
0186 BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
0187 }
0188
0189 explicit map(const element_type& key_value_pair): base_type::map()
0190 {
0191 insert(key_value_pair);
0192 }
0193
0194 # ifndef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
0195
0196
0197
0198
0199 map(map&& src)
0200 : base_type(boost::move(src))
0201 {
0202 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
0203 BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
0204 BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
0205 BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
0206 }
0207
0208 map& operator = (map src)
0209 {
0210 base_type::operator=(boost::move(src));
0211 return *this;
0212 }
0213
0214 # else
0215
0216 map& operator = (const map& src)
0217 {
0218 base_type::operator=(src);
0219 return *this;
0220 }
0221
0222 # endif
0223
0224 void swap(map& src) { base_type::swap(src); }
0225
0226
0227 using base_type::empty;
0228 using base_type::clear;
0229
0230 using base_type::begin;
0231 using base_type::end;
0232 using base_type::rbegin;
0233 using base_type::rend;
0234
0235 using base_type::size;
0236 using base_type::max_size;
0237
0238 using base_type::key_comp;
0239 using base_type::value_comp;
0240
0241 using base_type::erase;
0242 using base_type::find;
0243 using base_type::count;
0244
0245 using base_type::lower_bound;
0246 using base_type::upper_bound;
0247 using base_type::equal_range;
0248
0249 using base_type::operator[];
0250
0251 public:
0252
0253
0254
0255
0256 template<class SubObject>
0257 bool contains(const SubObject& sub)const
0258 { return icl::contains(*this, sub); }
0259
0260 bool within(const map& super)const
0261 { return icl::contains(super, *this); }
0262
0263
0264
0265
0266
0267
0268
0269 std::size_t iterative_size()const { return base_type::size(); }
0270
0271
0272
0273
0274
0275
0276 codomain_type operator()(const domain_type& key)const
0277 {
0278 const_iterator it = find(key);
0279 return it==end() ? identity_element<codomain_type>::value()
0280 : it->second;
0281 }
0282
0283
0284
0285
0286
0287
0288
0289
0290 map& add(const value_type& value_pair)
0291 {
0292 return _add<codomain_combine>(value_pair);
0293 }
0294
0295
0296
0297 iterator add(iterator prior, const value_type& value_pair)
0298 {
0299 return _add<codomain_combine>(prior, value_pair);
0300 }
0301
0302
0303
0304
0305
0306
0307 map& subtract(const element_type& value_pair)
0308 {
0309 on_invertible<type, is_total_invertible>
0310 ::subtract(*this, value_pair);
0311 return *this;
0312 }
0313
0314 map& subtract(const domain_type& key)
0315 {
0316 icl::erase(*this, key);
0317 return *this;
0318 }
0319
0320
0321
0322
0323 std::pair<iterator,bool> insert(const value_type& value_pair)
0324 {
0325 if(on_identity_absorbtion::is_absorbable(value_pair.second))
0326 return std::pair<iterator,bool>(end(),true);
0327 else
0328 return base_type::insert(value_pair);
0329 }
0330
0331 iterator insert(iterator prior, const value_type& value_pair)
0332 {
0333 if(on_identity_absorbtion::is_absorbable(value_pair.second))
0334 return end();
0335 else
0336 return base_type::insert(prior, value_pair);
0337 }
0338
0339 template<class Iterator>
0340 iterator insert(Iterator first, Iterator last)
0341 {
0342 iterator prior = end(), it = first;
0343 while(it != last)
0344 prior = this->insert(prior, *it++);
0345 }
0346
0347
0348 map& set(const element_type& key_value_pair)
0349 {
0350 return icl::set_at(*this, key_value_pair);
0351 }
0352
0353
0354
0355 size_type erase(const element_type& key_value_pair)
0356 {
0357 return icl::erase(*this, key_value_pair);
0358 }
0359
0360
0361
0362
0363
0364 void add_intersection(map& section, const element_type& key_value_pair)const
0365 {
0366 on_definedness<type, Traits::is_total>
0367 ::add_intersection(section, *this, key_value_pair);
0368 }
0369
0370
0371
0372
0373
0374 map& flip(const element_type& operand)
0375 {
0376 on_total_absorbable<type,_total,_absorbs>::flip(*this, operand);
0377 return *this;
0378 }
0379
0380 private:
0381 template<class Combiner>
0382 map& _add(const element_type& value_pair);
0383
0384 template<class Combiner>
0385 iterator _add(iterator prior, const element_type& value_pair);
0386
0387 template<class Combiner>
0388 map& _subtract(const element_type& value_pair);
0389
0390 template<class FragmentT>
0391 void total_add_intersection(type& section, const FragmentT& fragment)const
0392 {
0393 section += *this;
0394 section.add(fragment);
0395 }
0396
0397 void partial_add_intersection(type& section, const element_type& operand)const
0398 {
0399 const_iterator it_ = find(operand.first);
0400 if(it_ != end())
0401 {
0402 section.template _add<codomain_combine >(*it_);
0403 section.template _add<codomain_intersect>(operand);
0404 }
0405 }
0406
0407
0408 private:
0409
0410 template<class Type, bool is_total_invertible>
0411 struct on_invertible;
0412
0413 template<class Type>
0414 struct on_invertible<Type, true>
0415 {
0416 typedef typename Type::element_type element_type;
0417 typedef typename Type::inverse_codomain_combine inverse_codomain_combine;
0418
0419 static void subtract(Type& object, const element_type& operand)
0420 { object.template _add<inverse_codomain_combine>(operand); }
0421 };
0422
0423 template<class Type>
0424 struct on_invertible<Type, false>
0425 {
0426 typedef typename Type::element_type element_type;
0427 typedef typename Type::inverse_codomain_combine inverse_codomain_combine;
0428
0429 static void subtract(Type& object, const element_type& operand)
0430 { object.template _subtract<inverse_codomain_combine>(operand); }
0431 };
0432
0433 friend struct on_invertible<type, true>;
0434 friend struct on_invertible<type, false>;
0435
0436
0437
0438 template<class Type, bool is_total>
0439 struct on_definedness;
0440
0441 template<class Type>
0442 struct on_definedness<Type, true>
0443 {
0444 static void add_intersection(Type& section, const Type& object,
0445 const element_type& operand)
0446 { object.total_add_intersection(section, operand); }
0447 };
0448
0449 template<class Type>
0450 struct on_definedness<Type, false>
0451 {
0452 static void add_intersection(Type& section, const Type& object,
0453 const element_type& operand)
0454 { object.partial_add_intersection(section, operand); }
0455 };
0456
0457 friend struct on_definedness<type, true>;
0458 friend struct on_definedness<type, false>;
0459
0460
0461
0462 template<class Type, bool has_set_semantics, bool absorbs_identities>
0463 struct on_codomain_model;
0464
0465 template<class Type>
0466 struct on_codomain_model<Type, false, false>
0467 {
0468 static void subtract(Type&, typename Type::iterator it_,
0469 const typename Type::codomain_type& )
0470 { (*it_).second = identity_element<typename Type::codomain_type>::value(); }
0471 };
0472
0473 template<class Type>
0474 struct on_codomain_model<Type, false, true>
0475 {
0476 static void subtract(Type& object, typename Type::iterator it_,
0477 const typename Type::codomain_type& )
0478 { object.erase(it_); }
0479 };
0480
0481 template<class Type>
0482 struct on_codomain_model<Type, true, false>
0483 {
0484 typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
0485 static void subtract(Type&, typename Type::iterator it_,
0486 const typename Type::codomain_type& co_value)
0487 {
0488 inverse_codomain_intersect()((*it_).second, co_value);
0489 }
0490 };
0491
0492 template<class Type>
0493 struct on_codomain_model<Type, true, true>
0494 {
0495 typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
0496 static void subtract(Type& object, typename Type::iterator it_,
0497 const typename Type::codomain_type& co_value)
0498 {
0499 inverse_codomain_intersect()((*it_).second, co_value);
0500 if((*it_).second == identity_element<codomain_type>::value())
0501 object.erase(it_);
0502 }
0503 };
0504
0505
0506
0507 template<class Type, bool is_total, bool absorbs_identities>
0508 struct on_total_absorbable;
0509
0510 template<class Type>
0511 struct on_total_absorbable<Type, true, true>
0512 {
0513 typedef typename Type::element_type element_type;
0514 static void flip(Type& object, const typename Type::element_type&)
0515 { icl::clear(object); }
0516 };
0517
0518 template<class Type>
0519 struct on_total_absorbable<Type, true, false>
0520 {
0521 typedef typename Type::element_type element_type;
0522 typedef typename Type::codomain_type codomain_type;
0523
0524 static void flip(Type& object, const element_type& operand)
0525 {
0526 object.add(operand);
0527 ICL_FORALL(typename Type, it_, object)
0528 (*it_).second = identity_element<codomain_type>::value();
0529 }
0530 };
0531
0532 template<class Type>
0533 struct on_total_absorbable<Type, false, true>
0534 {
0535 typedef typename Type::element_type element_type;
0536 typedef typename Type::codomain_type codomain_type;
0537 typedef typename Type::iterator iterator;
0538 typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
0539
0540 static void flip(Type& object, const element_type& operand)
0541 {
0542 std::pair<iterator,bool> insertion = object.insert(operand);
0543 if(!insertion.second)
0544 on_codomain_model<Type, has_set_semantics<codomain_type>::value, true>
0545 ::subtract(object, insertion.first, operand.second);
0546 }
0547 };
0548
0549 template<class Type>
0550 struct on_total_absorbable<Type, false, false>
0551 {
0552 typedef typename Type::element_type element_type;
0553 typedef typename Type::codomain_type codomain_type;
0554 typedef typename Type::iterator iterator;
0555 typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
0556
0557 static void flip(Type& object, const element_type& operand)
0558 {
0559 std::pair<iterator,bool> insertion = object.insert(operand);
0560 if(!insertion.second)
0561 on_codomain_model<Type, has_set_semantics<codomain_type>::value, false>
0562 ::subtract(object, insertion.first, operand.second);
0563 }
0564 };
0565
0566 friend struct on_total_absorbable<type, true, true >;
0567 friend struct on_total_absorbable<type, false, true >;
0568 friend struct on_total_absorbable<type, true, false>;
0569 friend struct on_total_absorbable<type, false, false>;
0570
0571 };
0572
0573
0574
0575
0576
0577
0578 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
0579 template <class Combiner>
0580 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>&
0581 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>
0582 ::_add(const element_type& addend)
0583 {
0584 typedef typename on_absorbtion
0585 <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
0586
0587 const codomain_type& co_val = addend.second;
0588 if(on_absorbtion_::is_absorbable(co_val))
0589 return *this;
0590
0591 std::pair<iterator,bool> insertion
0592 = base_type::insert(value_type(addend.first, version<Combiner>()(co_val)));
0593
0594 if(!insertion.second)
0595 {
0596 iterator it = insertion.first;
0597 Combiner()((*it).second, co_val);
0598
0599 if(on_absorbtion_::is_absorbable((*it).second))
0600 erase(it);
0601 }
0602 return *this;
0603 }
0604
0605
0606 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
0607 template <class Combiner>
0608 typename map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>::iterator
0609 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>
0610 ::_add(iterator prior_, const value_type& addend)
0611 {
0612 typedef typename on_absorbtion
0613 <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
0614
0615 const codomain_type& co_val = addend.second;
0616 if(on_absorbtion_::is_absorbable(co_val))
0617 return end();
0618
0619 iterator inserted_
0620 = base_type::insert(prior_,
0621 value_type(addend.first, Combiner::identity_element()));
0622 Combiner()((*inserted_).second, addend.second);
0623
0624 if(on_absorbtion_::is_absorbable((*inserted_).second))
0625 {
0626 erase(inserted_);
0627 return end();
0628 }
0629 else
0630 return inserted_;
0631 }
0632
0633
0634
0635
0636
0637 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
0638 template <class Combiner>
0639 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>&
0640 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>::_subtract(const value_type& minuend)
0641 {
0642 typedef typename on_absorbtion
0643 <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
0644
0645 iterator it_ = find(minuend.first);
0646 if(it_ != end())
0647 {
0648 Combiner()((*it_).second, minuend.second);
0649 if(on_absorbtion_::is_absorbable((*it_).second))
0650 erase(it_);
0651 }
0652 return *this;
0653 }
0654
0655
0656
0657
0658
0659 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
0660 struct is_map<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
0661 {
0662 typedef is_map<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> > type;
0663 BOOST_STATIC_CONSTANT(bool, value = true);
0664 };
0665
0666 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
0667 struct has_inverse<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
0668 {
0669 typedef has_inverse<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> > type;
0670 BOOST_STATIC_CONSTANT(bool, value = (has_inverse<CodomainT>::value));
0671 };
0672
0673 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
0674 struct absorbs_identities<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
0675 {
0676 typedef absorbs_identities type;
0677 BOOST_STATIC_CONSTANT(int, value = Traits::absorbs_identities);
0678 };
0679
0680 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
0681 struct is_total<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
0682 {
0683 typedef is_total type;
0684 BOOST_STATIC_CONSTANT(int, value = Traits::is_total);
0685 };
0686
0687 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
0688 struct type_to_string<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
0689 {
0690 static std::string apply()
0691 {
0692 return "map<"+ type_to_string<DomainT>::apply() + ","
0693 + type_to_string<CodomainT>::apply() + ","
0694 + type_to_string<Traits>::apply() +">";
0695 }
0696 };
0697
0698
0699
0700 }}
0701
0702 #endif