Лучший способ перебрать целый ряд целых чисел?

Поскольку в C++11 введен цикл for, основанный на диапазоне (на основе диапазона в C++11), каков наилучший способ выражения цикла для целого ряда?

Вместо

for (int i=0; i<n; ++i)

Я хотел бы написать что-то вроде

for (int i : range(0,n))

Поддерживает ли новый стандарт что-либо подобное?

Обновление: эта статья описывает, как реализовать генератор диапазона в C++11: Генератор в C++

6 ответов

Решение

Хотя вы не можете сделать это с чистым C++ (с текущими возможностями стандартной библиотеки C++), вы можете сделать это с помощью boost:

#include <boost/range/irange.hpp>
#include <iostream>

using namespace boost;
using namespace std;

int main(int argc, char **argv)
{
    for(auto i : irange(1, 10))
        cout << i << "\n";
    return 0;
}

более того, Boost.Range содержит еще несколько интересных диапазонов, которые вы можете найти довольно полезными при использовании с новым for петля. Например, с Boost.Range вы можете сделать обратное for петля.

С C++20у нас будут диапазоны. Вы можете попробовать их, загрузив последний стабильный выпуск от его автора, Эрика Ниблера, с его гитхаба или зайдя в Wandbox. Вас интересуетranges::views::iota, что делает этот код законным:

#include <range/v3/all.hpp>
#include <iostream>

int main() {
    using namespace ranges;

    for (int i : views::iota(1, 10)) {
        std::cout << i << ' ';
    }
}

В этом подходе замечательно то, что views являются ленивыми. Это означает, что даже еслиviews::iota представляет собой диапазон от 1 к 10 эксклюзив, не более одного intиз этого диапазона существует в одной точке. Элементы создаются по запросу.

Лучший способ до сих пор это:

for (int i=0; i<n; ++i)

Я думаю, вы можете сделать это, но я бы не назвал это так аккуратно:

#include <iostream>

int main()
{
  for ( auto i : { 1,2,3,4,5 } )
  {
    std::cout<<i<<std::endl;
  }
}

Если вы не против выполнить цикл в обратном порядке, вы можете заменить

for (int i=0; i<n; ++i)

с более простым

for (int i=n; i--;)

В зависимости от того, что вы должны делать с целым числом, рассмотрите также <numeric> заголовок, в частности std::iota в сочетании с std::transform и std::fill в зависимости от случаев.

Что ж, мне очень нравится решение, представленное здесь (извините, оно не переведено на английский):

      #define FOR(I,UPPERBND) for(int I = 0; I<int(UPPERBND); ++I)

Основная идея описывается так: когда мы говорим о простых индексированных циклами итераций, нам не нужно об этом думать. Однако, когда мы используем конструкцию for(;;), всегда есть три шага: инициализация, проверка конечного условия, итерация. И это перебор для такого простого цикла, как просто i:[0,n). Мне понравилась идея, что мы хотим писать простые вещи простым способом. Когда вы видите это FOR(i,N) - вы просто понимаете, что в этом нет ничего особенного. Когда вы видите конструкцию for(;;) - нужно быть внимательнее и увидеть все три ее части. Просто пример из той статьи:

      for (int iter=0; iter<nb_iter; iter++) {          // some iterative computation
    for (int c=0; c<mesh.cells.nb(); c++)         // loop through all tetrahedra
        for (int lv0=0; lv0<4; lv0++)             // for every pair of
            for (int lv1 = lv0+1; lv1<4; lv1++)   // vertices in the tet
                for (int d=0; d<3; d++) {         // do stuff for each of 3 dimensions
                    nlRowScaling(weight);
                    nlBegin(NL_ROW);
                    nlCoefficient(mesh.cells.vertex(c, lv0)*3 + d,  1);
                    nlCoefficient(mesh.cells.vertex(c, lv1)*3 + d, -1);
                    nlEnd(NL_ROW);
                }
    [...]
}

стать:

      FOR(iter, nb_iter) {
    FOR(c, mesh.cells.nb())
        FOR(lv0, 4)
            for (int lv1 = lv0+1; lv1<4; lv1++)
                FOR(d, 3) {
                    nlRowScaling(weight);
                    nlBegin(NL_ROW);
                    nlCoefficient(mesh.cells.vertex(c, lv0)*3 + d,  1);
                    nlCoefficient(mesh.cells.vertex(c, lv1)*3 + d, -1);
                    nlEnd(NL_ROW);
                }
    [...]
}

И вы видите, на чем следует сосредоточить свое внимание.

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