#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
无法按预期工作?
答案 0 :(得分:8)
lambda没有类型std::function<bool(char)>
,它只是一些具有实现定义类型的可调用对象。
它可以转换到std::function<bool(char)>
,但这无助于编译器推断出模板案例的类型。例如,CharType
可能有很多可能性,lambda可以转换为std::function<bool(CharType)>
。
编译器尝试将lambda的类型与模板函数的参数进行匹配。 lambda具有类似lambda_t_1234
的类型,模板参数为std::function<bool(CharType)>
。这些类型是不相关的,并且不清楚CharType
应该在这里。
这对lambdas或std::function<>
也不是特别的。在所有这些情况下都会发生同样的情况:
template<typename Char>
void f(const std::basic_string<Char> &str) {
}
如果您尝试使用char*
参数调用此模板函数,它将无效,因为与模板参数的连接不明确。
答案 1 :(得分:4)
编译器的问题是决定使用哪个参数进行类型推导。如果你通过从第二个参数中删除可能的扣除来帮助编译,并且强制它使用第一个参数,它就按预期工作:
template<typename T> struct identity { using type = T; };
template<class CharType>
void f1(CharType* str, typename identity<function<bool(CharType)>>::type fn_filter)
{}