1 /*-----------------------------------------------------------------------------+
2 Copyright (c) 2010-2010: Joachim Faulhaber
3 +------------------------------------------------------------------------------+
4    Distributed under the Boost Software License, Version 1.0.
5       (See accompanying file LICENCE.txt or copy at
6            http://www.boost.org/LICENSE_1_0.txt)
7 +-----------------------------------------------------------------------------*/
8 #ifndef BOOST_ICL_CONCEPT_ELEMENT_SET_HPP_JOFA_100921
9 #define BOOST_ICL_CONCEPT_ELEMENT_SET_HPP_JOFA_100921
10 
11 #include <boost/icl/type_traits/is_combinable.hpp>
12 #include <boost/icl/concept/set_value.hpp>
13 #include <boost/icl/detail/std_set.hpp>
14 #include <boost/icl/detail/set_algo.hpp>
15 
16 
17 namespace boost{ namespace icl
18 {
19 
20 //==============================================================================
21 //= Addition<ElementSet>
22 //==============================================================================
23 /** \c add inserts \c operand into the map if it's key does
24     not exist in the map.
25     If \c operands's key value exists in the map, it's data
26     value is added to the data value already found in the map. */
27 template <class Type>
28 typename enable_if<is_element_set<Type>, Type>::type&
add(Type & object,const typename Type::value_type & operand)29 add(Type& object, const typename Type::value_type& operand)
30 {
31     object.insert(operand);
32     return object;
33 }
34 
35 /** \c add add \c operand into the map using \c prior as a hint to
36     insert \c operand after the position \c prior is pointing to. */
37 template <class Type>
38 typename enable_if<is_element_set<Type>, typename Type::iterator>::type
add(Type & object,typename Type::iterator prior,const typename Type::value_type & operand)39 add(Type& object, typename Type::iterator prior,
40     const typename Type::value_type& operand)
41 {
42     return object.insert(prior, operand);
43 }
44 
45 //==============================================================================
46 //= Subtraction
47 //==============================================================================
48 /** If the \c operand's key value is in the map, it's data value is
49     subtraced from the data value stored in the map. */
50 template<class Type>
51 typename enable_if<is_element_set<Type>, Type>::type&
subtract(Type & object,const typename Type::value_type & operand)52 subtract(Type& object, const typename Type::value_type& operand)
53 {
54     object.erase(operand);
55     return object;
56 }
57 
58 
59 //==============================================================================
60 //= Intersection
61 //==============================================================================
62 template<class Type>
63 inline typename enable_if<is_element_set<Type>, bool>::type
intersects(const Type & object,const typename Type::key_type & operand)64 intersects(const Type& object, const typename Type::key_type& operand)
65 {
66     return !(object.find(operand) == object.end());
67 }
68 
69 template<class Type>
70 inline typename enable_if<is_element_set<Type>, bool>::type
intersects(const Type & object,const Type & operand)71 intersects(const Type& object, const Type& operand)
72 {
73     if(iterative_size(object) < iterative_size(operand))
74         return Set::intersects(object, operand);
75     else
76         return Set::intersects(operand, object);
77 }
78 
79 //==============================================================================
80 //= Symmetric difference
81 //==============================================================================
82 template<class Type>
83 inline typename enable_if<is_element_set<Type>, Type>::type&
flip(Type & object,const typename Type::value_type & operand)84 flip(Type& object, const typename Type::value_type& operand)
85 {
86     typedef typename Type::iterator iterator;
87     std::pair<iterator,bool> insertion = object.insert(operand);
88     if(!insertion.second)
89         object.erase(insertion.first);
90 
91     return object;
92 }
93 
94 template<class Type>
95 inline typename enable_if<is_element_set<Type>, Type>::type&
operator ^=(Type & object,const typename Type::element_type & operand)96 operator ^= (Type& object, const typename Type::element_type& operand)
97 {
98     return icl::flip(object, operand);
99 }
100 
101 /** Symmetric subtract map \c x2 and \c *this.
102     So \c *this becomes the symmetric difference of \c *this and \c x2 */
103 template<class Type>
104 inline typename enable_if<is_element_set<Type>, Type>::type&
operator ^=(Type & object,const Type & operand)105 operator ^= (Type& object, const Type& operand)
106 {
107     typedef typename Type::const_iterator const_iterator;
108     const_iterator it_ = operand.begin();
109     while(it_ != operand.end())
110         icl::flip(object, *it_++);
111 
112     return object;
113 }
114 
115 //==============================================================================
116 //= Streaming<ElementSet>
117 //==============================================================================
118 template<class CharType, class CharTraits, class Type>
119 inline typename enable_if<is_element_set<Type>, std::basic_ostream<CharType, CharTraits> >::type&
operator <<(std::basic_ostream<CharType,CharTraits> & stream,const Type & object)120 operator << (std::basic_ostream<CharType, CharTraits>& stream, const Type& object)
121 {
122     stream << "{";
123     ICL_const_FORALL(typename Type, it, object)
124         stream << (*it) << " ";
125 
126     return stream << "}";
127 }
128 
129 
130 }} // namespace boost icl
131 
132 #endif
133 
134 
135