2015-10-23 17 views
7

Tôi đang thử nghiệm với lambda sử dụng và khi kiểm tra sau đây nó biên dịch nói 'hi'.Sử dụng lambda làm tham số cho std :: cout

auto lmda = [](std::ostream& os) -> std::ostream& { os << "hi"; return os; }; 
std::cout << lmda; 

Nhưng khi thêm chụp, nó không biên dịch. Ví dụ:

std::vector<int> v(5, 3); 
auto lmda = [&v](std::ostream& os) -> std::ostream& { os << v.size(); return os; }; 
std::cout << lmda; 

Build lỗi là:

In function 'int main()': 
10:18: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&' 
In file included from /usr/include/c++/4.9/iostream:39:0, 
      from 2: 
/usr/include/c++/4.9/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = main()::<lambda(std::ostream&)>]' 
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) 

Tôi không hiểu tại sao nó bị lỗi trong ví dụ thứ hai. Bất kỳ khách hàng tiềm năng nào?

Trả lời

5

Một lambda without a capture is convertible to a function pointer mà sẽ phù hợp với following overload:

basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&)); 

Khi cppreference liên kết ghi chú:

cuộc gọi func (* điều này);. Những quá tải này được sử dụng để thực hiện đầu ra I/O thao tác như std :: endl.

từ dự thảo C++ 11 tiêu chuẩn phần 5.1.2[expr.prim.lambda]:

Kiểu đóng cửa cho một lambda-biểu không có 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ư là toán tử gọi hàm của loại đóng . Giá trị trả về bởi chức năng chuyển đổi này sẽ là địa chỉ của một hàm rằng, khi gọi, có tác dụng tương tự như cách gọi hàm operator gọi kiểu đóng cửa của

+0

Lưu ý: quá tải này tồn tại để các trình xử lý như 'std :: endl' và' std :: boolalpha' hoạt động. Họ có thể chỉ là 'struct' với các toán tử '<<' bị quá tải, nhưng có thể bị hindsight. – Simple

+0

@Điểm đơn giản, được ghi chú trong liên kết cppreference mà tôi đưa vào nhưng thêm nó vào câu trả lời. –

0

Bạn đang xác định hàm chấp nhận luồng , sử dụng và sau đó trả về cùng một luồng.

Một sử dụng có thể có của nó sau:

#include <functional> 
#include <iostream> 
#include <vector> 

int main() { 
    std::vector<int> v(5, 3); 
    auto lmda = [&v](std::ostream& os) -> std::ostream& { os << v.size(); return os; }; 
    lmda(std::cout) << std::endl; 
} 
2

Một lambda không có chụp là chuyển đổi thành một pointer- chức năng.

[5.1.2/6] Loại đóng cho biểu thức lambda không chung chung không có lambda-capture có hàm chuyển đổi const không ảo rõ ràng công khai đến con trỏ để hoạt động với ngôn ngữ C++ liên kết (7.5) có cùng tham số và kiểu trả về làm toán tử gọi hàm của loại đóng. Giá trị được 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 tác dụng như gọi toán tử gọi hàm của loại đóng .

Một lambda chụp không thể chuyển đổi thành bất kỳ nội dung nào có thể in được.

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