|
428 | 428 | enable_borrowed_range<V>;
|
429 | 429 |
|
430 | 430 | namespace views { inline constexpr @\unspec@ slide = @\unspec@; }
|
| 431 | + |
| 432 | + // \ref{range.chunk.by}, chunk by view |
| 433 | + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@<iterator_t<V>, iterator_t<V>> Pred> |
| 434 | + requires @\libconcept{view}@<V> && is_object_v<Pred> |
| 435 | + class chunk_by_view; |
| 436 | + |
| 437 | + namespace views { inline constexpr @\unspec@ chunk_by = @\unspec@; } |
431 | 438 | }
|
432 | 439 |
|
433 | 440 | namespace std {
|
@@ -12532,3 +12539,332 @@
|
12532 | 12539 | \returns
|
12533 | 12540 | \tcode{y.\exposid{end_} - x.\exposid{last_ele_}}.
|
12534 | 12541 | \end{itemdescr}
|
| 12542 | + |
| 12543 | +\rSec2[range.chunk.by]{Chunk by view} |
| 12544 | + |
| 12545 | +\rSec3[range.chunk.by.overview]{Overview} |
| 12546 | + |
| 12547 | +\pnum |
| 12548 | +\tcode{chunk_by_view} takes a \libconcept{view} and a predicate, and |
| 12549 | +splits the \libconcept{view} into \tcode{subrange}s |
| 12550 | +between each pair of adjacent elements |
| 12551 | +for which the predicate returns \tcode{false}. |
| 12552 | + |
| 12553 | +\pnum |
| 12554 | +\indexlibrarymember{chunk_by}{views}% |
| 12555 | +The name \tcode{views::chunk_by} denotes |
| 12556 | +a range adaptor object\iref{range.adaptor.object}. |
| 12557 | +Given subexpressions \tcode{E} and \tcode{F}, |
| 12558 | +the expression \tcode{views::chunk_by(E, F)} is expression-equivalent to |
| 12559 | +\tcode{chunk_by_view(E, F)}. |
| 12560 | +\begin{example} |
| 12561 | +\begin{codeblock} |
| 12562 | +vector v = {1, 2, 2, 3, 0, 4, 5, 2}; |
| 12563 | + |
| 12564 | +for (auto r : v | views::chunk_by(ranges::less_equal{})) { |
| 12565 | + cout << '['; |
| 12566 | + auto sep = ""; |
| 12567 | + for(auto i : r) { |
| 12568 | + cout << sep << i; |
| 12569 | + sep = ", "; |
| 12570 | + } |
| 12571 | + cout << "] "; |
| 12572 | +} |
| 12573 | +\end{codeblock} |
| 12574 | +The above prints: \tcode{[1, 2, 2, 3] [0, 4, 5] [2]} |
| 12575 | +\end{example} |
| 12576 | + |
| 12577 | +\rSec3[range.chunk.by.view]{Class template \tcode{chunk_by_view}} |
| 12578 | + |
| 12579 | +\begin{codeblock} |
| 12580 | +namespace std::ranges { |
| 12581 | + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@<iterator_t<V>, iterator_t<V>> Pred> |
| 12582 | + requires @\libconcept{view}@<V> && is_object_v<Pred> |
| 12583 | + class chunk_by_view : public view_interface<chunk_by_view<V, Pred>> { |
| 12584 | + V @\exposid{base_}@ = V(); // \expos |
| 12585 | + @\exposid{copyable-box}@<Pred> @\exposid{pred_}@ = Pred(); // \expos |
| 12586 | + |
| 12587 | + // \ref{range.chunk.by.iter}, class \tcode{chunk_by_view::\exposid{iterator}} |
| 12588 | + class @\exposid{iterator}@; // \expos |
| 12589 | + |
| 12590 | + public: |
| 12591 | + chunk_by_view() requires @\libconcept{default_initializable}@<V> && @\libconcept{default_initializable}@<Pred> = default; |
| 12592 | + constexpr explicit chunk_by_view(V base, Pred pred); |
| 12593 | + |
| 12594 | + constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; } |
| 12595 | + constexpr V base() && { return std::move(@\exposid{base_}@); } |
| 12596 | + |
| 12597 | + constexpr const Pred& pred() const; |
| 12598 | + |
| 12599 | + constexpr @\exposid{iterator}@ begin(); |
| 12600 | + constexpr auto end(); |
| 12601 | + |
| 12602 | + constexpr iterator_t<V> @\exposid{find-next}@(iterator_t<V>); // \expos |
| 12603 | + constexpr iterator_t<V> @\exposid{find-prev}@(iterator_t<V>) // \expos |
| 12604 | + requires @\libconcept{bidirectional_range}@<V>; |
| 12605 | + }; |
| 12606 | + |
| 12607 | + template<class R, class Pred> |
| 12608 | + chunk_by_view(R&&, Pred) -> chunk_by_view<views::all_t<R>, Pred>; |
| 12609 | +} |
| 12610 | +\end{codeblock} |
| 12611 | + |
| 12612 | +\begin{itemdecl} |
| 12613 | +constexpr explicit chunk_by_view(V base, Pred pred); |
| 12614 | +\end{itemdecl} |
| 12615 | + |
| 12616 | +\begin{itemdescr} |
| 12617 | +\pnum |
| 12618 | +\effects |
| 12619 | +Initializes \exposid{base_} with \tcode{std::move(base)} and |
| 12620 | +\exposid{pred_} with \tcode{std::move(pred)}. |
| 12621 | +\end{itemdescr} |
| 12622 | + |
| 12623 | +\indexlibrarymember{pred}{chunk_by_view}% |
| 12624 | +\begin{itemdecl} |
| 12625 | +constexpr const Pred& pred() const; |
| 12626 | +\end{itemdecl} |
| 12627 | + |
| 12628 | +\begin{itemdescr} |
| 12629 | +\pnum |
| 12630 | +\effects |
| 12631 | +Equivalent to: \tcode{return *\exposid{pred_};} |
| 12632 | +\end{itemdescr} |
| 12633 | + |
| 12634 | +\begin{itemdecl} |
| 12635 | +constexpr @\exposid{iterator}@ begin(); |
| 12636 | +\end{itemdecl} |
| 12637 | + |
| 12638 | +\begin{itemdescr} |
| 12639 | +\pnum |
| 12640 | +\expects |
| 12641 | +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. |
| 12642 | + |
| 12643 | +\pnum |
| 12644 | +\returns |
| 12645 | +\tcode{\exposid{iterator}(*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_})))}. |
| 12646 | + |
| 12647 | +\pnum |
| 12648 | +\remarks |
| 12649 | +In order to provide |
| 12650 | +the amortized constant-time complexity required by the \libconcept{range} concept, |
| 12651 | +this function caches the result within the \tcode{chunk_by_view} |
| 12652 | +for use on subsequent calls. |
| 12653 | +\end{itemdescr} |
| 12654 | + |
| 12655 | +\begin{itemdecl} |
| 12656 | +constexpr auto end(); |
| 12657 | +\end{itemdecl} |
| 12658 | + |
| 12659 | +\begin{itemdescr} |
| 12660 | +\pnum |
| 12661 | +\effects |
| 12662 | +Equivalent to: |
| 12663 | +\begin{codeblock} |
| 12664 | +if constexpr (@\libconcept{common_range}@<V>) { |
| 12665 | + return @\exposid{iterator}@(*this, ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); |
| 12666 | +} else { |
| 12667 | + return default_sentinel; |
| 12668 | +} |
| 12669 | +\end{codeblock} |
| 12670 | +\end{itemdescr} |
| 12671 | + |
| 12672 | +\begin{itemdecl} |
| 12673 | +constexpr iterator_t<V> @\exposid{find-next}@(iterator_t<V> current); |
| 12674 | +\end{itemdecl} |
| 12675 | + |
| 12676 | +\begin{itemdescr} |
| 12677 | +\pnum |
| 12678 | +\expects |
| 12679 | +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. |
| 12680 | + |
| 12681 | +\pnum |
| 12682 | +\returns |
| 12683 | +\begin{codeblock} |
| 12684 | +ranges::next(ranges::adjacent_find(current, ranges::end(@\exposid{base_}@), not_fn(ref(*@\exposid{pred_}@))), |
| 12685 | + 1, ranges::end(@\exposid{base_}@)) |
| 12686 | +\end{codeblock} |
| 12687 | +\end{itemdescr} |
| 12688 | + |
| 12689 | +\begin{itemdecl} |
| 12690 | +constexpr iterator_t<V> @\exposid{find-prev}@(iterator_t<V> current) requires @\libconcept{bidirectional_range}@<V>; |
| 12691 | +\end{itemdecl} |
| 12692 | + |
| 12693 | +\begin{itemdescr} |
| 12694 | +\pnum |
| 12695 | +\expects |
| 12696 | +\begin{itemize} |
| 12697 | +\item |
| 12698 | +\tcode{current} is not equal to \tcode{ranges::begin(\exposid{base_})}. |
| 12699 | +\item |
| 12700 | +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. |
| 12701 | +\end{itemize} |
| 12702 | + |
| 12703 | +\pnum |
| 12704 | +\returns |
| 12705 | +An iterator \tcode{i} |
| 12706 | +in the range \range{ranges::begin(\exposid{base_})}{current} such that: |
| 12707 | +\begin{itemize} |
| 12708 | +\item |
| 12709 | +\tcode{ranges::adjacent_find(i, current, not_fn(ref(*\exposid{pred_})))} is equal to \tcode{current}; and |
| 12710 | +\item |
| 12711 | +if \tcode{i} is not equal to \tcode{ranges::begin(\exposid{base_})}, |
| 12712 | +then \tcode{bool(invoke(*\exposid{pred_}, *ranges::prev(i), *i))} |
| 12713 | +is \tcode{false}. |
| 12714 | +\end{itemize} |
| 12715 | +\end{itemdescr} |
| 12716 | + |
| 12717 | +\rSec3[range.chunk.by.iter]{Class \tcode{chunk_by_view::\exposid{iterator}}} |
| 12718 | + |
| 12719 | +\begin{codeblock} |
| 12720 | +namespace std::ranges { |
| 12721 | + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@<iterator_t<V>, iterator_t<V>> Pred> |
| 12722 | + requires @\libconcept{view}@<V> && is_object_v<Pred> |
| 12723 | + class chunk_by_view<V, Pred>::@\exposid{iterator}@ { |
| 12724 | + chunk_by_view* @\exposid{parent_}@ = nullptr; // \expos |
| 12725 | + iterator_t<V> @\exposid{current_}@ = iterator_t<V>(); // \expos |
| 12726 | + iterator_t<V> @\exposid{next_}@ = iterator_t<V>(); // \expos |
| 12727 | + |
| 12728 | + constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t<V> current, // \expos |
| 12729 | + iterator_t<V> next); |
| 12730 | + |
| 12731 | + public: |
| 12732 | + using value_type = subrange<iterator_t<V>>; |
| 12733 | + using difference_type = range_difference_t<V>; |
| 12734 | + using iterator_category = input_iterator_tag; |
| 12735 | + using iterator_concept = @\seebelow@; |
| 12736 | + |
| 12737 | + @\exposid{iterator}@() = default; |
| 12738 | + |
| 12739 | + constexpr value_type operator*() const; |
| 12740 | + constexpr @\exposid{iterator}@& operator++(); |
| 12741 | + constexpr @\exposid{iterator}@ operator++(int); |
| 12742 | + |
| 12743 | + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<V>; |
| 12744 | + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<V>; |
| 12745 | + |
| 12746 | + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); |
| 12747 | + friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); |
| 12748 | + }; |
| 12749 | +} |
| 12750 | +\end{codeblock} |
| 12751 | + |
| 12752 | +\pnum |
| 12753 | +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: |
| 12754 | +\begin{itemize} |
| 12755 | +\item |
| 12756 | +If \tcode{V} models \libconcept{bidirectional_range}, |
| 12757 | +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. |
| 12758 | +\item |
| 12759 | +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. |
| 12760 | +\end{itemize} |
| 12761 | + |
| 12762 | +\begin{itemdecl} |
| 12763 | +constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t<V> current, iterator_t<V> next); |
| 12764 | +\end{itemdecl} |
| 12765 | + |
| 12766 | +\begin{itemdescr} |
| 12767 | +\pnum |
| 12768 | +\effects |
| 12769 | +Initializes \exposid{parent_} with \tcode{addressof(parent)}, |
| 12770 | +\exposid{current_} with \tcode{current}, and |
| 12771 | +\exposid{next_} with \tcode{next}. |
| 12772 | +\end{itemdescr} |
| 12773 | + |
| 12774 | +\begin{itemdecl} |
| 12775 | +constexpr value_type operator*() const; |
| 12776 | +\end{itemdecl} |
| 12777 | + |
| 12778 | +\begin{itemdescr} |
| 12779 | +\pnum |
| 12780 | +\expects |
| 12781 | +\exposid{current_} is not equal to \exposid{next_}. |
| 12782 | + |
| 12783 | +\pnum |
| 12784 | +\returns |
| 12785 | +\tcode{subrange(\exposid{current_}, \exposid{next_})}. |
| 12786 | +\end{itemdescr} |
| 12787 | + |
| 12788 | +\begin{itemdecl} |
| 12789 | +constexpr @\exposid{iterator}@& operator++(); |
| 12790 | +\end{itemdecl} |
| 12791 | + |
| 12792 | +\begin{itemdescr} |
| 12793 | +\pnum |
| 12794 | +\expects |
| 12795 | +\exposid{current_} is not equal to \exposid{next_}. |
| 12796 | + |
| 12797 | +\pnum |
| 12798 | +\effects |
| 12799 | +Equivalent to: |
| 12800 | +\begin{codeblock} |
| 12801 | +@\exposid{current_}@ = @\exposid{next_}@; |
| 12802 | +@\exposid{next_}@ = @\exposid{parent_}@->@\exposid{find-next}@(@\exposid{current_}@); |
| 12803 | +return *this; |
| 12804 | +\end{codeblock} |
| 12805 | +\end{itemdescr} |
| 12806 | + |
| 12807 | +\begin{itemdecl} |
| 12808 | +constexpr @\exposid{iterator}@ operator++(int); |
| 12809 | +\end{itemdecl} |
| 12810 | + |
| 12811 | +\begin{itemdescr} |
| 12812 | +\pnum |
| 12813 | +\effects |
| 12814 | +Equivalent to: |
| 12815 | +\begin{codeblock} |
| 12816 | +auto tmp = *this; |
| 12817 | +++*this; |
| 12818 | +return tmp; |
| 12819 | +\end{codeblock} |
| 12820 | +\end{itemdescr} |
| 12821 | + |
| 12822 | +\begin{itemdecl} |
| 12823 | +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<V>; |
| 12824 | +\end{itemdecl} |
| 12825 | + |
| 12826 | +\begin{itemdescr} |
| 12827 | +\pnum |
| 12828 | +\effects |
| 12829 | +Equivalent to: |
| 12830 | +\begin{codeblock} |
| 12831 | +@\exposid{next_}@ = @\exposid{current_}@; |
| 12832 | +@\exposid{current_}@ = @\exposid{parent_}@->@\exposid{find-prev}@(@\exposid{next_}@); |
| 12833 | +return *this; |
| 12834 | +\end{codeblock} |
| 12835 | +\end{itemdescr} |
| 12836 | + |
| 12837 | +\begin{itemdecl} |
| 12838 | +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<V>; |
| 12839 | +\end{itemdecl} |
| 12840 | + |
| 12841 | +\begin{itemdescr} |
| 12842 | +\pnum |
| 12843 | +\effects |
| 12844 | +Equivalent to: |
| 12845 | +\begin{codeblock} |
| 12846 | +auto tmp = *this; |
| 12847 | +--*this; |
| 12848 | +return tmp; |
| 12849 | +\end{codeblock} |
| 12850 | +\end{itemdescr} |
| 12851 | + |
| 12852 | +\begin{itemdecl} |
| 12853 | +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); |
| 12854 | +\end{itemdecl} |
| 12855 | + |
| 12856 | +\begin{itemdescr} |
| 12857 | +\pnum |
| 12858 | +\returns |
| 12859 | +\tcode{x.\exposid{current_} == y.\exposid{current_}}. |
| 12860 | +\end{itemdescr} |
| 12861 | + |
| 12862 | +\begin{itemdecl} |
| 12863 | +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); |
| 12864 | +\end{itemdecl} |
| 12865 | + |
| 12866 | +\begin{itemdescr} |
| 12867 | +\pnum |
| 12868 | +\returns |
| 12869 | +\tcode{x.\exposid{current_} == x.\exposid{next_}}. |
| 12870 | +\end{itemdescr} |
0 commit comments