15#ifndef RANGES_V3_VIEW_SET_ALGORITHM_HPP
16#define RANGES_V3_VIEW_SET_ALGORITHM_HPP
36#include <range/v3/utility/static_const.hpp>
41#include <range/v3/detail/prologue.hpp>
51 template<
typename Rng1,
typename Rng2,
typename C,
typename P1,
typename P2,
52 template<bool,
typename...>
class Cursor, cardinality Cardinality>
53 struct set_algorithm_view
54 : view_facade<set_algorithm_view<Rng1, Rng2, C, P1, P2, Cursor, Cardinality>,
59 semiregular_box_t<C> pred_;
60 semiregular_box_t<P1> proj1_;
61 semiregular_box_t<P2> proj2_;
65 template<
bool IsConst>
66 using cursor = Cursor<IsConst, Rng1, Rng2, C, P1, P2>;
68 cursor<simple_view<Rng1>() && simple_view<Rng2>()> begin_cursor()
79 auto begin_cursor() const
80 -> CPP_ret(cursor<true>)(
81 requires range<Rng1 const> && range<Rng2 const>)
93 set_algorithm_view() =
default;
94 set_algorithm_view(Rng1 rng1, Rng2 rng2, C pred, P1 proj1, P2 proj2)
95 : pred_(std::move(pred))
96 , proj1_(std::move(proj1))
97 , proj2_(std::move(proj2))
98 , rng1_(std::move(rng1))
99 , rng2_(std::move(rng2))
103 template<
bool IsConst,
typename Rng1,
typename Rng2,
typename C,
typename P1,
105 struct set_difference_cursor
108 friend struct set_difference_cursor<!IsConst, Rng1, Rng2, C, P1, P2>;
109 using pred_ref_ = semiregular_box_ref_or_val_t<C, IsConst>;
110 using proj1_ref_ = semiregular_box_ref_or_val_t<P1, IsConst>;
111 using proj2_ref_ = semiregular_box_ref_or_val_t<P2, IsConst>;
117 using constify_if = meta::const_if_c<IsConst, T>;
119 using R1 = constify_if<Rng1>;
120 using R2 = constify_if<Rng2>;
123 sentinel_t<R1> end1_;
126 sentinel_t<R2> end2_;
146 using value_type = range_value_t<constify_if<Rng1>>;
148 single_pass_iterator_<iterator_t<R2>>>;
150 set_difference_cursor() =
default;
151 set_difference_cursor(pred_ref_ pred, proj1_ref_ proj1, proj2_ref_ proj2,
152 iterator_t<R1> it1, sentinel_t<R1> end1,
153 iterator_t<R2> it2, sentinel_t<R2> end2)
154 : pred_(std::move(pred))
155 , proj1_(std::move(proj1))
156 , proj2_(std::move(proj2))
157 , it1_(std::move(it1))
158 , end1_(std::move(end1))
159 , it2_(std::move(it2))
160 , end2_(std::move(end2))
164 template(
bool Other)(
165 requires IsConst && CPP_NOT(Other))
166 set_difference_cursor(
167 set_difference_cursor<Other, Rng1, Rng2, C, P1, P2> that)
168 : pred_(std::move(that.pred_))
169 , proj1_(std::move(that.proj1_))
170 , proj2_(std::move(that.proj2_))
171 , it1_(std::move(that.it1_))
172 , end1_(std::move(that.end1_))
173 , it2_(std::move(that.it2_))
174 , end2_(std::move(that.end2_))
177 auto CPP_auto_fun(read)()(
const)
188 auto equal(set_difference_cursor
const & that)
const
190 requires forward_range<Rng1>)
193 return it1_ == that.it1_;
195 bool equal(default_sentinel_t)
const
197 return it1_ == end1_;
200 auto CPP_auto_fun(move)()(
const)
202 return iter_move(it1_)
207 constexpr cardinality set_difference_cardinality(cardinality c1, cardinality c2)
209 return (c1 == unknown)
211 : (c1 >= 0) || (c1 == finite) ? finite :
212 (c2 >= 0) || (c2 == finite) ? infinite : unknown;
217 template<
typename Rng1,
typename Rng2,
typename C,
typename P1,
typename P2>
218 using set_difference_view =
219 detail::set_algorithm_view<Rng1, Rng2, C, P1, P2, detail::set_difference_cursor,
220 detail::set_difference_cardinality(
221 range_cardinality<Rng1>::value,
222 range_cardinality<Rng2>::value)>;
228 template(
typename Rng1,
typename Rng2,
typename C =
less,
236 set_difference_view<all_t<Rng1>, all_t<Rng2>, C, P1, P2>
237 operator()(Rng1 && rng1,
241 P2 proj2 = P2{})
const
243 return {all(
static_cast<Rng1 &&
>(rng1)),
244 all(
static_cast<Rng2 &&
>(rng2)),
253 using set_difference_base_fn::operator();
255 template(
typename Rng2,
typename C =
less,
typename P1 =
identity,
258 constexpr auto operator()(Rng2 && rng2,
261 P2 proj2 = P2{})
const
265 static_cast<C &&
>(pred),
278 template<
bool IsConst,
typename Rng1,
typename Rng2,
typename C,
typename P1,
280 struct set_intersection_cursor
283 friend struct set_intersection_cursor<!IsConst, Rng1, Rng2, C, P1, P2>;
284 using pred_ref_ = semiregular_box_ref_or_val_t<C, IsConst>;
285 using proj1_ref_ = semiregular_box_ref_or_val_t<P1, IsConst>;
286 using proj2_ref_ = semiregular_box_ref_or_val_t<P2, IsConst>;
292 using constify_if = meta::const_if_c<IsConst, T>;
294 using R1 = constify_if<Rng1>;
295 using R2 = constify_if<Rng2>;
298 sentinel_t<R1> end1_;
301 sentinel_t<R2> end2_;
305 while(it1_ != end1_ && it2_ != end2_)
307 if(invoke(pred_, invoke(proj1_, *it1_), invoke(proj2_, *it2_)))
311 if(!invoke(pred_, invoke(proj2_, *it2_), invoke(proj1_, *it1_)))
319 using value_type = range_value_t<R1>;
321 single_pass_iterator_<iterator_t<R2>>>;
323 set_intersection_cursor() =
default;
324 set_intersection_cursor(pred_ref_ pred, proj1_ref_ proj1, proj2_ref_ proj2,
325 iterator_t<R1> it1, sentinel_t<R1> end1,
326 iterator_t<R2> it2, sentinel_t<R2> end2)
327 : pred_(std::move(pred))
328 , proj1_(std::move(proj1))
329 , proj2_(std::move(proj2))
330 , it1_(std::move(it1))
331 , end1_(std::move(end1))
332 , it2_(std::move(it2))
333 , end2_(std::move(end2))
337 template(
bool Other)(
338 requires IsConst && CPP_NOT(Other))
339 set_intersection_cursor(
340 set_intersection_cursor<Other, Rng1, Rng2, C, P1, P2> that)
341 : pred_(std::move(that.pred_))
342 , proj1_(std::move(that.proj1_))
343 , proj2_(std::move(that.proj2_))
344 , it1_(std::move(that.it1_))
345 , end1_(std::move(that.end1_))
346 , it2_(std::move(that.it2_))
347 , end2_(std::move(that.end2_))
350 auto CPP_auto_fun(read)()(
const)
362 auto equal(set_intersection_cursor
const & that)
const
364 requires forward_range<Rng1>)
367 return it1_ == that.it1_;
369 bool equal(default_sentinel_t)
const
371 return (it1_ == end1_) || (it2_ == end2_);
374 auto CPP_auto_fun(move)()(
const)
376 return iter_move(it1_)
381 constexpr cardinality set_intersection_cardinality(cardinality c1, cardinality c2)
383 return (c1 == unknown) || (c2 == unknown)
385 : (c1 >= 0 || c1 == finite) || (c2 >= 0 || c2 == finite) ? finite
391 template<
typename Rng1,
typename Rng2,
typename C,
typename P1,
typename P2>
392 using set_intersection_view =
393 detail::set_algorithm_view<Rng1, Rng2, C, P1, P2, detail::set_intersection_cursor,
394 detail::set_intersection_cardinality(
395 range_cardinality<Rng1>::value,
396 range_cardinality<Rng2>::value)>;
402 template(
typename Rng1,
typename Rng2,
typename C =
less,
410 set_intersection_view<all_t<Rng1>, all_t<Rng2>, C, P1, P2>
411 operator()(Rng1 && rng1,
415 P2 proj2 = P2{})
const
417 return {all(
static_cast<Rng1 &&
>(rng1)),
418 all(
static_cast<Rng2 &&
>(rng2)),
427 using set_intersection_base_fn::operator();
429 template(
typename Rng2,
typename C =
less,
typename P1 =
identity,
432 constexpr auto operator()(Rng2 && rng2,
435 P2 proj2 = P2{})
const
439 static_cast<C &&
>(pred),
452 template<
bool IsConst,
typename Rng1,
typename Rng2,
typename C,
typename P1,
454 struct set_union_cursor
457 friend struct set_union_cursor<!IsConst, Rng1, Rng2, C, P1, P2>;
458 using pred_ref_ = semiregular_box_ref_or_val_t<C, IsConst>;
459 using proj1_ref_ = semiregular_box_ref_or_val_t<P1, IsConst>;
460 using proj2_ref_ = semiregular_box_ref_or_val_t<P2, IsConst>;
466 using constify_if = meta::const_if_c<IsConst, T>;
468 using R1 = constify_if<Rng1>;
469 using R2 = constify_if<Rng2>;
472 sentinel_t<R1> end1_;
475 sentinel_t<R2> end2_;
487 state = state_t::SECOND;
493 state = state_t::FIRST;
499 state = state_t::SECOND;
506 state = state_t::FIRST;
510 using value_type = common_type_t<range_value_t<R1>, range_value_t<R2>>;
511 using reference_type =
512 common_reference_t<range_reference_t<R1>, range_reference_t<R2>>;
513 using rvalue_reference_type =
514 common_reference_t<range_rvalue_reference_t<R1>,
515 range_rvalue_reference_t<R2>>;
517 single_pass_iterator_<iterator_t<R2>>>;
519 set_union_cursor() =
default;
520 set_union_cursor(pred_ref_ pred, proj1_ref_ proj1, proj2_ref_ proj2,
521 iterator_t<R1> it1, sentinel_t<R1> end1, iterator_t<R2> it2,
523 : pred_(std::move(pred))
524 , proj1_(std::move(proj1))
525 , proj2_(std::move(proj2))
526 , it1_(std::move(it1))
527 , end1_(std::move(end1))
528 , it2_(std::move(it2))
529 , end2_(std::move(end2))
533 template(
bool Other)(
534 requires IsConst AND CPP_NOT(Other))
535 set_union_cursor(set_union_cursor<Other, Rng1, Rng2, C, P1, P2> that)
536 : pred_(std::move(that.pred_))
537 , proj1_(std::move(that.proj1_))
538 , proj2_(std::move(that.proj2_))
539 , it1_(std::move(that.it1_))
540 , end1_(std::move(that.end1_))
541 , it2_(std::move(that.it2_))
542 , end2_(std::move(that.end2_))
544 reference_type read() const noexcept(noexcept(*it1_) && noexcept(*it2_))
546 if(state == state_t::SECOND)
553 if(state == state_t::FIRST)
560 auto equal(set_union_cursor
const & that)
const
562 requires forward_range<Rng1> && forward_range<Rng2>)
565 return (it1_ == that.it1_) && (it2_ == that.it2_);
567 bool equal(default_sentinel_t)
const
569 return (it1_ == end1_) && (it2_ == end2_);
571 rvalue_reference_type move() const
572 noexcept(noexcept(iter_move(it1_)) && noexcept(iter_move(it2_)))
574 if(state == state_t::SECOND)
575 return iter_move(it2_);
577 return iter_move(it1_);
581 constexpr cardinality set_union_cardinality(cardinality c1, cardinality c2)
583 return (c1 == infinite) || (c2 == infinite)
585 : (c1 == unknown) || (c2 == unknown) ? unknown : finite;
590 template<
typename Rng1,
typename Rng2,
typename C,
typename P1,
typename P2>
591 using set_union_view =
592 detail::set_algorithm_view<Rng1, Rng2, C, P1, P2, detail::set_union_cursor,
593 detail::set_union_cardinality(
594 range_cardinality<Rng1>::value,
595 range_cardinality<Rng2>::value)>;
602 template(
typename Rng1,
typename Rng2,
typename C =
less,
607 common_with<range_value_t<Rng1>, range_value_t<Rng2>> AND
608 common_reference_with<range_reference_t<Rng1>,
609 range_reference_t<Rng2>> AND
610 common_reference_with<range_rvalue_reference_t<Rng1>,
611 range_rvalue_reference_t<Rng2>> AND
615 set_union_view<all_t<Rng1>, all_t<Rng2>, C, P1, P2>
616 operator()(Rng1 && rng1,
620 P2 proj2 = P2{})
const
622 return {all(
static_cast<Rng1 &&
>(rng1)),
623 all(
static_cast<Rng2 &&
>(rng2)),
632 using set_union_base_fn::operator();
634 template(
typename Rng2,
typename C =
less,
typename P1 =
identity,
637 constexpr auto operator()(Rng2 && rng2,
640 P2 proj2 = P2{})
const
644 static_cast<C &&
>(pred),
657 template<
bool IsConst,
typename Rng1,
typename Rng2,
typename C,
typename P1,
659 struct set_symmetric_difference_cursor
662 friend struct set_symmetric_difference_cursor<!IsConst, Rng1, Rng2, C, P1,
664 using pred_ref_ = semiregular_box_ref_or_val_t<C, IsConst>;
665 using proj1_ref_ = semiregular_box_ref_or_val_t<P1, IsConst>;
666 using proj2_ref_ = semiregular_box_ref_or_val_t<P2, IsConst>;
672 using constify_if = meta::const_if_c<IsConst, T>;
674 using R1 = constify_if<Rng1>;
675 using R2 = constify_if<Rng2>;
678 sentinel_t<R1> end1_;
681 sentinel_t<R2> end2_;
697 state = state_t::ONLY_FIRST;
703 state = state_t::FIRST;
710 state = state_t::SECOND;
720 state = state_t::ONLY_SECOND;
724 using value_type = common_type_t<range_value_t<R1>, range_value_t<R2>>;
725 using reference_type =
726 common_reference_t<range_reference_t<R1>, range_reference_t<R2>>;
727 using rvalue_reference_type =
728 common_reference_t<range_rvalue_reference_t<R1>,
729 range_rvalue_reference_t<R2>>;
731 single_pass_iterator_<iterator_t<R2>>>;
733 set_symmetric_difference_cursor() =
default;
734 set_symmetric_difference_cursor(pred_ref_ pred, proj1_ref_ proj1,
735 proj2_ref_ proj2, iterator_t<R1> it1,
736 sentinel_t<R1> end1, iterator_t<R2> it2,
738 : pred_(std::move(pred))
739 , proj1_(std::move(proj1))
740 , proj2_(std::move(proj2))
741 , it1_(std::move(it1))
742 , end1_(std::move(end1))
743 , it2_(std::move(it2))
744 , end2_(std::move(end2))
749 template(
bool Other)(
750 requires IsConst && CPP_NOT(Other))
751 set_symmetric_difference_cursor(
752 set_symmetric_difference_cursor<Other, Rng1, Rng2, C, P1, P2> that)
753 : pred_(std::move(that.pred_))
754 , proj1_(std::move(that.proj1_))
755 , proj2_(std::move(that.proj2_))
756 , it1_(std::move(that.it1_))
757 , end1_(std::move(that.end1_))
758 , it2_(std::move(that.it2_))
759 , end2_(std::move(that.end2_))
762 reference_type read() const noexcept(noexcept(*it1_) && noexcept(*it2_))
764 if(state == state_t::SECOND || state == state_t::ONLY_SECOND)
777 case state_t::ONLY_FIRST:
780 case state_t::SECOND:
784 case state_t::ONLY_SECOND:
790 auto equal(set_symmetric_difference_cursor
const & that)
const
792 requires forward_range<R1> && forward_range<R2>)
795 return (it1_ == that.it1_) && (it2_ == that.it2_);
797 bool equal(default_sentinel_t)
const
799 return (it1_ == end1_) && (it2_ == end2_);
801 rvalue_reference_type move() const
802 noexcept(noexcept(iter_move(it1_)) && noexcept(iter_move(it2_)))
804 if(state == state_t::SECOND || state == state_t::ONLY_SECOND)
805 return iter_move(it2_);
807 return iter_move(it1_);
811 constexpr cardinality set_symmetric_difference_cardinality(cardinality c1,
814 return (c1 == unknown) || (c2 == unknown)
816 : (c1 == infinite) != (c2 == infinite)
818 : (c1 == infinite) && (c2 == infinite) ? unknown : finite;
824 template<
typename Rng1,
typename Rng2,
typename C,
typename P1,
typename P2>
825 using set_symmetric_difference_view = detail::set_algorithm_view<
826 Rng1, Rng2, C, P1, P2, detail::set_symmetric_difference_cursor,
827 detail::set_symmetric_difference_cardinality(range_cardinality<Rng1>::value,
828 range_cardinality<Rng2>::value)>;
834 template(
typename Rng1,
typename Rng2,
typename C =
less,
839 common_with<range_value_t<Rng1>, range_value_t<Rng2>> AND
840 common_reference_with<range_reference_t<Rng1>,
841 range_reference_t<Rng2>> AND
842 common_reference_with<range_rvalue_reference_t<Rng1>,
843 range_rvalue_reference_t<Rng2>> AND
847 set_symmetric_difference_view<all_t<Rng1>, all_t<Rng2>, C, P1, P2>
848 operator()(Rng1 && rng1,
852 P2 proj2 = P2{})
const
854 return {all(
static_cast<Rng1 &&
>(rng1)),
855 all(
static_cast<Rng2 &&
>(rng2)),
864 using set_symmetric_difference_base_fn::operator();
866 template(
typename Rng2,
typename C =
less,
typename P1 =
identity,
869 constexpr auto operator()(Rng2 && rng2,
872 P2 proj2 = P2{})
const
876 static_cast<C &&
>(pred),
888#include <range/v3/detail/epilogue.hpp>
The indirect_relation concept.
The viewable_range concept.
decltype(begin(declval(Rng &))) iterator_t
Definition access.hpp:698
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
Definition identity.hpp:25
Definition comparisons.hpp:50
Definition set_algorithm.hpp:227
Definition set_algorithm.hpp:252
Definition set_algorithm.hpp:401
Definition set_algorithm.hpp:426
Definition set_algorithm.hpp:833
Definition set_algorithm.hpp:863
Definition set_algorithm.hpp:600
Definition set_algorithm.hpp:631