Có phải lambda bị giam giữ được đảm bảo để trống theo tiêu chuẩn?


12

Tôi đang tìm kiếm một cách để xác định lambdas trống (không bị giam giữ) từ các lambdas khác trong một hàm mẫu. Tôi hiện đang sử dụng C ++ 17 nhưng tôi cũng tò mò về câu trả lời của C ++ 20.

Mã của tôi trông như thế này:

template<typename T>
auto func(T lambda) {
    // The aguments of the lambdas are unknown

    if constexpr (/* is captureless */) {
        // do stuff
    }
}

Được đảm bảo bởi tiêu chuẩn C ++ (17 hoặc 20) rằng lambda không bị giam giữ, có thể chuyển đổi thành con trỏ hàm, cũng sẽ làm cho std::is_emptynăng suất đúng?

Lấy mã này làm ví dụ:

auto a = []{}; // captureless
auto b = [c = 'z']{}; // has captures

static_assert(sizeof(a) == sizeof(b)); // Both are the same size
static_assert(!std::is_empty_v<decltype(b)>); // It has a `c` member
static_assert(std::is_empty_v<decltype(a)>); // Passes. It is guaranteed?

Ví dụ sống


2
Nếu bạn chỉ quan tâm đến lambdas không phải mẫu, bạn có thể sử dụng SFINAE để kiểm tra xem chuyển đổi sang một con trỏ hàm ( +lambda) có được định dạng tốt hay không.
HolyBlackCat

@HolyBlackCat Tôi đã nghĩ về điều đó, nhưng theo tôi nhớ, MSVC không cho phép điều đó vì họ đã quá tải toán tử chuyển đổi.
Trường đua Guillaume

@GuillaumeRacicot MS hiển thị một toán tử chuyển đổi riêng cho tất cả các quy ước gọi có sẵn. Chỉ cần chọn một và cố gắng chuyển đổi lambda thành một con trỏ hàm tương đương, và kiểm tra xem điều đó thành công hay thất bại.
Rémy Lebeau

+dường như làm việc ở đây .
HolyBlackCat

Câu trả lời:


13

Trên thực tế, tiêu chuẩn cấp phép rõ ràng cho lambdas có kích thước không phù hợp với tuyên bố của họ. [expr.prim.lambda.clenses] / 2 tiểu bang

Kiểu đóng được khai báo trong phạm vi khối nhỏ nhất, phạm vi lớp hoặc phạm vi không gian tên có chứa biểu thức lambda tương ứng. [Lưu ý: Điều này xác định tập hợp các không gian tên và các lớp được liên kết với kiểu đóng ([basic.lookup.argdep]). Các kiểu tham số của bộ khai báo lambda không ảnh hưởng đến các không gian tên và các lớp liên quan này. - lưu ý cuối] Loại đóng không phải là loại tổng hợp. Việc triển khai có thể định nghĩa kiểu đóng khác với những gì được mô tả dưới đây với điều kiện điều này không làm thay đổi hành vi có thể quan sát được của chương trình ngoài việc thay đổi:

  • kích thước và / hoặc căn chỉnh của loại đóng cửa,

  • loại đóng cửa có thể sao chép một cách tầm thường ([class.prop]) hay (2.3)

  • cho dù kiểu đóng là một lớp bố trí tiêu chuẩn ([class.prop]).

Việc triển khai không được thêm các thành viên của loại tham chiếu giá trị vào loại đóng.

nhấn mạnh của tôi

Vì vậy, điều này cho phép thực hiện để cung cấp cho lambda một thành viên ngay cả khi nó không bị bắt. Tôi không nghĩ rằng bất kỳ việc thực hiện nào sẽ xảy ra, nhưng họ được phép làm như vậy một cách hợp pháp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.