Header file range/v3/view/set_algorithm.hpp

#include <meta/meta.hpp>

#include <range/v3/range_fwd.hpp>

#include <range/v3/size.hpp>

#include <range/v3/begin_end.hpp>

#include <range/v3/range_traits.hpp>

#include <range/v3/view_facade.hpp>

#include <range/v3/utility/move.hpp>

#include <range/v3/utility/semiregular.hpp>

#include <range/v3/utility/functional.hpp>

#include <range/v3/utility/static_const.hpp>

#include <range/v3/view/view.hpp>

#include <range/v3/view/all.hpp>

namespace ranges
{
    inline namespace v3
    {
        namespace detail
        {
            template <typename Rng1, typename Rng2, typename C, typename P1, typename P2, template <bool, typename> typename Cursor, cardinality Cardinality>
            struct set_algorithm_view
            : view_facade<set_algorithm_view<Rng1, Rng2, C, P1, P2, Cursor, Cardinality>, Cardinality>
            {
                set_algorithm_view() = default;
                
                set_algorithm_view(Rng1 rng1, Rng2 rng2, C pred, P1 proj1, P2 proj2);
            };
            
            template <bool IsConst, typename Rng1, typename Rng2, typename C, typename P1, typename P2>
            struct set_difference_cursor
            {
                using value_type = range_value_t<constify_if<Rng1>>;
                
                using single_pass = meta::strict_or<SinglePass<range_iterator_t<R1>>, SinglePass<range_iterator_t<R2>>>;
                
                set_difference_cursor() = default;
                
                set_difference_cursor(pred_ref_ pred, proj1_ref_ proj1, proj2_ref_ proj2, range_iterator_t<R1> it1, range_sentinel_t<R1> end1, range_iterator_t<R2> it2, range_sentinel_t<R2> end2);
                
                decltype(*it1_) get() const noexcept(noexcept(decltype(*it1_)(*it1_)));
                
                void next();
                
                bool equal(set_difference_cursor const& that) const;
                
                bool done() const;
                
                decltype(iter_move(it1_)) move() const noexcept(noexcept(decltype(iter_move(it1_))(iter_move(it1_))));
            };
            
            constexpr cardinality set_difference_cardinality(cardinality c1, cardinality c2);
        }
        
        template <typename Rng1, typename Rng2, typename C, typename P1, typename P2>
        using set_difference_view = detail::set_algorithm_view<Rng1, Rng2, C, P1, P2, detail::set_difference_cursor, detail::set_difference_cardinality(range_cardinality<Rng1>::value, range_cardinality<Rng2>::value)>;
        
        namespace view
        {
            struct set_difference_fn
            {
                template <typename Rng1, typename Rng2, typename C, typename P1, typename P2, typename I1 = range_iterator_t<Rng1>, typename I2 = range_iterator_t<Rng2>>
                using Concept = meta::and_<InputRange<Rng1>, InputRange<Rng2>, IndirectCallableRelation<C, projected<I1, P1>, projected<I2, P2>>>;
                
                template <typename Rng1, typename Rng2, typename C = ordered_less, typename P1 = ident, typename P2 = ident, int _concept_requires_203 = 42, typename std::enable_if<(_concept_requires_203==43)||(Concept<Rng1, Rng2, C, P1, P2>()), int>::type=0>
                set_difference_view<all_t<Rng1>, all_t<Rng2>, C, P1, P2> operator()(Rng1&& rng1, Rng2&& rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const;
                
                template <typename Rng1, typename Rng2, typename C, typename P1, typename P2, typename I1 = range_iterator_t<Rng1>, typename I2 = range_iterator_t<Rng2>, int _concept_requires_221 = 42, typename std::enable_if<(_concept_requires_221==43)||(!Concept<Rng1, Rng2, C, P1, P2>()), int>::type=0>
                void operator()(Rng1&&, Rng2&&, C, P1, P2) const;
            };
            
            inline namespace 
            {
                constexpr auto& set_difference = static_const<view<set_difference_fn>>::value;
            }
        }
        
        namespace detail
        {
            template <bool IsConst, typename Rng1, typename Rng2, typename C, typename P1, typename P2>
            struct set_intersection_cursor
            {
                using value_type = range_value_t<R1>;
                
                using single_pass = meta::strict_or<SinglePass<range_iterator_t<R1>>, SinglePass<range_iterator_t<R2>>>;
                
                set_intersection_cursor() = default;
                
                set_intersection_cursor(pred_ref_ pred, proj1_ref_ proj1, proj2_ref_ proj2, range_iterator_t<R1> it1, range_sentinel_t<R1> end1, range_iterator_t<R2> it2, range_sentinel_t<R2> end2);
                
                decltype(*it1_) get() const noexcept(noexcept(decltype(*it1_)(*it1_)));
                
                void next();
                
                bool equal(set_intersection_cursor const& that) const;
                
                bool done() const;
                
                decltype(iter_move(it1_)) move() const noexcept(noexcept(decltype(iter_move(it1_))(iter_move(it1_))));
            };
            
            constexpr cardinality set_intersection_cardinality(cardinality c1, cardinality c2);
        }
        
        template <typename Rng1, typename Rng2, typename C, typename P1, typename P2>
        using set_intersection_view = detail::set_algorithm_view<Rng1, Rng2, C, P1, P2, detail::set_intersection_cursor, detail::set_intersection_cardinality(range_cardinality<Rng1>::value, range_cardinality<Rng2>::value)>;
        
        namespace view
        {
            struct set_intersection_fn
            {
                template <typename Rng1, typename Rng2, typename C, typename P1, typename P2, typename I1 = range_iterator_t<Rng1>, typename I2 = range_iterator_t<Rng2>>
                using Concept = meta::and_<InputRange<Rng1>, InputRange<Rng2>, IndirectCallableRelation<C, projected<I1, P1>, projected<I2, P2>>>;
                
                template <typename Rng1, typename Rng2, typename C = ordered_less, typename P1 = ident, typename P2 = ident, int _concept_requires_374 = 42, typename std::enable_if<(_concept_requires_374==43)||(Concept<Rng1, Rng2, C, P1, P2>()), int>::type=0>
                set_intersection_view<all_t<Rng1>, all_t<Rng2>, C, P1, P2> operator()(Rng1&& rng1, Rng2&& rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const;
                
                template <typename Rng1, typename Rng2, typename C, typename P1, typename P2, typename I1 = range_iterator_t<Rng1>, typename I2 = range_iterator_t<Rng2>, int _concept_requires_392 = 42, typename std::enable_if<(_concept_requires_392==43)||(!Concept<Rng1, Rng2, C, P1, P2>()), int>::type=0>
                void operator()(Rng1&&, Rng2&&, C, P1, P2) const;
            };
            
            inline namespace 
            {
                constexpr auto& set_intersection = static_const<view<set_intersection_fn>>::value;
            }
        }
        
        namespace detail
        {
            template <bool IsConst, typename Rng1, typename Rng2, typename C, typename P1, typename P2>
            struct set_union_cursor
            {
                using value_type = common_type_t<range_value_t<R1>, range_value_t<R2>>;
                
                using reference_type = common_reference_t<range_reference_t<R1>, range_reference_t<R2>>;
                
                using rvalue_reference_type = common_reference_t<range_rvalue_reference_t<R1>, range_rvalue_reference_t<R2>>;
                
                using single_pass = meta::strict_or<SinglePass<range_iterator_t<R1>>, SinglePass<range_iterator_t<R2>>>;
                
                set_union_cursor() = default;
                
                set_union_cursor(pred_ref_ pred, proj1_ref_ proj1, proj2_ref_ proj2, range_iterator_t<R1> it1, range_sentinel_t<R1> end1, range_iterator_t<R2> it2, range_sentinel_t<R2> end2);
                
                reference_type get() const noexcept(noexcept(*it1_)&&noexcept(*it2_));
                
                void next();
                
                bool equal(set_union_cursor const& that) const;
                
                bool done() const;
                
                rvalue_reference_type move() const noexcept(noexcept(iter_move(it1_))&&noexcept(iter_move(it2_)));
            };
            
            constexpr cardinality set_union_cardinality(cardinality c1, cardinality c2);
        }
        
        template <typename Rng1, typename Rng2, typename C, typename P1, typename P2>
        using set_union_view = detail::set_algorithm_view<Rng1, Rng2, C, P1, P2, detail::set_union_cursor, detail::set_union_cardinality(range_cardinality<Rng1>::value, range_cardinality<Rng2>::value)>;
        
        namespace view
        {
            struct set_union_fn
            {
                template <typename Rng1, typename Rng2, typename C, typename P1, typename P2, typename I1 = range_iterator_t<Rng1>, typename I2 = range_iterator_t<Rng2>>
                using Concept = meta::and_<InputRange<Rng1>, InputRange<Rng2>, Common<range_value_t<Rng1>, range_value_t<Rng2>>, CommonReference<range_reference_t<Rng1>, range_reference_t<Rng2>>, CommonReference<range_rvalue_reference_t<Rng1>, range_rvalue_reference_t<Rng2>>, IndirectCallableRelation<C, projected<I1, P1>, projected<I2, P2>>>;
                
                template <typename Rng1, typename Rng2, typename C = ordered_less, typename P1 = ident, typename P2 = ident, int _concept_requires_588 = 42, typename std::enable_if<(_concept_requires_588==43)||(Concept<Rng1, Rng2, C, P1, P2>()), int>::type=0>
                set_union_view<all_t<Rng1>, all_t<Rng2>, C, P1, P2> operator()(Rng1&& rng1, Rng2&& rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const;
                
                template <typename Rng1, typename Rng2, typename C, typename P1, typename P2, typename I1 = range_iterator_t<Rng1>, typename I2 = range_iterator_t<Rng2>, int _concept_requires_606 = 42, typename std::enable_if<(_concept_requires_606==43)||(!Concept<Rng1, Rng2, C, P1, P2>()), int>::type=0>
                void operator()(Rng1&&, Rng2&&, C, P1, P2) const;
            };
            
            inline namespace 
            {
                constexpr auto& set_union = static_const<view<set_union_fn>>::value;
            }
        }
        
        namespace detail
        {
            template <bool IsConst, typename Rng1, typename Rng2, typename C, typename P1, typename P2>
            struct set_symmetric_difference_cursor
            {
                using value_type = common_type_t<range_value_t<R1>, range_value_t<R2>>;
                
                using reference_type = common_reference_t<range_reference_t<R1>, range_reference_t<R2>>;
                
                using rvalue_reference_type = common_reference_t<range_rvalue_reference_t<R1>, range_rvalue_reference_t<R2>>;
                
                using single_pass = meta::strict_or<SinglePass<range_iterator_t<R1>>, SinglePass<range_iterator_t<R2>>>;
                
                set_symmetric_difference_cursor() = default;
                
                set_symmetric_difference_cursor(pred_ref_ pred, proj1_ref_ proj1, proj2_ref_ proj2, range_iterator_t<R1> it1, range_sentinel_t<R1> end1, range_iterator_t<R2> it2, range_sentinel_t<R2> end2);
                
                reference_type get() const noexcept(noexcept(*it1_)&&noexcept(*it2_));
                
                void next();
                
                bool equal(set_symmetric_difference_cursor const& that) const;
                
                bool done() const;
                
                rvalue_reference_type move() const noexcept(noexcept(iter_move(it1_))&&noexcept(iter_move(it2_)));
            };
            
            constexpr cardinality set_symmetric_difference_cardinality(cardinality c1, cardinality c2);
        }
        
        template <typename Rng1, typename Rng2, typename C, typename P1, typename P2>
        using set_symmetric_difference_view = detail::set_algorithm_view<Rng1, Rng2, C, P1, P2, detail::set_symmetric_difference_cursor, detail::set_symmetric_difference_cardinality(range_cardinality<Rng1>::value, range_cardinality<Rng2>::value)>;
        
        namespace view
        {
            struct set_symmetric_difference_fn
            {
                template <typename Rng1, typename Rng2, typename C, typename P1, typename P2, typename I1 = range_iterator_t<Rng1>, typename I2 = range_iterator_t<Rng2>>
                using Concept = meta::and_<InputRange<Rng1>, InputRange<Rng2>, Common<range_value_t<Rng1>, range_value_t<Rng2>>, CommonReference<range_reference_t<Rng1>, range_reference_t<Rng2>>, CommonReference<range_rvalue_reference_t<Rng1>, range_rvalue_reference_t<Rng2>>, IndirectCallableRelation<C, projected<I1, P1>, projected<I2, P2>>>;
                
                template <typename Rng1, typename Rng2, typename C = ordered_less, typename P1 = ident, typename P2 = ident, int _concept_requires_814 = 42, typename std::enable_if<(_concept_requires_814==43)||(Concept<Rng1, Rng2, C, P1, P2>()), int>::type=0>
                set_symmetric_difference_view<all_t<Rng1>, all_t<Rng2>, C, P1, P2> operator()(Rng1&& rng1, Rng2&& rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) const;
                
                template <typename Rng1, typename Rng2, typename C, typename P1, typename P2, typename I1 = range_iterator_t<Rng1>, typename I2 = range_iterator_t<Rng2>, int _concept_requires_832 = 42, typename std::enable_if<(_concept_requires_832==43)||(!Concept<Rng1, Rng2, C, P1, P2>()), int>::type=0>
                void operator()(Rng1&&, Rng2&&, C, P1, P2) const;
            };
            
            inline namespace 
            {
                constexpr auto& set_symmetric_difference = static_const<view<set_symmetric_difference_fn>>::value;
            }
        }
    }
}