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
10 
11 #include <boost/icl/impl_config.hpp>
12 
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)
17 #   include <map>
18 #   include <set>
19 #else // Default for implementing containers
20 #   include <map>
21 #   include <set>
22 #endif
23 
24 #include <string>
25 #include <boost/type_traits/ice.hpp>
26 #include <boost/call_traits.hpp>
27 #include <boost/icl/detail/notate.hpp>
28 #include <boost/icl/detail/design_config.hpp>
29 #include <boost/icl/detail/concept_check.hpp>
30 #include <boost/icl/detail/on_absorbtion.hpp>
31 #include <boost/icl/type_traits/is_map.hpp>
32 #include <boost/icl/type_traits/absorbs_identities.hpp>
33 #include <boost/icl/type_traits/is_total.hpp>
34 #include <boost/icl/type_traits/is_element_container.hpp>
35 #include <boost/icl/type_traits/has_inverse.hpp>
36 #include <boost/icl/type_traits/to_string.hpp>
37 
38 #include <boost/icl/associative_element_container.hpp>
39 #include <boost/icl/functors.hpp>
40 
41 namespace boost{namespace icl
42 {
43 
44 struct partial_absorber
45 {
46     enum { absorbs_identities = true };
47     enum { is_total = false };
48 };
49 
50 template<>
apply()51 inline std::string type_to_string<partial_absorber>::apply() { return "@0"; }
52 
53 struct partial_enricher
54 {
55     enum { absorbs_identities = false };
56     enum { is_total = false };
57 };
58 
59 template<>
apply()60 inline std::string type_to_string<partial_enricher>::apply() { return "e0"; }
61 
62 struct total_absorber
63 {
64     enum { absorbs_identities = true };
65     enum { is_total = true };
66 };
67 
68 template<>
apply()69 inline std::string type_to_string<total_absorber>::apply() { return "^0"; }
70 
71 struct total_enricher
72 {
73     enum { absorbs_identities = false };
74     enum { is_total = true };
75 };
76 
77 template<>
apply()78 inline std::string type_to_string<total_enricher>::apply() { return "e^0"; }
79 
80 
81 
82 /** \brief Addable, subractable and intersectable maps */
83 template
84 <
85     typename DomainT,
86     typename CodomainT,
87     class Traits = icl::partial_absorber,
88     ICL_COMPARE Compare = ICL_COMPARE_INSTANCE(ICL_COMPARE_DEFAULT, DomainT),
89     ICL_COMBINE Combine = ICL_COMBINE_INSTANCE(icl::inplace_plus, CodomainT),
90     ICL_SECTION Section = ICL_SECTION_INSTANCE(icl::inter_section, CodomainT),
91     ICL_ALLOC   Alloc   = std::allocator
92 >
93 class map: private ICL_IMPL_SPACE::map<DomainT, CodomainT, ICL_COMPARE_DOMAIN(Compare,DomainT),
94                                        Alloc<std::pair<const DomainT, CodomainT> > >
95 {
96 public:
97     typedef Alloc<typename std::pair<const DomainT, CodomainT> >  allocator_type;
98 
99     typedef typename icl::map<DomainT,CodomainT,Traits, Compare,Combine,Section,Alloc> type;
100     typedef typename ICL_IMPL_SPACE::map<DomainT, CodomainT, ICL_COMPARE_DOMAIN(Compare,DomainT),
101                                          allocator_type>   base_type;
102 
103     typedef Traits traits;
104 
105 public:
106     typedef DomainT                                     domain_type;
107     typedef typename boost::call_traits<DomainT>::param_type domain_param;
108     typedef DomainT                                     key_type;
109     typedef CodomainT                                   codomain_type;
110     typedef CodomainT                                   mapped_type;
111     typedef CodomainT                                   data_type;
112     typedef std::pair<const DomainT, CodomainT>         element_type;
113     typedef std::pair<const DomainT, CodomainT>         value_type;
114     typedef ICL_COMPARE_DOMAIN(Compare,DomainT)         domain_compare;
115     typedef ICL_COMBINE_CODOMAIN(Combine,CodomainT)     codomain_combine;
116     typedef domain_compare                              key_compare;
117     typedef ICL_COMPARE_DOMAIN(Compare,element_type)    element_compare;
118     typedef typename inverse<codomain_combine >::type   inverse_codomain_combine;
119     typedef typename mpl::if_
120         <has_set_semantics<codomain_type>
121         , ICL_SECTION_CODOMAIN(Section,CodomainT)
122         , codomain_combine
123         >::type                                         codomain_intersect;
124     typedef typename inverse<codomain_intersect>::type  inverse_codomain_intersect;
125     typedef typename base_type::value_compare           value_compare;
126 
127     typedef typename ICL_IMPL_SPACE::set<DomainT, domain_compare, Alloc<DomainT> > set_type;
128     typedef set_type                                       key_object_type;
129 
130 
131     BOOST_STATIC_CONSTANT(bool, _total   = (Traits::is_total));
132     BOOST_STATIC_CONSTANT(bool, _absorbs = (Traits::absorbs_identities));
133     BOOST_STATIC_CONSTANT(bool,
134         total_invertible = (mpl::and_<is_total<type>, has_inverse<codomain_type> >::value));
135 
136     typedef on_absorbtion<type,codomain_combine,Traits::absorbs_identities>
137                                                         on_identity_absorbtion;
138 
139 public:
140     typedef typename base_type::pointer                 pointer;
141     typedef typename base_type::const_pointer           const_pointer;
142     typedef typename base_type::reference               reference;
143     typedef typename base_type::const_reference         const_reference;
144     typedef typename base_type::iterator                iterator;
145     typedef typename base_type::const_iterator          const_iterator;
146     typedef typename base_type::size_type               size_type;
147     typedef typename base_type::difference_type         difference_type;
148     typedef typename base_type::reverse_iterator        reverse_iterator;
149     typedef typename base_type::const_reverse_iterator  const_reverse_iterator;
150 
151 public:
152     BOOST_STATIC_CONSTANT(bool,
153         is_total_invertible = (   Traits::is_total
154                                && has_inverse<codomain_type>::value));
155 
156     BOOST_STATIC_CONSTANT(int, fineness = 4);
157 
158 public:
159     //==========================================================================
160     //= Construct, copy, destruct
161     //==========================================================================
map()162     map()
163     {
164         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
165         BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
166         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
167         BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
168     }
169 
map(const key_compare & comp)170     map(const key_compare& comp): base_type(comp){}
171 
172     template <class InputIterator>
map(InputIterator first,InputIterator past)173     map(InputIterator first, InputIterator past)
174         : base_type(first,past){}
175 
176     template <class InputIterator>
map(InputIterator first,InputIterator past,const key_compare & comp)177     map(InputIterator first, InputIterator past, const key_compare& comp)
178         : base_type(first,past,comp)
179     {}
180 
map(const map & src)181     map(const map& src)
182         : base_type(src)
183     {
184         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
185         BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
186         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
187         BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
188     }
189 
map(const element_type & key_value_pair)190     explicit map(const element_type& key_value_pair): base_type::map()
191     {
192         insert(key_value_pair);
193     }
194 
195 #   ifndef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
196     //==========================================================================
197     //= Move semantics
198     //==========================================================================
199 
map(map && src)200     map(map&& src)
201         : base_type(boost::move(src))
202     {
203         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
204         BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
205         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
206         BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
207     }
208 
operator =(map src)209     map& operator = (map src)
210     {
211         base_type::operator=(boost::move(src));
212         return *this;
213     }
214     //==========================================================================
215 #   else
216 
operator =(const map & src)217     map& operator = (const map& src)
218     {
219         base_type::operator=(src);
220         return *this;
221     }
222 
223 #   endif // BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
224 
swap(map & src)225     void swap(map& src) { base_type::swap(src); }
226 
227     //==========================================================================
228     using base_type::empty;
229     using base_type::clear;
230 
231     using base_type::begin;
232     using base_type::end;
233     using base_type::rbegin;
234     using base_type::rend;
235 
236     using base_type::size;
237     using base_type::max_size;
238 
239     using base_type::key_comp;
240     using base_type::value_comp;
241 
242     using base_type::erase;
243     using base_type::find;
244     using base_type::count;
245 
246     using base_type::lower_bound;
247     using base_type::upper_bound;
248     using base_type::equal_range;
249 
250     using base_type::operator[];
251 
252 public:
253     //==========================================================================
254     //= Containedness
255     //==========================================================================
256 
257     template<class SubObject>
contains(const SubObject & sub) const258     bool contains(const SubObject& sub)const
259     { return icl::contains(*this, sub); }
260 
within(const map & super) const261     bool within(const map& super)const
262     { return icl::contains(super, *this); }
263 
264     //==========================================================================
265     //= Size
266     //==========================================================================
267     /** \c iterative_size() yields the number of elements that is visited
268         throu complete iteration. For interval sets \c iterative_size() is
269         different from \c size(). */
iterative_size() const270     std::size_t iterative_size()const { return base_type::size(); }
271 
272     //==========================================================================
273     //= Selection
274     //==========================================================================
275 
276     /** Total select function. */
operator ()(const domain_type & key) const277     codomain_type operator()(const domain_type& key)const
278     {
279         const_iterator it = find(key);
280         return it==end() ? identity_element<codomain_type>::value()
281                          : it->second;
282     }
283 
284     //==========================================================================
285     //= Addition
286     //==========================================================================
287     /** \c add inserts \c value_pair into the map if it's key does
288         not exist in the map.
289         If \c value_pairs's key value exists in the map, it's data
290         value is added to the data value already found in the map. */
add(const value_type & value_pair)291     map& add(const value_type& value_pair)
292     {
293         return _add<codomain_combine>(value_pair);
294     }
295 
296     /** \c add add \c value_pair into the map using \c prior as a hint to
297         insert \c value_pair after the position \c prior is pointing to. */
add(iterator prior,const value_type & value_pair)298     iterator add(iterator prior, const value_type& value_pair)
299     {
300         return _add<codomain_combine>(prior, value_pair);
301     }
302 
303     //==========================================================================
304     //= Subtraction
305     //==========================================================================
306     /** If the \c value_pair's key value is in the map, it's data value is
307         subtraced from the data value stored in the map. */
subtract(const element_type & value_pair)308     map& subtract(const element_type& value_pair)
309     {
310         on_invertible<type, is_total_invertible>
311             ::subtract(*this, value_pair);
312         return *this;
313     }
314 
subtract(const domain_type & key)315     map& subtract(const domain_type& key)
316     {
317         icl::erase(*this, key);
318         return *this;
319     }
320 
321     //==========================================================================
322     //= Insertion, erasure
323     //==========================================================================
insert(const value_type & value_pair)324     std::pair<iterator,bool> insert(const value_type& value_pair)
325     {
326         if(on_identity_absorbtion::is_absorbable(value_pair.second))
327             return std::pair<iterator,bool>(end(),true);
328         else
329             return base_type::insert(value_pair);
330     }
331 
insert(iterator prior,const value_type & value_pair)332     iterator insert(iterator prior, const value_type& value_pair)
333     {
334         if(on_identity_absorbtion::is_absorbable(value_pair.second))
335             return end();
336         else
337             return base_type::insert(prior, value_pair);
338     }
339 
340     template<class Iterator>
insert(Iterator first,Iterator last)341     iterator insert(Iterator first, Iterator last)
342     {
343         iterator prior = end(), it = first;
344         while(it != last)
345             prior = this->insert(prior, *it++);
346     }
347 
348     /** With <tt>key_value_pair = (k,v)</tt> set value \c v for key \c k */
set(const element_type & key_value_pair)349     map& set(const element_type& key_value_pair)
350     {
351         return icl::set_at(*this, key_value_pair);
352     }
353 
354     /** erase \c key_value_pair from the map.
355         Erase only if, the exact value content \c val is stored for the given key. */
erase(const element_type & key_value_pair)356     size_type erase(const element_type& key_value_pair)
357     {
358         return icl::erase(*this, key_value_pair);
359     }
360 
361     //==========================================================================
362     //= Intersection
363     //==========================================================================
364     /** The intersection of \c key_value_pair and \c *this map is added to \c section. */
add_intersection(map & section,const element_type & key_value_pair) const365     void add_intersection(map& section, const element_type& key_value_pair)const
366     {
367         on_definedness<type, Traits::is_total>
368             ::add_intersection(section, *this, key_value_pair);
369     }
370 
371     //==========================================================================
372     //= Symmetric difference
373     //==========================================================================
374 
flip(const element_type & operand)375     map& flip(const element_type& operand)
376     {
377         on_total_absorbable<type,_total,_absorbs>::flip(*this, operand);
378         return *this;
379     }
380 
381 private:
382     template<class Combiner>
383     map& _add(const element_type& value_pair);
384 
385     template<class Combiner>
386     iterator _add(iterator prior, const element_type& value_pair);
387 
388     template<class Combiner>
389     map& _subtract(const element_type& value_pair);
390 
391     template<class FragmentT>
total_add_intersection(type & section,const FragmentT & fragment) const392     void total_add_intersection(type& section, const FragmentT& fragment)const
393     {
394         section += *this;
395         section.add(fragment);
396     }
397 
partial_add_intersection(type & section,const element_type & operand) const398     void partial_add_intersection(type& section, const element_type& operand)const
399     {
400         const_iterator it_ = find(operand.first);
401         if(it_ != end())
402         {
403             section.template _add<codomain_combine  >(*it_);
404             section.template _add<codomain_intersect>(operand);
405         }
406     }
407 
408 
409 private:
410     //--------------------------------------------------------------------------
411     template<class Type, bool is_total_invertible>
412     struct on_invertible;
413 
414     template<class Type>
415     struct on_invertible<Type, true>
416     {
417         typedef typename Type::element_type element_type;
418         typedef typename Type::inverse_codomain_combine inverse_codomain_combine;
419 
subtractboost::icl::map::on_invertible420         static void subtract(Type& object, const element_type& operand)
421         { object.template _add<inverse_codomain_combine>(operand); }
422     };
423 
424     template<class Type>
425     struct on_invertible<Type, false>
426     {
427         typedef typename Type::element_type element_type;
428         typedef typename Type::inverse_codomain_combine inverse_codomain_combine;
429 
subtractboost::icl::map::on_invertible430         static void subtract(Type& object, const element_type& operand)
431         { object.template _subtract<inverse_codomain_combine>(operand); }
432     };
433 
434     friend struct on_invertible<type, true>;
435     friend struct on_invertible<type, false>;
436     //--------------------------------------------------------------------------
437 
438     //--------------------------------------------------------------------------
439     template<class Type, bool is_total>
440     struct on_definedness;
441 
442     template<class Type>
443     struct on_definedness<Type, true>
444     {
add_intersectionboost::icl::map::on_definedness445         static void add_intersection(Type& section, const Type& object,
446                                      const element_type& operand)
447         { object.total_add_intersection(section, operand); }
448     };
449 
450     template<class Type>
451     struct on_definedness<Type, false>
452     {
add_intersectionboost::icl::map::on_definedness453         static void add_intersection(Type& section, const Type& object,
454                                      const element_type& operand)
455         { object.partial_add_intersection(section, operand); }
456     };
457 
458     friend struct on_definedness<type, true>;
459     friend struct on_definedness<type, false>;
460     //--------------------------------------------------------------------------
461 
462     //--------------------------------------------------------------------------
463     template<class Type, bool has_set_semantics, bool absorbs_identities>
464     struct on_codomain_model;
465 
466     template<class Type>
467     struct on_codomain_model<Type, false, false>
468     {                // !codomain_is_set, !absorbs_identities
subtractboost::icl::map::on_codomain_model469         static void subtract(Type&, typename Type::iterator it_,
470                               const typename Type::codomain_type& )
471         { (*it_).second = identity_element<typename Type::codomain_type>::value(); }
472     };
473 
474     template<class Type>
475     struct on_codomain_model<Type, false, true>
476     {                // !codomain_is_set, absorbs_identities
subtractboost::icl::map::on_codomain_model477         static void subtract(Type& object, typename Type::iterator       it_,
478                                      const typename Type::codomain_type&     )
479         { object.erase(it_); }
480     };
481 
482     template<class Type>
483     struct on_codomain_model<Type, true, false>
484     {               // !codomain_is_set, !absorbs_identities
485         typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
subtractboost::icl::map::on_codomain_model486         static void subtract(Type&, typename Type::iterator       it_,
487                               const typename Type::codomain_type& co_value)
488         {
489             inverse_codomain_intersect()((*it_).second, co_value);
490         }
491     };
492 
493     template<class Type>
494     struct on_codomain_model<Type, true, true>
495     {               // !codomain_is_set, absorbs_identities
496         typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
subtractboost::icl::map::on_codomain_model497         static void subtract(Type& object, typename Type::iterator       it_,
498                                      const typename Type::codomain_type& co_value)
499         {
500             inverse_codomain_intersect()((*it_).second, co_value);
501             if((*it_).second == identity_element<codomain_type>::value())
502                 object.erase(it_);
503         }
504     };
505     //--------------------------------------------------------------------------
506 
507     //--------------------------------------------------------------------------
508     template<class Type, bool is_total, bool absorbs_identities>
509     struct on_total_absorbable;
510 
511     template<class Type>
512     struct on_total_absorbable<Type, true, true>
513     {
514         typedef typename Type::element_type  element_type;
flipboost::icl::map::on_total_absorbable515         static void flip(Type& object, const typename Type::element_type&)
516         { icl::clear(object); }
517     };
518 
519     template<class Type>
520     struct on_total_absorbable<Type, true, false>
521     {
522         typedef typename Type::element_type  element_type;
523         typedef typename Type::codomain_type codomain_type;
524 
flipboost::icl::map::on_total_absorbable525         static void flip(Type& object, const element_type& operand)
526         {
527             object.add(operand);
528             ICL_FORALL(typename Type, it_, object)
529                 (*it_).second = identity_element<codomain_type>::value();
530         }
531     };
532 
533     template<class Type>
534     struct on_total_absorbable<Type, false, true>
535     {                         // !is_total, absorbs_identities
536         typedef typename Type::element_type   element_type;
537         typedef typename Type::codomain_type  codomain_type;
538         typedef typename Type::iterator       iterator;
539         typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
540 
flipboost::icl::map::on_total_absorbable541         static void flip(Type& object, const element_type& operand)
542         {
543             std::pair<iterator,bool> insertion = object.insert(operand);
544             if(!insertion.second)
545                 on_codomain_model<Type, has_set_semantics<codomain_type>::value, true>
546                 ::subtract(object, insertion.first, operand.second);
547         }
548     };
549 
550     template<class Type>
551     struct on_total_absorbable<Type, false, false>
552     {                         // !is_total  !absorbs_identities
553         typedef typename Type::element_type   element_type;
554         typedef typename Type::codomain_type  codomain_type;
555         typedef typename Type::iterator       iterator;
556         typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
557 
flipboost::icl::map::on_total_absorbable558         static void flip(Type& object, const element_type& operand)
559         {
560             std::pair<iterator,bool> insertion = object.insert(operand);
561             if(!insertion.second)
562                 on_codomain_model<Type, has_set_semantics<codomain_type>::value, false>
563                 ::subtract(object, insertion.first, operand.second);
564         }
565     };
566 
567     friend struct on_total_absorbable<type, true,  true >;
568     friend struct on_total_absorbable<type, false, true >;
569     friend struct on_total_absorbable<type, true,  false>;
570     friend struct on_total_absorbable<type, false, false>;
571     //--------------------------------------------------------------------------
572 };
573 
574 
575 
576 //==============================================================================
577 //= Addition<ElementMap>
578 //==============================================================================
579 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
580     template <class Combiner>
581 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>&
582     map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>
_add(const element_type & addend)583     ::_add(const element_type& addend)
584 {
585     typedef typename on_absorbtion
586         <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
587 
588     const codomain_type& co_val    = addend.second;
589     if(on_absorbtion_::is_absorbable(co_val))
590         return *this;
591 
592     std::pair<iterator,bool> insertion
593         = base_type::insert(value_type(addend.first, version<Combiner>()(co_val)));
594 
595     if(!insertion.second)
596     {
597         iterator it = insertion.first;
598         Combiner()((*it).second, co_val);
599 
600         if(on_absorbtion_::is_absorbable((*it).second))
601             erase(it);
602     }
603     return *this;
604 }
605 
606 
607 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
608     template <class Combiner>
609 typename map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>::iterator
610     map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>
_add(iterator prior_,const value_type & addend)611     ::_add(iterator prior_, const value_type& addend)
612 {
613     typedef typename on_absorbtion
614         <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
615 
616     const codomain_type& co_val    = addend.second;
617     if(on_absorbtion_::is_absorbable(co_val))
618         return end();
619 
620     iterator inserted_
621         = base_type::insert(prior_,
622                             value_type(addend.first, Combiner::identity_element()));
623     Combiner()((*inserted_).second, addend.second);
624 
625     if(on_absorbtion_::is_absorbable((*inserted_).second))
626     {
627         erase(inserted_);
628         return end();
629     }
630     else
631         return inserted_;
632 }
633 
634 
635 //==============================================================================
636 //= Subtraction<ElementMap>
637 //==============================================================================
638 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
639     template <class Combiner>
640 map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>&
_subtract(const value_type & minuend)641     map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>::_subtract(const value_type& minuend)
642 {
643     typedef typename on_absorbtion
644         <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
645 
646     iterator it_ = find(minuend.first);
647     if(it_ != end())
648     {
649         Combiner()((*it_).second, minuend.second);
650         if(on_absorbtion_::is_absorbable((*it_).second))
651             erase(it_);
652     }
653     return *this;
654 }
655 
656 
657 //-----------------------------------------------------------------------------
658 // type traits
659 //-----------------------------------------------------------------------------
660 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
661 struct is_map<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
662 {
663     typedef is_map<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> > type;
664     BOOST_STATIC_CONSTANT(bool, value = true);
665 };
666 
667 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
668 struct has_inverse<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
669 {
670     typedef has_inverse<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> > type;
671     BOOST_STATIC_CONSTANT(bool, value = (has_inverse<CodomainT>::value));
672 };
673 
674 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
675 struct absorbs_identities<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
676 {
677     typedef absorbs_identities type;
678     BOOST_STATIC_CONSTANT(int, value = Traits::absorbs_identities);
679 };
680 
681 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
682 struct is_total<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
683 {
684     typedef is_total type;
685     BOOST_STATIC_CONSTANT(int, value = Traits::is_total);
686 };
687 
688 template <class DomainT, class CodomainT, class Traits, ICL_COMPARE Compare, ICL_COMBINE Combine, ICL_SECTION Section, ICL_ALLOC Alloc>
689 struct type_to_string<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> >
690 {
applyboost::icl::type_to_string691     static std::string apply()
692     {
693         return "map<"+ type_to_string<DomainT>::apply()  + ","
694                      + type_to_string<CodomainT>::apply() + ","
695                      + type_to_string<Traits>::apply() +">";
696     }
697 };
698 
699 
700 
701 }} // namespace icl boost
702 
703 #endif // BOOST_ICL_MAP_HPP_JOFA_070519
704 
705