2013-05-15 23 views
14

Có thể áp dụng sửa đổi noexcept cho biểu thức lambda không? Nếu vậy, làm thế nào?Sử dụng noexcept làm bộ sửa đổi lambda hoặc ràng buộc tham số

Có thể hạn chế noexcept đối số chức năng không? Ví dụ, một cái gì đó giống như trong đoạn mã sau, trong đó ý nghĩa là hàm gọi lại phải là noexcept?

//probably not valid code - I'm just trying to express the idea 
void f_async(std::function<void (int) noexcept> callback) noexcept 
{ 
    ... 
} 

này có thể gần được thực hiện với đoạn mã sau, nhưng tôi đang tự hỏi nếu có một cách để sử dụng một cái gì đó giống như sự thay thế ở trên.

void f_async(std::function<void (int)> callback) 
    noexcept(callback(std::declval<int>())) 
{ 
    ... 
} 

Vấn đề ở đây tất nhiên là f_async có thể noexcept(false) nếu gọi lại là noexcept(false) - Tôi muốn làm một tuyên bố mạnh rằng f_asyncluônnoexcept, có nghĩa là nó chỉ có thể được gọi nếu bạn sử dụng một callback noexcept.

Trả lời

16

Có thể áp dụng sửa đổi noexcept cho biểu thức lambda? Nếu vậy, làm thế nào?

Thêm noexcept sau ngoặc:

[](Args args) noexcept { ... } 

noexcept có thể được thực hiện một hạn chế trên một đối số chức năng?

Vâng, sử dụng enable_if:

template <typename F> 
auto f_async(const F& func) noexcept 
     -> typename std::enable_if<noexcept(func(0))>::type { 
    func(0); 
} 

int main() { 
    f_async([](int x) noexcept {}); 
    f_async([](int x) {}); // <- this line won't compile 
} 

Tuy nhiên, phương pháp này có thể không làm việc trực tiếp trong g ++ 4.7 (nó làm việc trong vang ++ 3.2), vì nó có thể không mangle noexcept biểu hiện nào:

3.cpp: 5: 6: xin lỗi, chưa thực hiện: mangling noexcept_expr

Bạn có thể giải quyết vấn đề này bằng cách sử dụng cấu trúc bao bọc:

template <typename F, typename... Args> 
struct EnableIfNoexcept 
     : std::enable_if<noexcept(std::declval<F>()(std::declval<Args>()...))> {}; 

template <typename F> 
auto f_async(const F& func) noexcept -> typename EnableIfNoexcept<F, int>::type { 
    func(0); 
} 
+0

Thú vị - Tôi chưa từng thấy điều này 'std :: enable_if' trước đây. Trông đầy hứa hẹn. –

+1

Thử tốt, nhưng không hoạt động khi chuyển chức năng miễn phí sang f_async trong clang 3.5. –

+0

http://rextester.com/RDIX55455 –

4

Liên quan đến câu hỏi đầu tiên:

modifier noexcept có thể được áp dụng cho một biểu thức lambda? Nếu vậy, làm thế nào?

Vâng, chỉ cần thêm các đặc điểm kỹ thuật ngoại lệ sau khi danh sách tham số:

[] (int i) noexcept { return i * 1; }; 
//   ^^^^^^^^ 

mỗi đoạn 5.1.2/5 của C++ 11 Tiêu chuẩn:

Kiểu đóng cửa cho một biểu thức lambda có một toán tử gọi hàm nội tuyến công khai (13.5.4) có tham số và kiểu trả về được mô tả theo mệnh đề khai báo tham số của biểu thức lambda-expression và kiểu trailingreturn- tương ứng. Toán tử gọi hàm này được khai báo const (9.3.1) nếu và chỉ khi mệnh đề khai báo tham số của lambda-expression không được theo sau bởi mutable. Nó không phải là ảo cũng không được khai báo dễ bay hơi. Đối số mặc định (8.3.6) sẽ không được xác định trong mệnh đề khai báo tham số của một trình khai báo lambda. Bất kỳ đặc điểm kỹ thuật ngoại lệ nào được chỉ định trên biểu thức lambda áp dụng cho hàm tương ứng toán tử gọi. Một thuộc tính-specifier-seq trong một trình khai báo lambda sẽ gán cho kiểu của toán tử gọi hàm tương ứng. [Lưu ý: Tên được tham chiếu trong trình khai báo lambda được tra cứu trong ngữ cảnh trong mà biểu thức lambda xuất hiện. —end note]

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