35

For the following code:

auto F(int count) -> decltype([](int m) { return 0; }) 
{                                                               
    return [](int m) { return 0; };                                  
}

g++ 4.5 gives the errors:

test1.cpp:1:32: error: expected primary-expression before 'int'
test1.cpp:1:32: error: expected ')' before 'int'

What is the problem? What is the correct way to return a lambda from a function?

HighCommander4
  • 50,428
  • 24
  • 122
  • 194

3 Answers3

46

You cannot use a lambda expression except by actually creating that object- that makes it impossible to pass to type deduction like decltype.

Ironically, of course, the lambda return rules make it so that you CAN return lambdas from lambdas, as there are some situations in which the return type doesn't have to be specified.

You only have two choices- return a polymorphic container such as std::function, or make F itself an actual lambda.

auto F = [](int count) { return [](int m) { return 0; }; };
Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 5
    +1 for clearing up the problem. I checked out the SC22-N-4411 draft and found sort of scary the phrase that says that "each lambda expression has a unique type". – 6502 Jan 31 '11 at 00:32
  • 4
    @6502: Yes, that fact made me realize why my executable size suddenly increased 10% due to `stable_sort`. – user541686 Aug 10 '12 at 19:01
  • It's not scary at all. Inlining makes your program execute faster. – Puppy Aug 14 '12 at 12:46
  • 3
    Why don't decltype(std::declval<[](){}>()) work? Isn't this what declval is for? To create an instance of a type in unevaluated context? Is there no way to prohibit dumb optimizers to allocate a function pointer on the stack? – Meteorhead Nov 04 '14 at 10:43
  • 1
    Not possible because for one, `[](){}` is not a type and therefore cannot be passed as a template parameter... but secondly because it simply doesn't actually make any sense. – Puppy Jul 14 '15 at 12:04
  • @Meteorhead `[](){}` isn't a type, so we'd need `std::declval`, which just leads back to the same problem. It's the chicken and the egg, basically: We can't deduce a lambda's type because it can't be passed to `decltype`, but we can't turn it into a `decltype`-friendly value because we'd need its type to do that. It's kinda annoying, really. – Justin Time - Reinstate Monica Dec 14 '16 at 23:08
12

With C++14, you can now simply omit the return type:

auto F(int count)
{
    return [](int m) { return 0; };
}
Zark Bardoo
  • 468
  • 5
  • 15
11

something like this fits your needs?

#include <functional>

std::function<int(int)> F(int count)
{                                                               
    return [](int m) { return 0; };                                  
}
Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112