9

I'm wondering why in the following code the compiler is unable to use lambda as the argument for function foo() (template argument deduction/substitution failed), while a simple function works:

template<class ...Args>
void foo(int (*)(Args...))
{
}

int bar(int)
{
    return 0;
}

int main() {
    //foo([](int) { return 0; }); // error
    foo(bar);
    return 0;
}

The intel compiler (version 18.0.3 )

template.cxx(12): error: no instance of function template "foo" matches the argument list
            argument types are: (lambda [](int)->int)
      foo([](int) { return 0; }); // error
      ^
template.cxx(2): note: this candidate was rejected because at least one template argument could not be deduced
  void foo(int (*)(Args...))

Any ideas?

songyuanyao
  • 147,421
  • 15
  • 261
  • 354
krojew
  • 1,116
  • 10
  • 30
  • Possible duplicate of [Passing a lambda into a function template](https://stackoverflow.com/questions/40235053/passing-a-lambda-into-a-function-template) – Daniel Langr Jul 20 '18 at 06:58

1 Answers1

9

Template argument deduction doesn't consider implicit conversion.

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.

You can convert the lambda to function pointer explicitly, e.g. you can use static_cast,

foo(static_cast<int(*)(int)>([](int) { return 0; }));

or operator+,

foo(+[](int) { return 0; });
songyuanyao
  • 147,421
  • 15
  • 261
  • 354
  • 1
    Is the `+` trick still considered to be a hack or does it start to be an idiom? I'm not asking if it's well defined, I know it is; just does it adds to the #wtf/line of the code base? – YSC Jul 20 '18 at 07:13
  • @YSC I don't know, [it](https://stackoverflow.com/q/18889028/3309790)'s quite opinion-based. I like it personally because it looks quite natural to me. – songyuanyao Jul 20 '18 at 07:25
  • Why not just `+` instead of that cast? – Yakk - Adam Nevraumont Jul 20 '18 at 10:34
  • @Yakk-AdamNevraumont Its intent might be not clear enough; so you agree to consider it as an idiom as YSC said? – songyuanyao Jul 20 '18 at 10:44
  • 1
    I guess; but non-surprising magic is less wtf than surprising magic. There is a narrow level of expertise where "you cannot pass that lambda to a template function expecting a function pointer" surprises yet "oh operator+" dorsn't remove it; outside of that window, the code does what you'd expect and does nothing surprising. If `+` failed to do the "obvious" thing I'd say it is a harmful wtf. – Yakk - Adam Nevraumont Jul 20 '18 at 11:12
  • @Yakk-AdamNevraumont I got what you mean, and agreed. – songyuanyao Jul 20 '18 at 11:18