4

Consider the following code:

vector<int> v;
for(vector<int>::iterator vi = n.begin(), int i = 0;
    vi != n.end();
    ++vi, ++i){}

Is there a reason why this is not allowed? I want to be able to define 2 new counters, both vi and the index i.

Henry Henrinson
  • 5,203
  • 7
  • 44
  • 76
  • The standard forbids it. – Luchian Grigore Oct 21 '13 at 14:37
  • Excellent answer Luchian. Can you expand? – Henry Henrinson Oct 21 '13 at 14:38
  • 5
    You can declare multiple objects of the same type, but not of different types. The allowed syntax is `for(T a=x, b=y, c=z; ...)`. Can't really say why. – juanchopanza Oct 21 '13 at 14:39
  • A closely related (duplicate?) topic can be found at http://stackoverflow.com/q/8783896/1945549. For what it's worth you can of course declare one or both counters before the loop and it'll work. But that isn't satisfying in terms of keeping the variables local to the loop. – Roland Sarrazin Oct 21 '13 at 14:41
  • Are you interested in workarounds or just want to know the reason this is not allowed? – jrok Oct 21 '13 at 14:45
  • @jrok Both, really. I don't really udnerstand why this is not allowed and, on the topic of workaroudn, I assume you can just define the variable outside (but that's a bit inelegant) – Henry Henrinson Oct 21 '13 at 14:48
  • Duplicate. [See this](http://stackoverflow.com/questions/8100051/for-loops-init-statement-with-two-types-of-variable) – smRaj Oct 21 '13 at 15:03
  • If you really want to initialise it in the `for` statement then you can use a `tuple`: `for (auto i = std::make_tuple(n.begin(), 0); ...` – Simple Oct 21 '13 at 15:39

6 Answers6

4

This is the explanation from the book C++ Primer:

As in any other declaration, init-statement can define several objects. However, init-statement may be only a single declaration statement. Therefore, all the variables must have the same base type. As one example, we might write a loop to duplicate the elements of a vector on the end as follows:

// remember the size of v and stop when we get to the original last element

for (decltype(v.size()) i = 0, sz = v.size(); i != sz; ++i)

    v.push_back(v[i]);

In this loop we define both the index, i, and the loop control, sz, in init-statement.

This makes sense, the syntax of for loop is:

C++11 §6.5.3 The for statement [stmt.for]

The for statement

for ( for-init-statement ; condition opt ; expression opt ) statement

for-init-statement is one statement only. Declaration two different types of variables would make it at least two statements.

Community
  • 1
  • 1
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
2

If you want to use two variables of differing type in a for loop, one must be declared outside the scope of the for loop. You can enforce the scope of the second one by enclosing the loop inside a set of braces:

vector<int> v;
{
int i = 0;
for(vector<int>::iterator vi = n.begin(); vi != n.end(); ++vi, ++i) { /* DO STUFF */ }
} //i's scope ends here.
Casey
  • 10,297
  • 11
  • 59
  • 88
2

Is there a reason why this is not allowed?

Because the arcane declaration syntax of C++ doesn't allow you to declare objects of unrelated types in the same declaration statement; and the initialiser of a for loop only allows a single declaration statement.

I want to be able to define 2 new counters, both vi and the index i.

You could declare one or both outside the loop, if you don't mind polluting the surrounding block. Otherwise, you could put them in a stucture:

for (struct {vector<int>::iterator vi; int i;} x = {n.begin(), 0}; 
     x.vi != n.end();
     ++x.vi, ++x.i) {}
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
2

The answer is "there isn't really any reason other than the syntax requires it".

I can imagine, though, that code could get very complex if it were allowed, so that's a good reason not to add support for this into the language.

You can create your own scope to bound it instead:

std::vector<int> v;
{
   std::vector<int>::iterator it = n.begin(), end = n.end();
   int i = 0;

   for ( ; it != end; ++it, ++i)
   {}
}
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
1

You can only write one declaration statement, but it can define multiple variables, e.g.:

for ( int i = 0, j = 10 ; ... )
Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
0

A look at the comma operator wikipedia page would help, specifically the first example.

int a=1, b=2, c=3, i=0; // comma acts as separator in this line, not as an operator 

Also, why not do something like this?

vector<int> v;
vector<int>::iterator vi = n.begin();
int i = 0;
for(; vi != n.end(); ++vi, ++i)
{
}
Alden
  • 2,229
  • 1
  • 15
  • 21