为什么 std::function 不能接受推导类型作为其模板参数

Why can std::function not accept a deduced type as its template parameter?

本文关键字:参数 function std 不能接受 为什么 类型      更新时间:2023-10-16
#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不能按预期工作?

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应该在这里是什么。

这对 lambda 或 std::function<> 来说也不是特别的。在所有此类情况下都会发生同样的情况:

template<typename Char>
void f(const std::basic_string<Char> &str) {
}

如果尝试使用 char* 参数调用此模板函数,它将不起作用,因为与模板参数的连接不清楚。

编译器的问题是决定将哪些参数用于类型推导。如果您通过破坏第二个参数的可能推导来帮助编译并强制它使用第一个参数,则它会按预期工作:

template<typename T> struct identity { using type = T; };
template<class CharType>
void f1(CharType* str, typename identity<function<bool(CharType)>>::type fn_filter)
{}

现场示例