Подтвердить что ты не робот

Почему так сложно записывать for-loop в С++ с двумя переменными цикла?

Возможный дубликат:
In C++ why can’t I write a for() loop like this: for( int i = 1, double i2 = 0; …

Разработчик C C написал бы это:

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

Разработчик С++ написал бы это, чтобы предотвратить переполнение переменной цикла за пределами цикла:

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

Однако, если у вас есть 2 переменные цикла, вы больше не сможете этого делать. Не компилируется следующее:

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

Оператор запятой не позволяет определить две переменные таким образом, поэтому мы должны записать это следующим образом:

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

Побеждает преимущество наличия реальных локальных переменных цикла.

Решение может заключаться в том, чтобы поместить всю конструкцию между фигурными скобками, например:

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

Но это вряд ли более элегантно.

Нет ли лучшего способа сделать это в С++ (или С++ 0x)?

4b9b3361

Ответ 1

Вам просто нужно понять, что первый оператор - это объявление (и эта запятая не является оператором запятой). Это не сложнее сделать:

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

Чем оно:

int i, double d;

Потому что for (init cond; expr) statement расширяется до:

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

Трюк заключается в том, чтобы сделать оператор init конструктивным определением и экземпляром, например:

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

Что становится таким же, как:

{
    struct
    {
        int myIndex;
        MyElement* ptr;
    } data = {0, Pool->First};

    while (data.ptr)
    {
        {
            // blah...
        }
        ++data.myIndex, data.ptr = data.ptr->next;
    }
}

Но я нахожу это довольно уродливым. На практике я бы просто разделил его так, как ты. Если область действия действительно является проблемой, которой она, вероятно, не является, добавьте дополнительные фигурные скобки.

Я не думаю, что здесь можно многое улучшить без небольшого шаблона кода.

Ответ 2

Если бы я действительно хотел ограничить область охвата цикла, я бы использовал:

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

Ответ 3

По крайней мере, С++ позволяет объявлять переменные в предложении if, которое иногда используется для объявления переменной, которая видна только тогда, когда какое-либо условие истинно:

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.

Это может быть метод ограничения объема ptr и индекса при сохранении читаемости.