使用lambda作为std :: cout的参数

时间:2015-10-23 09:29:01

标签: c++ c++11 lambda

我正在尝试使用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)

我不明白为什么它在第二个例子中失败了。 任何领导?

3 个答案:

答案 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;
}