std::function作为模板参数时传入普通函数编译匹配失败如何解决
问题原因
C++模板参数推导阶段不会执行隐式类型转换,仅会对输入参数的原始类型做匹配。你定义的run模板函数第三个参数是std::function<double(const T &, const T &)>类型,而调用时传入的scoreValue1、scoreValue2是普通函数指针类型double (*)(const data_t &, const data_t &),二者并非同一类型,无法通过函数指针推导出std::function对应的模板参数T。即使前两个vector参数已经可以确定T是data_t,但所有出现模板参数T的位置推导结果必须完全一致,最终导致模板匹配失败,触发对应报错。
解决方法
提供三种常用的可行方案,可根据场景选择:
- 方案1:调用时手动指定模板参数,跳过编译器推导步骤
调用run函数时直接指定T为data_t,后续函数指针可以正常隐式转换为对应std::function类型:run<data_t>(dataA, dataB, scoreValue1); run<data_t>(dataA, dataB, scoreValue2); - 方案2:将可调用对象单独作为模板参数(推荐)
修改run函数的模板定义,把第三个参数的类型单独设为模板参数,既可以规避类型推导问题,还能避免std::function的类型擦除开销,同时支持传入函数指针、lambda、仿函数、std::function等所有符合调用签名的可调用对象:
该方案下原调用代码不需要做任何修改即可正常编译运行。template <class T, class Fn> void run(const std::vector<T> & dataA, const std::vector<T> & dataB, Fn function) { double value = 0; for(size_t i=0; i<dataA.size(); ++i) value += function(dataA[i], dataB[i]); std::cout << value << std::endl; } - 方案3:调用时手动将函数指针封装为
std::function
传参时主动把函数指针转换为匹配的std::function类型,C++17及以上版本可以直接使用类模板参数推导简化写法:
低版本C++需要显式写出run(dataA, dataB, std::function(scoreValue1)); run(dataA, dataB, std::function(scoreValue2));std::function的模板参数:run(dataA, dataB, std::function<double(const data_t&, const data_t&)>(scoreValue1)); run(dataA, dataB, std::function<double(const data_t&, const data_t&)>(scoreValue2));
内容的提问来源于stack exchange,提问作者thewoz
相关产品推荐
相关产品推荐

