防止在过程相似但输出不同的函数中出现代码重复

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

本文关键字:函数 代码 过程 相似 输出      更新时间:2023-10-16

我们有一个函数foo(g, v, output),它接受一个顶点v,在某个图g中搜索附近的顶点,并返回一些关于搜索过程中路径(步骤)的信息向量。

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

问题是我们现在有多个函数(重复代码)做这样的事情:
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
}

你怎么能做到只有一个函数可能接受enum并返回一个由所需字段填充的向量?

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

*在现实中,它实际上更糟,因为我们实际上需要测试每个v,所以有一个函数调用foo_xs,一个函数调用foo_ys等等…

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

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

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

引用

  • http://www.boost.org/doc/libs/1_59_0/libs/graph/doc/visitor_concepts.html
  • http://www.boost.org/doc/libs/1_59_0/libs/graph/doc/DFSVisitor.html

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

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

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

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

应该这样做:

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;
}   

你没有提供足够的信息,很难再多说了