0

Why does not this work with lambdas? It only works when I assing lambda to std::function before calling the function I want. Doesn't work when I construct lambda in place or assign lambda to auto.

#include <functional>

template <typename R>
R foo (std::function<R()> fun)
{
    puts(__PRETTY_FUNCTION__);
}
int main()
{
    std::function<int()> lambda = []{ return 1; };
    foo (lambda); // --> OK

    foo ([]() -> int { return 1; } ); // --> ERROR

    auto lambda2 = []{ return 1; };
    foo (lambda2); // --> ERROR
}
YotKay
  • 1,127
  • 1
  • 9
  • 25
  • You should *really* return something from your `foo` function. Not returning anything, like you do in your MCVE, leads to [*undefined behavior*](http://en.cppreference.com/w/cpp/language/ub). – Some programmer dude Sep 27 '17 at 06:43
  • And do you *need* the function argument to be a `std::function` object? Can't it simply be a template? Like e.g. `template auto foo(F fun) -> decltype(fun()) { ... }`. – Some programmer dude Sep 27 '17 at 06:44
  • No, because I need to take the return type the lambda returns. As far as I know there is not trait for this. – YotKay Sep 27 '17 at 06:53
  • 1
    That's what the `decltype(fun())` thing does. It gets the return type of `fun` no matter if it's a lambda, a pointer to a function, or any other callable object. – Some programmer dude Sep 27 '17 at 06:54
  • You are right. That was what I was searching for. You solved my problem. Thank you :-) – YotKay Sep 27 '17 at 06:56
  • As a matter of fact I tried this approach earlier, with decltype, but I made an error and wrote "decltype(fun)" instead of "decltype(fun())" – YotKay Sep 27 '17 at 06:58

2 Answers2

2

The problem is that <R> is not deducible from the lambda. In fact, there are many types R such that std::function can hold your lambda.

When the argument provided is std::function<int()>, R can trivially be deduced as int(). But lambda's have their own unique type. It's not std::function.

MSalters
  • 173,980
  • 10
  • 155
  • 350
1

You need to add template parameter to foo:

foo<int> ([]() -> int { return 1; } ); // --> OK
foo<int> (lambda2); // --> OK
Zefick
  • 2,014
  • 15
  • 19