diff --git a/sprout/algorithm/find_difference.hpp b/sprout/algorithm/find_difference.hpp new file mode 100644 index 00000000..6d40b075 --- /dev/null +++ b/sprout/algorithm/find_difference.hpp @@ -0,0 +1,115 @@ +#ifndef SPROUT_ALGORITHM_FIND_DIFFERENCE_HPP +#define SPROUT_ALGORITHM_FIND_DIFFERENCE_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair + find_difference_impl_check( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2 + ) + { + return sprout::tuples::get<2>(current) + ? sprout::pair( + sprout::tuples::get<0>(current), + sprout::tuples::get<1>(current) + ) + : sprout::pair(last1, last2) + ; + } + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + find_difference_impl_1( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::tuples::tuple type; + return sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 ? current + : n == 1 ? sprout::tuples::get<1>(current) == last2 + ? type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true) + : comp(*sprout::tuples::get<0>(current), *sprout::tuples::get<1>(current)) + ? type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true) + : comp(*sprout::tuples::get<1>(current), *sprout::tuples::get<0>(current)) + ? type(sprout::tuples::get<0>(current), sprout::next(sprout::tuples::get<1>(current)), false) + : type(sprout::next(sprout::tuples::get<0>(current)), sprout::next(sprout::tuples::get<1>(current)), false) + : sprout::detail::find_difference_impl_1( + sprout::detail::find_difference_impl_1( + current, + last1, last2, comp, n / 2 + ), + last1, last2, comp, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + find_difference_impl( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::tuples::tuple type; + return sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 ? current + : sprout::detail::find_difference_impl( + sprout::detail::find_difference_impl_1( + current, + last1, last2, comp, n + ), + last1, last2, comp, n * 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + find_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + typedef sprout::tuples::tuple type; + return sprout::detail::find_difference_impl_check( + sprout::detail::find_difference_impl(type(first1, first2, false), last1, last2, comp, 1), + last1, last2 + ); + } + } // namespace detail + + // + // find_difference + // + // recursion depth: + // O(log N) + // + template + inline SPROUT_CONSTEXPR sprout::pair + find_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + return sprout::detail::find_difference(first1, last1, first2, last2, comp); + } + template + inline SPROUT_CONSTEXPR sprout::pair + find_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 + ) + { + return sprout::find_difference(first1, last1, first2, last2, sprout::less<>()); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_FIND_DIFFERENCE_HPP diff --git a/sprout/algorithm/find_intersection.hpp b/sprout/algorithm/find_intersection.hpp new file mode 100644 index 00000000..c5f0fde0 --- /dev/null +++ b/sprout/algorithm/find_intersection.hpp @@ -0,0 +1,113 @@ +#ifndef SPROUT_ALGORITHM_FIND_INTERSECTION_HPP +#define SPROUT_ALGORITHM_FIND_INTERSECTION_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair + find_intersection_impl_check( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2 + ) + { + return sprout::tuples::get<2>(current) + ? sprout::pair( + sprout::tuples::get<0>(current), + sprout::tuples::get<1>(current) + ) + : sprout::pair(last1, last2) + ; + } + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + find_intersection_impl_1( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::tuples::tuple type; + return sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 || sprout::tuples::get<1>(current) == last2 ? current + : n == 1 ? comp(*sprout::tuples::get<0>(current), *sprout::tuples::get<1>(current)) + ? type(sprout::next(sprout::tuples::get<0>(current)), sprout::tuples::get<1>(current), false) + : comp(*sprout::tuples::get<1>(current), *sprout::tuples::get<0>(current)) + ? type(sprout::tuples::get<0>(current), sprout::next(sprout::tuples::get<1>(current)), false) + : type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true) + : sprout::detail::find_intersection_impl_1( + sprout::detail::find_intersection_impl_1( + current, + last1, last2, comp, n / 2 + ), + last1, last2, comp, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + find_intersection_impl( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::tuples::tuple type; + return sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 || sprout::tuples::get<1>(current) == last2 ? current + : sprout::detail::find_intersection_impl( + sprout::detail::find_intersection_impl_1( + current, + last1, last2, comp, n + ), + last1, last2, comp, n * 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + find_intersection( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + typedef sprout::tuples::tuple type; + return sprout::detail::find_intersection_impl_check( + sprout::detail::find_intersection_impl(type(first1, first2, false), last1, last2, comp, 1), + last1, last2 + ); + } + } // namespace detail + + // + // find_intersection + // + // recursion depth: + // O(log N) + // + template + inline SPROUT_CONSTEXPR sprout::pair + find_intersection( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + return sprout::detail::find_intersection(first1, last1, first2, last2, comp); + } + template + inline SPROUT_CONSTEXPR sprout::pair + find_intersection( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 + ) + { + return sprout::find_intersection(first1, last1, first2, last2, sprout::less<>()); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_FIND_INTERSECTION_HPP diff --git a/sprout/algorithm/find_symmetric_difference.hpp b/sprout/algorithm/find_symmetric_difference.hpp new file mode 100644 index 00000000..9d1144c7 --- /dev/null +++ b/sprout/algorithm/find_symmetric_difference.hpp @@ -0,0 +1,103 @@ +#ifndef SPROUT_ALGORITHM_FIND_SYMMETRIC_DIFFERENCE_HPP +#define SPROUT_ALGORITHM_FIND_SYMMETRIC_DIFFERENCE_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair + find_symmetric_difference_impl_check(sprout::tuples::tuple const& current) { + return sprout::pair( + sprout::tuples::get<0>(current), + sprout::tuples::get<1>(current) + ); + } + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + find_symmetric_difference_impl_1( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::tuples::tuple type; + return sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 || sprout::tuples::get<1>(current) == last2 ? current + : n == 1 ? comp(*sprout::tuples::get<0>(current), *sprout::tuples::get<1>(current)) || comp(*sprout::tuples::get<1>(current), *sprout::tuples::get<0>(current)) + ? type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true) + : type(sprout::next(sprout::tuples::get<0>(current)), sprout::next(sprout::tuples::get<1>(current)), false) + : sprout::detail::find_symmetric_difference_impl_1( + sprout::detail::find_symmetric_difference_impl_1( + current, + last1, last2, comp, n / 2 + ), + last1, last2, comp, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + find_symmetric_difference_impl( + sprout::tuples::tuple const& current, + InputIterator1 last1, InputIterator2 last2, Compare comp, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::tuples::tuple type; + return sprout::tuples::get<2>(current) || sprout::tuples::get<0>(current) == last1 ? current + : sprout::detail::find_symmetric_difference_impl( + sprout::detail::find_symmetric_difference_impl_1( + current, + last1, last2, comp, n + ), + last1, last2, comp, n * 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + find_symmetric_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + typedef sprout::tuples::tuple type; + return sprout::detail::find_symmetric_difference_impl_check( + sprout::detail::find_symmetric_difference_impl(type(first1, first2, false), last1, last2, comp, 1) + ); + } + } // namespace detail + + // + // find_symmetric_difference + // + // recursion depth: + // O(log N) + // + template + inline SPROUT_CONSTEXPR sprout::pair + find_symmetric_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + return sprout::detail::find_symmetric_difference(first1, last1, first2, last2, comp); + } + template + inline SPROUT_CONSTEXPR sprout::pair + find_symmetric_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 + ) + { + return sprout::find_symmetric_difference(first1, last1, first2, last2, sprout::less<>()); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_FIND_SYMMETRIC_DIFFERENCE_HPP diff --git a/sprout/algorithm/fixed/set_difference.hpp b/sprout/algorithm/fixed/set_difference.hpp index b25365ec..7f5fd499 100644 --- a/sprout/algorithm/fixed/set_difference.hpp +++ b/sprout/algorithm/fixed/set_difference.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -63,12 +64,7 @@ namespace sprout { sprout::next(first1), last1, first2, last2, result, comp, size, args..., *first1 ) - : first2 != last2 - ? sprout::fixed::detail::set_difference_impl( - first1, last1, sprout::next(first2), last2, result, comp, - size, args... - ) - : sprout::detail::container_complate(result, args...) + : sprout::detail::container_complate(result, args...) : sprout::detail::container_complate(result, args...) ; } @@ -91,6 +87,24 @@ namespace sprout { sprout::size(result) ); } + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::is_fixed_container::value, + typename sprout::fixed::result_of::algorithm::type + >::type + set_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Result const& result, Compare comp + ) + { + return sprout::remake( + result, sprout::size(result), + sprout::make_set_difference_iterator(first1, last1, first2, last2, comp), + sprout::make_set_difference_iterator(last1, last1, last2, last2, comp) + ); + } } // namespace detail // // set_difference diff --git a/sprout/algorithm/fixed/set_intersection.hpp b/sprout/algorithm/fixed/set_intersection.hpp index 8567d35e..c2f19501 100644 --- a/sprout/algorithm/fixed/set_intersection.hpp +++ b/sprout/algorithm/fixed/set_intersection.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -59,16 +60,8 @@ namespace sprout { sprout::next(first1), last1, sprout::next(first2), last2, result, comp, size, args..., *first1 ) - : sprout::fixed::detail::set_intersection_impl( - sprout::next(first1), last1, first2, last2, result, comp, - size, args... - ) - : first2 != last2 - ? sprout::fixed::detail::set_intersection_impl( - first1, last1, sprout::next(first2), last2, result, comp, - size, args... - ) : sprout::detail::container_complate(result, args...) + : sprout::detail::container_complate(result, args...) : sprout::detail::container_complate(result, args...) ; } @@ -91,6 +84,24 @@ namespace sprout { sprout::size(result) ); } + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::is_fixed_container::value, + typename sprout::fixed::result_of::algorithm::type + >::type + set_intersection( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Result const& result, Compare comp + ) + { + return sprout::remake( + result, sprout::size(result), + sprout::make_set_intersection_iterator(first1, last1, first2, last2, comp), + sprout::make_set_intersection_iterator(last1, last1, last2, last2, comp) + ); + } } // namespace detail // // set_intersection diff --git a/sprout/algorithm/fixed/set_symmetric_difference.hpp b/sprout/algorithm/fixed/set_symmetric_difference.hpp index a95dcbcd..1bd95977 100644 --- a/sprout/algorithm/fixed/set_symmetric_difference.hpp +++ b/sprout/algorithm/fixed/set_symmetric_difference.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,24 @@ namespace sprout { sprout::size(result) ); } + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::is_fixed_container::value, + typename sprout::fixed::result_of::algorithm::type + >::type + set_symmetric_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Result const& result, Compare comp + ) + { + return sprout::remake( + result, sprout::size(result), + sprout::make_set_symmetric_difference_iterator(first1, last1, first2, last2, comp), + sprout::make_set_symmetric_difference_iterator(last1, last1, last2, last2, comp) + ); + } } // namespace detail // // set_symmetric_difference diff --git a/sprout/algorithm/next_difference.hpp b/sprout/algorithm/next_difference.hpp new file mode 100644 index 00000000..266ca461 --- /dev/null +++ b/sprout/algorithm/next_difference.hpp @@ -0,0 +1,41 @@ +#ifndef SPROUT_ALGORITHM_NEXT_DIFFERENCE_HPP +#define SPROUT_ALGORITHM_NEXT_DIFFERENCE_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + // + // next_difference + // + // recursion depth: + // O(log(N1+N2)) + // + template + inline SPROUT_CONSTEXPR sprout::pair + next_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + typedef sprout::pair type; + return first1 == last1 ? type(last1, last2) + : sprout::find_difference(sprout::next(first1), last1, first2, last2, comp) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + next_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 + ) + { + return sprout::next_difference(first1, last1, first2, last2, sprout::less<>()); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_NEXT_DIFFERENCE_HPP diff --git a/sprout/algorithm/next_intersection.hpp b/sprout/algorithm/next_intersection.hpp new file mode 100644 index 00000000..4dd37054 --- /dev/null +++ b/sprout/algorithm/next_intersection.hpp @@ -0,0 +1,41 @@ +#ifndef SPROUT_ALGORITHM_NEXT_INTERSECTION_HPP +#define SPROUT_ALGORITHM_NEXT_INTERSECTION_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + // + // next_intersection + // + // recursion depth: + // O(log(N1+N2)) + // + template + inline SPROUT_CONSTEXPR sprout::pair + next_intersection( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + typedef sprout::pair type; + return first1 == last1 || first2 == last2 ? type(last1, last2) + : sprout::find_intersection(sprout::next(first1), last1, sprout::next(first2), last2, comp) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + next_intersection( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 + ) + { + return sprout::next_intersection(first1, last1, first2, last2, sprout::less<>()); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_NEXT_INTERSECTION_HPP diff --git a/sprout/algorithm/next_symmetric_difference.hpp b/sprout/algorithm/next_symmetric_difference.hpp new file mode 100644 index 00000000..1e7e0473 --- /dev/null +++ b/sprout/algorithm/next_symmetric_difference.hpp @@ -0,0 +1,48 @@ +#ifndef SPROUT_ALGORITHM_NEXT_SYMMETRIC_DIFFERENCE_HPP +#define SPROUT_ALGORITHM_NEXT_SYMMETRIC_DIFFERENCE_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + // + // next_symmetric_difference + // + // recursion depth: + // O(log(N1+N2)) + // + template + inline SPROUT_CONSTEXPR sprout::pair + next_symmetric_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + typedef sprout::pair type; + return first1 != last1 + ? first2 != last2 + ? comp(*first1, *first2) + ? sprout::find_symmetric_difference(sprout::next(first1), last1, first2, last2, comp) + : sprout::find_symmetric_difference(first1, last1, sprout::next(first2), last2, comp) + : type(sprout::next(first1), first2) + : first2 != last2 + ? type(first1, sprout::next(first2)) + : type(last1, last2) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + next_symmetric_difference( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 + ) + { + return sprout::next_symmetric_difference(first1, last1, first2, last2, sprout::less<>()); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_NEXT_SYMMETRIC_DIFFERENCE_HPP diff --git a/sprout/algorithm/next_union.hpp b/sprout/algorithm/next_union.hpp new file mode 100644 index 00000000..cffbfc0e --- /dev/null +++ b/sprout/algorithm/next_union.hpp @@ -0,0 +1,49 @@ +#ifndef SPROUT_ALGORITHM_NEXT_UNION_HPP +#define SPROUT_ALGORITHM_NEXT_UNION_HPP + +#include +#include +#include +#include + +namespace sprout { + // + // next_union + // + // recursion depth: + // O(1) + // + template + inline SPROUT_CONSTEXPR sprout::pair + next_union( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp + ) + { + typedef sprout::pair type; + return first1 != last1 + ? first2 != last2 + ? comp(*first1, *first2) + ? type(sprout::next(first1), first2) + : comp(*first2, *first1) + ? type(first1, sprout::next(first2)) + : type(sprout::next(first1), sprout::next(first2)) + : type(sprout::next(first1), first2) + : first2 != last2 + ? type(first1, sprout::next(first2)) + : type(last1, last2) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + next_union( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 + ) + { + return sprout::next_union(first1, last1, first2, last2, sprout::less<>()); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_NEXT_UNION_HPP diff --git a/sprout/algorithm/non_modifying.hpp b/sprout/algorithm/non_modifying.hpp index e05e0b98..95e2f2b1 100644 --- a/sprout/algorithm/non_modifying.hpp +++ b/sprout/algorithm/non_modifying.hpp @@ -46,6 +46,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #endif // #ifndef SPROUT_ALGORITHM_NON_MODIFYIING_HPP diff --git a/sprout/algorithm/set_intersection_iterator.hpp b/sprout/algorithm/set_intersection_iterator.hpp new file mode 100644 index 00000000..a096386e --- /dev/null +++ b/sprout/algorithm/set_intersection_iterator.hpp @@ -0,0 +1,202 @@ +#ifndef SPROUT_ITERATOR_SET_INTERSECTION_ITERATOR_HPP +#define SPROUT_ITERATOR_SET_INTERSECTION_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + // + // set_intersection_iterator + // + template< + typename LIterator, typename RIterator, + typename Compare = sprout::less<> + > + class set_intersection_iterator + : public std::iterator< + typename sprout::min_iterator_category< + typename sprout::common_iterator_category::type, + std::forward_iterator_tag + >::type, + typename sprout::common_iterator_value_type::type, + typename sprout::common_iterator_difference_type::type, + typename sprout::common_iterator_pointer::type, + typename sprout::common_iterator_reference::type + > + { + public: + typedef LIterator iterator_type; + typedef RIterator iterator2_type; + typedef Compare compare_type; + typedef typename sprout::min_iterator_category< + typename sprout::common_iterator_category::type, + std::forward_iterator_tag + >::type iterator_category; + typedef typename sprout::common_iterator_value_type::type value_type; + typedef typename sprout::common_iterator_difference_type::type difference_type; + typedef typename sprout::common_iterator_pointer::type pointer; + typedef typename sprout::common_iterator_reference::type reference; + protected: + typedef sprout::pair pair_type; + protected: + pair_type current; + iterator_type lst1; + iterator2_type lst2; + Compare comp; + private: + SPROUT_CONSTEXPR set_intersection_iterator(set_intersection_iterator const& other, pair_type const& next) + : current(next) + , lst1(other.lst1), lst2(other.lst2) + , comp(other.comp) + {} + public: + set_intersection_iterator() + : current(), lst1(), lst2(), comp() + {} + set_intersection_iterator(set_intersection_iterator const&) = default; + SPROUT_CONSTEXPR set_intersection_iterator( + iterator_type it1, iterator_type lst1, + iterator2_type it2, iterator2_type lst2, + Compare comp = Compare() + ) + : current(sprout::find_intersection(it1, lst1, it2, lst2, comp)) + , lst1(lst1), lst2(lst2) + , comp(comp) + {} + template + SPROUT_CONSTEXPR set_intersection_iterator(set_intersection_iterator const& it) + : current(it.base(), it.base2()) + , lst1(it.last1()), lst2(it.last2()) + , comp(it.compare()) + {} + template + set_intersection_iterator& operator=(set_intersection_iterator const& it) { + set_intersection_iterator temp(it); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR iterator_type base() const { + return current.first; + } + SPROUT_CONSTEXPR iterator_type last1() const { + return lst1; + } + SPROUT_CONSTEXPR iterator2_type base2() const { + return current.second; + } + SPROUT_CONSTEXPR iterator2_type last2() const { + return lst2; + } + SPROUT_CONSTEXPR Compare compare() const { + return comp; + } + SPROUT_CONSTEXPR bool is_in_left() const { + return true; + } + SPROUT_CONSTEXPR reference operator*() const { + return *current.first; + } + SPROUT_CONSTEXPR pointer operator->() const { + return &*(*this); + } + set_intersection_iterator& operator++() { + current = sprout::next_intersection(current.first, lst1, current.second, lst2, comp); + return *this; + } + set_intersection_iterator operator++(int) { + set_intersection_iterator result(*this); + current = sprout::next_intersection(current.first, lst1, current.second, lst2, comp); + return result; + } + SPROUT_CONSTEXPR set_intersection_iterator next() const { + return set_intersection_iterator( + *this, + sprout::next_intersection(current.first, lst1, current.second, lst2, comp) + ); + } + void swap(set_intersection_iterator& other) + SPROUT_NOEXCEPT_EXPR( + SPROUT_NOEXCEPT_EXPR(sprout::swap(current, other.current)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst1, other.lst1)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst2, other.lst2)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(comp, other.comp)) + ) + { + sprout::swap(current, other.current); + sprout::swap(lst1, other.lst1); + sprout::swap(lst2, other.lst2); + sprout::swap(comp, other.comp); + } + }; + + template< + typename LIterator1, typename RIterator1, typename Compare1, + typename LIterator2, typename RIterator2, typename Compare2 + > + inline SPROUT_CONSTEXPR bool operator==( + sprout::set_intersection_iterator const& lhs, + sprout::set_intersection_iterator const& rhs + ) + { + return lhs.base() == rhs.base() && lhs.base2() == rhs.base2(); + } + template< + typename LIterator1, typename RIterator1, typename Compare1, + typename LIterator2, typename RIterator2, typename Compare2 + > + inline SPROUT_CONSTEXPR bool operator!=( + sprout::set_intersection_iterator const& lhs, + sprout::set_intersection_iterator const& rhs + ) + { + return !(lhs == rhs); + } + + // + // make_set_intersection_iterator + // + template + inline SPROUT_CONSTEXPR sprout::set_intersection_iterator + make_set_intersection_iterator(LIterator it1, LIterator lst1, RIterator it2, RIterator lst2, Compare comp) { + return sprout::set_intersection_iterator(it1, lst1, it2, lst2, comp); + } + template + inline SPROUT_CONSTEXPR sprout::set_intersection_iterator + make_set_intersection_iterator(LIterator it1, LIterator lst1, RIterator it2, RIterator lst2) { + return sprout::set_intersection_iterator(it1, lst1, it2, lst2); + } + + // + // swap + // + template + inline void + swap( + sprout::set_intersection_iterator& lhs, + sprout::set_intersection_iterator& rhs + ) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + + // + // iterator_next + // + template + inline SPROUT_CONSTEXPR sprout::set_intersection_iterator + iterator_next(sprout::set_intersection_iterator const& it) { + return it.next(); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_SET_INTERSECTION_ITERATOR_HPP diff --git a/sprout/iterator/adaptor.hpp b/sprout/iterator/adaptor.hpp index 307feb18..bd6ddfe3 100644 --- a/sprout/iterator/adaptor.hpp +++ b/sprout/iterator/adaptor.hpp @@ -16,6 +16,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include diff --git a/sprout/iterator/set_difference_iterator.hpp b/sprout/iterator/set_difference_iterator.hpp new file mode 100644 index 00000000..8aa1ac04 --- /dev/null +++ b/sprout/iterator/set_difference_iterator.hpp @@ -0,0 +1,202 @@ +#ifndef SPROUT_ITERATOR_SET_DIFFERENCE_ITERATOR_HPP +#define SPROUT_ITERATOR_SET_DIFFERENCE_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + // + // set_difference_iterator + // + template< + typename LIterator, typename RIterator, + typename Compare = sprout::less<> + > + class set_difference_iterator + : public std::iterator< + typename sprout::min_iterator_category< + typename sprout::common_iterator_category::type, + std::forward_iterator_tag + >::type, + typename sprout::common_iterator_value_type::type, + typename sprout::common_iterator_difference_type::type, + typename sprout::common_iterator_pointer::type, + typename sprout::common_iterator_reference::type + > + { + public: + typedef LIterator iterator_type; + typedef RIterator iterator2_type; + typedef Compare compare_type; + typedef typename sprout::min_iterator_category< + typename sprout::common_iterator_category::type, + std::forward_iterator_tag + >::type iterator_category; + typedef typename sprout::common_iterator_value_type::type value_type; + typedef typename sprout::common_iterator_difference_type::type difference_type; + typedef typename sprout::common_iterator_pointer::type pointer; + typedef typename sprout::common_iterator_reference::type reference; + protected: + typedef sprout::pair pair_type; + protected: + pair_type current; + iterator_type lst1; + iterator2_type lst2; + Compare comp; + private: + SPROUT_CONSTEXPR set_difference_iterator(set_difference_iterator const& other, pair_type const& next) + : current(next) + , lst1(other.lst1), lst2(other.lst2) + , comp(other.comp) + {} + public: + set_difference_iterator() + : current(), lst1(), lst2(), comp() + {} + set_difference_iterator(set_difference_iterator const&) = default; + SPROUT_CONSTEXPR set_difference_iterator( + iterator_type it1, iterator_type lst1, + iterator2_type it2, iterator2_type lst2, + Compare comp = Compare() + ) + : current(sprout::find_difference(it1, lst1, it2, lst2, comp)) + , lst1(lst1), lst2(lst2) + , comp(comp) + {} + template + SPROUT_CONSTEXPR set_difference_iterator(set_difference_iterator const& it) + : current(it.base(), it.base2()) + , lst1(it.last1()), lst2(it.last2()) + , comp(it.compare()) + {} + template + set_difference_iterator& operator=(set_difference_iterator const& it) { + set_difference_iterator temp(it); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR iterator_type base() const { + return current.first; + } + SPROUT_CONSTEXPR iterator_type last1() const { + return lst1; + } + SPROUT_CONSTEXPR iterator2_type base2() const { + return current.second; + } + SPROUT_CONSTEXPR iterator2_type last2() const { + return lst2; + } + SPROUT_CONSTEXPR Compare compare() const { + return comp; + } + SPROUT_CONSTEXPR bool is_in_left() const { + return true; + } + SPROUT_CONSTEXPR reference operator*() const { + return *current.first; + } + SPROUT_CONSTEXPR pointer operator->() const { + return &*(*this); + } + set_difference_iterator& operator++() { + current = sprout::next_difference(current.first, lst1, current.second, lst2, comp); + return *this; + } + set_difference_iterator operator++(int) { + set_difference_iterator result(*this); + current = sprout::next_difference(current.first, lst1, current.second, lst2, comp); + return result; + } + SPROUT_CONSTEXPR set_difference_iterator next() const { + return set_difference_iterator( + *this, + sprout::next_difference(current.first, lst1, current.second, lst2, comp) + ); + } + void swap(set_difference_iterator& other) + SPROUT_NOEXCEPT_EXPR( + SPROUT_NOEXCEPT_EXPR(sprout::swap(current, other.current)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst1, other.lst1)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst2, other.lst2)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(comp, other.comp)) + ) + { + sprout::swap(current, other.current); + sprout::swap(lst1, other.lst1); + sprout::swap(lst2, other.lst2); + sprout::swap(comp, other.comp); + } + }; + + template< + typename LIterator1, typename RIterator1, typename Compare1, + typename LIterator2, typename RIterator2, typename Compare2 + > + inline SPROUT_CONSTEXPR bool operator==( + sprout::set_difference_iterator const& lhs, + sprout::set_difference_iterator const& rhs + ) + { + return lhs.base() == rhs.base() && lhs.base2() == rhs.base2(); + } + template< + typename LIterator1, typename RIterator1, typename Compare1, + typename LIterator2, typename RIterator2, typename Compare2 + > + inline SPROUT_CONSTEXPR bool operator!=( + sprout::set_difference_iterator const& lhs, + sprout::set_difference_iterator const& rhs + ) + { + return !(lhs == rhs); + } + + // + // make_set_difference_iterator + // + template + inline SPROUT_CONSTEXPR sprout::set_difference_iterator + make_set_difference_iterator(LIterator it1, LIterator lst1, RIterator it2, RIterator lst2, Compare comp) { + return sprout::set_difference_iterator(it1, lst1, it2, lst2, comp); + } + template + inline SPROUT_CONSTEXPR sprout::set_difference_iterator + make_set_difference_iterator(LIterator it1, LIterator lst1, RIterator it2, RIterator lst2) { + return sprout::set_difference_iterator(it1, lst1, it2, lst2); + } + + // + // swap + // + template + inline void + swap( + sprout::set_difference_iterator& lhs, + sprout::set_difference_iterator& rhs + ) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + + // + // iterator_next + // + template + inline SPROUT_CONSTEXPR sprout::set_difference_iterator + iterator_next(sprout::set_difference_iterator const& it) { + return it.next(); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_SET_DIFFERENCE_ITERATOR_HPP diff --git a/sprout/iterator/set_intersection_iterator.hpp b/sprout/iterator/set_intersection_iterator.hpp new file mode 100644 index 00000000..a096386e --- /dev/null +++ b/sprout/iterator/set_intersection_iterator.hpp @@ -0,0 +1,202 @@ +#ifndef SPROUT_ITERATOR_SET_INTERSECTION_ITERATOR_HPP +#define SPROUT_ITERATOR_SET_INTERSECTION_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + // + // set_intersection_iterator + // + template< + typename LIterator, typename RIterator, + typename Compare = sprout::less<> + > + class set_intersection_iterator + : public std::iterator< + typename sprout::min_iterator_category< + typename sprout::common_iterator_category::type, + std::forward_iterator_tag + >::type, + typename sprout::common_iterator_value_type::type, + typename sprout::common_iterator_difference_type::type, + typename sprout::common_iterator_pointer::type, + typename sprout::common_iterator_reference::type + > + { + public: + typedef LIterator iterator_type; + typedef RIterator iterator2_type; + typedef Compare compare_type; + typedef typename sprout::min_iterator_category< + typename sprout::common_iterator_category::type, + std::forward_iterator_tag + >::type iterator_category; + typedef typename sprout::common_iterator_value_type::type value_type; + typedef typename sprout::common_iterator_difference_type::type difference_type; + typedef typename sprout::common_iterator_pointer::type pointer; + typedef typename sprout::common_iterator_reference::type reference; + protected: + typedef sprout::pair pair_type; + protected: + pair_type current; + iterator_type lst1; + iterator2_type lst2; + Compare comp; + private: + SPROUT_CONSTEXPR set_intersection_iterator(set_intersection_iterator const& other, pair_type const& next) + : current(next) + , lst1(other.lst1), lst2(other.lst2) + , comp(other.comp) + {} + public: + set_intersection_iterator() + : current(), lst1(), lst2(), comp() + {} + set_intersection_iterator(set_intersection_iterator const&) = default; + SPROUT_CONSTEXPR set_intersection_iterator( + iterator_type it1, iterator_type lst1, + iterator2_type it2, iterator2_type lst2, + Compare comp = Compare() + ) + : current(sprout::find_intersection(it1, lst1, it2, lst2, comp)) + , lst1(lst1), lst2(lst2) + , comp(comp) + {} + template + SPROUT_CONSTEXPR set_intersection_iterator(set_intersection_iterator const& it) + : current(it.base(), it.base2()) + , lst1(it.last1()), lst2(it.last2()) + , comp(it.compare()) + {} + template + set_intersection_iterator& operator=(set_intersection_iterator const& it) { + set_intersection_iterator temp(it); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR iterator_type base() const { + return current.first; + } + SPROUT_CONSTEXPR iterator_type last1() const { + return lst1; + } + SPROUT_CONSTEXPR iterator2_type base2() const { + return current.second; + } + SPROUT_CONSTEXPR iterator2_type last2() const { + return lst2; + } + SPROUT_CONSTEXPR Compare compare() const { + return comp; + } + SPROUT_CONSTEXPR bool is_in_left() const { + return true; + } + SPROUT_CONSTEXPR reference operator*() const { + return *current.first; + } + SPROUT_CONSTEXPR pointer operator->() const { + return &*(*this); + } + set_intersection_iterator& operator++() { + current = sprout::next_intersection(current.first, lst1, current.second, lst2, comp); + return *this; + } + set_intersection_iterator operator++(int) { + set_intersection_iterator result(*this); + current = sprout::next_intersection(current.first, lst1, current.second, lst2, comp); + return result; + } + SPROUT_CONSTEXPR set_intersection_iterator next() const { + return set_intersection_iterator( + *this, + sprout::next_intersection(current.first, lst1, current.second, lst2, comp) + ); + } + void swap(set_intersection_iterator& other) + SPROUT_NOEXCEPT_EXPR( + SPROUT_NOEXCEPT_EXPR(sprout::swap(current, other.current)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst1, other.lst1)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst2, other.lst2)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(comp, other.comp)) + ) + { + sprout::swap(current, other.current); + sprout::swap(lst1, other.lst1); + sprout::swap(lst2, other.lst2); + sprout::swap(comp, other.comp); + } + }; + + template< + typename LIterator1, typename RIterator1, typename Compare1, + typename LIterator2, typename RIterator2, typename Compare2 + > + inline SPROUT_CONSTEXPR bool operator==( + sprout::set_intersection_iterator const& lhs, + sprout::set_intersection_iterator const& rhs + ) + { + return lhs.base() == rhs.base() && lhs.base2() == rhs.base2(); + } + template< + typename LIterator1, typename RIterator1, typename Compare1, + typename LIterator2, typename RIterator2, typename Compare2 + > + inline SPROUT_CONSTEXPR bool operator!=( + sprout::set_intersection_iterator const& lhs, + sprout::set_intersection_iterator const& rhs + ) + { + return !(lhs == rhs); + } + + // + // make_set_intersection_iterator + // + template + inline SPROUT_CONSTEXPR sprout::set_intersection_iterator + make_set_intersection_iterator(LIterator it1, LIterator lst1, RIterator it2, RIterator lst2, Compare comp) { + return sprout::set_intersection_iterator(it1, lst1, it2, lst2, comp); + } + template + inline SPROUT_CONSTEXPR sprout::set_intersection_iterator + make_set_intersection_iterator(LIterator it1, LIterator lst1, RIterator it2, RIterator lst2) { + return sprout::set_intersection_iterator(it1, lst1, it2, lst2); + } + + // + // swap + // + template + inline void + swap( + sprout::set_intersection_iterator& lhs, + sprout::set_intersection_iterator& rhs + ) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + + // + // iterator_next + // + template + inline SPROUT_CONSTEXPR sprout::set_intersection_iterator + iterator_next(sprout::set_intersection_iterator const& it) { + return it.next(); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_SET_INTERSECTION_ITERATOR_HPP diff --git a/sprout/iterator/set_symmetric_difference_iterator.hpp b/sprout/iterator/set_symmetric_difference_iterator.hpp new file mode 100644 index 00000000..b30684f8 --- /dev/null +++ b/sprout/iterator/set_symmetric_difference_iterator.hpp @@ -0,0 +1,270 @@ +#ifndef SPROUT_ITERATOR_SET_SYMMETRIC_DIFFERENCE_ITERATOR_HPP +#define SPROUT_ITERATOR_SET_SYMMETRIC_DIFFERENCE_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template< + typename LIterator, typename RIterator, + typename Compare + > + class set_symmetric_difference_iterator_impl { + protected: + typedef LIterator iterator_type; + typedef RIterator iterator2_type; + typedef Compare compare_type; + typedef typename sprout::min_iterator_category< + typename sprout::common_iterator_category::type, + std::forward_iterator_tag + >::type iterator_category; + typedef typename sprout::common_iterator_value_type::type value_type; + typedef typename sprout::common_iterator_difference_type::type difference_type; + typedef typename sprout::common_iterator_pointer::type pointer; + typedef typename sprout::common_iterator_reference::type reference; + protected: + typedef sprout::pair pair_type; + protected: + static SPROUT_CONSTEXPR bool check_in_left( + iterator_type it1, iterator_type lst1, + iterator2_type it2, iterator2_type lst2, + Compare comp + ) + { + return it1 != lst1 ? (it2 != lst2 ? comp(*it1, *it2) : true) + : !(it2 != lst2) + ; + } + protected: + pair_type current; + iterator_type lst1; + iterator2_type lst2; + Compare comp; + protected: + bool in_left; + protected: + set_symmetric_difference_iterator_impl() + : current(), lst1(), lst2(), comp(), in_left(true) + {} + set_symmetric_difference_iterator_impl(set_symmetric_difference_iterator_impl const&) = default; + SPROUT_CONSTEXPR set_symmetric_difference_iterator_impl( + pair_type const& current, + iterator_type lst1, iterator2_type lst2, + Compare comp + ) + : current(current) + , lst1(lst1), lst2(lst2) + , comp(comp) + , in_left(check_in_left(current.first, lst1, current.second, lst2, comp)) + {} + SPROUT_CONSTEXPR set_symmetric_difference_iterator_impl( + pair_type const& current, + iterator_type lst1, iterator2_type lst2, + Compare comp, + bool in_left + ) + : current(current) + , lst1(lst1), lst2(lst2) + , comp(comp) + , in_left(in_left) + {} + }; + } // namespace detail + + // + // set_symmetric_difference_iterator + // + template< + typename LIterator, typename RIterator, + typename Compare = sprout::less<> + > + class set_symmetric_difference_iterator + : public std::iterator< + typename sprout::min_iterator_category< + typename sprout::common_iterator_category::type, + std::forward_iterator_tag + >::type, + typename sprout::common_iterator_value_type::type, + typename sprout::common_iterator_difference_type::type, + typename sprout::common_iterator_pointer::type, + typename sprout::common_iterator_reference::type + > + , private sprout::detail::set_symmetric_difference_iterator_impl + { + private: + typedef sprout::detail::set_symmetric_difference_iterator_impl impl_type; + public: + typedef typename impl_type::iterator_type iterator_type; + typedef typename impl_type::iterator2_type iterator2_type; + typedef typename impl_type::compare_type compare_type; + typedef typename impl_type::iterator_category iterator_category; + typedef typename impl_type::value_type value_type; + typedef typename impl_type::difference_type difference_type; + typedef typename impl_type::pointer pointer; + typedef typename impl_type::reference reference; + protected: + typedef typename impl_type::pair_type pair_type; + private: + using impl_type::check_in_left; + protected: + using impl_type::current; + using impl_type::lst1; + using impl_type::lst2; + using impl_type::comp; + private: + using impl_type::in_left; + private: + SPROUT_CONSTEXPR set_symmetric_difference_iterator(set_symmetric_difference_iterator const& other, pair_type const& next) + : impl_type(next, other.lst1, other.lst2, other.comp) + {} + public: + set_symmetric_difference_iterator() + : impl_type() + {} + set_symmetric_difference_iterator(set_symmetric_difference_iterator const&) = default; + SPROUT_CONSTEXPR set_symmetric_difference_iterator( + iterator_type it1, iterator_type lst1, + iterator2_type it2, iterator2_type lst2, + Compare comp = Compare() + ) + : impl_type(sprout::find_symmetric_difference(it1, lst1, it2, lst2, comp), lst1, lst2, comp) + {} + template + SPROUT_CONSTEXPR set_symmetric_difference_iterator(set_symmetric_difference_iterator const& it) + : impl_type(pair_type(it.base(), it.base2()), it.last1(), it.last2(), it.compare(), it.is_in_left()) + {} + template + set_symmetric_difference_iterator& operator=(set_symmetric_difference_iterator const& it) { + set_symmetric_difference_iterator temp(it); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR iterator_type base() const { + return current.first; + } + SPROUT_CONSTEXPR iterator_type last1() const { + return lst1; + } + SPROUT_CONSTEXPR iterator2_type base2() const { + return current.second; + } + SPROUT_CONSTEXPR iterator2_type last2() const { + return lst2; + } + SPROUT_CONSTEXPR Compare compare() const { + return comp; + } + SPROUT_CONSTEXPR bool is_in_left() const { + return in_left; + } + SPROUT_CONSTEXPR reference operator*() const { + return is_in_left() ? *current.first : *current.second; + } + SPROUT_CONSTEXPR pointer operator->() const { + return &*(*this); + } + set_symmetric_difference_iterator& operator++() { + current = sprout::next_symmetric_difference(current.first, lst1, current.second, lst2, comp); + in_left = check_in_left(current.first, lst1, current.second, lst2, comp); + return *this; + } + set_symmetric_difference_iterator operator++(int) { + set_symmetric_difference_iterator result(*this); + current = sprout::next_symmetric_difference(current.first, lst1, current.second, lst2, comp); + in_left = check_in_left(current.first, lst1, current.second, lst2, comp); + return result; + } + SPROUT_CONSTEXPR set_symmetric_difference_iterator next() const { + return set_symmetric_difference_iterator( + *this, + sprout::next_symmetric_difference(current.first, lst1, current.second, lst2, comp) + ); + } + void swap(set_symmetric_difference_iterator& other) + SPROUT_NOEXCEPT_EXPR( + SPROUT_NOEXCEPT_EXPR(sprout::swap(current, other.current)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst1, other.lst1)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst2, other.lst2)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(comp, other.comp)) + ) + { + sprout::swap(current, other.current); + sprout::swap(lst1, other.lst1); + sprout::swap(lst2, other.lst2); + sprout::swap(comp, other.comp); + sprout::swap(in_left, other.in_left); + } + }; + + template< + typename LIterator1, typename RIterator1, typename Compare1, + typename LIterator2, typename RIterator2, typename Compare2 + > + inline SPROUT_CONSTEXPR bool operator==( + sprout::set_symmetric_difference_iterator const& lhs, + sprout::set_symmetric_difference_iterator const& rhs + ) + { + return lhs.base() == rhs.base() && lhs.base2() == rhs.base2(); + } + template< + typename LIterator1, typename RIterator1, typename Compare1, + typename LIterator2, typename RIterator2, typename Compare2 + > + inline SPROUT_CONSTEXPR bool operator!=( + sprout::set_symmetric_difference_iterator const& lhs, + sprout::set_symmetric_difference_iterator const& rhs + ) + { + return !(lhs == rhs); + } + + // + // make_set_symmetric_difference_iterator + // + template + inline SPROUT_CONSTEXPR sprout::set_symmetric_difference_iterator + make_set_symmetric_difference_iterator(LIterator it1, LIterator lst1, RIterator it2, RIterator lst2, Compare comp) { + return sprout::set_symmetric_difference_iterator(it1, lst1, it2, lst2, comp); + } + template + inline SPROUT_CONSTEXPR sprout::set_symmetric_difference_iterator + make_set_symmetric_difference_iterator(LIterator it1, LIterator lst1, RIterator it2, RIterator lst2) { + return sprout::set_symmetric_difference_iterator(it1, lst1, it2, lst2); + } + + // + // swap + // + template + inline void + swap( + sprout::set_symmetric_difference_iterator& lhs, + sprout::set_symmetric_difference_iterator& rhs + ) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + + // + // iterator_next + // + template + inline SPROUT_CONSTEXPR sprout::set_symmetric_difference_iterator + iterator_next(sprout::set_symmetric_difference_iterator const& it) { + return it.next(); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_SET_SYMMETRIC_DIFFERENCE_ITERATOR_HPP diff --git a/sprout/iterator/set_union_iterator.hpp b/sprout/iterator/set_union_iterator.hpp index a8bc3967..0354d8a5 100644 --- a/sprout/iterator/set_union_iterator.hpp +++ b/sprout/iterator/set_union_iterator.hpp @@ -7,7 +7,10 @@ #include #include #include +#include #include +#include +#include namespace sprout { // @@ -41,6 +44,8 @@ namespace sprout { typedef typename sprout::common_iterator_difference_type::type difference_type; typedef typename sprout::common_iterator_pointer::type pointer; typedef typename sprout::common_iterator_reference::type reference; + protected: + typedef sprout::pair pair_type; private: static SPROUT_CONSTEXPR bool check_in_left( iterator_type it1, iterator_type lst1, @@ -53,15 +58,22 @@ namespace sprout { ; } protected: - iterator_type current1; + pair_type current; iterator_type lst1; - iterator2_type current2; iterator2_type lst2; Compare comp; + private: bool in_left; + private: + SPROUT_CONSTEXPR set_union_iterator(set_union_iterator const& other, pair_type const& next) + : current(next) + , lst1(other.lst1), lst2(other.lst2) + , comp(other.comp) + , in_left(check_in_left(next.first, lst1, next.second, lst2, comp)) + {} public: set_union_iterator() - : current1(), lst1(), current2(), lst2(), comp(), in_left(true) + : current(), lst1(), lst2(), comp(), in_left(true) {} set_union_iterator(set_union_iterator const&) = default; SPROUT_CONSTEXPR set_union_iterator( @@ -69,15 +81,15 @@ namespace sprout { iterator2_type it2, iterator2_type lst2, Compare comp = Compare() ) - : current1(it1), lst1(lst1) - , current2(it2), lst2(lst2) + : current(it1, it2) + , lst1(lst1), lst2(lst2) , comp(comp) , in_left(check_in_left(it1, lst1, it2, lst2, comp)) {} template SPROUT_CONSTEXPR set_union_iterator(set_union_iterator const& it) - : current1(it.base()), lst1(it.last1()) - , current2(it.base2()), lst2(it.last2()) + : current(it.base(), it.base2()) + , lst1(it.last1()), lst2(it.last2()) , comp(it.compare()) , in_left(it.is_in_left()) {} @@ -88,13 +100,13 @@ namespace sprout { return *this; } SPROUT_CONSTEXPR iterator_type base() const { - return current1; + return current.first; } SPROUT_CONSTEXPR iterator_type last1() const { return lst1; } SPROUT_CONSTEXPR iterator2_type base2() const { - return current2; + return current.second; } SPROUT_CONSTEXPR iterator2_type last2() const { return lst2; @@ -106,79 +118,38 @@ namespace sprout { return in_left; } SPROUT_CONSTEXPR reference operator*() const { - return is_in_left() ? *current1 : *current2; + return is_in_left() ? *current.first : *current.second; } SPROUT_CONSTEXPR pointer operator->() const { return &*(*this); } set_union_iterator& operator++() { - if (current1 != lst1) { - if (current2 != lst2) { - if (comp(*current1, *current2)) { - ++current1; - } else if (comp(*current2, *current1)) { - ++current2; - } else { - ++current1; - ++current2; - } - } else { - ++current1; - } - } else if (current2 != lst2) { - ++current2; - } - in_left = check_in_left(current1, lst1, current2, lst2, comp); + current = sprout::next_union(current.first, lst1, current.second, lst2, comp); + in_left = check_in_left(current.first, lst1, current.second, lst2, comp); return *this; } set_union_iterator operator++(int) { set_union_iterator result(*this); - if (current1 != lst1) { - if (current2 != lst2) { - if (comp(*current1, *current2)) { - ++current1; - } else if (comp(*current2, *current1)) { - ++current2; - } else { - ++current1; - ++current2; - } - } else { - ++current1; - } - } else if (current2 != lst2) { - ++current2; - } - in_left = check_in_left(current1, lst1, current2, lst2, comp); + current = sprout::next_union(current.first, lst1, current.second, lst2, comp); + in_left = check_in_left(current.first, lst1, current.second, lst2, comp); return result; } SPROUT_CONSTEXPR set_union_iterator next() const { - return current1 != lst1 - ? current2 != lst2 - ? comp(*current1, *current2) - ? set_union_iterator(sprout::next(current1), lst1, current2, lst2, comp) - : comp(*current2, *current1) - ? set_union_iterator(current1, lst1, sprout::next(current2), lst2, comp) - : set_union_iterator(sprout::next(current1), lst1, sprout::next(current2), lst2, comp) - : set_union_iterator(sprout::next(current1), lst1, current2, lst2, comp) - : current2 != lst2 - ? set_union_iterator(current1, lst1, sprout::next(current2), lst2, comp) - : *this - ; + return set_union_iterator( + *this, + sprout::next_union(current.first, lst1, current.second, lst2, comp) + ); } void swap(set_union_iterator& other) SPROUT_NOEXCEPT_EXPR( - SPROUT_NOEXCEPT_EXPR(sprout::swap(current1, other.current1)) + SPROUT_NOEXCEPT_EXPR(sprout::swap(current, other.current)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst1, other.lst1)) - && SPROUT_NOEXCEPT_EXPR(sprout::swap(current2, other.current2)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(lst2, other.lst2)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(comp, other.comp)) - && SPROUT_NOEXCEPT_EXPR(sprout::swap(in_left, other.in_left)) ) { - sprout::swap(current1, other.current1); + sprout::swap(current, other.current); sprout::swap(lst1, other.lst1); - sprout::swap(current2, other.current2); sprout::swap(lst2, other.lst2); sprout::swap(comp, other.comp); sprout::swap(in_left, other.in_left);