Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using lambda as parameter to std::cout

Tags:

c++

c++11

lambda

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?

like image 302
Mohamed B Avatar asked Oct 23 '15 09:10

Mohamed B


People also ask

How do you call a lambda in C++?

A lambda is also just a function object, so you need to have a () to call it, there is no way around it (except of course some function that invokes the lambda like std::invoke ). If you want you can drop the () after the capture list, because your lambda doesn't take any parameters.

Can std :: function store lambda?

Instances of std::function can store, copy, and invoke any CopyConstructible Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.

What is the correct syntax for lambda expression in C++11?

Lambdas can both capture variables and accept input parameters. A parameter list (lambda declarator in the Standard syntax) is optional and in most aspects resembles the parameter list for a function. auto y = [] (int first, int second) { return first + second; };

Is a lambda a std :: function?

Lambda's type One important thing to note is that a lambda is not a std::function .

How do you pass a lambda expression as a function parameter?

The simplest way is to use std::function as a function parameter. This would allow you to pass a function object or a lambda to the function. Does the C++ standard require that the type of a lambda expression with no captures be a function pointer or convertible to a function pointer?

Can lambda expressions have managed types in C++?

Using Lambda Expressions with Managed Types (C++/CLI) Example. The capture clause of a lambda expression cannot contain a variable that has a managed type. However, you can pass an argument that has a managed type to the parameter list of a lambda expression.

How does the compiler determine the return type of a Lambda?

If the lambda body contains one return statement, the compiler deduces the return type from the type of the return expression. Otherwise, the compiler deduces the return type as void.

Can you convert a lambda function to a function in C?

If the lambda does not capture any variables and you want a function pointer, it can be done; details are given at C++ | Converting captureless generic lambda to function pointers. If it does capture variables, and you want a function pointer, that just isn’t happening; capturing lambdas cannot be converted to functions.


3 Answers

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

like image 72
Shafik Yaghmour Avatar answered Oct 10 '22 03:10

Shafik Yaghmour


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.

like image 20
n. 1.8e9-where's-my-share m. Avatar answered Oct 10 '22 02:10

n. 1.8e9-where's-my-share m.


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;
}
like image 36
skypjack Avatar answered Oct 10 '22 04:10

skypjack