2017-01-18 17 views
46
#include <iostream> 

void IsTrue(const bool value) { 
    if (value) { 
    std::cout << "value is True!\n"; 
    } 
} 

int main() 
{ 
    IsTrue([]() { ; /* some lambda */ }); 

    return 0; 
} 

Output:Tại sao một lambda chuyển đổi thành một bool có giá trị là đúng?

value is True! 

Tại sao lambda đánh giá để true trên GCC & Clang? MSVC không thể xây dựng này (không thể chuyển đổi lambda thành bool).

Đây có phải là lỗi trình biên dịch không? Hoặc đoạn nào của tiêu chuẩn cho phép điều này?

+11

Không chắc chắn nếu điều này là hợp pháp hay không nhưng nó dường như chuyển đổi lambda thành một con trỏ hàm và sau đó sử dụng giá trị đó (không phải là null) vào bool để nó biên dịch. Nếu bạn thêm một capture [nó không biên dịch] (http://coliru.stacked-crooked.com/a/f28beac0173e86e4). – NathanOliver

+8

MSVC có [một phần mở rộng không chuẩn] (https://adishavit.github.io/2016/magical-captureless-lambdas/), do đó, nó yêu cầu bạn phải khai báo rõ ràng loại con trỏ hàm đích, nếu không chuyển đổi sẽ thất bại. – cpplearner

+0

Ngoài ra, hãy xem [Truyền lambda là con trỏ hàm] (http://stackoverflow.com/q/28746744/1708801) –

Trả lời

44

Tiêu chuẩn C++ 14 (§5.1.2) nói:

Kiểu đóng cửa cho một lambda-biểu hiện không chung không có lambda-chụp có một tổ chức phi công chuyển đổi const không ảo rõ ràng chức năng đến con trỏ tới hàm với liên kết ngôn ngữ C++ (7.5) có cùng tham số và kiểu trả về với kiểu kết thúc là toán tử gọi hàm . Giá trị trả về bởi hàm chuyển đổi này sẽ là địa chỉ của hàm mà khi được gọi, có cùng hiệu lực khi gọi toán tử gọi hàm của loại đóng.

Vì con trỏ hàm được chuyển đổi hoàn toàn thành bool, bạn nhận được kết quả bạn đã hiển thị. Điều này hoàn toàn hợp pháp.

MSVC không biên dịch điều này vì toán tử chuyển đổi này bị quá tải với các quy ước gọi điện khác nhau (__stdcall, __cdecl, v.v.). Khi biên dịch cho x64 tất cả các quy ước gọi đó không được sử dụng, do đó, chỉ có một toán tử chuyển đổi và nó biên dịch tốt.

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