Почему & quot; путь конструктора & quot; объявления переменной в «for-loop»; разрешено, но в «операторе if» не положено?

Возможный дубликат:
Почему переменные, определенные в условном выражении, не могут быть построены с аргументами?

Рассмотрим этот простой пример:

/*1*/ int main() {
/*2*/   for (int i(7); i;){break;}
/*3*/   if (int i(7)) {}
/*4*/ }

Почему строка-2 прекрасно компилируется, а строка-3 выдает ошибку? Это немного странно для меня, почему оператор if в этом аспекте трактуется хуже, чем цикл for?

Если это зависит от компилятора — я проверил с GCC-4.5.1:

prog.cpp: в функции ‘int main ()’:
prog.cpp: 3: 7: ошибка: ожидаемое первичное выражение перед int
prog.cpp: 3: 7: ошибка: ожидается «)» перед «int»

Я был вдохновлен этим вопрос

[ОБНОВИТЬ]

Я знаю, что это прекрасно компилируется:

/*1*/ int main() {
/*2*/   for (int i = 7; i;){break;}
/*3*/   if (int i = 7) {}
/*4*/ }
[UPDATE2]

Кажется, это чисто академический вопрос — но это может быть чрезвычайно важно для таких типов, как std::unique_ptr<> который не может быть скопирован:

#include <memory>
int main() {
if (std::unique_ptr<int> i = new (std::nothrow) int(7)) {
}
if (std::unique_ptr<int> i(new (std::nothrow) int(7))) {
}
}

Ни один из этих двух видов не допускается. Не уверен насчет нового синтаксиса C ++ 11 {}?

15

Решение

Стандарт C ++ не дает обоснования, но я подозреваю, что использование нотации конструктора может вызвать некоторые несоответствия. Например, поскольку объявления функций в if Утверждение, самый неприятный разбор на самом деле будет означать, что было задумано. Например:

int f();        // function declaration (simple form or the most vexing parse)
if (int f()) {  // illegal in C++ but, when allowed, would be a zero-initialized int
}

В C ++ 2011 вы можете использовать фигурную инициализацию:

if (int x{f()}) {
...
}

К сожалению, инициализация скобки не всегда означает то же самое, что использование нотации конструктора (я думаю, что это называется прямая инициализация).

Что касается обновления: вы можете использовать один из них:

if (std::unique_ptr<int> p = std::unique_ptr<int>(new int(1))) { ... }
if (auto p = std::unique_ptr<int>(new int(2))) { ... }
if (std::unique_ptr<int>{new int(3)}) { ... }

Вроде бы вариантов много 🙂

11

Другие решения

С точки зрения синтаксиса причина проста.

Первый элемент for заявление заявления. Операторы могут создавать переменные, а также инициализировать их. if условным является состояние. Спецификация определяет, что условие может создавать переменную, но только = инициализация.

Будь рад, что спецификации даже позволяет вам создать переменные в if совсем. Он должен иметь специальную грамматику, чтобы даже допустить это («условие» отличается от «выражения»), и это, вероятно, было чем-то унаследованным от C.

При этом C ++ 11 определяет условие как возможность инициализировать объявление с приготовился-INIT-лист (spec-говорить для «списка инициализатора»). Так что должен быть законным Но поскольку VS2012 еще не поддерживает списки инициализаторов …

2

По вопросам рекламы [email protected]