2014-11-01 19 views
10

Tôi đang đọc đây trên cppreference về cách một kiểu trả về của một lambda C++ 11 là suy luận:C++ 11 hạn chế về kiểu lambda trở

if the body consists of the single return statement, the return type is the type of the returned expression (after rvalue-to-lvalue, array-to-pointer, or function-to-pointer implicit conversion)

Vì vậy, tôi nghĩ rằng đó có nghĩa là một lambda có thể chỉ có một câu lệnh trả về. Nhưng tại sao nó hoạt động với nhiều câu lệnh trả về vẫn còn?

compiles này trên cả hai trình biên dịch:

auto f = [] (bool c1, bool c2) { 
    if (c1) return 1; 
    if (c2) return 2; 
    else return 3; 
}; 
+2

Trang bạn liên kết đến cũng cho thấy rằng các quy tắc thay đổi trong C++ 14. Đoán đầu tiên của tôi là các trình biên dịch đang thực hiện các quy tắc C++ 14 ngay cả trong chế độ C++ 11. – hvd

+0

@hvd Yup, đó là điều tôi nghi ngờ nhưng tôi vẫn hoài nghi. – 0x499602D2

+0

FWIW, tôi đã kiểm tra những gì C++ 11 nói, và nó phù hợp với những gì bạn đã tìm thấy trực tuyến, do đó, có, nó sẽ tạo ra một chẩn đoán thời gian biên dịch. Điều đó nói rằng, việc thực hiện quy tắc C++ 14 không thể gây ra mã C++ 11 hợp lệ bị từ chối, vì vậy nó chỉ có thể là một vấn đề nhỏ. – hvd

Trả lời

13

Đó là hơi không chính xác. [Expr.prim.lambda]/4:

If a lambda-expression does not include a lambda-declarator, it is as if the lambda-declarator were () . If a lambda-expression does not include a trailing-return-type, it is as if the trailing-return-type denotes the following type:

  • if the compound-statement is of the form

    {attribute-specifier-seqoptreturnexpression; }

    the type of the returned expression after lvalue-to-rvalue conversion (4.1), array-to-pointer conversion (4.2), and function-to-pointer conversion (4.3);

  • otherwise, void .

Vì vậy, các kiểu trả về là chỉ suy luận nếu toàn bộ cơ thể của biểu thức lambda chỉ bao gồm một return tuyên bố duy nhất.

Cả GCC và Clang đều không tuân thủ tiêu chuẩn trong trường hợp này khi chúng phát hành một thông báo lỗi nếu và chỉ khi hai câu lệnh return dẫn đến các khoản khấu trừ không nhất quán. Điều này là do họ đã triển khai chuẩn C++ 14 mà loại trừ kiểu trả về ngay cả với nhiều câu lệnh return và/hoặc nhiều câu lệnh khác hiện diện. [Expr.prim.lambda]/4 quy định rằng

The lambda return type is auto , which is replaced by the trailing-return-type if provided and/or deduced from return statements as described in 7.1.6.4.

§7.1.6.4/9

If a function with a declared return type that contains a placeholder type has multiple return statements, the return type is deduced for each return statement. If the type deduced is not the same in each deduction, the program is ill-formed.

+2

FWIW, [Tôi đã hỏi về điều này] (http://stackoverflow.com/questions/8582610/compiler-warning-lambda-return-type-cannot-be-deduced) năm trước :) – jrok

3

Nó hoạt động với ví dụ của bạn bởi vì tất cả các return báo cáo trở về giá trị cùng loại. Nhưng hãy thử thay đổi thứ hai return để một kiểu khác nhau, ví dụ:

auto f = [] (bool c1, bool c2) { 
    if (c1) return 1; 
    if (c2) return ""; 
    else return 3; 
}; 

Biên dịch này với kêu vang ++ mang lại các lỗi sau:

main.cpp:3:13: error: return type 'const char *' must match previous return type 'int' when lambda expression has unspecified explicit 
     return type 
    if (c2) return ""; 
     ^
1 error generated. 
+0

Anh ấy hỏi lý do tại sao nhiều câu trả lại được cho phép bất chấp câu trích dẫn nói gì (có thể chỉ có một câu). Điều này không liên quan gì đến loại biểu thức trả về. – 0x499602D2

+0

@ 0x499602D2 Trích dẫn (không đầy đủ) không cho biết nhiều báo cáo trả lại không được phép. Trích dẫn hoàn chỉnh dường như ngụ ý rằng, nhưng nó chỉ đơn giản là không chính xác. –

+0

@KonradRudolph Đó là những gì OP nghĩ. – 0x499602D2

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