C++ 如何绕过C++;无法将模板中的函数类型与lambda匹配

C++ 如何绕过C++;无法将模板中的函数类型与lambda匹配,c++,templates,lambda,functional-programming,template-argument-deduction,C++,Templates,Lambda,Functional Programming,Template Argument Deduction,如果您有以下用于筛选列表的模板: 模板 内联标准::列表过滤器(标准::列表常量和a,布尔(f)(T)){ std::列表输出; std::copy_if(a.begin(),a.end(),std::back_插入器(输出),f); 返回输出; } 然后试着用里面的lambda来称呼它,比如: std::list lst={1,2,3,4,5}; 自动筛选=list_filter(lst,[](int el)->bool{return(el%2==0);}); 它将为调用列表过滤器(…,s

如果您有以下用于筛选列表的模板:

模板
内联标准::列表过滤器(标准::列表常量和a,布尔(f)(T)){
std::列表输出;
std::copy_if(a.begin(),a.end(),std::back_插入器(输出),f);
返回输出;
}
然后试着用里面的lambda来称呼它,比如:

std::list lst={1,2,3,4,5};
自动筛选=list_filter(lst,[](int el)->bool{return(el%2==0);});
它将为调用列表过滤器(…,std::。\ucxx11::列表)::)生成
没有匹配函数的错误。

有没有办法绕过该限制而不将lambda提取到单独的函数中?为什么C++不允许这种明显的模式?< /P> < P>隐式转换(从lambda没有捕获列表到函数指针)不会被考虑进去,它不能在第二个函数参数上推导模板参数<代码> t>代码>

类型演绎不考虑隐式转换(除了上面列出的类型调整):这是以后发生的工作。

您可以通过
static\u cast
操作符+
将lambda显式转换为函数指针。e、 g

auto filtered = list_filter(lst, +[](int el) -> bool { return (el % 2 == 0); });
或者使用(从C++20开始)从推导中排除第二个函数参数。e、 g

template <typename T>
inline std::list<T> list_filter(std::list<T> const& a, bool (f)(std::type_identity_t<T>)) {
    ...
}
模板
内联标准::列表过滤器(标准::列表常量和a,布尔(f)(标准::类型标识){
...
}

顺便说一句,如果您的编译器不支持C++20,您可以轻松地创建自己的
type_标识。

带有捕获的lambda与函数指针不兼容(这就是参数
f

对于可调用对象,我建议您从标准库本身得到一个提示:对整个可调用对象使用模板参数:

template <typename T, typename F>
inline std::list<T> list_filter(std::list<T> const& a, F f) {
    std::list<T> output;
    std::copy_if(a.begin(), a.end(), std::back_inserter(output), f);
    return output;
}
模板
内联标准::列表过滤器(标准::列表常量&a,F){
std::列表输出;
std::copy_if(a.begin(),a.end(),std::back_插入器(输出),f);
返回输出;
}

这是一个有趣的工程:
std::type_identity\u t
@Const有关详细信息,请参阅。@AntonKochkov是的,caputring lambdas无法转换为函数指针。您可以将函数参数从函数指针更改为
std::function
,(与函数指针相同的演绎问题,也需要上面的解决方案,即使用
std::function
),或者按照@someprogrammerdude的建议,直接传递lambda。@宋元耀能否提供有关这一行的一些信息:+[](int-el)->bool{return(el%2==0);}@Const如果您感兴趣,我最近特别写了一篇关于使用类型标识映射控制模板参数推断的文章,通过将参数放置在非推断上下文中来删除参数。为什么需要为参数指定签名?只需为可调用对象使用单独的模板参数即可。@super为了清晰起见。为了避免误用。当callable被传递到
copy\u if
时,它需要有正确的签名,否则将产生编译时错误。在这方面你真的一无所获。