/*-----------------------------------------------------------------------------+ | |
Copyright (c) 2010-2010: Joachim Faulhaber | |
+------------------------------------------------------------------------------+ | |
Distributed under the Boost Software License, Version 1.0. | |
(See accompanying file LICENCE.txt or copy at | |
http://www.boost.org/LICENSE_1_0.txt) | |
+-----------------------------------------------------------------------------*/ | |
#ifndef BOOST_ICL_CONCEPT_ELEMENT_SET_HPP_JOFA_100921 | |
#define BOOST_ICL_CONCEPT_ELEMENT_SET_HPP_JOFA_100921 | |
#include <boost/icl/type_traits/is_combinable.hpp> | |
#include <boost/icl/concept/set_value.hpp> | |
#include <boost/icl/detail/std_set.hpp> | |
#include <boost/icl/detail/set_algo.hpp> | |
namespace boost{ namespace icl | |
{ | |
//============================================================================== | |
//= Addition<ElementSet> | |
//============================================================================== | |
/** \c add inserts \c operand into the map if it's key does | |
not exist in the map. | |
If \c operands's key value exists in the map, it's data | |
value is added to the data value already found in the map. */ | |
template <class Type> | |
typename enable_if<is_element_set<Type>, Type>::type& | |
add(Type& object, const typename Type::value_type& operand) | |
{ | |
object.insert(operand); | |
return object; | |
} | |
/** \c add add \c operand into the map using \c prior as a hint to | |
insert \c operand after the position \c prior is pointing to. */ | |
template <class Type> | |
typename enable_if<is_element_set<Type>, typename Type::iterator>::type | |
add(Type& object, typename Type::iterator prior, | |
const typename Type::value_type& operand) | |
{ | |
return object.insert(prior, operand); | |
} | |
//============================================================================== | |
//= Subtraction | |
//============================================================================== | |
/** If the \c operand's key value is in the map, it's data value is | |
subtraced from the data value stored in the map. */ | |
template<class Type> | |
typename enable_if<is_element_set<Type>, Type>::type& | |
subtract(Type& object, const typename Type::value_type& operand) | |
{ | |
object.erase(operand); | |
return object; | |
} | |
//============================================================================== | |
//= Intersection | |
//============================================================================== | |
template<class Type> | |
inline typename enable_if<is_element_set<Type>, Type>::type | |
operator & (Type object, const Type& operand) | |
{ | |
return object &= operand; | |
} | |
template<class Type> | |
inline typename enable_if<is_element_set<Type>, bool>::type | |
intersects(const Type& object, const typename Type::key_type& operand) | |
{ | |
return !(object.find(operand) == object.end()); | |
} | |
template<class Type> | |
inline typename enable_if<is_element_set<Type>, bool>::type | |
intersects(const Type& object, const Type& operand) | |
{ | |
if(iterative_size(object) < iterative_size(operand)) | |
return Set::intersects(object, operand); | |
else | |
return Set::intersects(operand, object); | |
} | |
//============================================================================== | |
//= Symmetric difference | |
//============================================================================== | |
template<class Type> | |
inline typename enable_if<is_element_set<Type>, Type>::type& | |
flip(Type& object, const typename Type::value_type& operand) | |
{ | |
typedef typename Type::iterator iterator; | |
std::pair<iterator,bool> insertion = object.insert(operand); | |
if(!insertion.second) | |
object.erase(insertion.first); | |
return object; | |
} | |
template<class Type> | |
inline typename enable_if<is_element_set<Type>, Type>::type& | |
operator ^= (Type& object, const typename Type::element_tpye& operand) | |
{ | |
return icl::flip(object, operand); | |
} | |
/** Symmetric subtract map \c x2 and \c *this. | |
So \c *this becomes the symmetric difference of \c *this and \c x2 */ | |
template<class Type> | |
inline typename enable_if<is_element_set<Type>, Type>::type& | |
operator ^= (Type& object, const Type& operand) | |
{ | |
typedef typename Type::const_iterator const_iterator; | |
const_iterator it_ = operand.begin(); | |
while(it_ != operand.end()) | |
icl::flip(object, *it_++); | |
return object; | |
} | |
//============================================================================== | |
//= Streaming<ElementSet> | |
//============================================================================== | |
template<class CharType, class CharTraits, class Type> | |
inline typename enable_if<is_element_set<Type>, std::basic_ostream<CharType, CharTraits> >::type& | |
operator << (std::basic_ostream<CharType, CharTraits>& stream, const Type& object) | |
{ | |
stream << "{"; | |
ICL_const_FORALL(typename Type, it, object) | |
stream << (*it) << " "; | |
return stream << "}"; | |
} | |
}} // namespace boost icl | |
#endif | |