Spec-Zone.ru › C++

std::ranges::fold_left_with_iter, std::ranges::fold_left_with_iter_result

Определено в заголовочном файле <algorithm>
Сигнатура вызова
template< std::input_iterator I, std::sentinel_for<I> S, class T,
          /*indirectly-binary-left-foldable*/<T, I> F >
constexpr ranges::fold_left_with_iter_result<I, /* see below */>
    fold_left_with_iter( I first, S last, T init, F f );
(1) (начиная с C++23)
(до C++26)
template< std::input_iterator I, std::sentinel_for<I> S,
          class T = std::iter_value_t<I>,
          /*indirectly-binary-left-foldable*/<T, I> F >
constexpr ranges::fold_left_with_iter_result<I, /* see below */>
    fold_left_with_iter( I first, S last, T init, F f );
(начиная с C++26)
template< ranges::input_range R, class T,
          /*indirectly-binary-left-foldable*/<T, ranges::iterator_t<R>> F >
constexpr ranges::fold_left_with_iter_result<ranges::borrowed_iterator_t<R>,
                                             /* see below */>
    fold_left_with_iter( R&& r, T init, F f );
(2) (начиная с C++23)
(до C++26)
template< ranges::input_range R, class T = ranges::range_value_t<R>,
          /*indirectly-binary-left-foldable*/<T, ranges::iterator_t<R>> F >
constexpr ranges::fold_left_with_iter_result<ranges::borrowed_iterator_t<R>,
                                             /* see below */>
    fold_left_with_iter( R&& r, T init, F f );
(начиная с C++26)
Вспомогательный шаблон класса
template< class I, class T >
using fold_left_with_iter_result = ranges::in_value_result<I, T>;
(3) (начиная с C++23)

Определение /*indirectly-binary-left-foldable*/ см. на этой странице.

Выполняет свёртку элементов исходного диапазона слева, то есть возвращает результат вычисления цепочки выражений:
f(f(f(f(init, x1), x2), ...), xn), где x1, x2, ..., xn — элементы исходного диапазона. Также возвращает итератор за последним элементом исходного диапазона.

1) Исходный диапазон задаётся [first, last).
2) Исходный диапазон задаётся r.
3) Псевдоним типа возвращаемого значения.

Функциональные сущности, описанные на этой странице, являются функциональными объектами алгоритмов (неформально известными как niebloids), то есть:

  • При вызове ни одной из них нельзя указывать явный список аргументов шаблона.
  • Ни одна из них не видна при поиске, зависящем от аргументов.
  • Если какая-либо из них найдена при обычном поиске неквалифицированного имени как имя слева от оператора вызова функции, поиск, зависящий от аргументов, подавляется.

Параметры

first, last - пара итератора и сентинела, задающая исходный диапазон
r - исходный диапазон
init - начальное значение свёртки
f - бинарный функциональный объект

Возвращаемое значение

Объект типа ranges::fold_left_with_iter_result, в котором:

  • Поле данных in содержит итератор за последним элементом исходного диапазона.
  • Поле данных value содержит результат свёртки слева, который равен init, если исходный диапазон пуст.

Второй аргумент шаблона типа возвращаемого значения — это тип результата F после удаления ссылочных и cv-квалификаторов.

Примечания

В следующей таблице сравниваются все алгоритмы свёртки с ограничениями. U ниже — тип результата свёртки; это тип результата F после удаления ссылочных и cv-квалификаторов.

Шаблон функции свёртки Начало свёртки Начальное значение Возвращаемый тип
ranges::fold_left слева init U
ranges::fold_left_first слева первый элемент std::optional<U>
ranges::fold_right справа init U
ranges::fold_right_last справа последний элемент std::optional<U>
ranges::fold_left_with_iter слева init

(1) ranges::in_value_result<I,U>

(2) ranges::in_value_result<BR,U>,

где BR — это ranges::borrowed_iterator_t<R>

ranges::fold_left_first_with_iter слева первый элемент

(1) ranges::in_value_result<I,std::optional<U>>

(2) ranges::in_value_result<BR,std::optional<U>>

где BR — это ranges::borrowed_iterator_t<R>

Макрос проверки поддержки Значение Стандарт Функция
__cpp_lib_ranges_fold 202207L (C++23) std::ranges алгоритмы свёртки
__cpp_lib_algorithm_default_value_type 202403L (C++26) Инициализация списком для алгоритмов (1,2)

Возможные реализации

class fold_left_with_iter_fn
{
    template<class O, class I, class S, class T, class F>
    constexpr auto impl(I&& first, S&& last, T&& init, F f) const
    {
        using U = std::decay_t<std::invoke_result_t<F&, T, std::iter_reference_t<I>>>;
        using Ret = ranges::fold_left_with_iter_result<O, U>;
        if (first == last)
            return Ret{std::move(first), U(std::move(init))};
        U accum = std::invoke(f, std::move(init), *first);
        for (++first; first != last; ++first)
            accum = std::invoke(f, std::move(accum), *first);
        return Ret{std::move(first), std::move(accum)};
    }
public:
    template<std::input_iterator I, std::sentinel_for<I> S, class T = std::iter_value_t<I>,
             /*indirectly-binary-left-foldable*/<T, I> F>
    constexpr auto operator()(I first, S last, T init, F f) const
    {
        return impl<I>(std::move(first), std::move(last), std::move(init), std::ref(f));
    }
    
    using BR = ranges::borrowed_iterator_t<R>;
    
    template<ranges::input_range R, class T = ranges::range_value_t<R>,
             /*indirectly-binary-left-foldable*/<T, ranges::iterator_t<R>> F>
    constexpr auto operator()(R&& r, T init, F f) const
    {
        return impl<BR>(ranges::begin(r), ranges::end(r), std::move(init), std::ref(f));
    }
    
    template<ranges::forward_range R, class T = ranges::range_value_t<R>,
             /*indirectly-binary-left-foldable*/<T, ranges::iterator_t<R>> F>
    constexpr auto operator()(R&& r, T init, F f) const
    {
        return impl<BR>(ranges::begin(r),
                        ranges::next(ranges::begin(r), ranges::end(r)),
                        std::move(init), std::ref(f));
    }
};

inline constexpr fold_left_with_iter_fn fold_left_with_iter;

Пример

#include <algorithm>
#include <cassert>
#include <complex>
#include <functional>
#include <ranges>
#include <utility>
#include <vector>

int main()
{
    namespace ranges = std::ranges;

    std::vector v{1, 2, 3, 4, 5, 6, 7, 8};
    
    auto sum = ranges::fold_left_with_iter(v.begin(), v.end(), 6, std::plus<int>());
    assert(sum.value == 42);
    assert(sum.in == v.end());
    
    auto mul = ranges::fold_left_with_iter(v, 0X69, std::multiplies<int>());
    assert(mul.value == 4233600);
    assert(mul.in == v.end());
    
    // Get the product of the std::pair::second of all pairs in the vector:
    std::vector<std::pair<char, float>> data {{'A', 2.f}, {'B', 3.f}, {'C', 3.5f}};
    auto sec = ranges::fold_left_with_iter
    (
        data | ranges::views::values, 2.0f, std::multiplies<>()
    );
    assert(sec.value == 42);
    
    // Use a program defined function object (lambda-expression):
    auto lambda = [](int x, int y){ return x + 0B110 + y; };
    auto val = ranges::fold_left_with_iter(v, -42, lambda);
    assert(val.value == 42);
    assert(val.in == v.end());

    using CD = std::complex<double>;
    std::vector<CD> nums{{1, 1}, {2, 0}, {3, 0}};
    #ifdef __cpp_lib_algorithm_default_value_type
        auto res = ranges::fold_left_with_iter(nums, {7, 0}, std::multiplies{});
    #else
        auto res = ranges::fold_left_with_iter(nums, CD{7, 0}, std::multiplies{});
    #endif
    assert((res.value == CD{42, 42}));
}

Ссылки

  • Стандарт C++23 (ISO/IEC 14882:2024):
    • 27.6.18 Свёртка [alg.fold]

См. также

ranges::fold_left
(C++23)
выполняет свёртку диапазона элементов слева
(функциональный объект алгоритма)
ranges::fold_left_first
(C++23)
выполняет свёртку диапазона элементов слева, используя первый элемент в качестве начального значения
(функциональный объект алгоритма)
ranges::fold_right
(C++23)
выполняет свёртку диапазона элементов справа
(функциональный объект алгоритма)
ranges::fold_right_last
(C++23)
выполняет свёртку диапазона элементов справа, используя последний элемент в качестве начального значения
(функциональный объект алгоритма)
ranges::fold_left_first_with_iter
(C++23)
выполняет свёртку диапазона элементов слева, используя первый элемент в качестве начального значения, и возвращает пару (итератор, optional)
(функциональный объект алгоритма)
accumulate
суммирует элементы диапазона или выполняет их свёртку
(шаблон функции)
reduce
(C++17)
аналог std::accumulate, за исключением того, что операции выполняются не по порядку
(шаблон функции)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/algorithm/ranges/fold_left_with_iter

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API