Диапазон на основе l oop: перебрать вектор, расширенный одним элементом - PullRequest
1 голос
/ 18 февраля 2020

Я хочу добиться более менее эквивалентного этому Python кода на C ++ (но более эффективного использования памяти):

a = [1, 5, 3]
additional = 6
for elem in [additional] + a:
    print(elem) # prints: 6 1 5 3

# alternative without creating the additional vector:
import itertools
for elem in itertools.chain([additional], a):
    print(elem)

Единственный известный мне способ сделать это в C ++:

#include <iostream>
#include <vector>

int main() {
        std::vector<int> a = {1, 5, 3};
        int additional = 6;

        for (int i = 0; i < a.size() + 1; ++i) {
                int cur_elem;
                if (i == 0) {
                        cur_elem = additional;
                } else {
                        cur_elem = a[i-1];
                }
                std::cout << cur_elem << std::endl;
        }
}

Есть ли способ сделать это с диапазоном, основанным на l oop? Я нашел оператор Boost join, но, похоже, он использует только итерации, поэтому мне нужно создать дополнительный вектор (как в примере Python).

В идеале, итерация была бы без создания объединенного объекта в память и алгоритмы стандартной библиотеки.

1 Ответ

6 голосов
/ 18 февраля 2020

Это можно сделать с помощью функции предстоящих диапазонов.

Вот пример использования библиотеки Eri c Ниблера range-v3:

#include <iostream>
#include <vector>

#include <range/v3/view/concat.hpp>
#include <range/v3/view/single.hpp>

int main() {
    std::vector<int> a = {1, 5, 3};
    int additional = 6;
    for (auto i : ranges::concat_view(ranges::single_view{additional}, a)) {
        std::cout << i;
    }
}

Смотрите вживую!

при использовании представлений все операции итератора являются ленивыми, и дополнительная память не используется (например: дополнительные векторы / массивы не создаются)

Или без for l oop:

ranges::copy(ranges::concat_view(ranges::single_view{additional}, a), ranges::make_ostream_joiner(std::cout, ","));

Смотрите это в прямом эфире!

(Честно говоря, мне больше нравится версия for, хотя)

Стандартно-совместимое решение

Существует небольшая проблема с вышеприведенным решением: concat_view не попало в C ++ 20. Если вы хотите строго совместимое решение, вы можете создать собственную версию или использовать join_view вместо:

#include <iostream>
#include <vector>

#include <ranges>

int main() {
    std::vector<int> a = {1, 5, 3};
    int additional = 6;

    std::vector v{{additional}, a};

    for(int i : std::ranges::join_view{v}) {
        std::cout << i;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...