为何无法自动推导不同类型的模板参数?需显式指定类型吗?
你的问题出在两个模板参数的推导逻辑上,拆解来看:
1. T1的推导冲突
你的模板函数要求两个输入参数都是T1类型,但调用时传入的是int(2)和double(3.2)。编译器在推导T1时,会从第一个参数得出T1=int,从第二个参数得出T1=double,这两个结果矛盾,直接导致模板推导失败,所以编译器报“找不到匹配的重载函数”。
2. T2无法被推导
C++的模板参数推导不能从返回值反向推导——也就是说,你用auto接收返回值的操作,无法让编译器反推出T2的类型。T2作为返回值类型,没有任何输入来源可以让编译器自动确定它,必须要么显式指定,要么通过其他方式(比如默认模板参数)来确定。
为什么显式指定<double, double>能运行?
当你显式指定模板参数时,相当于直接告诉编译器:T1=double,T2=double。这时候,传入的int类型的2会被隐式转换成double,两个参数类型统一;返回值类型也明确为double,完全符合函数的定义,所以编译通过。
必须显式指定类型吗?不用,你可以修改模板设计
如果你不想每次调用都显式写模板参数,可以调整模板的定义方式:
方案1:让编译器自动推导返回值(C++14+)
把返回值改成auto,让编译器根据函数内表达式的类型自动推导返回值,同时放开两个参数的类型限制,不用强制为同一个T1:
template <typename T1, typename T2> auto Calculation(T1 arg_one, T2 arg_two) { return arg_one + arg_two * 3.14; }
这样调用Calculation(2, 3.2)时,T1推导为int,T2推导为double,返回值由arg_one + arg_two *3.14的结果类型(double)决定,完全不需要手动指定模板参数。
方案2:给返回值参数加默认类型(C++11+)
如果你需要保留返回值的模板参数,可以用std::common_type_t给返回值参数加一个默认值,让它自动取两个输入参数的共同类型:
#include <type_traits> template <typename T1, typename T2, typename R = std::common_type_t<T1, T2>> R Calculation(T1 arg_one, T2 arg_two) { return static_cast<R>(arg_one + arg_two * 3.14); }
这种方式下,调用时可以省略R的指定,编译器会自动用两个输入参数的共同类型作为返回值类型;你也可以在需要的时候显式指定R,比如Calculation<int, double, float>(2, 3.2)来强制返回float类型。
内容的提问来源于stack exchange,提问作者user19245401

