2011-10-25 28 views
16

Tôi muốn tìm điểm, có toạ độ Y ít hơn (nếu có nhiều điểm như vậy, hãy tìm điểm có điểm X nhỏ nhất). Khi viết nó với lambda:lambda return bool

std::min_element(begin, end, [](PointAndAngle& p1, PointAndAngle& p2) { 
     if (p1.first->y() < p2.first->y()) 
      return true; 
     else if (p1.first->y() > p2.first->y()) 
      return false; 
     else 
      return p1.first->x() < p2.first->x(); 
    } 

Tôi nhận:

error C3499: a lambda that has been specified to have a void return type cannot return a value 

sự khác biệt giữa những gì là:

// works 
    std::min_element(begin, end, [](PointAndAngle& p1, PointAndAngle& p2) { 
     return p1.first->y() < p2.first->y(); 
    } 

// does not work 
    std::min_element(begin, end, [](PointAndAngle& p1, PointAndAngle& p2) { 
     if (p1.first->y() < p2.first->y()) 
      return true; 
     else 
      return false; 
    } 
+1

Cấu trúc 'if (expression) trả về true; khác trở về sai; 'về cơ bản là xấu. Hai lần như xấu xí nếu biểu thức thực sự là boolean. –

+3

@ MichaelKrelin-hacker: Đúng, nhưng đó là _not_ tại sao trình biên dịch từ chối ví dụ cuối cùng. – MSalters

+1

Những người thay thế, chắc chắn, đó là lý do tại sao bình luận và không trả lời. Đây là câu trả lời cho câu hỏi "sự khác biệt" là gì. Và đây là sự khác biệt chính;) –

Trả lời

13

Loại trả về lambdas có thể được suy ra ngầm, nhưng bạn cần có một câu lệnh return để đạt được điều này; đó là lý do tại sao lambda "hoạt động" của bạn hoạt động (kiểu trả về được suy ra là bool).

giải pháp của sehe tuyên bố rõ ràng loại trả về, vì vậy nó cũng hoạt động tốt.

Cập nhật:

Tiêu chuẩn C++ 11, §5.1.2/4 trạng thái:

Nếu một lambda-biểu hiện không bao gồm một dấu-trở-type, nó là như thể loại dấu trả về biểu thị loại sau:

  • Nếu câu lệnh ghép là của f orm { return expression ; } loại biểu thức được trả về sau chuyển đổi lvalue-to-rvalue (4.1), chuyển đổi mảng-thành-con trỏ (4.2) và chuyển đổi chức năng thành con trỏ (4.3);

  • nếu không, void.

lambda không hoạt động của bạn thuộc danh mục thứ hai.

+0

Điều thú vị là wikipedia cũng bao gồm * nếu tất cả các vị trí trả về một giá trị trả lại cùng loại khi biểu thức trả về được truyền qua 'decltype'. * Trong tập hợp các lambda có thể bỏ qua kiểu trả về . Nhưng có vẻ như, theo tiêu chuẩn, đây không phải là trường hợp. – mackenir

+0

@mackenir: Trên thực tế trước khi đào sâu vào tiêu chuẩn, tôi nghĩ rằng nó có thể là một giới hạn của trình biên dịch (câu trả lời ban đầu là như vậy, nhưng các chỉnh sửa đã rất sớm sau khi đăng vì vậy đã không được đăng nhập). Wikipedia chắc chắn là không chính xác về mặt kỹ thuật ở đó. – Jon

+0

BTW bạn có mua bản sao tiêu chuẩn C++ 11 không? Tôi không thể tìm thấy nó để tải về miễn phí. – mackenir

12

Như Mike ghi chú khác, nếu cơ thể của lambda là một câu lệnh trả về đơn, thì kiểu trả về được suy ra từ đó (xem 5.1.2/4) (nhờ Mike).

std::min_element(begin, end, [] (const PointAndAngle & p1, const PointAndAngle & p2) 
    -> bool 
{ 
    if (p1.first->y() < p2.first->y()) 
     return true; 
    else 
     return false; 
} 

Lưu ý -> bool.

+0

Và có lẽ cũng tốt để lấy các đối số bằng tham chiếu const, vì thuật toán cũng có thể muốn cung cấp cho bạn điều đó. –

+0

cảm ơn bạn! không nên có '-> bool' sau() thay vì []? – relaxxx

+0

Tôi đoán đó là vì ở dạng đơn giản một dòng, cmpiler có thể dễ dàng suy ra kiểu trả về, cái mà anh ta có thể không thể một khi bạn giới thiệu một điều kiện. Mặc dù bạn nói đúng rằng nó luôn luôn là một ý tưởng tốt để được rõ ràng về kiểu trả về. –