Daily bit(e) C++. std::ranges::fold_left_with_iter, std::ranges::fold_left_first_with_iter
Добавлено 5 октября 2026 в 16:14
Daily bit(e) C++ 137, алгоритмы свертки C++23 для диапазонов с граничным условием (sentinel ranges) – std::ranges::fold_left_with_iter и std::ranges::fold_left_first_with_iter.

std::ranges::fold_left_with_iter и std::ranges::fold_left_first_with_iter – это альтернативные версии алгоритмов fold_left, которые дополнительно возвращают вычисленный итератор конца диапазона.
Это оказывается полезным в тех случаях, когда конец диапазона определяется с помощью граничного условия. Полученный итератор конца можно использовать повторно, избегая необходимости вычислять его заново.
#include <algorithm>
#include <vector>
#include <ranges>
#include <concepts>
// Утилита для получения базового типа вложенного итератора
template <typename T>
auto absolute_base(T t)
{
if constexpr (requires (T t)
{
{ t.base() } -> std::same_as<typename T::iterator_type>;
}) return absolute_base(t.base()); else return t;
}
std::vector<int> data{1,2,3,4,5,6,7,8,9};
// представление без последних 3 элементов
constexpr auto view = std::views::reverse | std::views::drop(3) |
std::views::reverse;
auto [it, value] = std::ranges::fold_left_with_iter(data | view,
0, std::plus<>{});
// value == 21 (0+1+2+3+4+5+6)
// "it" - это реверсивный итератор реверсивного итератора;
// мы не можем написать it == data.end(),
// но можем написать absolute_base(it) == data.end()
for (auto v : std::ranges::subrange(absolute_base(it), data.end()))
{
// обработка оставшейся части диапазона
// итерация по {7, 8, 9}
}
