Throw and ternary operator in C++

一曲冷凌霜 提交于 2019-11-28 12:18:04

It is standard C++. Either (or both) of the then/else expressions in a conditional expression is allowed to be a throw-expression instead (C++98 5.16/2).

If Visual Studio crashes when compiling it... that would seem to be unfortunate!

Comeau compiles it without errors (here's my minimal compilable test case):

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

which is pretty good evidence that it's allowed by the standard. So is the fact that MSVC crashes, rather than failing cleanly with an error.

Also, it appears to be fixed in 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

and x64 version:

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

Upgrade your compiler if possible, this is far from the only bug fixed in 2010.

From the C++11 February Draft

§ 5.16/2 If either the second or the third operand has type (possibly cv-qualified) void, then the lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the second and third operands, and one of the following shall hold:
— The second or the third operand (but not both) is a throw-expression (15.1); the result is of the type of the other and is a prvalue.
— Both the second and the third operands have type void; the result is of type void and is a prvalue. [ Note: This includes the case where both operands are throw-expressions. —end note ]

It appears that throw counts as evaluating to a void, and that this is allowed.

The internal crash can be considered a bug of Visual Studio. A compiler should never crash because of the code being compiled.

This is a very strange usage of the ternary operator, a simple if before the return would be a much preferable idiom:

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

return m_something;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!