Algorithm solution:
std::generate(numbers.begin(), numbers.end(), rand);
Range-based for-loop solution:
for (int& x : numbers) x = rand();
Why would I want to use the more verbose std::generate
over range-based for-loops in C++11?
Whether the for loop is range based or not does not make a difference at all, it only simplifies the code inside the parenthesis. Algorithms are clearer in that they show the intent. |
|||
|
In my opinion, the manual loop, though might reduce verbosity, lacks readabitly:
I would not use this loop to initialize1 the range defined by numbers, because when I look at it, it seems to me that it is iterating over a range of numbers, but in actuality it does not (in essence), i.e instead of reading from the range, it is writing to the range. The intent is much clearer when you use 1. initialize in this context means to give meaningful value to the elements of the container. |
|||||||||||||||||||||
|
The first version
tells us that you want to generate a sequence of values. In the second version the reader will have to figure that out himself. Saving on typing is usually suboptimal, as it is most often lost in reading time. Most code is read a lot more than it is typed. |
|||||||||||||||||||||
|
In my opinion, Effective STL Item 43: "Prefer algorithm calls to hand-written loops." is still a good advice. I usually write wrapper functions to get rid of the
I believe it beats the range based for loop both in communicating the intent and in readability. Having said that, I must admit that in C++98 some STL algorithm calls yielded unutterable code and following "Prefer algorithm calls to hand-written loops" did not seem like a good idea. Luckily, lambdas have changed that. Consider the following example from Herb Sutter: Lambdas, Lambdas Everywhere. Task: Find first element in v that is Without lambdas:
With lambda
|
|||||||||||||
|
My answer would be maybe and no. If we're talkinng about C++11, then maybe (more like no). For example
But using range-based for is a lot better:
On the other hand, if we're talking about C++1y, then I would argue that no, the algorithms will not be obsoleted by range based for. In C++ standard committee there is a study group that is working on a proposal to add ranges to C++, and also there is work being done on polymorphic lambdas. Ranges would remove the need to use pair of iterators and polymorphic lambda would let you to not specify exact argument type of lambda. This means that
|
|||||||||||||||
|
Personally, my initial reading of:
is "we're assigning to everything in a range. The range is My initial reading of:
is "we're doing something to everything in a range. The range is Those are pretty darn similar, but not identical. One plausible reason I might want to provoke the first reading, is because I think the most important fact about this code is that it assigns to the range. So there's your "why would I want to...". I use There are confounding factors, though. Range-based for loops have an inherently more direct way of expressing that the range is As against that, I think it has always been the case that the simplest algorithms have only a marginal benefit over the equivalent loops. Range-based for loops improve loops (primarily by removing most of the boilerplate, although there's a little more to them than that). So the margins draw tighter and perhaps you change your mind in some specific cases. But there's a still a style difference there. |
|||||||||||||
|
There are some things you cannot do (simply) with range-based loops that algorithms that take iterators as input can.
For example with Fill the container up to
Iterator-based algorithms give you a better control on the range you are operating on. |
|||||
|
For the particular case of That said, I've have another reason to not throw away the std::algorithm - there are certain algorithms which are specialized for some data types. The simplest example would be So I'm trying to play an efficiency card here. Your hand-written loop might be as fast as a std::algorithm version, but it can hardly be faster. And more than that, std::algorithm may be specialized for particular containers and types and it's done under the clean STL interface. |
||||
|
One thing that should be noticed is that an algorithm express what is done, not how. Range-based loop include the way things are done: start with the first, apply and go next element until the end. Even a simple algorithm could do things differently (at least some overloads for specific containers, not even thinking about the horrible vector), and at least the way it is done is not the writer business. TO me that's much of the difference, encapsulate as much as you can, and that justifies the sentence when you can, use algorithms. |
|||
|
Range-based for-loop is just that. Until of course standard is changed. Algorithm is a function. A function which puts some requirements on its parameters. The requirements are phrased in a standard to allow for example implementation that takes advantage of all available execution threads and will speed you up automatically. |
|||
|
begin()
andend()
? – the_mandrill Jan 10 at 13:15range
function in their toolbox by now. (i.e.for(auto& x : range(first, last))
) – R. Martinho Fernandes Jan 10 at 13:15boost::generate(numbers, rand); // ♪
– Xeo Jan 10 at 13:20