/// \file // Range v3 library // // Copyright Eric Niebler 2014 // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef RANGES_V3_ALGORITHM_SET_ALGORITHM_HPP #define RANGES_V3_ALGORITHM_SET_ALGORITHM_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ranges { inline namespace v3 { /// \addtogroup group-algorithms /// @{ struct includes_fn { template() && Sentinel() && Sentinel())> bool operator()(I1 begin1, S1 end1, I2 begin2, S2 end2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { for(; begin2 != end2; ++begin1) { if(begin1 == end1 || invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1))) return false; if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) ++begin2; } return true; } template, typename I2 = iterator_t, CONCEPT_REQUIRES_(Comparable() && Range() && Range())> bool operator()(Rng1 && rng1, Rng2 && rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { return (*this)(begin(rng1), end(rng1), begin(rng2), end(rng2), std::move(pred), std::move(proj1), std::move(proj2)); } }; /// \sa `includes_fn` /// \ingroup group-algorithms RANGES_INLINE_VARIABLE(with_braced_init_args, includes) struct set_union_fn { template() && Sentinel() && Sentinel())> tagged_tuple operator()(I1 begin1, S1 end1, I2 begin2, S2 end2, O out, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { for(; begin1 != end1; ++out) { if(begin2 == end2) { auto tmp = copy(begin1, end1, out); return make_tagged_tuple(tmp.first, begin2, tmp.second); } if(invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1))) { *out = *begin2; ++begin2; } else { *out = *begin1; if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) ++begin2; ++begin1; } } auto tmp = copy(begin2, end2, out); return make_tagged_tuple(begin1, tmp.first, tmp.second); } template, typename I2 = iterator_t, CONCEPT_REQUIRES_(Mergeable() && Range() && Range())> tagged_tuple), tag::in2(safe_iterator_t), tag::out(O)> operator()(Rng1 &&rng1, Rng2 &&rng2, O out, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { return (*this)(begin(rng1), end(rng1), begin(rng2), end(rng2), std::move(out), std::move(pred), std::move(proj1), std::move(proj2)); } }; /// \sa `set_union_fn` /// \ingroup group-algorithms RANGES_INLINE_VARIABLE(with_braced_init_args, set_union) struct set_intersection_fn { template() && Sentinel() && Sentinel())> O operator()(I1 begin1, S1 end1, I2 begin2, S2 end2, O out, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { while(begin1 != end1 && begin2 != end2) { if(invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) ++begin1; else { if(!invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1))) { *out = *begin1; ++out; ++begin1; } ++begin2; } } return out; } template, typename I2 = iterator_t, CONCEPT_REQUIRES_(Mergeable() && Range() && Range())> O operator()(Rng1 && rng1, Rng2 && rng2, O out, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { return (*this)(begin(rng1), end(rng1), begin(rng2), end(rng2), std::move(out), std::move(pred), std::move(proj1), std::move(proj2)); } }; /// \sa `set_intersection_fn` /// \ingroup group-algorithms RANGES_INLINE_VARIABLE(with_braced_init_args, set_intersection) struct set_difference_fn { template() && Sentinel() && Sentinel())> tagged_pair operator()(I1 begin1, S1 end1, I2 begin2, S2 end2, O out, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { while(begin1 != end1) { if(begin2 == end2) return copy(begin1, end1, out); if(invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) { *out = *begin1; ++out; ++begin1; } else { if(!invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1))) ++begin1; ++begin2; } } return {begin1, out}; } template, typename I2 = iterator_t, CONCEPT_REQUIRES_(Mergeable() && Range() && Range())> tagged_pair), tag::out(O)> operator()(Rng1 &&rng1, Rng2 && rng2, O out, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { return (*this)(begin(rng1), end(rng1), begin(rng2), end(rng2), std::move(out), std::move(pred), std::move(proj1), std::move(proj2)); } }; /// \sa `set_difference_fn` /// \ingroup group-algorithms RANGES_INLINE_VARIABLE(with_braced_init_args, set_difference) struct set_symmetric_difference_fn { template() && Sentinel() && Sentinel())> tagged_tuple operator()(I1 begin1, S1 end1, I2 begin2, S2 end2, O out, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { while(begin1 != end1) { if(begin2 == end2) { auto tmp = copy(begin1, end1, out); return tagged_tuple{tmp.first, begin2, tmp.second}; } if(invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) { *out = *begin1; ++out; ++begin1; } else { if(invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1))) { *out = *begin2; ++out; } else ++begin1; ++begin2; } } auto tmp = copy(begin2, end2, out); return tagged_tuple{begin1, tmp.first, tmp.second}; } template, typename I2 = iterator_t, CONCEPT_REQUIRES_(Mergeable() && Range() && Range())> tagged_tuple), tag::in2(safe_iterator_t), tag::out(O)> operator()(Rng1 &&rng1, Rng2 &&rng2, O out, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const { return (*this)(begin(rng1), end(rng1), begin(rng2), end(rng2), std::move(out), std::move(pred), std::move(proj1), std::move(proj2)); } }; /// \sa `set_symmetric_difference_fn` /// \ingroup group-algorithms RANGES_INLINE_VARIABLE(with_braced_init_args, set_symmetric_difference) /// @} } // namespace v3 } // namespace ranges #endif // include guard