1

I am trying to execute the following code in C++. The program converts a lambda with no capture to a function pointer.

#include <utility>

template <typename R, typename... Args>
R run(R (*func)(Args...), Args&&... args) {
        func(std::forward<Args>(args)...);
}

int main() {
        run([] (int x, int y) {
            return x + y;
        }, 100, 200);
        return 0;
}

However, when I compile it, I get the following error -

test.cc: In function ‘int main()’:
test.cc:11:20: error: no matching function for call to ‘run(main()::<lambda(int, int)>, int, int)’
         }, 100, 200);
                    ^
test.cc:11:20: note: candidate is:
test.cc:4:3: note: template<class R, class ... Args> R run(R (*)(Args ...), Args&& ...)
 R run(R (*func)(Args...), Args&&... args) {
   ^
test.cc:4:3: note:   template argument deduction/substitution failed:
test.cc:11:20: note:   mismatched types ‘R (*)(Args ...)’ and ‘main()::<lambda(int, int)>’
         }, 100, 200);
                    ^

As far as I am aware this is fine. I have also tried explicitly giving the template arguments in the call to run. That doesnt work either.

Any ideas?

ssb
  • 7,422
  • 10
  • 36
  • 61
  • 3
    `run(+[](int x, int y){ return x+y; }, 100, 200)` will work fine ;) – dyp Jul 02 '15 at 16:39
  • 1
    What does the `+` do? – ssb Jul 02 '15 at 16:40
  • 2
    Forces a conversion to a function pointer (the operand of unary + has a limited number of supported types). – chris Jul 02 '15 at 16:40
  • 1
    It's one of the most silly ways to confuse readers of your source code. The actual issue in your code is that a lambda *is not a function* (nor a function pointer), and hence the pattern matching for function pointers (in the function parameter `func` of `run`) cannot be applied to it. – dyp Jul 02 '15 at 16:42

1 Answers1

4

A lambda is not a function pointer. It cannot be deduced as a function pointer. It is a closure. However, if (and only if) it takes no capture, it can be explicitly converted to a function pointer via some sorcery:

    run(+[] (int x, int y) {
    //  ^^^
        return x + y;
    }, 100, 200);

That said, it'd be better to simply have run take an arbitrary callable:

template <typename F, typename... Args>
auto run(F func, Args&&... args) 
    -> decltype(func(std::forward<Args>(args)...)) // only for C++11
{ 
    return func(std::forward<Args>(args)...);
}
Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977