【发布时间】:2017-11-08 15:02:21
【问题描述】:
假设我想编写一个函数,例如,返回某个范围内 x 的 f(x) 之和。
double func() {
double sum = 0.;
for (int i=0; i<100; i++) {
sum += f(i);
}
return sum;
}
但有时,除了最终的总和,我还需要部分项,所以我可以这样做
pair<vector<double>,double> func_terms() {
double sum = 0.;
vector<double> terms(100);
for (int i=0; i<100; i++) {
terms[i] = f(i);
sum += terms[i];
}
return {terms, sum};
}
问题是,这是代码重复。在这个例子中这似乎很无害,但是假设函数要大得多(正是在这种情况下促使我提出这个问题),并且两个版本只有几行不同(在这个例子中,逻辑是只有后一个版本在添加到 sum 之前将项存储在向量中,并返回与该向量的对;任何其他逻辑都是等效的)。然后我将不得不编写和维护同一个函数的两个几乎相同的版本,不同之处仅在于几行和 return 语句。我的问题是是否有处理此类问题的习语/模式/最佳实践。可以让我在两个版本之间共享通用代码的东西。
简而言之:我可以编写两个函数并且必须维护两个几乎相同的版本。或者我可以只使用后者,但只要我只需要总和,那将是非常浪费的,这是不可接受的。处理这个问题的最佳模式是什么?
我认为使用 C++17 可以做类似的事情
template<bool partials>
double func(vector<double>* terms=nullptr) {
double sum = 0.;
if constexpr (partials)
*terms = vector<double>(100);
for (int i=0; i<100; i++) {
if constexpr (partials) {
(*terms)[i] = f(i);
sum += (*terms)[i];
} else {
sum += f(i);
}
}
return sum;
}
这与我的意图非常接近,除了使用指针(我不能使用引用,因为terms 可能为空)。
【问题讨论】:
-
你可以使用
optional,它在 boost 和 afaik 中可用,最新的 c++ 版本之一也有它 -
去掉
sum,然后去掉return {terms, std::accumulate(terms.begin(), terms.end(), 0.))}? -
@Jarod42,它仍然需要两个函数:一个返回 {terms, std::accumulate...} 另一个返回 {std::accumulate...} 并且没有地址当代码比 std:: 累积调用更复杂时,代码重复的问题似乎是 OP 所建议的
-
您能否详细说明您在实现
double func() { return func_terms().second; }时在实践中观察到的性能差异?优化器实际上可能比您预期的要好。