Why is this lambda streamable?
Asked Answered
C

1

11

To my surprise the following code prints 1.

std::cout << [](const char* arg){ return arg[0]=='s'; } << std::endl;

Can someone explain this, please?

Cavorelievo answered 10/7, 2017 at 2:31 Comment(2)
I think it's being converted to bool.Fragment
The interesting part would be if std::cin >> [](const char* arg){ return arg[0]=='s'; } worked. ;)Suck
B
12

It's converting to a function pointer, and then through that to a bool:

void foo ();
std::cout << &foo << std::endl;

Prints the same thing, and the same warnings; I happened to compile with gcc set to 17 standard and I saw:

main.cpp:6:56: warning: the address of 'static constexpr bool main()::<lambda(const char*)>::_FUN(const char*)' will never be NULL [-Waddress]
  std::cout << [](const char* arg){ return arg[0]=='s'; } << std::endl;

With the code above you see the same warning.

To add on a bit to my answer: there is a stream overload for void*. However, function pointers, unlike pointers to data, cannot implicitly convert to void*. The only implicit conversion for function pointers is boolean, and of course there is a stream operation for bool, so that overload is selected and that implicit conversion occurs. See: How to print function pointers with cout?.

Blasting answered 10/7, 2017 at 2:35 Comment(3)
@M.M The lambda is converting to a function pointer first, and then through that, to a bool. I didn't actually know that function pointers convert to bools when streamed, rather odd to be honest.Blasting
@NirFriedman That is totally reasonable. Per 8.1.5.1(6) of the current working draft of the standard, a captureless lambda has a conversion operator to pointer to function and per 7.14 a pointer can be implicitly converted to bool. The crucial point is that the second conversion happens implicitly which is why the two conversions are allowed. If it was a second user-defined conversion it wouldn't happen.Antenna
@HenriMenke Since lambdas functions are not really "user defined", I'm somewhat surprised that lambda -> function pointer is treated as a user-defined conversion. But yes, my comment about function pointers being streamed as booleans was just saying that at first glance it seems a bit surprising (and not very useful). Once you think a bit more about it makes sense, just an example of surprising behavior emerging from several reasonable things meeting.Blasting

© 2022 - 2024 — McMap. All rights reserved.