我见过这些问题:
但他们不考虑可变参数函数和可变参数模板。
考虑编写函数以找到2或3个正数的平均值的问题。
我们可以通过四种方式实现此功能:
使用默认参数:
int average(int x , int y , int z=-1);
使用函数重载:
int average(int x , int y);
int average(int x , int y , int z);
int average(int x,int y, ...);
int sum=0;
int count=0;
void average(){
return;
}
template <class A, class ...B> void average(A argHead, B... argTail){
sum =sum+argHead;
count+=1;
average(argTail...);
}
使用一种方法优于另一种方法有哪些优缺点?
答案 0 :(得分:1)
考虑到约束条件,即两个或三个正数的平均值,第二个选项是最好的。
第一个选项,带有可选参数,需要测试积极性:
int average(int x,int y,int z=-1) {
if (z<0) return (x+y)/2;
else return (x+y+z)/3;
}
在提供寻找平均值的服务方面,该测试是不必要的。此外,它是脆弱的:考虑找到也可能是负数的平均值是合理的,而且这个解决方案与那种情况不兼容。
第三个选项,即可变参数函数,是不合适的,因为您需要在调用中提供信息以指示存在多少参数,例如:带有终止负数,或带有表示剩余参数数量的第一个参数。这使界面复杂化。此外,它不是类型安全的,并且负担依赖于函数的用户在仅使用int
调用它时一丝不苟 - 编译器不会禁止或警告不正确的使用。
使用可变参数模板是一种很好的通用解决方案,可以轻松扩展到任意数量的参数。但是,我们只需要两个和三个参数情况,因此对于应用程序而言过于复杂。如果你要使用它,你会想要使用不需要全局变量的不同实现。以下使用命名空间隐藏一些实现细节,并通过在递归之前修复头类型来强制使用int
参数:
namespace impl {
int sum() { return 0; }
template <typename... V>
int sum(int a,V... rest) { return a+sum(rest...); }
}
template <typename... V>
int average(int a,V... rest) {
return impl::sum(a,rest...)/(1+sizeof...(V));
}