C++模板函数传入Lambda编译失败的原因及修复方法
C++代码编译失败的原因及修复方案
原代码
struct S { unsigned u; float f; S(unsigned u0, float f0) : u(u0), f(f0) {} }; template<typename T> bool contains(std::vector<T> vec, T elem, bool equivalent(const T&, const T&)) { // some implementation } int main() { std::vector<S> vec{{15, 17.8}}; std::cout << contains(vec, S(15,159.48), [](S& a, S& b) -> bool {return a.u == b.u;}) << std::endl; }
编译错误信息
main.cpp:32:18: error: no matching function for call to 'contains' std::cout << contains(vec, S(15,159.48), [](S& a, S& b) -> bool {return a.u == b.u;}) << std::endl; ^~~~~~~~ main.cpp:14:27: note: candidate template ignored: could not match 'bool (*)(const T &, const T &)' against '(lambda at main.cpp:32:46)' template<typename T> bool contains(std::vector<T> vec, T elem, bool equivalent(const T&, const T&))
错误原因
- 参数const限定不匹配:
contains的第三个参数要求是接受两个const T&类型参数的函数指针,但传入的lambda参数是S&(非const引用),类型无法匹配。 - 模板推导限制:即使lambda参数类型正确,无捕获lambda到函数指针的隐式转换不会被模板类型推导纳入考虑,进一步导致匹配失败。
修复方案
方案一:修正lambda参数类型
将lambda的参数改为const S&,使其类型与函数指针的要求一致,无捕获lambda可隐式转换为对应函数指针,即可通过编译:
std::cout << contains(vec, S(15,159.48), [](const S& a, const S& b) -> bool {return a.u == b.u;}) << std::endl;
方案二:改用模板化比较器(更推荐)
把contains的第三个参数改为模板类型,支持任意可调用对象(lambda、函数指针、仿函数等),同时优化参数传递避免不必要的拷贝:
template<typename T, typename Compare> bool contains(const std::vector<T>& vec, const T& elem, Compare equivalent) { for (const auto& item : vec) { if (equivalent(item, elem)) { return true; } } return false; }
调用时lambda可以保持简洁(建议仍用const S&参数避免不必要的拷贝):
std::cout << contains(vec, S(15,159.48), [](const S& a, const S& b) {return a.u == b.u;}) << std::endl;
内容的提问来源于stack exchange,提问作者Nicnajder
相关产品推荐
相关产品推荐

