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.

Daily bit(e) C++

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}
}

Пример на Compiler Explorer

Теги

C++ / CppDaily bit(e) C++Программирование