Прямая инициализация объекта внутри условия

Можно определить и скопировать инициализацию переменной внутри условия оператора if:

if(int i = 17) { ... }

Это также работает с пользовательскими типами, учитывая, что они перегружают operator bool:

if(Foo f = 42)      { ... }
if(Foo f = Foo(43)) { ... }

Почему я не могу использовать прямую инициализацию, например следующее:

if(Foo f(51)) { ... }

GCC испускает error: expected primary-expression before 'f'.

Live on Coliru

Есть ли причина, кроме "потому что грамматика говорит так"? И как я могу обойти это?

Я работаю с VС++ 03, где Foo:

  • - это объект, чувствительный к RAII, для которого я позаботился о том, чтобы не определять конструктор копирования
  • - это шаблон, принимающий аргументы пользователя
  • имеет конструктор с двумя параметрами

... поэтому я бы предпочел не копировать его или не повторять его тип.

Примечание. Хотя моя фактическая проблема связана с С++ 03, я (академически) интересуюсь ответами на С++ 11.

Ответ 1

В С++ 03 можно использовать синтаксис только для копирования:

selection-statement:
    if ( условие ) statement     [...]

условие:     выражение     type-specifier-seq declarator =Назначение выражение

С С++ 11 была добавлена ​​инициализация списка:

условие:
    выражение
    атрибут-specifier-seq opt decl-specifier-seq declarator = initializer-clause
    атрибут-specifier-seq opt decl-specifier-seq declarator приготовился-INIT-лист

Синтаксис прямой инициализации, т.е. Foo f(…), по-видимому, был исключен по той же причине, что и для нестатических инициализаторов элементов данных, это было запрещено: неоднозначность, в частности "самый неприятный синтаксический анализ".

Ответ 2

Поскольку стандарт С++ 03 разрешает инициализацию присваивания внутри условий:

condition:
    expression
    type-specifier-seq declarator = assignment-expression

Ответ 3

Учитывая ваши ограничения, я верю в С++ 03, ваш единственный вариант - объявить переменную вне инструкции if, добавив фигурные скобки для определения области видимости:

{
    Foo f(51, 52);
    if (f) {
        //...
    }
}

В С++ 11 вы можете использовать синтаксис синтаксиса:

if (Foo f{51, 52}) {
    //...
}