Trong C ++, nếu ném là một biểu thức, thì kiểu của nó là gì?


115

Tôi đã chọn nó trong một trong những lần tìm kiếm ngắn gọn của tôi để reddit:

http://www.smallshire.org.uk/sufficientlysmall/2009/07/31/in-c-throw-is-an-expression/

Về cơ bản, tác giả chỉ ra rằng trong C ++:

throw "error"

là một biểu hiện. Điều này thực sự được viết khá rõ ràng trong Tiêu chuẩn C ++, cả trong văn bản chính và ngữ pháp. Tuy nhiên, điều không rõ ràng (với tôi ít nhất) là kiểu biểu thức là gì? Tôi đoán là " void", nhưng một chút thử nghiệm với g ++ 4.4.0 và Comeau đã mang lại mã này:

    void f() {
    }

    struct S {};

    int main() {
        int x = 1;
        const char * p1 = x == 1 ? "foo" : throw S();  // 1
        const char * p2 = x == 1 ? "foo" : f();        // 2
    }

Các trình biên dịch không gặp vấn đề gì với // 1 nhưng cản trở // 2 vì các kiểu trong toán tử điều kiện là khác nhau. Vì vậy, kiểu của một throwbiểu thức dường như không có giá trị.

Vậy đo la cai gi?

Nếu bạn trả lời, vui lòng sao lưu các báo cáo của bạn với trích dẫn từ Tiêu chuẩn.


Điều này hóa ra không liên quan nhiều đến loại biểu thức ném như cách toán tử điều kiện xử lý với biểu thức ném - điều mà tôi chắc chắn không biết trước ngày hôm nay. Cảm ơn tất cả những người đã trả lời, nhưng đặc biệt là với David Thornley.

c++  throw 

10
+1 Câu hỏi tuyệt vời. Và một cách thông minh để kiểm tra nó.
Jeremy Powell,

1
Liên kết đó dường như làm cho nó khá rõ ràng rằng kiểu được trình biên dịch xác định là bất cứ thứ gì nó cần.
Draemon 31-07-09

Tôi nghĩ rằng bài báo được liên kết đã được cập nhật kể từ khi tôi xem xét nó và tôi chắc chắn rằng thực tế là như vậy. Tuy nhiên, tôi không thể tìm thấy nó trong tiêu chuẩn.

Aand có thể không - double d = ném "foo"; là lỗi với g + = (chưa kiểm tra nó với comeau)

+1 Tôi tò mò muốn biết câu trả lời.
AraK,

Câu trả lời:


96

Theo tiêu chuẩn, 5.16 đoạn 2 điểm đầu tiên, "Toán hạng thứ hai hoặc thứ ba (nhưng không phải cả hai) là một biểu thức ném (15.1); kết quả thuộc loại khác và là một giá trị." Do đó, toán tử điều kiện không quan tâm kiểu biểu thức ném là gì, mà sẽ chỉ sử dụng kiểu khác.

Trên thực tế, 15.1, đoạn 1 nói rõ ràng "Một biểu thức ném có kiểu void."


9
OK - Tôi nghĩ chúng ta có một người chiến thắng.

Lưu ý rằng biểu thức ném là biểu thức gán. Vì vậy, chúng là một lỗi cú pháp như một đối số đối với hầu hết các toán tử. Rõ ràng, bạn có thể ẩn chúng trong dấu ngoặc đơn, nhưng nếu chúng không bị bỏ qua (ví dụ: đối số đầu tiên của toán tử nội trang), thì đó là lỗi kiểu.
AProgrammer, 31-07-09

4
Điều thực sự làm tôi ngạc nhiên là họ đã nghĩ ra trường hợp này và đưa ra một điều gì đó hợp lý.
Omnifarious

31

"Một biểu thức ném có kiểu void"

ISO14882 Phần 15


Sau đó, cả g ++ và Comeau đều thiếu sót khi không đưa ra lỗi cho trường hợp // 1 của tôi?

2
@Neil, không thực sự vì theo C ++ / 5,16 / 2, toán hạng thứ hai và thứ ba của các nhà điều hành có điều kiện có thể được loạivoid
mloskot

13

Từ [expr.cond.2] (toán tử có điều kiện ?:):

Nếu toán hạng thứ hai hoặc thứ ba có kiểu (có thể là cv-enough fi ed) void, thì chuyển đổi lvalue-to-rvalue, array-to-pointer và function-to-pointer standard được thực hiện trên toán hạng thứ hai và thứ ba, và một trong những điều sau đây sẽ giữ:

- Toán hạng thứ hai hoặc thứ ba (nhưng không phải cả hai) là một biểu thức ném; kết quả là loại khác và là một giá trị.

- Cả toán hạng thứ hai và thứ ba đều có kiểu void; kết quả là kiểu void và là một rvalue. [Lưu ý: điều này bao gồm trường hợp cả hai toán hạng đều là biểu thức ném. - ghi chú cuối]

Vì vậy, với //1bạn trong trường hợp đầu tiên, với //2, bạn đã vi phạm "một trong những điều sau đây sẽ giữ", vì không ai trong số họ làm, trong trường hợp đó.


3

Bạn có thể có một máy in loại nhổ nó ra cho bạn :

template<typename T>
struct PrintType;

int main()
{
    PrintType<decltype(throw "error")> a; 
}

Về cơ bản, việc thiếu triển khai PrintTypesẽ gây ra báo cáo lỗi biên dịch cho biết:

trình diễn ngầm của mẫu không xác định PrintType<void>

vì vậy, chúng tôi thực sự có thể xác minh rằng các throwbiểu thức thuộc loại void(và vâng, các trích dẫn Chuẩn được đề cập trong các câu trả lời khác xác minh rằng đây không phải là kết quả cụ thể về triển khai - mặc dù gcc gặp khó khăn trong việc in thông tin có giá trị)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.