C++泛型函数组合报错:无法推导模板参数A
C++泛型函数组合编译错误解决
我想练习C++中的函数组合(定义为x ↦ f(g(x))),先实现了基于int类型的版本,运行正常;但改成模板泛型后,调用compose(square, inc)时出现编译错误:couldn't deduce template parameter A,相关代码如下:
原可运行代码
int inc(int x) { return x + 1; } int square (int x) { return x * x; } std::function<int (int) > compose(std::function<int (int) > f, std::function<int (int) > g) { return [=](int x) { return f(g(x)); }; } int main() { auto op = compose(square, inc); std::cout<<op(6)<<"\n"; }
泛型报错代码
template<typename A> A inc(A x) { return x + 1; } template<typename A> A square(A x) { return x * x; } template<typename A, typename B, typename C> std::function<C (A) > compose(std::function<C (A)> f, std::function<A (B) > g) { return [=](A x) { return f(g(x)); }; } int main() { auto op = compose(square, inc); // <- 错误位置 std::cout<<op(6)<<"\n"; }
错误原因
核心问题在于模板参数推导与std::function的隐式转换冲突:
- 原int版本中,
inc和square是具体的int(int)类型函数,编译器可以自动将它们隐式转换为std::function<int(int)>,完成compose的参数匹配。 - 泛型版本中,
inc和square是函数模板而非具体函数实体。C++无法直接将未实例化的模板隐式转换为std::function,导致模板参数A、B、C无法被推导。
解决方法
方法1:显式实例化模板函数
调用compose时直接指定模板函数的实例化类型,让编译器生成具体函数实体:
auto op = compose(square<int>, inc<int>);
方法2:修改compose模板,直接推导可调用对象类型
放弃用std::function作为参数,直接推导传入的可调用对象类型,避免隐式转换问题。C++14及以上可使用泛型lambda实现:
template<typename F, typename G> auto compose(F f, G g) { return [=](auto x) { return f(g(x)); }; }
这种写法无需手动指定类型,兼容性和灵活性更强。如果是C++11,可通过decltype和std::result_of推导类型:
#include <type_traits> template<typename F, typename G> auto compose(F f, G g) -> decltype(f(g(std::declval<typename std::result_of<G(int)>::type>()))) { return [=](typename std::result_of<G(int)>::type x) { return f(g(x)); }; }
方法3:显式构造std::function传入
手动将模板函数实例化后包装为std::function对象,再传递给compose:
std::function<int(int)> f = square<int>; std::function<int(int)> g = inc<int>; auto op = compose(f, g);
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

