Mohamed B
Mohamed B

Reputation: 83

Using lambda as parameter to std::cout

I am experimenting with lambda use and when testing the following it compile say 'hi'.

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

But when adding capture, it does not compile. Example:

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

Build error is:

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)

I don't get why it fails in the second example. Any lead?

Upvotes: 8

Views: 3912

Answers (3)

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158599

A lambda without a capture is convertible to a function pointer which will match the following overload:

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

As the cppreference links notes:

Calls func(*this);. These overloads are used to implement output I/O manipulators such as std::endl.

from the draft C++11 standard section 5.1.2 [expr.prim.lambda]:

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator

Upvotes: 7

n. m. could be an AI
n. m. could be an AI

Reputation: 120049

A lambda with no capture is convertible to a pointer-to-function.

[5.1.2/6] The closure type for a non-generic lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function with C ++ language linkage (7.5) having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.

A lambda with capture is not convertible to anything printable.

Upvotes: 3

skypjack
skypjack

Reputation: 50548

You are defining a function that accepts a stream, uses it and then return the same stream.

A possible use of it follows:

#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;
}

Upvotes: 2

Related Questions