1

This question is related to this one.

Why doesn't this compile:

int main() {
    auto foo = [&]() -> int {foo; return {};}();
    (void)(foo);
}

LIVE on Coliru

Error:

main.cpp: In lambda function:
main.cpp:3:30: error: use of 'foo' before deduction of 'auto'
     auto foo = [&]() -> int {foo; return {};}();
                              ^~~

But casting foo to the resulting type allows compilation:

int main() {
    auto foo = [&]() -> int {int(foo); (void)(foo);return {};}();
    (void)(foo);
}

LIVE on Coliru

Community
  • 1
  • 1
xinaiz
  • 7,744
  • 6
  • 34
  • 78

1 Answers1

5

Vexing parses again. If something can be a declaration, it is a declaration.

int(foo); is int (foo); is int foo;. Then the foo in (void)(foo); refers to the int.


The first snippet runs into [dcl.spec.auto]/10:

If the type of an entity with an undeduced placeholder type is needed to determine the type of an expression, the program is ill-formed.

The type of foo is needed to determine the type of the expression foo within the lambda body, but at that point you haven't deduced foo's type yet, so the program is ill-formed.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • As I get it, it's only half an answer. I guess OP would like to know a workaround and use `foo` inside the lambda. – YSC Mar 27 '17 at 19:03
  • I understand. But why doesn't the first example compile since foo type should be known since lambda has explicit return type? – xinaiz Mar 27 '17 at 19:08
  • 1
    @BlackMoses To add a bit more info: a lambda's type depends on its body (for example, figuring out which entities are captured and become members of the generated class). Its type is not determined solely by its parameters and return type. You then made its body depend on its type by your capture. –  Mar 27 '17 at 19:23