2012-07-17 45 views
6

Tiêu chuẩn C++ 11 nói (hoặc ít nhất, phiên bản tôi có - không phải là chính thức một):Tại sao "chuyển đổi con trỏ lambda thành chức năng" ẩn chứa "chụp tham chiếu" các thành viên tĩnh?

Kiểu đóng cửa cho một lambda-biểu với không lambda-chụp có công cộng hàm chuyển đổi không rõ ràng không ảo cho con trỏ để hoạt động có cùng tham số và kiểu trả về như toán tử gọi hàm của loại đóng .

Tôi hiểu tại sao không thể lấy con trỏ hàm từ lambda stateful vì con trỏ hàm không thể tự giữ bất kỳ dữ liệu nào. Tuy nhiên, khi các đối tượng bị bắt chỉ là một thành viên tĩnh/biến tĩnh, không có giới hạn như vậy vì các tham chiếu đến các đối tượng đã chụp có thể được hardwired trong chính hàm đó.

struct A { 
    static int count = 0; 
    void foo() { 
     static int bar = 0; 
     auto fun = [&]()->void { 
      count++; 
      bar++; 
     }; 
     void(*ptrFun)(); 
     ptrFun = fun; // forbidden by the quoted wording 
    } 
}; 

Tại sao không phải lúc nào cũng có thể chuyển đổi lambda thành con trỏ hàm ngay khi trước đây là trạng thái không trạng thái? Tôi có thiếu một cái gì đó hay không ủy ban đã quên điểm cụ thể này?

+1

Tôi dự đoán rằng đó là để tránh yêu cầu trình biên dịch có thể chứng minh được nhiều thứ về những gì đang bị bắt. – Flexo

+0

Trình biên dịch đã có thể tự động nắm bắt các biến ngay sau khi chúng được sử dụng (sử dụng [&] tự động, vì vậy nó sẽ không đòi hỏi nhiều công việc hơn để kiểm tra xem chúng có phải là thành viên tĩnh hay toàn cục hay không được tuyên bố trước đó. –

+0

Trên thực tế tôi đã không thử nghiệm nó trên bất kỳ trình biên dịch (Tôi chỉ có MSVC10 mà không hỗ trợ chuyển đổi con trỏ chức năng ở tất cả). Tôi đoán nó là một phần mở rộng GCC? Dù sao, câu hỏi của tôi là: nó được cho phép theo tiêu chuẩn (có lẽ tôi đã bỏ lỡ điều gì đó)? Nếu không, tại sao nó bị cấm (có thể có một giới hạn kỹ thuật mà tôi không biết)? –

Trả lời

9

A::count không cần phải bị bắt. Chỉ có this và các biến cục bộ cần được chụp. Các biến có thời gian lưu trữ tĩnh (ví dụ: các thành viên dữ liệu tĩnh, biến phạm vi không gian tên hoặc biến tĩnh cục bộ) không cần phải được giữ vì chúng là "duy nhất". Có chính xác một ví dụ của mỗi biến như vậy, do đó, một tham chiếu đến đối tượng không cần phải được chụp.

Nếu bạn xóa ảnh chụp mặc định khỏi lambda của mình (tức là, thay đổi [&] thành []) và xác định count, nó sẽ biên dịch mà không có lỗi. (Tôi đã xác minh rằng cả Visual C++ 2012 RC và g ++ 4.5.1 chấp nhận mã, thay đổi duy nhất tôi phải thực hiện là di chuyển khởi tạo nội tuyến của count, vì không có trình biên dịch nào hỗ trợ tính năng C++ 11.)

+0

Có tất nhiên ... Tôi cảm thấy ngu ngốc bây giờ :) Nhưng, nếu chúng ta muốn nắm bắt một biến địa phương tĩnh? –

+0

Chúng cũng không cần phải được chụp, vì cùng một lý do: mỗi biến cục bộ tĩnh là "duy nhất" và có địa chỉ đã biết. Tôi đã sửa đổi câu trả lời để tham khảo "biến có thời lượng lưu trữ tĩnh". Vẫn có thể có một số sự tinh tế ở đây, mặc dù không có ý thức nào (và VC11 và g ++ 4.5.1 đều chấp nhận chương trình với 'count' như một biến không gian tên, một thành phần dữ liệu tĩnh, hoặc như một hàm- tĩnh cục bộ). –

+0

Tôi không biết nó được cho phép, cảm ơn bạn! –

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