2

I have the following functions:

template <class InType, class OutType>
OutType foo(const InType &a, std::function<OutType (const InType &)> func)
{
    return func(a);
}

template <class T>
T bar(T a, T b)
{
    return a + b;
}

I can call them like so:

double x = foo<int, double>(1, [] (const int &v) { return float(v) * 1.5f; });
double y = bar<int>(1.0, 2.0);

...and use template argument deduction with bar

double z = bar(1.0, 2.0);

...but if I try to use template argument deduction with foo:

double w = foo(1, [] (const int &v) { return float(v) * 1.5f; });

It fails with this error:

no matching function for call to 'foo'
    double w = foo(1, [] (const int &v) { return float(v) * 1.5f; });
               ^~~
note: candidate template ignored: could not match 'function<type-parameter-0-1 (const type-parameter-0-0 &)>' against '(lambda at ../path/to/file.cpp:x:y)'
OutType foo(const InType &a, std::function<OutType (const InType &)> func)
        ^

Why is that? From my vantage point it's obvious what the argument types should be deduced as.

Bri Bri
  • 2,169
  • 3
  • 19
  • 44

1 Answers1

3

Type deduction does not consider implicit conversions, that happens later during overload resolution. If you were to pass a std::function directly, it would deduce properly. It can't implicitly construct a std::function from your lambda without the type of the std::function to know whether it's possible. I know to us it looks like there is enough information for the compiler to properly deduce the types involved, but this is a constraint.

David
  • 27,652
  • 18
  • 89
  • 138
  • Type deduction only considers *some* implicit conversions. Not ones that involve converting constructors. – Brian Bi Jul 29 '16 at 22:26
  • It's too bad this is the case. Otherwise it'd be possible to express some power logic without C++'s typical verbosity and template shenanigans. – Bri Bri Jul 29 '16 at 23:06