Лямбда может быть неявно преобразована в указатель на функцию, но здесь не этого. Скорее, компилятор не может вывести T
, потому что преобразование лямбда-указателя в указатель на функцию не происходит во время вывода.
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);
| ^
Компилятор может установить соединение между T(*)(T)
и int(*)(int)
и он может установить связь между int(*)(int)
и лямбда-типом, но не может установить связь между T(*)(T)
и лямбда-типом.
Вы можете исправить это, выполнив одно из двух подключений для него: явное указание аргумента шаблона функции или приведение лямбды к типу указателя функции. Первый пропускает этап вывода, а затем успешно выполняется неявное преобразование лямбда-указателя в указатель на функцию. Второй позволяет сделать вывод, потому что второй параметр является совместимым типом указателя функции.
// 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;
};
Однако я бы рекомендовал исправить проблему другим способом - нет причин, по которым функция должна работать с векторами, указателями на функции и целыми числами. Почему он не может работать со связанными списками, функторами и двойниками? На самом деле нет причин ограничивать такие типы; просто позвольте им быть тем, чем они являются, и посмотрите, удастся ли создать экземпляр:
template <class TContainer, TFunction>
void map(TContainer & values, TFunction const & func) {
for (auto &value : values) {
value = func(value);
}
}