2011-12-06 32 views
15

Một ít được biết đến, nhưng hầu như không bao giờ sử dụng C++ tính năng được đưa ra một tuyên bố:chức năng cú pháp cố gắng nắm bắt và chính

void foo(); 

Một có thể, định nghĩa pháp lý có thể là:

void foo() try { 
    throw 42; 
} 
catch(...) { 
} 

Ở đây whole function implementation wrapped is within a try/catch pair, có vẻ tương tự như cho phép this.

Điều đó có hợp pháp để làm cho int main() không? Ví dụ:

int main() try { 
    throw 42; 
} 
catch(...) { 
} 

The rules for main, n3290 § 3.6.1 chủ yếu nói về những gì lý lẽ nó nên mất và những gì nó trả - họ dường như không cấm một cách rõ ràng như họ làm với nhiều điều kỳ lạ khác (ví dụ liên kết) bạn có thể bị cám dỗ để thử.

Điều này có hợp pháp và được xác định rõ không?

+2

Câu hỏi học thuật thú vị, mặc dù tôi không chắc nó có nhiều sử dụng thực tế. http://stackoverflow.com/a/620817/10077 –

+0

Pháp lý? Về mặt kỹ thuật, hầu hết các trình biên dịch sẽ hỗ trợ nó. Được xác định rõ? Không thực sự như tôi chắc chắn không thể nghĩ ra bất kỳ lý do lành mạnh nào để làm điều này. – AJG85

+0

@ AJG85 - Tôi có nghĩa là được định nghĩa rõ ràng theo nghĩa "gọi không phải hành vi không xác định, cũng không thực hiện hành vi được xác định", không phải trong "cũng được thử nghiệm trong việc triển khai phổ biến" cách – Flexo

Trả lời

7

Các tiêu chuẩn không cấm sử dụng của nó trong vòng [basic.start.main], và, trong khi buộc tất cả triển khai để hỗ trợ ít nhất int main() {/*...*/ }int main(int argc, char* argv[]) {/*...*/}, không giới hạn việc triển khai cho hai khai báo đó (3.6.1, đoạn 2).

Từ đó trong sự cô lập, nó sẽ xuất hiện ít nhất là nó là hợp pháp, mặc dù tất nhiên chỉ liên quan đến khai báo hàm, chứ không chỉ định nghĩa hàm.

Đọc trên, [except.handle], đoạn 13 tiểu bang sau đây:

Exceptions ném vào destructors của các đối tượng với dung lượng tĩnh thời gian hoặc trong nhà xây dựng của các đối tượng không gian tên-phạm vi không bắt bởi một function-try-block trên main(). (15,3 para. 13)

Nó làm cho đề cập cụ thể của một chức năng-thử-block đặt trên main(), mà mạnh mẽ ngụ ý rằng một cấu trúc như vậy là hợp pháp và đã xác định hành vi. Thêm vào thông tin rằng main() chỉ đặc biệt trong tên và kiểu trả về của nó, và việc triển khai có thể không quá tải để thay đổi bất kỳ hành vi nào, tạo ra một trường hợp khá mạnh mẽ hoạt động theo kiểu bình thường ngoại trừ khi được chú ý đặc biệt . Nói cách khác, có, nó là hợp pháp và được xác định rõ.

Các bài viết trên blog tôi cung cấp trong phiên bản đầu tiên của câu trả lời này thực sự làm một công việc tốt để minh họa các quy tắc được đưa ra bởi blockquote trên, vì vậy tôi sẽ retain the link to it, mặc dù nó không trực tiếp thảo luận về vấn đề này trong OP của câu hỏi.

Về nhận xét về OP, bạn có thể phát hành báo cáo trả lại trong một khối chức năng -try-block và [ngoại trừ.xử lý] có điều này để nói:

Chảy ra khỏi cuối khối chức năng thử tương đương với trả lại không có giá trị; điều này dẫn đến hành vi không xác định trong hàm trả về giá trị (6.6.3). (15.3 đoạn 15)

Nếu bạn đang ở trong khối bị chặn ở cuối main, bạn sẽ không chảy qua thân của hàm (đây sẽ là khối thử trong trường hợp này) , vì vậy quy tắc tự động gọi chính là return 0; khi lưu chuyển không áp dụng. Bạn cần trả lại một số int (có thể là một mã lỗi) để tránh không trở thành không xác định.

+1

Không có nhiều thông tin (trên định nghĩa), các 'static' constatations khá đơn giản: các đối tượng" global "được khởi tạo trước khi' main' được gọi và destructed sau khi nó đã trả về ... vì vậy rõ ràng không nằm trong 'try/catch' khối. Đối với những nhận xét về cú pháp của hàm tạo, vâng nó lạ nhưng không thực sự trả lời câu hỏi ... –

+0

Tôi đồng ý với đánh giá đó, và đã lưu ý nó; cảm ơn. Tôi tìm thấy một tham chiếu rõ ràng đến 'main()' có các khối chức năng thử, vì vậy tôi nghĩ rằng bài viết là khá vô dụng anyway. Tôi sẽ chỉnh sửa để làm rõ điều này. – matthias

+0

Trích dẫn đó từ 15.3 khá thú vị.(Đó có thể sẽ là câu hỏi tiếp theo của tôi nếu nó là hợp pháp) Kết hợp với DR mà Johannes liên kết với điều đó dường như trả lời nó như được cho phép. – Flexo

0

Tôi đã thử nó, nó biên dịch và chạy như mong đợi. Một công thức đặc biệt, nhưng tôi không nghĩ nó phá vỡ bất kỳ quy tắc nào. Để rõ ràng (đối với bản thân và mantainers đang trong tương lai), bạn cũng có thể nói lại nó như:

int main() 
{ 
    try { 
     throw 42; 
    } 
    catch(int /*...*/) { 
    } 
} 
+4

Nó cũng hoạt động trên trình biên dịch của tôi. Vấn đề với "nó biên dịch và chạy" là tôi biết biên dịch của tôi biên dịch và chạy rất nhiều thứ mà không được xác định rõ. – Flexo

+1

Điểm công bằng, @awoodland. Vì vậy, trong nghi ngờ, tôi sẽ đề nghị sử dụng công thức tôi đề cập ở trên, mà dường như làm chính xác những gì bạn yêu cầu. Công thức ban đầu của bạn dường như không vi phạm bất kỳ quy tắc nào từ tiêu chuẩn. – alexandreC

Các vấn đề liên quan