diff --git a/source/algorithms.tex b/source/algorithms.tex index ab0b1c63ab..1d3f89cbc7 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -642,6 +642,9 @@ template struct in_found_result; + template + struct in_value_result; + template struct out_value_result; } @@ -1215,6 +1218,91 @@ @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> constexpr bool ends_with(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + // \ref{alg.fold}, fold + template + class @\exposid{flipped}@ { // \expos + F @\exposid{f}@; // \expos + + public: + template requires @\libconcept{invocable}@ + invoke_result_t operator()(T&&, U&&); + }; + + template + concept @\defexposconcept{indirectly-binary-left-foldable-impl}@ = // \expos + @\libconcept{movable}@ && @\libconcept{movable}@ && + @\libconcept{convertible_to}@ && @\libconcept{invocable}@> && + @\libconcept{assignable_from}@>>; + + template + concept @\defexposconcept{indirectly-binary-left-foldable}@ = // \expos + @\libconcept{copy_constructible}@ && @\libconcept{indirectly_readable}@ && + @\libconcept{invocable}@> && + @\libconcept{convertible_to}@>, + decay_t>>> && + @\exposconcept{indirectly-binary-left-foldable-impl}@>>>; + + template + concept @\defexposconcept{indirectly-binary-right-foldable}@ = // \expos + @\exposconcept{indirectly-binary-left-foldable}@<@\exposid{flipped}@, T, I>; + + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + @\exposconcept{indirectly-binary-left-foldable}@ F> + constexpr auto fold_left(I first, S last, T init, F f); + + template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> + constexpr auto fold_left(R&& r, T init, F f); + + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, + @\exposconcept{indirectly-binary-left-foldable}@, I> F> + requires @\libconcept{constructible_from}@, iter_reference_t> + constexpr auto fold_left_first(I first, S last, F f); + + template<@\libconcept{input_range}@ R, @\exposconcept{indirectly-binary-left-foldable}@, iterator_t> F> + requires @\libconcept{constructible_from}@, range_reference_t> + constexpr auto fold_left_first(R&& r, F f); + + template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + @\exposconcept{indirectly-binary-right-foldable}@ F> + constexpr auto fold_right(I first, S last, T init, F f); + + template<@\libconcept{bidirectional_range}@ R, class T, + @\exposconcept{indirectly-binary-right-foldable}@> F> + constexpr auto fold_right(R&& r, T init, F f); + + template <@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, + @\exposconcept{indirectly-binary-right-foldable}@, I> F> + requires @\libconcept{constructible_from}@, iter_reference_t> + constexpr auto fold_right_last(I first, S last, F f); + + template<@\libconcept{bidirectional_range}@ R, + @\exposconcept{indirectly-binary-right-foldable}@, iterator_t> F> + requires @\libconcept{constructible_from}@, range_reference_t> + constexpr auto fold_right_last(R&& r, F f); + + template + using fold_left_with_iter_result = in_value_result; + template + using fold_left_first_with_iter_result = in_value_result; + + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + @\exposconcept{indirectly-binary-left-foldable}@ F> + constexpr @\seebelow@ fold_left_with_iter(I first, S last, T init, F f); + + template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> + constexpr @\seebelow@ fold_left_with_iter(R&& r, T init, F f); + + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, + @\exposconcept{indirectly-binary-left-foldable}@, I> F> + requires @\libconcept{constructible_from}@, iter_reference_t> + constexpr @\seebelow@ fold_left_first_with_iter(I first, S last, F f); + + template<@\libconcept{input_range}@ R, + @\exposconcept{indirectly-binary-left-foldable}@, iterator_t> F> + requires @\libconcept{constructible_from}@, range_reference_t> + constexpr @\seebelow@ fold_left_first_with_iter(R&& r, F f); } // \ref{alg.modifying.operations}, mutating sequence operations @@ -3104,6 +3192,24 @@ } }; + template + struct in_value_result { + [[no_unique_address]] I in; + [[no_unique_address]] T value; + + template + requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ + constexpr operator in_value_result() const & { + return {in, value}; + } + + template + requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ + constexpr operator in_value_result() && { + return {std::move(in), std::move(value)}; + } + }; + template struct out_value_result { [[no_unique_address]] O out; @@ -4518,6 +4624,170 @@ \end{codeblock} \end{itemdescr} +\rSec2[alg.fold]{Fold} + +\indexlibraryglobal{fold_left}% +\begin{itemdecl} +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, @\exposconcept{indirectly-binary-left-foldable}@ F> + constexpr auto ranges::fold_left(I first, S last, T init, F f); +template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> + constexpr auto ranges::fold_left(R&& r, T init, F f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +ranges::fold_left_with_iter(std::move(first), last, std::move(init), f).value +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{fold_left_first}% +\begin{itemdecl} +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, + @\exposconcept{indirectly-binary-left-foldable}@, I> F> + requires @\libconcept{constructible_from}@, iter_reference_t> + constexpr auto ranges::fold_left_first(I first, S last, F f); +template<@\libconcept{input_range}@ R, @\exposconcept{indirectly-binary-left-foldable}@, iterator_t> F> + requires @\libconcept{constructible_from}@, range_reference_t> + constexpr auto ranges::fold_left_first(R&& r, F f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +ranges::fold_left_first_with_iter(std::move(first), last, f).value +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{fold_right}% +\begin{itemdecl} +template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + @\exposconcept{indirectly-binary-right-foldable}@ F> + constexpr auto ranges::fold_right(I first, S last, T init, F f); +template<@\libconcept{bidirectional_range}@ R, class T, + @\exposconcept{indirectly-binary-right-foldable}@> F> + constexpr auto ranges::fold_right(R&& r, T init, F f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using U = decay_t, T>>; +if (first == last) + return U(std::move(init)); +I tail = ranges::next(first, last); +U accum = invoke(f, *--tail, std::move(init)); +while (first != tail) + accum = invoke(f, *--tail, std::move(accum)); +return accum; +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{fold_right_last}% +\begin{itemdecl} +template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, + @\exposconcept{indirectly-binary-right-foldable}@, I> F> + requires @\libconcept{constructible_from}@, iter_reference_t> + constexpr auto ranges::fold_right_last(I first, S last, F f); +template<@\libconcept{bidirectional_range}@ R, + @\exposconcept{indirectly-binary-right-foldable}@, iterator_t> F> + requires @\libconcept{constructible_from}@, range_reference_t> + constexpr auto ranges::fold_right_last(R&& r, F f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{U} be +\tcode{decltype(ranges::fold_right(first, last, iter_value_t(*first), f))}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (first == last) + return optional(); +I tail = ranges::prev(ranges::next(first, std::move(last))); +return optional(in_place, + ranges::fold_right(std::move(first), tail, iter_value_t(*tail), std::move(f))); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{fold_left_with_iter}% +\begin{itemdecl} +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + @\exposconcept{indirectly-binary-left-foldable}@ F> + constexpr @\seebelow@ ranges::fold_left_with_iter(I first, S last, T init, F f); +template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> + constexpr @\seebelow@ ranges::fold_left_with_iter(R&& r, T init, F f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{U} be \tcode{decay_t>>}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (first == last) + return {std::move(first), U(std::move(init))}; +U accum = invoke(f, std::move(init), *first); +for (++first; first != last; ++first) + accum = invoke(f, std::move(accum), *first); +return {std::move(first), std::move(accum)}; +\end{codeblock} + +\pnum +\remarks +The return type is +\tcode{fold_left_with_iter_result} for the first overload and +\tcode{fold_left_with_iter_result, U>} +for the second overload. +\end{itemdescr} + +\indexlibraryglobal{fold_left_first_with_iter}% +\begin{itemdecl} +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, + @\exposconcept{indirectly-binary-left-foldable}@, I> F> + requires @\libconcept{constructible_from}@, iter_reference_t> + constexpr @\seebelow@ ranges::fold_left_first_with_iter(I first, S last, F f); +template<@\libconcept{input_range}@ R, @\exposconcept{indirectly-binary-left-foldable}@, iterator_t> F> + requires @\libconcept{constructible_from}@, range_reference_t> + constexpr @\seebelow@ ranges::fold_left_first_with_iter(R&& r, F f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{U} be +\begin{codeblock} +decltype(ranges::fold_left(std::move(first), last, iter_value_t(*first), f)) +\end{codeblock} + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (first == last) + return {std::move(first), optional()}; +optional init(in_place, *first); +for (++first; first != last; ++first) + *init = invoke(f, std::move(*init), *first); +return {std::move(first), std::move(init)}; +\end{codeblock} + +\pnum +\remarks +The return type is +\tcode{fold_left_first_with_iter_result>} +for the first overload and +\tcode{fold_left_first_with_iter_result, optional>} +for the second overload. +\end{itemdescr} + \rSec1[alg.modifying.operations]{Mutating sequence operations} \rSec2[alg.copy]{Copy} diff --git a/source/support.tex b/source/support.tex index ccc0ba2309..d0c1397c32 100644 --- a/source/support.tex +++ b/source/support.tex @@ -681,6 +681,7 @@ #define @\defnlibxname{cpp_lib_ranges_chunk}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_chunk_by}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_contains}@ 202207L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_fold}@ 202207L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_ranges_join_with}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_slide}@ 202202L // also in \libheader{ranges}