Ant*_*kov 2 c++ lambda templates functional-programming template-argument-deduction
如果您有以下过滤列表模板:
template <typename T>
inline std::list<T> list_filter(std::list<T> const& a, bool (f)(T)) {
std::list<T> output;
std::copy_if(a.begin(), a.end(), std::back_inserter(output), f);
return output;
}
Run Code Online (Sandbox Code Playgroud)
然后尝试使用里面的 lambda 调用它,例如:
std::list<int> lst = {1,2,3,4,5};
auto filtered = list_filter(lst, [](int el) -> bool { return (el % 2 == 0); });
Run Code Online (Sandbox Code Playgroud)
它将产生错误no matching function for call to list_filter(..., std::__cxx11::list<int>)::<lambda(int)>)'。
有没有办法绕过这个限制而不将 lambda 提取到单独的函数中?为什么 C++ 不允许这种明显的模式?
在模板参数推导中不会考虑隐式转换(从没有捕获列表的 lambda 到函数指针),它无法T在第二个函数参数上推导出模板参数。
类型推导不考虑隐式转换(上面列出的类型调整除外):这是重载解析的工作,稍后会发生。
您可以通过static_cast, 或将 lambda 显式转换为函数指针operator+。例如
auto filtered = list_filter(lst, +[](int el) -> bool { return (el % 2 == 0); });
Run Code Online (Sandbox Code Playgroud)
或者使用std::type_identity(C++20 起)从推导中排除第二个函数参数。例如
template <typename T>
inline std::list<T> list_filter(std::list<T> const& a, bool (f)(std::type_identity_t<T>)) {
...
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,type_identity如果您的编译器不支持 C++20,您可以轻松制作自己的。