如何将模板化std::function作为参数?修复二维vector遍历函数匹配错误
修复二维vector遍历函数的编译错误:
no matching function for call to ‘each(...)’ 问题重现
我想要为二维vector编写一个each遍历函数,但出现编译错误:
error: no matching function for call to ‘each(std::vector<std::vector<int> >&, main()::<lambda(int&)>)’,附上代码如下:
#include <iostream> #include <vector> #include <functional> using namespace std; template <class VarType> void each(vector<vector<VarType>> &ve, function<void (VarType &)> action) { for(vector<VarType> &v : ve) { for(VarType &p : v) { action(p); } } } int main() { vector<vector<int>> map(5); for(vector<int> &ve : map) { ve.resize(4); } each(map, [](int &val) { val = 1; }); }
错误原因分析
这个编译错误的核心是模板参数推导失败:编译器需要同时推导VarType并匹配std::function<void(VarType&)>的类型,但lambda是一个匿名 functor 类型,并非std::function本身。编译器无法从lambda自动推导出VarType来实例化std::function,最终导致模板匹配失败。
解决方案
以下是三种可行的修复方案,按推荐程度排序:
方案1:将函数对象改为独立模板参数(推荐)
把each的第二个参数改成独立的模板参数,让编译器直接推导任何可调用对象的类型(包括lambda、函数指针、自定义functor等),同时避免std::function带来的类型擦除开销:
#include <iostream> #include <vector> using namespace std; // 修改后的each函数:Func是独立的模板参数 template <class VarType, class Func> void each(vector<vector<VarType>> &ve, Func action) { for(vector<VarType> &v : ve) { for(VarType &p : v) { action(p); } } } int main() { vector<vector<int>> map(5); for(vector<int> &ve : map) { ve.resize(4); } // 直接调用,无需额外转换 each(map, [](int &val) { val = 1; }); // 验证结果 for(auto &row : map) { for(int val : row) { cout << val << " "; } cout << endl; } }
该方案通用性强、性能最优,完全适配所有可调用类型。
方案2:显式指定模板参数调用
如果你想保留std::function的函数声明,可以在调用each时手动指定VarType的类型,帮编译器完成推导:
// 原each函数定义不变 int main() { // ... 初始化代码不变 // 显式指定模板参数<int> each<int>(map, [](int &val) { val = 1; }); }
这种方法无需修改函数定义,但灵活性稍差,每次调用都要手动指定类型。
方案3:显式转换lambda为std::function
也可以把lambda手动转换成std::function<void(int&)>,让编译器能匹配到模板:
// 原each函数定义不变 int main() { // ... 初始化代码不变 each(map, std::function<void(int&)>([](int &val) { val = 1; })); }
该方法无需修改函数,但会引入std::function的类型擦除开销,性能不如方案1。
内容的提问来源于stack exchange,提问作者Kang Tae Jong
相关产品推荐
相关产品推荐

