C ++:函数重载vs Variadic函数vs Variadic模板vs默认参数

时间:2015-03-07 07:24:13

标签: c++ performance function variadic-templates variadic-functions

我见过这些问题:

但他们不考虑可变参数函数和可变参数模板。

考虑编写函数以找到2或3个正数的平均值的问题。

我们可以通过四种方式实现此功能:

  1. 使用默认参数:

    int average(int x , int y , int z=-1);
    
  2. 使用函数重载:

    int average(int x , int y);
    int average(int x , int y , int z);
    
  3. 使用variadic function

    int average(int x,int y, ...);
    
  4. 使用variadic template

    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...);
    }
    
  5. 使用一种方法优于另一种方法有哪些优缺点?

1 个答案:

答案 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));
}