Как суммировать std::range?

Есть ли способ суммировать диапазон С++ 20, кроме итерации по нему?

Я решаю задачи из Project Euler, чтобы улучшить свои навыки C++, и хотел решить задачу 37 с помощью библиотеки std::ranges.

Мой код выглядит примерно так:

#include <iostream>
#include <ranges>
#include <numeric>

using namespace std;

bool is_truncatable(const int n)
{
    // Blah blah...
}

int truncatable_primes()
{
    const auto range = views::iota(10); // Goes on to infinity.
    const int total_num_of_truncatable_primes = 11; // Given.
    auto all_truncatable_primes = range | views::filter([] (int n) { return is_truncatable(n); }) 
                                        | views::take(total_num_of_truncatable_primes);
    
    const int sum = accumulate(all_truncatable_primes.begin(), all_truncatable_primes.end(), 0); // Does not compile.

    return sum;
}

int main()
{
    const auto answer = truncatable_primes();
    cout << answer << endl;

    return EXIT_SUCCESS;
}

Поскольку диапазона ranges::accumulate пока нет, существует ли идиоматический способ суммировать диапазон all_truncatable_primes, или я вынужден использовать цикл for?

std::ranges::fold_left(rng, 0, std::plus<>{});. Для непустых диапазонов есть fold_right и fold_left_first. Но это C++23.
Red.Wave 26.06.2024 18:49
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
135
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете добавить | views::common, чтобы его можно было использовать со стандартным алгоритмом:

auto all_truncatable_primes = range | views::filter([] (int n) { return is_truncatable(n); }) 
                                    | views::take(total_num_of_truncatable_primes)
                                    | views::common;

const int sum = accumulate(all_truncatable_primes.begin(), all_truncatable_primes.end(), 0);

Демо

Ответ принят как подходящий

all_truncatable_primes не является common_range, а это означает, что его begin() и end() имеют разные типы.

Это несовместимо с алгоритмами C++98, которые требуют, чтобы оба были одного типа (например, std::accumulate). Один из вариантов — применить views::common, чтобы сделать common_range:

auto all_truncatable_primes = range | views::filter([] (int n) { return is_truncatable(n); }) 
                                    | views::take(total_num_of_truncatable_primes)
                                    | views::common;
const int sum = accumulate(all_truncatable_primes.begin(), all_truncatable_primes.end(), 0);

Более подходящий способ — использовать C++23 ranges::fold_left, который можно рассматривать как версию диапазона std::accumulate:

auto all_truncatable_primes = range | views::filter([] (int n) { return is_truncatable(n); }) 
                                    | views::take(total_num_of_truncatable_primes);
const int sum = ranges::fold_left(all_truncatable_primes, 0, std::plus{});

Другие вопросы по теме

Как распечатать неструктурные результаты функций constexpr во время компиляции с помощью clang++?
Почему take(n), используемый в istream_view, приводит к пропуску следующего токена в C++20?
Почему объявление функции глобальной области со встроенным типом arg должно быть видимым перед неквалифицированным вызовом этого имени с аргументом типа шаблона?
Есть ли способ отсортировать одну переменную-член в коллекции структур с помощью стандартной библиотеки C++?
Не могу создать std::ranges::subrange с помощью моего итератора
Трехстороннее сравнение по умолчанию генерирует больше кода, чем ожидалось
C++20 и новее – как лучше всего реализовать «перечисление с большей функциональностью»?
Неожиданный результат с `std::views::transform`, вероятно, вызван "безымянным временным"
Неявные варианты выражения понятия обрабатываются неправильно?
Где из стандарта я прочитал, что исключения производного класса, хранящиеся по ссылке на базовый класс, отсекаются при обнаружении?