2016-02-22 30 views
6

Nói rằng tôi có những tờ khai:Đúc một con trỏ hàm thành một noexcept định con trỏ hàm

using fp_type = void(*)(); 
using fp2_type = void(*)() noexcept; 

void func(){} 
fp_type fp(func); 

là các diễn viên fp2_type(fp) tốt được hình thành? Cách khác xung quanh (đúc một con trỏ hàm được chỉ định noexcept vào một con trỏ hàm mà không có một specifier không nhận dạng)?

+1

"Cách khác xung quanh" là tốt và thực sự là một chuyển đổi tiềm ẩn. 'fp2_type (fp)' trông giống như nó phải là 'reinterpret_cast'. –

+2

Câu hỏi thú vị. Ghi chú: * "15.4.12 Một đặc tả ngoại lệ không được coi là một phần của loại hàm" * –

+0

Thực ra, đây là trước hay sau khi chúng tạo ra một phần đặc tả ngoại lệ của hệ thống kiểu (tức là, đối với C++ 1z hoặc C + + 14/sớm hơn)? –

Trả lời

3

này là vô hình thành trong C++ 14 và trước đó:

using fp2_type = void(*)() noexcept; 

do N4140 [except.spec]/2:

Một ngoại lệ đặc điểm kỹ thuật sẽ không xuất hiện trong khai báo typedef hoặc tuyên bố bí danh.

Vì vậy, tôi sẽ giả định rằng câu hỏi là dành cho C++ 1z, trong đó đặc tả ngoại lệ là một phần của hệ thống kiểu.


[conv.fctptr]/1:

Một prvalue kiểu “con trỏ đến noexcept chức năng” có thể được chuyển đổi sang một prvalue kiểu “con trỏ đến chức năng”. Kết quả là một con trỏ tới hàm .

Do đó, void (*)() noexcept có thể được (ẩn) được chuyển đổi thành void (*)().

[expr.static.cast]/7:

Nghịch đảo của bất kỳ chuỗi chuyển đổi tiêu chuẩn (khoản [conv]) không chứa một sự chuyển đổi [(nhiều trường hợp khác bỏ qua)] con trỏ hàm ([conv.fctptr]), có thể thực hiện sử dụng rõ ràng static_cast.

Không có gì khác trong [expr.static.cast] cho phép chuyển đổi void (*)() để void (*)() noexcept một trong hai, vì vậy đây không phải là một sự chuyển đổi có thể được thực hiện bởi một static_cast.

[expr.reinterpret.cast]/6:

Một con trỏ hàm có thể được chuyển đổi một cách rõ ràng để một con trỏ hàm của một loại khác nhau. Ảnh hưởng của việc gọi hàm thông qua con trỏ đến một loại hàm ([dcl.fct]) không giống với loại được sử dụng trong định nghĩa của hàm này là không xác định. Ngoại trừ việc chuyển đổi một prvalue kiểu “con trỏ đến T1” với loại “con trỏ đến T2” (nơi T1T2 nhiều loại chức năng) và quay trở lại kiểu ban đầu của nó mang lại giá trị con trỏ gốc, kết quả của một con trỏ như vậy chuyển đổi không được chỉ định.[Lưu ý: xem thêm [conv.ptr] để biết thêm chi tiết chi tiết về chuyển đổi con trỏ. - lưu ý cuối cùng]

Vì vậy, reinterpret_cast có thể thực hiện chuyển đổi này.

Kể từ fp2_type(fp) tương đương với C-style cast (fp2_type) fp ([expr.type.conv]/1), và since C-style casts do a reinterpret_cast when static_cast is not possible (bỏ qua const_cast vì đơn giản, vì nó không có liên quan ở đây), fp2_type(fp) là một tốt được hình thành reinterpret_cast. Kết quả của một diễn viên như vậy không thể được sử dụng ngoại trừ để đúc nó trở lại, tuy nhiên.

+0

Câu hỏi liên quan, nếu bạn có thể chuyển đổi một chức năng noexcept thành một thường xuyên, bạn có thể làm tương tự (hoặc ngược lại) với const và con trỏ hàm thành viên dễ bay hơi bây giờ? – dascandy

+0

Có tồn tại một giải pháp cho vấn đề truyền theo C++ 11/14. Khai báo một hàm với specifier noexcept, như void f() noexcept; sau đó cast như decltype (& f) (fp). Có thể thêm điều này vào câu trả lời của bạn? – user1095108

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