The lambda can implicitly be converted to a function pointer, but that's not what's failing here. Rather, the compiler is failing to deduce T
because the lambda-to-function-pointer conversion doesn't happen during deduction.
main.cpp:5:6: note: template argument deduction/substitution failed:
main.cpp:21:16: note: mismatched types 'T (*)(T)' and '<lambda(int)>'
21 | map(v, mul3);
| ^
The compiler can make the connection between T(*)(T)
and int(*)(int)
and it can make the connection between int(*)(int)
and the lambda type, but it can't make the connection between T(*)(T)
and the lambda type.
You can fix this by making one of the two connections for it: explicitly specifying the function's template argument, or casting the lambda to the function pointer type. The first skips the deduction step an then the implicit lambda-to-function-pointer conversion succeeds. The second allows deduction to succeed because the second parameter is a compatible function pointer type.
// Option 1: Specifying T allows implicit conversion of the lambda to fnptr
map<int>(v, mul3);
// Option 2a: Cast of lambda to fnptr allows T to be deduced
map(v, static_cast<int(*)(int)>(mul3));
// Option 2b: Converting lambda to fnptr at mul3 initialization allows T to be deduced
int (*mul3)(int) = [](int value) {
return value * 3;
};
However, I would recommend fixing the issue a different way -- there's no reason the function has to work with vectors, function pointers, and ints. Why can't it work with linked lists, functors, and doubles? There's really no reason to constrain the types like this; just let them be whatever they are and see if the instantiation succeeds:
template <class TContainer, TFunction>
void map(TContainer & values, TFunction const & func) {
for (auto &value : values) {
value = func(value);
}
}