2011-10-31 77 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;