2015-07-02 3 views
10

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

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

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

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

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

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

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

+0

Связано с [Может ли переменная быть определена только в области if-утверждения, аналогично тому, как это часто делается для for-loops?] (Http://stackoverflow.com/q/24017216/1708801) –

+0

Почему вы думаете, что декларация 'Foo f = 42' подразумевает копирование/перемещение? Не следует копировать работу по элиции? – Columbo

+0

@Columbo AFAIK copy elision - это оптимизация, которая выполняется или не может выполняться, но даже если это не тот объект, который нуждается в конструкторе копии, который я отключил, чтобы избежать «auto_ptr»-подобного зла. В конце концов я работал над проблемой, передав 'std :: pair'. – Quentin

ответ

10

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

выбор-заявление:
        if (состояние)заявление
        [...]

состояние:
        выражение
        типа спецификатор-сл описатель= Назначение выражение

Так как C++, 11, list- Добавлена ​​инициализация:

состояние:
        выражение
        атрибут спецификатор-сл неавтоматическогоДецл-спецификатор-сл описатель=инициализатор придаточного
        атрибут спецификатор-сл неавтоматическогоДецл-спецификатор-сл описатель приготовился-INIT-лист

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

2

Поскольку стандарт C++ 03 позволяет только назначение инициализации в условиях:

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

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

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

В C++ 11 можно использовать приготовился синтаксис инициализации:

if (Foo f{51, 52}) { 
    //... 
} 
Смежные вопросы