我正在尝试使用lambda,在测试以下时,编译说'hi'。
auto lmda = [](std::ostream& os) -> std::ostream& { os << "hi"; return os; };
std::cout << lmda;
但是在添加捕获时,它不会编译。 例如:
std::vector<int> v(5, 3);
auto lmda = [&v](std::ostream& os) -> std::ostream& { os << v.size(); return os; };
std::cout << lmda;
构建错误是:
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)
我不明白为什么它在第二个例子中失败了。 任何领导?
答案 0 :(得分:6)
与without a capture is convertible to a function pointer匹配的lambda following overload:
basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );
正如cppreference链接说明:
调用func(* this);.这些重载用于实现输出I / O. 操纵者,如std :: endl。
草案C ++ 11标准部分5.1.2
[expr.prim.lambda] :
没有lambda-capture的lambda表达式的闭包类型有一个 public非虚拟非显式const转换函数指针 使用具有与闭包相同的参数和返回类型 type的函数调用运算符。此转换返回的值 function应该是一个函数的地址,当被调用时,它具有 与调用闭包类型的函数调用操作符
的效果相同
答案 1 :(得分:3)
没有捕获的lambda可以转换为指向函数的指针。
[5.1.2 / 6]没有lambda-capture的非泛型lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向C ++语言链接的函数(7.5) )拥有相同的 参数和返回类型作为闭包类型的函数调用操作符。此转换函数返回的值应为函数的地址,该函数在调用时具有与调用闭包相同的效果 type的函数调用操作符。
带捕获的lambda无法转换为可打印的任何内容。
答案 2 :(得分:1)
您正在定义一个接受流的函数,使用它然后返回相同的流。
可能的用途如下:
#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;
}