在具有不同输出的过程相似的函数中防止代码重复?

Preventing code duplication in procedurally similar functions that have different output?

我们有一些函数 foo(g, v, output) 接受顶点 v 搜索一些图 g 附近的顶点和 returns 一些关于路径的信息向量(步骤) 在那次搜索中花费了。

现在这些步骤是一个大结构(越来越大),我们通常只需要每个步骤的一些特定数据(结构的成员)。

问题是我们现在有多个函数(重复代码)在做这样的事情:

foo_get_xs(g, v, result) {
  // initialize vectors needed to catch output from foo (1)
  foo(g, v, output); // (2)
  // parse output to get only xs // (3)
}

foo_get_xs(g, v, result) {
  // initialize vectors needed to catch output from foo
  foo(g, v, output);
  // parse output to get only ys
}

foo_get_xs(g, v, result) {
  // initialize vectors needed to catch output from foo
  foo(g, v, output);
  // parse output to get only zs
}

你怎么能做到只有一个函数可能接受枚举和 returns 一个由所需字段填充的向量?

问题是每个字段的类型不同。除此之外,我们复制 (1)、(2) 和 (3) 的大部分内容。

* 实际上更糟,因为我们实际上需要对每个 v 进行测试,所以有一个调用 foo_xs 的函数,一个调用 foo_ys 的函数等等。 ..

一个选项可以是传递一个回调函数,该函数在路径的每一步都被调用。

然后您将提供几个函数,用所需的字段填充向量。不幸的是,向量需要是抽象的。

或者,为您需要的不同字段类型使用模板。这将避免重复源代码。

您还可以考虑使用所需节点的引用向量,并将各个字段作为 post 处理操作传输。

像这样的东西应该可以工作:

enum Field { xs, ys, zs };
template<Field f>
struct FieldGetter;

template<>
struct FieldGetter<xs> {
   typedef int type;
   static int get( const BigStructure &o ) { return o.xs; }
}
...

template<Field f, typename T=FieldGetter<f>::type>
std::vector<T> foo_get_xs(g, v, result) {
   // initialize vectors needed to catch output from foo
  foo(g, v, output);
  // parse output to get only ys
  std::vector<T> res;
  for( const auto &o : output )
      res.emplace_back( FieldGetter<f>::get( o ) );
  return res;
}   

很难多说,因为你提供的信息不够

为了解决这个问题,boost-graph使用了visitor的概念。每个图算法使用一个访问者类型,并在发生图遍历事件时调用访问者的方法。

例如,DFS 访问者必须为 discover vertex 事件定义一个方法,为 finish vertex 事件定义另一个方法。

在您的情况下,您将为每个 foo_get_XXX() 函数定义一个访问者实现,并且该访问者只会报告有用的信息。

参考资料