Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it so 'hard' to write a for-loop in C++ with 2 loop variables? [duplicate]

Tags:

c++

c++11

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)?

like image 486
Patrick Avatar asked Aug 09 '10 12:08

Patrick


People also ask

Can we use 2 variables in for loop in C?

Yes, by using the comma operator. E.g. for (i=0, j=0; i<10; i++, j++) { ... }

Can multiple initializations and multiple increments decrements be done in a for loop?

No, you can only have one initializing statement.

Can you initialize more than one variable in a for loop?

In Java, multiple variables can be initialized in the initialization block of for loop regardless of whether you use it in the loop or not.


2 Answers

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.

like image 125
GManNickG Avatar answered Sep 20 '22 12:09

GManNickG


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)
like image 28
Peter G. Avatar answered Sep 19 '22 12:09

Peter G.