Бросок и троичный оператор в C ++ - PullRequest
7 голосов
/ 31 октября 2011

Следующий код компилируется с G ++ 4.6.1, но не с Visual Studio 2008

return (m_something == 0) ? 
    throw std::logic_error("Something wrong happened") : m_something;

Дело в том, что компилятор Visual Studio выполняет внутренний сбой.

Я хочу знать, является ли это стандартным C ++ и почему он не компилируется с Visual Studio, а с G ++?

Ответы [ 4 ]

11 голосов
/ 31 октября 2011

Это стандарт C ++.Любое (или оба) из выражений then / else в условном выражении может быть вместо этого выражением throw (C ++ 98 5.16 / 2).

Если происходит сбой Visual Studio при компиляции ...это казалось бы неудачным!

4 голосов
/ 31 октября 2011

Comeau компилирует его без ошибок (вот мой минимальный компилируемый тестовый пример):

int main(void)
{
    int x = 17;
    return x ? throw "Something wrong happened" : 5;
}

, что является довольно хорошим доказательством того, что это разрешено стандартом.Таков тот факт, что MSVC аварийно завершает работу, а не завершается с ошибкой.

Кроме того, похоже, что это исправлено в VC ++ 2010

R:\>cl ternarythrowtest.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

ternarythrowtest.cpp
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:ternarythrowtest.exe
ternarythrowtest.obj

и версии x64:

R:\>cl ternarythrowtest.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

ternarythrowtest.cpp
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:ternarythrowtest.exe
ternarythrowtest.obj

Обновите ваш компилятор, если это возможно, это далеко не единственная ошибка, исправленная в 2010 году.

3 голосов
/ 31 октября 2011

Из C ++ 11 февраля Черновик

§ 5.16 / 2 Если второй или третий операнд имеет тип (возможно, cv-квалифицированный) void, то lvalue-to-rvalue (4.1), array-to-pointer (4.2) и function-to- для указателя (4.3) выполняются стандартные преобразования второго и третьего операндов, и должно выполняться одно из следующих:
- второй или третий операнд (но не оба) является выражением броска (15.1); результат имеет тип другого и является prvalue.
- и второй, и третий операнды имеют тип void; результат имеет тип void и является prvalue. [Примечание: это включает случай, когда оба операнда являются выражениями броска —Конечная записка]

Похоже, что throw считается оценкой void, и это разрешено.

2 голосов
/ 31 октября 2011

Внутренний сбой можно считать ошибкой Visual Studio.Компилятор никогда не должен аварийно завершать работу из-за компилируемого кода.

Это очень странное использование тернарного оператора, простое, если перед возвратом будет гораздо более предпочтительная идиома:

if(m_something == 0)
    throw std::logic_error("Something wrong happened");

return m_something;
...