#include <functional>
using namespace std;
template<class CharType>
void f1(CharType* str, function<bool(CharType)> fn_filter)
{}
template<class CharType>
void f2(CharType* str, function<bool(char)> fn_filter)
{}
void f3(char* str, char c)
{
auto fn_filter = [=](char e) -> bool
{
return e == c;
};
f1(str, fn_filter); // error C2784
f2(str, fn_filter); // OK
}
int main()
{
f3("ok", 'k');
}
// error C2784: 'void f1(CharType *,std::function<bool(CharType)>)'
// : could not deduce template argument for 'std::function<bool(CharType)>'
// from 'f2::<lambda_36be5ecc63077ff97cf3d16d1d5001cb>'
Мой компилятор VC ++ 2013.
Почему f1
не работает, как ожидалось?
Проблема для компилятора состоит в том, чтобы решить, какой из ваших параметров использовать для вывода типа. Если вы помогаете компиляции, нарушая возможный вывод из второго параметра и сила это использовать первый, он работает как положено:
template<typename T> struct identity { using type = T; };
template<class CharType>
void f1(CharType* str, typename identity<function<bool(CharType)>>::type fn_filter)
{}
Лямбда не имеет типа std::function<bool(char)>
это просто вызываемый объект с реализацией определенного типа.
Может быть переоборудованный в std::function<bool(char)>
, но это не помогает компилятору определить тип для случая шаблона. Там может быть, например, много возможностей для CharType
для которого лямбда может быть преобразована в std::function<bool(CharType)>
,
Компилятор пытается сопоставить тип лямбды с параметром функции шаблона. Лямбда имеет, например, такой тип lambda_t_1234
и параметр шаблона std::function<bool(CharType)>
, Типы не связаны, и не ясно, что CharType
должен быть здесь.
Это также не является особенным для лямбд или std::function<>
, То же самое происходит во всех таких случаях:
template<typename Char>
void f(const std::basic_string<Char> &str) {
}
Если вы попытаетесь вызвать эту функцию шаблона с char*
Параметр не будет работать, потому что связь с параметром шаблона не ясна.