Theo đề xuất (được chấp nhận) này, vì C++ 17; như noexcept là một phần của loại hàm, mã sẽ ở trên có in true
không?
Có.
Loại f
sẽ được khấu trừ thành void(*)() noexcept
vì chuyển đổi chức năng thành con trỏ áp dụng cho asdf
sẽ giữ nguyên thuộc tính noexcept
. Một cuộc gọi đến một con trỏ chức năng noexcept
chắc chắn không thể ném một ngoại lệ, trừ khi một trong các biểu thức con của nó thực hiện.
Để biết từ ngữ chính xác, hãy xem [expr.unary.noexcept]/3 và [expect.spec]/13. Lưu ý rằng từ ngữ mới trong đoạn sau từ bản thảo C++ 17 xuất phát từ P0012R1, được liên kết trong OP.
Kết quả của các nhà điều hành noexcept
là true
nếu tập các trường hợp ngoại lệ tiềm năng của biểu thức ([except.spec]) là trống rỗng, và false
khác.
...
- Nếu
e
là một lời gọi hàm ([expr.call]):
- Nếu nó postfix thể hiện là một (có thể trong ngoặc đơn) id-biểu ([expr.prim.id]), quyền truy cập thành viên của lớp ([expr.ref]) hoặc hoạt động trỏ tới thành viên ([expr.mptr.oper]) có biểu thức truyền là một biểu thức id , S là tập hợp các loại trong đặc tả ngoại lệ của thực thể được chọn bởi biểu thức id chứa (sau khi quá tải, nếu có). ...
Vì vậy, các trường hợp ngoại trừ tiềm năng của f()
cũng giống như tập các loại trong đặc tả ngoại lệ của f
, mà là trống kể từ f
được khai báo noexcept
.
Hãy chuyển sang câu hỏi thứ hai:
Các noexcept
nêu rõ dường như bỏ qua trong C++ 14 hoặc 11. Sẽ làm việc mã này như dự định trong C++ 17?
Câu hỏi của bạn có vẻ như: sẽ std::function<void() noexcept>
từ chối giữ chức năng có thể ném ngoại lệ?
Tôi có thể nói rằng đó là không rõ ràng. Trong từ ngữ hiện tại của tiêu chuẩn, std::function<void() noexcept>
không thực sự được xác định, giống như std::function<double(float) const>
is not defined. Điều này tất nhiên không phải là một vấn đề trong C++ 14, vì noexcept
không được coi là một phần của kiểu hàm.
Liệu std::function<void() noexcept>
có thể đột nhập vào C++ 17 không? Điều đó không chắc chắn với tôi. Chúng ta hãy nhìn vào từ ngữ hiện tại để đoán hành vi "nên" là gì.
Tiêu chuẩn yêu cầu đối số cho constructor của std::function<R(ArgTypes..)>
là "giá trị trái-Callable" cho loại đối số ArgTypes...
và kiểu trả về R
, mà means:
Một loại callable ([func.def]) F
là Lvalue-Callable đối với loại đối số ArgTypes
và trả về loại R
nếu biểu thức INVOKE(declval<F&>(), declval<ArgTypes>()..., R)
, được coi là toán hạng chưa được đánh giá (Điều khoản [expr]), được định dạng tốt ([func.require]).
Có lẽ phải có yêu cầu bổ sung nếu loại chức năng là noexcept
, thì noexcept(INVOKE(...))
cũng phải đúng. Tuy nhiên, từ ngữ này không có trong bản nháp hiện tại.
Trong P0012R1, có một nhận xét rằng:
Nó là một vấn đề mở như thế nào để tuyên truyền "noexcept" qua std::function
.
Tôi đoán là chúng có nghĩa là không rõ ràng cách std::function
có thể được triển khai nếu yêu cầu bổ sung này được áp dụng. Hy vọng rằng, một người khác có thể cung cấp thêm chi tiết.
g ++ trả về 'true' cho' noexcept (f()) 'mà không có' -std = C++ 1z' (nhưng clang không trả về 'false'). – Holt
Để có thêm niềm vui, hãy thay đổi 'auto f = asdf;' thành 'void (* f)() noexcept = asdf;'. Bây giờ GCC in 'false' trong khi clang in' true'. – hvd
@Holt Cảm ơn thông tin. Tôi đang sử dụng MSVC (trả về 'false'). Điều gì sẽ khác với họ? Đó có phải là lỗi của g ++ hoặc C++ 14 hoặc tiêu chuẩn trước đó không quy định gì về hệ thống kiểu 'noexcept'? – Gear