diff --git a/alib2common/src/core/components/setComponents.hpp b/alib2common/src/core/components/setComponents.hpp index a0e81b68750462565bb8741529e7cb032bf7d9fd..fbef1e2d66fdc58d7494738dc1618260fd8d4a9d 100644 --- a/alib2common/src/core/components/setComponents.hpp +++ b/alib2common/src/core/components/setComponents.hpp @@ -149,8 +149,7 @@ public: * CommonException if one of the added elements is not available in context of datatype where the set is used */ void set ( SetComponentType data ) { - std::set_difference ( m_data.begin ( ), m_data.end ( ), data.begin ( ), data.end ( ), ext::make_callback_iterator < const ComponentType & > ( std::bind ( & SetComponent::checkRemove, this, std::placeholders::_1 ) ) ); - std::set_difference ( data.begin ( ), data.end ( ), m_data.begin ( ), m_data.end ( ), ext::make_callback_iterator < const ComponentType & > ( std::bind ( & SetComponent::checkAdd, this, std::placeholders::_1 ) ) ); + ext::set_symmetric_difference ( m_data.begin ( ), m_data.end ( ), data.begin ( ), data.end ( ), ext::make_callback_iterator < const ComponentType & > ( std::bind ( & SetComponent::checkRemove, this, std::placeholders::_1 ) ), ext::make_callback_iterator < const ComponentType & > ( std::bind ( & SetComponent::checkAdd, this, std::placeholders::_1 ) ) ); m_data = std::move ( data ); } diff --git a/alib2std/src/extensions/algorithm.hpp b/alib2std/src/extensions/algorithm.hpp index 87dd17a41d7c7212134786277aec0ac517ffebb6..e92dcadaff7fd71aceb3cc26006395f76fb22879 100644 --- a/alib2std/src/extensions/algorithm.hpp +++ b/alib2std/src/extensions/algorithm.hpp @@ -80,6 +80,56 @@ bool excludes(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) return excludes(first1, last1, first2, last2, std::less<decltype(*first1)>()); } +/** + * \brief + * Constructs sorted ranges beginning in the location pointed by result1 and result2 with the set differences of the two sorted ranges [first1,last1) and [first2,last2). + * + * The symmetric difference of two sets is formed by the elements that are present in one of the sets, but not in the other. The result1 and result2 are each representing half of the symmetric difference, i.e. each being a set difference of the first range to the second and of the second range to the first. Among the equivalent elements in each range, those discarded are those that appear before in the existent order before the call. The existing order is also preserved for the copied elements. + * + * The elements are compared using comp callback. Two elements, a and b are considered equivalent if (!comp(a,b) && !comp(b,a)). + * + * The elements in the ranges shall already be ordered according to this same criterion (operator< or comp). The resulting range is also sorted according to this. + */ +template < class InputIterator1, class InputIterator2, class OutputIterator1, class OutputIterator2, class Compare > +void set_symmetric_difference ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator1 result1, OutputIterator2 result2, Compare comp ) { + while ( first1 != last1 && first2 != last2 ) { + if ( comp ( * first1, * first2 ) ) { + * result1 = * first1; + ++ result1; + ++ first1; + } else if ( comp ( * first2, * first1 ) ) { + * result2 = * first2; + ++ result2; + ++ first2; + } else { + ++first1; + ++first2; + } + } + + if ( first1 == last1 ) { + std::copy ( first2, last2, result2 ); + } + if ( first2 == last2 ) { + std::copy ( first1, last1, result1 ); + } +} + +/** + * \brief + * Constructs sorted ranges beginning in the location pointed by result1 and result2 with the set differences of the two sorted ranges [first1,last1) and [first2,last2). + * + * The symmetric difference of two sets is formed by the elements that are present in one of the sets, but not in the other. The result1 and result2 are each representing half of the symmetric difference, i.e. each being a set difference of the first range to the second and of the second range to the first. Among the equivalent elements in each range, those discarded are those that appear before in the existent order before the call. The existing order is also preserved for the copied elements. + * + * The elements are compared using operator <. Two elements, a and b are considered equivalent if (!(a<b) && !(b<a)). + * + * The elements in the ranges shall already be ordered according to this same criterion (operator< or comp). The resulting range is also sorted according to this. + */ +template < class InputIterator1, class InputIterator2, class OutputIterator1, class OutputIterator2 > +void set_symmetric_difference ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator1 result1, OutputIterator2 result2 ) { + set_symmetric_difference ( first1, last1, first2, last2, result1, result2, std::less < decltype ( * first1 ) > ( ) ); +} + /** * \brief * In container tranformation of all elements according to the \p tranform.