2011-10-31 33 views
7

Các mã sau biên dịch với G ++ 4.6.1, nhưng không phải với Visual Studio 2008Ném và điều hành ternary trong C++

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

Sự thật là Studio biên dịch trực quan thực hiện một vụ tai nạn nội bộ.

Tôi muốn biết nếu điều này là tiêu chuẩn C + + và tại sao nó không biên dịch với Visual Studio, nhưng không với G + +?

+8

Bất kể mã hợp lệ là điều này hay không theo tiêu chuẩn, khi một trình biên dịch treo với một lỗi trình biên dịch nội bộ (đó là những gì VC làm, IIUC), sau đó đó là một lỗi trong trình biên dịch. Trình biên dịch được cho là phát ra một thông điệp có ý nghĩa ngay cả đối với mã bị lỗi, không phải là một báo cáo sự cố. – sbi

+0

Hãy nhớ đây là toán tử * có điều kiện *, điều này xảy ra là toán tử * a * ternary. – GManNickG

+0

Vâng, đã bối rối khi "ternary" không có trong spec ở bất cứ đâu. –

Trả lời

11

Đây là tiêu chuẩn C++. Một trong hai (hoặc cả hai) của các biểu thức sau đó/else trong một biểu thức có điều kiện được phép là một biểu thức ném thay thế (C++ 98 5.16/2).

Nếu Visual Studio gặp sự cố khi biên dịch ... có vẻ như không may!

+1

§5.16/2 cho phép cả hai biểu thức được ném biểu thức trong C++ 11. – Mat

+0

@Mat: oops, bạn hoàn toàn đúng, văn bản ở đây không thay đổi và lựa chọn thứ hai cho phép cả hai được ném trong C++ 98. –

4

Comeau biên dịch nó mà không có lỗi (đây là trường hợp thử nghiệm tối thiểu compilable của tôi):

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

đó là bằng chứng khá tốt mà nó cho phép theo tiêu chuẩn. Vì vậy, thực tế là MSVC gặp sự cố, thay vì thất bại với lỗi.

Ngoài ra, nó dường như được cố định trong 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 

và x64 phiên bản:

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 

Nâng cấp trình biên dịch của bạn nếu có thể, đây là xa lỗi chỉ cố định trong năm 2010.

+0

Thật vậy, điều này có lẽ là do tuân thủ C++ 11, hãy xem câu trả lời của @ MooingDuck. –

+1

@ AndréCaron: Điều đó không giải thích được "Lỗi trình biên dịch nội bộ". Và xem câu trả lời của John, nó cũng được cho phép trong C++ 98. –

+0

Tôi thuộc nhóm @ fmorency, và tôi là người đã gặp phải sự cố Microsoft Compiler với biểu thức nhà điều hành ném-trong-một-ternary. Chúng tôi đã cố gắng tìm ra nếu nó là tiêu chuẩn, không phải nếu đây là một lỗi trong trình biên dịch của Microsoft (có rõ ràng là * một lỗi *, kể từ khi nó bị treo). –

3

Từ C++ 11 Tháng 2 Dự thảo

§ 5,16/2 Nếu một trong hai thứ hai hoặc thứ ba toán hạng có kiểu (có thể cv-đủ điều kiện) có hiệu lực, sau đó vế trái-to-rvalue (4.1) , chuyển đổi tiêu chuẩn từ điểm đến con trỏ (4.2) và chuyển đổi tiêu chuẩn chức năng sang con trỏ (4.3) được thực hiện trên toán hạng thứ hai và thứ ba, và một trong các điều sau sẽ giữ:
- Toán hạng hai hoặc thứ ba (nhưng không cả hai) là một biểu thức ném (15.1); kết quả là loại của cái kia và là một giá trị.
- Cả toán hạng thứ hai và thứ ba đều có loại void; kết quả là loại void và là một giá trị. [Lưu ý: Điều này bao gồm trường hợp cả hai toán hạng là biểu thức ném. —end note]

Có vẻ như throw được tính là đánh giá thành void và điều này được cho phép.

+1

C++ 11 hiếm khi liên quan đến VS2008 (ngoại trừ việc đây không phải là quy tắc C++ 11, nó không thay đổi kể từ C++ 98, xem câu trả lời của John). –

+0

Tôi không có bản sao của bản nháp C++ 03 (cho VS2008) để trích dẫn từ, hoặc tôi sẽ trích dẫn từ đó. Bạn nói đúng là nó không nhất thiết phải áp dụng cho VS2008. –

1

Lỗi nội bộ có thể được coi là lỗi của Visual Studio. Trình biên dịch sẽ không bao giờ bị lỗi vì mã được biên dịch.

Đây là một cách sử dụng rất lạ của các nhà điều hành ternary, một đơn giản nếu trước sự trở lại sẽ là một thành ngữ nhiều lợi thế:

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

return m_something; 
Các vấn đề liên quan