7

The code below was compiled without error:

std::string lastName, chldName;
while([&]()
{
      return true;
})
{
  //codes...
}   

But when I tried this way:

std::string lastName, chldName;
while([&]()
{
      std::cin >>lastName;
      return true;
})
{
  //codes...
}   

The compiler complained that :

error: could not convert 'main()::{(* & lastName)}' from 'main()::' to 'bool'

How to understand this error?Is it possible to use lambda this way?

Yue Wang
  • 1,710
  • 3
  • 18
  • 43

3 Answers3

10

Your first example works not how you want, it's equivalent to while (true), since lambda will be converted to function-pointer, that will be converted to bool (true) - it should be

while([&]()
{
   return true;
}())

Note to call of lambda

Your second example will not compile without call of lambda, since you are trying to access to catched-variables, thats forbids conversion from lambda to function-pointer, that can be converted to bool, but it will neither compiled with (),

If a lambda-expression does not include a trailing-return-type, it is as if the trailing-return-type denotes the following type:

— if the compound-statement is of the form { attribute-specifier-seqopt return expression ; } the type of the returned expression after lvalue-to-rvalue conversion (4.1), array-to-pointer conver- sion (4.2), and function-to-pointer conversion (4.3);

— otherwise, void.

In your case, return type will be deduced to void, but since you return bool, you should use trailing-return-type

while([&]() -> bool
{
      std::cin >>lastName;
      return true;
}())
ForEveR
  • 55,233
  • 2
  • 119
  • 133
5

There is no need to explicitly express the return type,the issue is that you are asking the while loops condition whether the lambda function its self is true, rather than the value it returns.

You actually need to the call lambda function in the loop condition.

while([] {
    return true;
 }()) {
 ///....
 }

EDIT

The reason the first compiles and the second doesn't is because the first doesn't capture anything. The standard allows this to then be converted to a normal function pointer which can be evaluated as a bool (nullptr being false).

The second captures, which stops the compiler from converting it to a function pointer and thus doesn't compile.

111111
  • 15,686
  • 6
  • 47
  • 62
  • Is the same problem you would have with a named funcion: `while(returnTrue())` would work, `while(returnTrue)` would not. – Coffee on Mars Dec 16 '13 at 10:25
  • 1
    @CoffeeonMars A function name can be converted to a function pointer, which in turn can be converted to `bool`. Therefore, `while(foo)` *does* compile for some function `foo`, e.g. `void foo();`. – dyp Dec 16 '13 at 10:26
  • @DyP you are correct, I forgot that conversion. For the sake of completeness, it rises a warning on VC2012. – Coffee on Mars Dec 16 '13 at 10:29
  • AFAIK, the Standard *does not* allow the first to be converted to a function pointer; even though it doesn't capture anything it still has a lambda-capture. See [expr.prim.lambda]/6 – dyp Dec 16 '13 at 10:29
  • @111111 I need a little bit of time to think about your reply, many thanks. – Yue Wang Dec 16 '13 at 10:39
1

Note that in your code you're NOT CALLING the lambda.

while([&]()
{
      return true;
})

With no call it's not the lambda's return value that is problematic.

A lambda that doesn't capture anything can be implicitly converted to function pointer, which in turn can convert to bool.

The following compiles with g++ 4.7.2, but not with Visual C++ 12.0:

int main()
{
    if( [](){} ) {}
}

The following, where the lambda does capture (and thus cannot be converted), doesn't compile with either compiler:

int main()
{
    int x;
    if( [&](){(void)x;} ) {}
}
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • Which applies to both examples; but AFAIK neither should compile. – dyp Dec 16 '13 at 10:20
  • @DyP: an implicit conversion pointer was used by C++03 isotreams, to provide implicit conversion to `bool`. – Cheers and hth. - Alf Dec 16 '13 at 10:31
  • I'm not sure what iostreams have to do with this example o.O Anyway, the Standard specifies the existence of the function-pointer conversion depending on the existence of a *lambda-capture* (the thing inside the `[]`), not if the lambda captures anything. Which makes the first example `while([&]{ return true; })` ill-formed as well. – dyp Dec 16 '13 at 10:33
  • @Cheersandhth.-Alf I need a little bit of time to read and think about your reply, many thanks! – Yue Wang Dec 16 '13 at 10:40
  • @Dyp: Regarding ill-formed-ness you're correct, i.e. that this is a g++ compiler defect. However, I think most people read your comment as meaning that this answer was incorrect: in spite of being the first correct answer, it got no votes. Anyway, the formal: C++11 §5.1.2/3 "An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than ...", where the following list does not include a conversion. Para 6 which you cited as formal cause is only relevant for in-practice understanding the bug. – Cheers and hth. - Alf Dec 16 '13 at 12:30
  • Well I think the OP's problem was the missing `()` to call the lambda (which you didn't state in the original version of your answer); of course my comment wasn't meant to imply that your answer is wrong. I had a discussion already about adding features to closure types, see [these comments](http://stackoverflow.com/questions/17822131/resolving-ambiguous-overload-on-function-pointer-and-stdfunction-for-a-lambda/17822241#comment26037403_17822241). Applying the same reasoning here would mean that there shall be no such conversion operator for lambdas with a lambda-capture. – dyp Dec 16 '13 at 12:41
  • @Dyp: Uhm, from that discussion, Daniel Krügler handles defect reports and such. And also from that discussion, clc++m is *not* an authority in itself, although in my biased opinion (I'm a clc++m mod) quite a bit more authoritative than SO. Now Usenet is largely dead, but still the only clc++m rejection reason for content, apart from format, signature, attachments and non-English, is whether an article is about too basic stuff. Anybody is free to make any claim whatsoever, and have the article published. :-) And yes it works. – Cheers and hth. - Alf Dec 16 '13 at 12:49