• 13
• 15
• 27
• 9
• 9

# "Automatic" fill

This topic is 2671 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi,
Im testing the fill <algorithm> command.
I want to fill a vector of five elements with numbers 1 - 5.
I think a for loop could do this. But there is a problem:

vector<int> vec(5);
for(int f = 1; f < 5; ++f)
{
fill( vec.begin()+(--f), vec.end(), f );
}

As you can see I want to start at position 0, and with the val 1. Then it should
automatically assign each value every iteration.
Logically I think it would work, but instead it becomes an endless loop.
I know I could do one more value and it would work, but do you see any thinner solution or answer? Thanks!

##### Share on other sites
Think logically about what the '--f' is doing in that loop and you'll soon realise why it becomes an infinite loop.

I'm pretty sure you have a nice chunk of undefined behaviour there as well with the args to the 'fill' function; if memory serves the order parameters are evaluated aren't fixed, and I'm pretty sure the access/modification to 'f' is undefined as well (lack of sequence points).
(Someone correct me if I'm wrong here).

##### Share on other sites
Why are you trying to use std::fill() here? Using std::fill() to set the value for a single element seems rather silly.

##### Share on other sites
When you fix that, be sure to change your loop condition either to f<=5 or f < 6. Otherwise you'll only get the numbers 1 -> 4.

##### Share on other sites
vector<int> vec(5);int f = 1;for(auto it = vec.begin(); it != vec.end(); ++it){    *it = f++;}

##### Share on other sites
Quote:
 Original post by Chris_Fvector vec(5);int f = 1;for(auto it = vec.begin(); it != vec.end(); ++it){ *it = f++;}

You can simplify it even more if you're going to use C++0x, by using initializer lists (assuming compiler support is there currently):

std::vector<int> vec = {1, 2, 3, 4, 5};

##### Share on other sites
From your answers I think I now know why it doesn't work, the for-loop is
a statement in which a formal parameter always increment it's own scope no matter if you try to use it just for positioning instructions only:

fill(vec.begin() + 0, vec.end(), 1)
->
fill(vec.begin() + 4, vec.end(), 5)
---------------------------------- =
fill(vec.begin() +(--f), vec.end(), f)

Besides your examples, this also works well :
fill(vec.begin()+f, vec.end(), f + 1)

But is it someway possible to make use of "icrementing / decrementing instructions" in iterative loops at all?

##### Share on other sites
Basically you are just trying to use an algorithm for something that it is not supposed for. Why use a O(n*n) algorithm for a O(n) operation?

There are many better ways, e.g using a counting_iterator from boost.

#include <vector>#include <boost/iterator/counting_iterator.hpp>#include <iostream>#include <algorithm>#include <iterator>int main(){    std::vector<int> vec(5);    std::copy(boost::make_counting_iterator(1), boost::make_counting_iterator(6), vec.begin());    std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));    std::cout << '\n';}

##### Share on other sites
I didn't understand what the OP problem is, sorry.

I just wanted to point out that this statement is undefined behavior:
fill( vec.begin()+(--f), vec.end(), f );

You are modifying f and using it in another part of the expression, without a sequence point in between.

##### Share on other sites
The purpose of std::fill is to assign the same value to many elements of a sequence.

What you are trying to do is assign a different value to each of several elements, following some rule. The natural choice of standard library algorithm for this is std::generate.

The example of std::generate given in this doc even solves your specific problem.

You can also use a "counting iterator" (via third-party tools, or rolling it yourself) as shown in visitor's code. The idea is that we have objects that obey the iterator interface while pretending to "iterate" over a virtual, not-actually-existing "container" of all the integers in order; then we use the standard library algorithm std::copy to copy from this virtual container into a real one in order to get a sequence of real elements.

The infinite loop in your code is caused by the fact that '--f' changes the value of f in addition to simply producing the value used in your calculation. This cancels out the '++f' in the for-loop clause, so each time through the loop, 'f' has the same value, and the loop-exit condition is never met.

EDIT: Except for the part where, as alvaro correctly points out, this actually invokes undefined behaviour, although all practical compilers would produce something that ends up in an infinite loop (it's just that the actual effects on the container might vary).