2011-10-31 80 views
7

下面的代码编译与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 ++吗?

+8

无论这是有效的代码或不按标准,当一个编译器崩溃时出现内部编译器错误(这是VC所做的,IIUC),那么这是编译器中的错误。编译器应该发出一个有意义的消息,即使是错误的代码,而不是崩溃报告。 – sbi

+0

请记住,这是*条件运算符*,它恰好是* a *三元运算符。 – GManNickG

+0

是的,当“三元”不在规范的任何地方时,感到困惑。 –

回答

11

它是标准的C++。条件表达式中的then/else表达式中的任何一个(或两者)允许为throw-expression(C++ 98 5.16/2)。

如果Visual Studio在编译时崩溃......这似乎是不幸的!

+1

§5.16/ 2允许这两个表达式在C++ 11中都是抛出表达式。 – Mat

+0

@Mat:oops,你说的很对,这里的文本没有改变,第二个选择也允许在C++ 98中抛出。 –

4

科莫编译它没有错误(这是我最小的编译测试用例):

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年

唯一的错误
+0

确实,这可能是因为遵循C++ 11,请参阅@ MooingDuck的答案。 –

+1

@AndréCaron:这无法解释“内部编译器错误”。看到John的答案,它也允许在C++ 98中使用。 –

+0

我在@ fmorency的团队,我是用他的三元运算符表达式遇到Microsoft Compiler崩溃的人。我们试图弄清楚它是否是标准的,而不是这是否是微软编译器中的一个错误(显然存在* a *错误,因为它是崩溃的)。 –

3

从C++ 2月11日草案

§5.16/2如果第二或第三操作数的类型(可能CV-合格)无效,那么左值到右值(4.1) ,数组到指针(4.2)和函数到指针(4.3)的标准转换在第二个和第三个操作数上执行,并且下列之一成立:
- 第二个或第三个操作数(但不是两者)是一个投掷表达式(15.1);结果是另一种的类型,是一个价值。
- 第二个和第三个操作数的类型都是void;结果是void类型并且是一个prvalue。 [注意:这包括两个操作数都是throw-expressions的情况。 - 注意]

看来throw计为评估void,这是允许的。

+1

C++ 11与VS2008几乎没有关系(除了这不是C++ 11规则,它自C++ 98以来一直没有变化,请参阅John的答案)。 –

+0

我没有C++ 03草稿(适用于VS2008)的引用,或者我会引用它。你说得对,它不一定适用于VS2008。 –

1

内部崩溃可被视为Visual Studio的错误。编译器永远不会崩溃,因为正在编译的代码。

这是三元运算符的一个很奇怪的用法,简单的,如果之前的回报将是一个更加理想的成语:

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

return m_something;