如何编写接收一个double参数和偶数个int参数的函数模板的正确语法?
如何编写接收一个double参数和偶数个int参数的函数模板的正确语法?
看起来你是想写一个编译时展开的求和函数,计算sum(t_k * p^ex_k),但混淆了模板参数包和函数参数包的区别,这也是你代码出错的核心原因。我来一步步帮你理清思路,给出正确的实现。
首先拆解你的核心需求:
- 输入:一个
double p,然后偶数个int(每两个一组,分别是系数t_k和指数ex_k) - 输出:所有
t_k * p^ex_k的和,且求和的项数在编译时确定
你原来代码的核心问题
你之前写的template<int... xs>是非类型模板参数包——这些是编译时固定的int值,需要在调用函数时作为模板参数显式指定(比如xfun<2,2,3,3>(0.1)),但你想把int作为函数参数传递,这完全是两个不同的概念。你真正需要的是函数参数包:也就是在函数调用时传递的可变数量参数,对应的模板应该用类型参数包typename... Ints。
正确的实现(C++11/14/17通用)
我们用递归展开参数包的方式实现,配合终止函数完成求和,同时加上编译期检查确保参数合法:
#include <cmath> #include <cstdio> #include <type_traits> // 终止条件:当只剩double参数时,返回0(递归结束) double xfun(double) { return 0.0; } // 递归展开:每次处理一对(t, ex),剩下的参数包继续递归 template<typename... Ints> double xfun(double p, int t, int ex, Ints... remaining_ints) { // 编译期检查:剩下的所有参数必须是int static_assert((std::is_same_v<Ints, int> && ...), "所有后续参数必须是整数!"); // 编译期检查:剩余参数的数量必须是偶数(保证每两个一组) static_assert((sizeof...(remaining_ints) % 2 == 0), "整数参数的总数必须是偶数!"); // 计算当前项,加上剩余参数的递归结果 return t * std::pow(p, ex) + xfun(p, remaining_ints...); } int main () { // 预期结果:0.0234 = 2*0.1² + 3*0.1³ +4*0.1⁴ printf ("x = %f\n", xfun (0.1, 2,2, 3,3, 4,4)); // 预期结果:0.56 =5*0.1¹ +6*0.1² printf ("x = %f\n", xfun (0.1, 5,1, 6,2)); }
代码细节解释
- 终止函数:当递归到只剩
double p时,返回0,结束递归链条。 - 递归函数:
- 接收
double p、一对int(t和ex),然后是剩余的参数包remaining_ints static_assert是编译期检查,提前拦截非法输入(比如传递非int参数、奇数个int参数),避免运行时踩坑- 计算当前项
t * pow(p, ex),然后递归调用xfun处理剩下的参数包
- 接收
为什么你之前用int...会失败?
如果你写成:
template<int... Ints> double xfun(double p, int t, int ex, Ints... remaining_ints) { ... }
这里的int... Ints是非类型模板参数包,编译器会认为你要传递编译时固定的int值作为模板参数,比如:
// 这种写法才符合非类型模板参数包的调用逻辑,但完全不符合你的需求 xfun<3,3,4,4>(0.1, 2, 2);
而你希望的是把int作为函数参数传递,所以这种写法完全不匹配,编译器自然会报错。
总结
- 用类型参数包
typename... Ints配合函数参数包来接收可变数量的int参数 - 写终止函数处理递归结束的边界情况
- 加上编译期检查确保参数合法,提前发现错误
- 一定要区分开模板参数包(编译时常量)和函数参数包(运行时传递的参数),不要混淆两者的用法
这段代码直接编译运行就能得到你预期的结果,完全满足你的需求~




