16

Possible Duplicate:
In C++ why can’t I write a for() loop like this: for( int i = 1, double i2 = 0; …

A C developer would write this:

int myIndex; for (myIndex=0;myIndex<10;++myIndex) ... 

A C++ developer would write this to prevent the loop variable from leaking outside the loop:

for (int myIndex=0;myIndex<10;++myIndex) ... 

However, if you have 2 loop variables, you cannot do this anymore. The following doesn't compile:

for (int myIndex=0,MyElement *ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ... 

The comma operator does not allow two variables to be defined this way, so we have to write it like this:

int myIndex; MyElement *ptr; for (myIndex=0,ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ... 

Which defeats the advantage of having real loop-local variables.

A solution could be to put the whole construction between braces, like this:

{ int myIndex; MyElement *ptr; for (myIndex=0,ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ... } 

But this is hardly more elegant.

Isn't there a better way of doing this in C++ (or C++0x)?

4
  • 1
    Why would a C programmer necessarily put the variable above the loop? Commented Aug 9, 2010 at 12:46
  • 7
    @GMan Declaring it inside the for statement is only valid since C99, IIRC Commented Aug 9, 2010 at 12:47
  • 7
    @Wim: Which was 11 years ago. :) Commented Aug 9, 2010 at 12:54
  • 3
    As myIndex is not part of the conditional test I personally think it is bad style to put in inside the for(;;) it just makes the code hard to read. Commented Aug 9, 2010 at 13:24

3 Answers 3

23

You just have to understand the first statement is a declaration (and that comma is not the comma operator). It's not any harder to do:

for (int i, double d; ...) 

Than it is:

int i, double d; 

Because for (init cond; expr) statement gets expanded to:

{ init while (cond) { statement expr; } } 

A trick is to make that init statement a struct definition and instance, like:

for (struct { int myIndex; MyElement* ptr;} data = {0, Pool->First}; data.ptr; ++data.myIndex, data.ptr = data.ptr->next) { // blah... } 

Which becomes the same as:

{ struct { int myIndex; MyElement* ptr; } data = {0, Pool->First}; while (data.ptr) { { // blah... } ++data.myIndex, data.ptr = data.ptr->next; } } 

But I find that pretty ugly. In practice, I'd just split it up like you have. If scope is really a problem, which it probably isn't, throw the extra braces around there.

I don't think there's much to improve here without a bit of boilerplate code.

Sign up to request clarification or add additional context in comments.

8 Comments

Oh that's an ugly solution, I'm kinda glad I didn't think of it. :-) I too much prefer putting the loop in its own block.
Answer accepted. There doesn't seem a more elegant way than defining the variables outside the for-loop and putting the whole block between braces.
+1 for thinking outside the box! But yes, ugly! :-)
@Martin: Note that an init statement ends with ;, so putting it into the equivalence is redundant/erroneous. (See §6.5.3.)
@GMan: Sorry. :-)
|
8

If I really wanted to confine the scope to the loop I would use:

#include <utility> for (auto i = std::make_pair(0,Pool->First); i.second; ++i.first, i.second=i.second->next) 

3 Comments

But now you loose all the information that was given by the variables names: i.first and i.second do not convey any information about the purpose of the variables, whereas myIndex and ptr give some (not a lot, but some).
Yes, there is a tradeoff to make here - I would say it is the standard tradeoff when using pair. If the purpose of the pair members is evident I would stick to pair. If not I would switch to a solution with explicit names.
@LucTouraille: you can always define a small struct for this in place of std::pair<>..
2

At least C++ allows us to declare variables in the if clause, which which is sometimes used to declare a variable that only is only visible when some condition is true:

if (MyElement *ptr=Pool->First) // block is only entered when ptr!=0 { for (int myIndex=0;ptr;++myIndex,ptr=ptr->next) { } } // ptr is out of scope now. 

This could be a method to limit the scope of ptr and index, while maintaining readability.

2 Comments

There is really no need for the if statement. You can add braces (almost) anywhere you like to set up a new scope.
The if() for() ... pattern works also well with macros.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.