Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throw and ternary operator in C++

The following code compiles with G++ 4.6.1, but not with Visual Studio 2008

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

The fact is the Visual Studio compiler performs an internal crash.

I want to know if this is standard C++ and why it doesn't compile with Visual Studio, but does with G++?

like image 377
fmorency Avatar asked Oct 31 '11 18:10

fmorency


People also ask

What is ternary operator in C?

Ternary Operator in C is an operator which takes three operands or variables, unlike the other operators which take one or two operands. Ternary operator in C is also known as Conditional Operator. It is a way to shorten the simple if-else code of the block.

What is ternary operator in C with example?

It helps to think of the ternary operator as a shorthand way or writing an if-else statement. Here's a simple decision-making example using if and else: int a = 10, b = 20, c; if (a < b) { c = a; } else { c = b; } printf("%d", c); This example takes more than 10 lines, but that isn't necessary.

Can we throw exception in ternary operator?

You can't throw an exception in a ternary clause. Both options must return a value, which throw new Exception(); doesn't satisfy.

What is ternary operator syntax?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.


3 Answers

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!

like image 67
John Marshall Avatar answered Oct 11 '22 01:10

John Marshall


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.

like image 27
Ben Voigt Avatar answered Oct 11 '22 00:10

Ben Voigt


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.

like image 26
Mooing Duck Avatar answered Oct 10 '22 23:10

Mooing Duck