Personally, my initial reading:
std::generate(numbers.begin(), numbers.end(), rand);
: "We assign everything in the range. The range of numbers . The values assigned are random."
My initial reading:
for (int& x : numbers) x = rand();
- "we do something in everything in the range. The range of numbers . We do the assignment of a random value."
It is pretty darn similar, but not identical. One of the plausible reasons why I could provoke the first reading is because I think the most important fact in this code is that it assigns to a range. So, "why I want ...". I use generate because in c ++ std::generate means "range assignment". Since btw does std::copy , the difference between the two is what you assign.
However, there are confounding factors. For range-based loops, there is a more direct way to express that range of
numbers than iterator-based algorithms. This is why people work on range-based algorithm libraries:
boost::range::generate(numbers, rand); Looks better than the
std::generate version.
In contrast, int& in your range-based loop is a wrinkle. What if the value type of the range is not int , then we are doing something annoyingly subtle here, which depends on its being converted to int& , while the generate code depends only on the return from rand assigned to the element. Even if the value type is int , I can still stop thinking about whether it is or not. Therefore, auto , which diverts attention to types until I see what is assigned, with auto &x I say: "Take a reference to a range element, no matter what type it is." Back in C ++ 03, algorithms (because they are function templates) were a way to hide exact types, now this is a way.
I think it has always been that simplest algorithms have only a slight advantage over equivalent loops. Ranges for loops improve the contours (basically, removing most of the pattern, although a little more for them). Thus, margins become more stringent and you may change your mind in some specific cases. But there is still a difference in style.