Reputation: 1421
Since C++11 introduced the range-based for loop (range-based for in c++11), what is the neatest way to express looping over a range of integers?
Instead of
for (int i=0; i<n; ++i)
I'd like to write something like
for (int i : range(0,n))
Does the new standard support anything of that kind?
Update: this article describes how to implement a range generator in C++11: Generator in C++
Upvotes: 69
Views: 68099
Reputation: 13444
With C++20
we will have ranges. If you don't have access to C++20, you can try them out by downloading the lastest stable release from it's author, Eric Niebler, from his github, or go to Wandbox. What you are interested in is ranges::views::iota
, which makes this code legal:
#include <range/v3/view/iota.hpp>
#include <iostream>
int main() {
using namespace ranges;
for (const int i : views::iota(1, 10)) {
std::cout << i << ' ';
}
}
What's great about this approach is that view
s are lazy. This means that even though views::iota
represents a range from 1
to 10
exclusive, no more than one int
from that range exists at a given time. The elements are generated on demand.
If you do have access to C++20, this version works out of the box:
#include <ranges>
#include <iostream>
int main() {
for (const int i : std::views::iota(1, 10)) {
std::cout << i << ' ';
}
}
Upvotes: 47
Reputation: 16
Well, I really like the solution, provided here (I'm sorry, it's not translated in English):
#define FOR(I,UPPERBND) for(int I = 0; I<int(UPPERBND); ++I)
The main idea is described in this way: when we talk about simple iteration-indexed-cycles, we do not need to think about it. However, when we use for(;;) construction- there are always three steps: initialization, end condition check, iteration. And this is an overkill for such a simple loop, as just i:[0,n). I liked the idea, that we want to write simple things in a simple way. When you see that FOR(i,N) - you just know, that there are nothing special. When you see the for(;;) construction - you have to be more careful and see all three parts of it. Just an example from that article:
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);
}
[...]
}
become a:
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);
}
[...]
}
And you see, where you should concentrate your attention.
Upvotes: -5
Reputation: 1296
If you don't mind doing the loop in reverse order, you can replace
for (int i=0; i<n; ++i)
with simpler
for (int i=n; i--;)
Upvotes: 4
Reputation: 13718
While its not provided by C++11, you can write your own view or use the one from boost:
#include <boost/range/irange.hpp>
#include <iostream>
int main(int argc, char **argv)
{
for (auto i : boost::irange(1, 10))
std::cout << i << "\n";
}
Moreover, Boost.Range
contains a few more interesting ranges which you could find pretty useful combined with the new for
loop. For example, you can get a reversed view.
Upvotes: 39
Reputation: 20769
Depending on what you have to do with the integer, consider the also the <numeric>
header, in particular
std::iota
in conjunction with std::transform
and std::fill
depending on the cases.
Upvotes: 0
Reputation: 64303
The neatest way is still this:
for (int i=0; i<n; ++i)
I guess you can do this, but I wouldn't call it so neat:
#include <iostream>
int main()
{
for ( auto i : { 1,2,3,4,5 } )
{
std::cout<<i<<std::endl;
}
}
Upvotes: 43