如何使用不同的参数列表重载函数并避免代码重复?

时间:2017-02-07 23:02:20

标签: c++ oop c++11 templates

我想用不同的参数列表重载一个函数。

例如,声明如下:

void processGraph(const std::vector<int>& vertexData)
void processGraph(const std::vector<int>& vertexData, const std::vector<int>& edgeData)

在应用程序中,有些图表有边缘数据,有些则没有。

此函数将迭代顶点和边缘数据。

for (int i = 0; i < vnum; ++i) { 
for (int j = idx[i]; j < idx[i+1]; ++j) {
    int dst = edge[j]
    vertexData[i] = vertexData[i] + 1; // update vertex
    edgeData[j] = edgeData[j] + 1; // update edge
}
}

我必须在两个函数中复制代码,它们只在一行中有所不同 - 更新边缘线。

目前我正在使用宏来避免重复。

我不会重载该功能。

void processGraph(const std::vector<int>& vertexData
#ifdef PROCESSEDGE
, const std::vector<int>& edgeData
#endif
)

在定义中

// inside some for loop
vertexData[i] = j; // update vertex
#ifdef PROCESSEDGE
edgeData[k] = l; // update edge
#endif

对于不同的配置,我添加了PROCESSEDGE宏。

很明显,这没有开销。但它并不优雅。

我想到的另一个想法是在c ++ 11中使用一些编译时条件。

声明如下所示

void processGraph(const std::vector<int>& vertexData, const std::vector<EdgeType>& edgeData)

实施

// inside some for loop
vertexData[i] = j; // update vertex
if (!std::is_same<Empty, EdgeData>::value)
edgeData[k] = l; // update edge

因为在编译时评估条件,所以它应该没有运行时开销。但就我而言,if语句也不优雅。

优雅地做到这一点的最佳做法是什么?

[更新]我希望一切都是静态完成的。

1 个答案:

答案 0 :(得分:0)

选项1:提供伪造的边缘数据,您委派的实施可以随意涂抹,然后将其放在地板上。这增加了一些内存需求,但循环中的赋值很简单,循环中没有添加分支。

void processGraph(const std::vector<int>& vertexData) {
    std::vector<int> dummyEdgeData;
    dummyEdgeData.resize(/* some appropriate value */);
    processGraph(vetexData, dummyEdgeData);
}

void processGraph(const std::vector<int>& vertexData, const std::vector<int>& edgeData) {
    // inside some for loop
    vertexData[i] = j; // update vertex
    edgeData[k] = l; // update edge
}

选项2:如果没有边缘数据,请相信循环内的分支将被很好地预测。

选项3:使用仿函数(如lambda)处理分配并提供“正确”分配,就像std::for_each允许您提供循环体一样。

template <typename Functor>
void processGraphLoop(Functor f) {
    // inside some for loop
    f(i, j, k, l);
}

void processGraph(const std::vector<int>& vertexData) {
    processGraphLoop([&](int i, int j, int k, int l) {
                         vertexData[i] = j;
                     });
}

void processGraph(const std::vector<int>& vertexData, const std::vector<int>& edgeData) {
    processGraphLoop([&](int i, int j, int k, int l) {
                         vertexData[i] = j;
                         edgeData[k] = l;
                     });
}