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/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>
35 
36 #include <boost/icl/associative_element_container.hpp>
37 #include <boost/icl/functors.hpp>
38 #include <boost/icl/type_traits/to_string.hpp>
39 
40 namespace boost{namespace icl
41 {
42 
43 struct partial_absorber
44 {
45     enum { absorbs_identities = true };
46     enum { is_total = false };
47 };
48 
49 template<>
apply()50 inline std::string type_to_string<partial_absorber>::apply() { return "@0"; }
51 
52 struct partial_enricher
53 {
54     enum { absorbs_identities = false };
55     enum { is_total = false };
56 };
57 
58 template<>
apply()59 inline std::string type_to_string<partial_enricher>::apply() { return "e0"; }
60 
61 struct total_absorber
62 {
63     enum { absorbs_identities = true };
64     enum { is_total = true };
65 };
66 
67 template<>
apply()68 inline std::string type_to_string<total_absorber>::apply() { return "^0"; }
69 
70 struct total_enricher
71 {
72     enum { absorbs_identities = false };
73     enum { is_total = true };
74 };
75 
76 template<>
apply()77 inline std::string type_to_string<total_enricher>::apply() { return "e^0"; }
78 
79 
80 
81 /** \brief Addable, subractable and intersectable maps */
82 template
83 <
84     typename DomainT,
85     typename CodomainT,
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
91 >
92 class map: private ICL_IMPL_SPACE::map<DomainT, CodomainT, ICL_COMPARE_DOMAIN(Compare,DomainT),
93                                        Alloc<std::pair<const DomainT, CodomainT> > >
94 {
95 public:
96     typedef Alloc<typename std::pair<const DomainT, CodomainT> >  allocator_type;
97 
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;
101 
102     typedef Traits traits;
103 
104 public:
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)
121         , codomain_combine
122         >::type                                         codomain_intersect;
123     typedef typename inverse<codomain_intersect>::type  inverse_codomain_intersect;
124     typedef typename base_type::value_compare           value_compare;
125 
126     typedef typename ICL_IMPL_SPACE::set<DomainT, domain_compare, Alloc<DomainT> > set_type;
127     typedef set_type                                       key_object_type;
128 
129 
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));
134 
135     typedef on_absorbtion<type,codomain_combine,Traits::absorbs_identities>
136                                                         on_identity_absorbtion;
137 
138 public:
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;
149 
150 public:
151     BOOST_STATIC_CONSTANT(bool,
152         is_total_invertible = (   Traits::is_total
153                                && has_inverse<codomain_type>::value));
154 
155     BOOST_STATIC_CONSTANT(int, fineness = 4);
156 
157 public:
158     //==========================================================================
159     //= Construct, copy, destruct
160     //==========================================================================
map()161     map()
162     {
163         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
164         BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
165         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
166         BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
167     }
168 
map(const key_compare & comp)169     map(const key_compare& comp): base_type(comp){}
170 
171     template <class InputIterator>
map(InputIterator first,InputIterator past)172     map(InputIterator first, InputIterator past)
173         : base_type(first,past){}
174 
175     template <class InputIterator>
map(InputIterator first,InputIterator past,const key_compare & comp)176     map(InputIterator first, InputIterator past, const key_compare& comp)
177         : base_type(first,past,comp)
178     {}
179 
map(const map & src)180     map(const map& src)
181         : base_type(src)
182     {
183         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
184         BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
185         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
186         BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
187     }
188 
map(const element_type & key_value_pair)189     explicit map(const element_type& key_value_pair): base_type::map()
190     {
191         insert(key_value_pair);
192     }
193 
194 #   ifndef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
195     //==========================================================================
196     //= Move semantics
197     //==========================================================================
198 
map(map && src)199     map(map&& src)
200         : base_type(boost::move(src))
201     {
202         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<DomainT>));
203         BOOST_CONCEPT_ASSERT((LessThanComparableConcept<DomainT>));
204         BOOST_CONCEPT_ASSERT((DefaultConstructibleConcept<CodomainT>));
205         BOOST_CONCEPT_ASSERT((EqualComparableConcept<CodomainT>));
206     }
207 
operator =(map src)208     map& operator = (map src)
209     {
210         base_type::operator=(boost::move(src));
211         return *this;
212     }
213     //==========================================================================
214 #   else
215 
operator =(const map & src)216     map& operator = (const map& src)
217     {
218         base_type::operator=(src);
219         return *this;
220     }
221 
222 #   endif // BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
223 
swap(map & src)224     void swap(map& src) { base_type::swap(src); }
225 
226     //==========================================================================
227     using base_type::empty;
228     using base_type::clear;
229 
230     using base_type::begin;
231     using base_type::end;
232     using base_type::rbegin;
233     using base_type::rend;
234 
235     using base_type::size;
236     using base_type::max_size;
237 
238     using base_type::key_comp;
239     using base_type::value_comp;
240 
241     using base_type::erase;
242     using base_type::find;
243     using base_type::count;
244 
245     using base_type::lower_bound;
246     using base_type::upper_bound;
247     using base_type::equal_range;
248 
249     using base_type::operator[];
250 
251 public:
252     //==========================================================================
253     //= Containedness
254     //==========================================================================
255 
256     template<class SubObject>
contains(const SubObject & sub) const257     bool contains(const SubObject& sub)const
258     { return icl::contains(*this, sub); }
259 
within(const map & super) const260     bool within(const map& super)const
261     { return icl::contains(super, *this); }
262 
263     //==========================================================================
264     //= Size
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(). */
iterative_size() const269     std::size_t iterative_size()const { return base_type::size(); }
270 
271     //==========================================================================
272     //= Selection
273     //==========================================================================
274 
275     /** Total select function. */
operator ()(const domain_type & key) const276     codomain_type operator()(const domain_type& key)const
277     {
278         const_iterator it = find(key);
279         return it==end() ? identity_element<codomain_type>::value()
280                          : it->second;
281     }
282 
283     //==========================================================================
284     //= Addition
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. */
add(const value_type & value_pair)290     map& add(const value_type& value_pair)
291     {
292         return _add<codomain_combine>(value_pair);
293     }
294 
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. */
add(iterator prior,const value_type & value_pair)297     iterator add(iterator prior, const value_type& value_pair)
298     {
299         return _add<codomain_combine>(prior, value_pair);
300     }
301 
302     //==========================================================================
303     //= Subtraction
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. */
subtract(const element_type & value_pair)307     map& subtract(const element_type& value_pair)
308     {
309         on_invertible<type, is_total_invertible>
310             ::subtract(*this, value_pair);
311         return *this;
312     }
313 
subtract(const domain_type & key)314     map& subtract(const domain_type& key)
315     {
316         icl::erase(*this, key);
317         return *this;
318     }
319 
320     //==========================================================================
321     //= Insertion, erasure
322     //==========================================================================
insert(const value_type & value_pair)323     std::pair<iterator,bool> insert(const value_type& value_pair)
324     {
325         if(on_identity_absorbtion::is_absorbable(value_pair.second))
326             return std::pair<iterator,bool>(end(),true);
327         else
328             return base_type::insert(value_pair);
329     }
330 
insert(iterator prior,const value_type & value_pair)331     iterator insert(iterator prior, const value_type& value_pair)
332     {
333         if(on_identity_absorbtion::is_absorbable(value_pair.second))
334             return end();
335         else
336             return base_type::insert(prior, value_pair);
337     }
338 
339     template<class Iterator>
insert(Iterator first,Iterator last)340     iterator insert(Iterator first, Iterator last)
341     {
342         iterator prior = end(), it = first;
343         while(it != last)
344             prior = this->insert(prior, *it++);
345     }
346 
347     /** With <tt>key_value_pair = (k,v)</tt> set value \c v for key \c k */
set(const element_type & key_value_pair)348     map& set(const element_type& key_value_pair)
349     {
350         return icl::set_at(*this, key_value_pair);
351     }
352 
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. */
erase(const element_type & key_value_pair)355     size_type erase(const element_type& key_value_pair)
356     {
357         return icl::erase(*this, key_value_pair);
358     }
359 
360     //==========================================================================
361     //= Intersection
362     //==========================================================================
363     /** 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) const364     void add_intersection(map& section, const element_type& key_value_pair)const
365     {
366         on_definedness<type, Traits::is_total>
367             ::add_intersection(section, *this, key_value_pair);
368     }
369 
370     //==========================================================================
371     //= Symmetric difference
372     //==========================================================================
373 
flip(const element_type & operand)374     map& flip(const element_type& operand)
375     {
376         on_total_absorbable<type,_total,_absorbs>::flip(*this, operand);
377         return *this;
378     }
379 
380 private:
381     template<class Combiner>
382     map& _add(const element_type& value_pair);
383 
384     template<class Combiner>
385     iterator _add(iterator prior, const element_type& value_pair);
386 
387     template<class Combiner>
388     map& _subtract(const element_type& value_pair);
389 
390     template<class FragmentT>
total_add_intersection(type & section,const FragmentT & fragment) const391     void total_add_intersection(type& section, const FragmentT& fragment)const
392     {
393         section += *this;
394         section.add(fragment);
395     }
396 
partial_add_intersection(type & section,const element_type & operand) const397     void partial_add_intersection(type& section, const element_type& operand)const
398     {
399         const_iterator it_ = find(operand.first);
400         if(it_ != end())
401         {
402             section.template _add<codomain_combine  >(*it_);
403             section.template _add<codomain_intersect>(operand);
404         }
405     }
406 
407 
408 private:
409     //--------------------------------------------------------------------------
410     template<class Type, bool is_total_invertible>
411     struct on_invertible;
412 
413     template<class Type>
414     struct on_invertible<Type, true>
415     {
416         typedef typename Type::element_type element_type;
417         typedef typename Type::inverse_codomain_combine inverse_codomain_combine;
418 
subtractboost::icl::map::on_invertible419         static void subtract(Type& object, const element_type& operand)
420         { object.template _add<inverse_codomain_combine>(operand); }
421     };
422 
423     template<class Type>
424     struct on_invertible<Type, false>
425     {
426         typedef typename Type::element_type element_type;
427         typedef typename Type::inverse_codomain_combine inverse_codomain_combine;
428 
subtractboost::icl::map::on_invertible429         static void subtract(Type& object, const element_type& operand)
430         { object.template _subtract<inverse_codomain_combine>(operand); }
431     };
432 
433     friend struct on_invertible<type, true>;
434     friend struct on_invertible<type, false>;
435     //--------------------------------------------------------------------------
436 
437     //--------------------------------------------------------------------------
438     template<class Type, bool is_total>
439     struct on_definedness;
440 
441     template<class Type>
442     struct on_definedness<Type, true>
443     {
add_intersectionboost::icl::map::on_definedness444         static void add_intersection(Type& section, const Type& object,
445                                      const element_type& operand)
446         { object.total_add_intersection(section, operand); }
447     };
448 
449     template<class Type>
450     struct on_definedness<Type, false>
451     {
add_intersectionboost::icl::map::on_definedness452         static void add_intersection(Type& section, const Type& object,
453                                      const element_type& operand)
454         { object.partial_add_intersection(section, operand); }
455     };
456 
457     friend struct on_definedness<type, true>;
458     friend struct on_definedness<type, false>;
459     //--------------------------------------------------------------------------
460 
461     //--------------------------------------------------------------------------
462     template<class Type, bool has_set_semantics, bool absorbs_identities>
463     struct on_codomain_model;
464 
465     template<class Type>
466     struct on_codomain_model<Type, false, false>
467     {                // !codomain_is_set, !absorbs_identities
subtractboost::icl::map::on_codomain_model468         static void subtract(Type&, typename Type::iterator it_,
469                               const typename Type::codomain_type& )
470         { (*it_).second = identity_element<typename Type::codomain_type>::value(); }
471     };
472 
473     template<class Type>
474     struct on_codomain_model<Type, false, true>
475     {                // !codomain_is_set, absorbs_identities
subtractboost::icl::map::on_codomain_model476         static void subtract(Type& object, typename Type::iterator       it_,
477                                      const typename Type::codomain_type&     )
478         { object.erase(it_); }
479     };
480 
481     template<class Type>
482     struct on_codomain_model<Type, true, false>
483     {               // !codomain_is_set, !absorbs_identities
484         typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
subtractboost::icl::map::on_codomain_model485         static void subtract(Type&, typename Type::iterator       it_,
486                               const typename Type::codomain_type& co_value)
487         {
488             inverse_codomain_intersect()((*it_).second, co_value);
489         }
490     };
491 
492     template<class Type>
493     struct on_codomain_model<Type, true, true>
494     {               // !codomain_is_set, absorbs_identities
495         typedef typename Type::inverse_codomain_intersect inverse_codomain_intersect;
subtractboost::icl::map::on_codomain_model496         static void subtract(Type& object, typename Type::iterator       it_,
497                                      const typename Type::codomain_type& co_value)
498         {
499             inverse_codomain_intersect()((*it_).second, co_value);
500             if((*it_).second == identity_element<codomain_type>::value())
501                 object.erase(it_);
502         }
503     };
504     //--------------------------------------------------------------------------
505 
506     //--------------------------------------------------------------------------
507     template<class Type, bool is_total, bool absorbs_identities>
508     struct on_total_absorbable;
509 
510     template<class Type>
511     struct on_total_absorbable<Type, true, true>
512     {
513         typedef typename Type::element_type  element_type;
flipboost::icl::map::on_total_absorbable514         static void flip(Type& object, const typename Type::element_type&)
515         { icl::clear(object); }
516     };
517 
518     template<class Type>
519     struct on_total_absorbable<Type, true, false>
520     {
521         typedef typename Type::element_type  element_type;
522         typedef typename Type::codomain_type codomain_type;
523 
flipboost::icl::map::on_total_absorbable524         static void flip(Type& object, const element_type& operand)
525         {
526             object.add(operand);
527             ICL_FORALL(typename Type, it_, object)
528                 (*it_).second = identity_element<codomain_type>::value();
529         }
530     };
531 
532     template<class Type>
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;
539 
flipboost::icl::map::on_total_absorbable540         static void flip(Type& object, const element_type& operand)
541         {
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);
546         }
547     };
548 
549     template<class Type>
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;
556 
flipboost::icl::map::on_total_absorbable557         static void flip(Type& object, const element_type& operand)
558         {
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);
563         }
564     };
565 
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     //--------------------------------------------------------------------------
571 };
572 
573 
574 
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>
_add(const element_type & addend)582     ::_add(const element_type& addend)
583 {
584     typedef typename on_absorbtion
585         <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
586 
587     const codomain_type& co_val    = addend.second;
588     if(on_absorbtion_::is_absorbable(co_val))
589         return *this;
590 
591     std::pair<iterator,bool> insertion
592         = base_type::insert(value_type(addend.first, version<Combiner>()(co_val)));
593 
594     if(!insertion.second)
595     {
596         iterator it = insertion.first;
597         Combiner()((*it).second, co_val);
598 
599         if(on_absorbtion_::is_absorbable((*it).second))
600             erase(it);
601     }
602     return *this;
603 }
604 
605 
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>
_add(iterator prior_,const value_type & addend)610     ::_add(iterator prior_, const value_type& addend)
611 {
612     typedef typename on_absorbtion
613         <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
614 
615     const codomain_type& co_val    = addend.second;
616     if(on_absorbtion_::is_absorbable(co_val))
617         return end();
618 
619     iterator inserted_
620         = base_type::insert(prior_,
621                             value_type(addend.first, Combiner::identity_element()));
622     Combiner()((*inserted_).second, addend.second);
623 
624     if(on_absorbtion_::is_absorbable((*inserted_).second))
625     {
626         erase(inserted_);
627         return end();
628     }
629     else
630         return inserted_;
631 }
632 
633 
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>&
_subtract(const value_type & minuend)640     map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc>::_subtract(const value_type& minuend)
641 {
642     typedef typename on_absorbtion
643         <type,Combiner,absorbs_identities<type>::value>::type on_absorbtion_;
644 
645     iterator it_ = find(minuend.first);
646     if(it_ != end())
647     {
648         Combiner()((*it_).second, minuend.second);
649         if(on_absorbtion_::is_absorbable((*it_).second))
650             erase(it_);
651     }
652     return *this;
653 }
654 
655 
656 //-----------------------------------------------------------------------------
657 // type traits
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> >
661 {
662     typedef is_map<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> > type;
663     BOOST_STATIC_CONSTANT(bool, value = true);
664 };
665 
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> >
668 {
669     typedef has_inverse<icl::map<DomainT,CodomainT,Traits,Compare,Combine,Section,Alloc> > type;
670     BOOST_STATIC_CONSTANT(bool, value = (has_inverse<CodomainT>::value));
671 };
672 
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> >
675 {
676     typedef absorbs_identities type;
677     BOOST_STATIC_CONSTANT(int, value = Traits::absorbs_identities);
678 };
679 
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> >
682 {
683     typedef is_total type;
684     BOOST_STATIC_CONSTANT(int, value = Traits::is_total);
685 };
686 
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> >
689 {
applyboost::icl::type_to_string690     static std::string apply()
691     {
692         return "map<"+ type_to_string<DomainT>::apply()  + ","
693                      + type_to_string<CodomainT>::apply() + ","
694                      + type_to_string<Traits>::apply() +">";
695     }
696 };
697 
698 
699 
700 }} // namespace icl boost
701 
702 #endif // BOOST_ICL_MAP_HPP_JOFA_070519
703