例如,为什么我不能这样写:
void f(double x, double y = x);
声明一个函数f
,调用f(x)
等同于f(x,x)
?
如果这对您没有用,这是一个可能的使用场景。在此示例中,我声明f
如下:
void f(double x, double y = expensiveComputation(x));
其中expensiveComputation
表示,你猜对了,这是一个计算速度非常慢的函数。我希望f
的用户可以传递y
的值,如果他之前已经计算过它,那么我不必在f
内再次计算它。现在,我当然也可以通过编写两个重载来解决这个问题:
void f(double x, double y);
void f(double x) { f(x, expensiveComputation(x)); }
但随着参数数量的增加,写入重载会变得很烦人。例如,尝试写:
void f(double x, double p = expensiveComputation(x),
double q = expensiveComputation2(x, p),
double r = expensiveComputation3(x, p, q),
double s = expensiveComputation3(x, p, q, r));
使用重载。这只是丑陋的。默认参数是性感的。是否存在更深层次的语法原因,为什么以前的参数不能用于定义参数默认值?
答案 0 :(得分:1)
我不知道为什么默认参数不能这样,但也许你可以尝试将所有这些参数包装在一个struct(class)中?
struct ParamSet
{
double x;
double p;
double q;
ParamSet(double x)
: x(x)
, p(ExpensiveCompute1(x))
, q(ExpensiveCompute2(x, p))
{
}
ParamSet(double x, double p)
: x(x)
, p(p)
, q(ExpensiveCompute2(x, p))
{
}
ParamSet(double x, double p, double q)
: x(x), p(p), q(q)
{
}
private:
double ExpensiveCompute1(double x) {}
double ExpensiveCompute2(double x, double p) {}
};
void f(ParamSet ps);
仍然需要ctor重载,但没有比编写像你提供的expensiveComputation()
系列更有用了,至少所有东西都包含在结构中
此外,f()
的签名可以修复,只有1个版本。
答案 1 :(得分:0)
您可以使用可变参数模板进行类似的操作:
template<typename... Args> void f(double x, Args... args)
{
typedef typename common_type<double, Args...>::type common;
std::vector<common, sizeof...(args)> arguments = {{ args... }};
if (arguments.size < 2) arguments.push_back(expensiveComputation(arguments[0]));
if (arguments.size < 3) arguments.push_back(expensiveComputation2(arguments[0], arguments[1]));
if (arguments.size < 4) arguments.push_back(expensiveComputation3(arguments[0], arguments[1], arguments[2]));
if (arguments.size < 5) arguments.push_back(expensiveComputation4(arguments[0], arguments[1], arguments[2], arguments[3]));
}