更好地设计使用具有不同参数的函数指针

时间:2011-01-13 18:12:32

标签: c++ function-pointers

我有一个优化算法,可以找到图表的最佳分区。

分区的质量有很多度量(被优化的变量),所以我认为使用函数指针来处理这些质量函数是个好主意,并将其传递给我的优化算法函数。

这很好用,但问题是不同的质量函数需要一些不同的参数。

例如,一个质量函数为find_linearised_stability,它需要markov_time参数:

float find_linearised_stability(cliques::Graph<T> &my_graph, cliques::Partition &my_partition,
                               std::vector<float> &markov_times, std::vector<float> &stabilities)

并用于优化功能:

cliques::find_optimal_partition_louvain(my_new_graph, markov_times, &cliques::find_linearised_stability);

但是另一个质量函数find_modularity不需要markov_time参数。当然我可以把它作为一个参数包括在内,而不是在函数中使用它,但这似乎是不好的做法,一旦我开始添加很多不同的质量函数就会变得笨拙。

对于这种情况,什么是更好的设计?

3 个答案:

答案 0 :(得分:6)

使用功能对象。其中一个函数对象可以有一个传递给构造函数的markov_time成员:

struct find_linearised_stability {
    std::vector<float> & markov_times_;

    find_linearised_stability(std::vector<float> & markov_times)
        :markov_times_(markov_times)
    {}

    float operator () (cliques::Graph<T> &my_graph, cliques::Partition &my_partition,
                 std::vector<float> &stabilities)
    {
        // use markov_times_ in here, we didn't need to pass it since it's a member
    }
};

(您可能需要根据自己的需要调整常数/参考值)

然后你可以这样调用你的函数:

cliques::find_optimal_partition_louvain(my_new_graph, cliques::find_linearised_stability(markov_times));

“声明...函数时,我使用什么类型的函数对象?”

使其成为一个函数模板,将函数对象类型作为模板参数,因此:

template<typename PR>
whatever find_optimal_partition_louvain(my_new_graph, PR & pr)
{
    ...
    pr(my_new_graph, partition, stabilities);
    ...
}

答案 1 :(得分:2)

你唯一的选择是boost :: bind或类似存储在boost :: function之类的东西。

如果分析显示速度太慢,那么你将会陷入“糟糕的练习”版本,因为任何替代方案都会与UB发生冲突和/或最终变得像更合理的替代方案一样“慢”

答案 2 :(得分:0)

    之前不知道
  1. 参数:为包含所有信息的每个函数(引用/指针)添加参数,每个函数都使用它需要的任何东西
  2. 参数之前是已知的:使用boost :: bind,例如:
  3. 示例源代码:

    #include <iostream>
    #include <cstddef>
    #include <algorithm>
    #include <boost/bind.hpp>
    using namespace std;
    
    void output(int a, int b)
    {
        cout << a << ", " << b << '\n';
    }
    
    int main()
    {
        int arr[] = { 1, 2, 3, 4, 5 };
        for_each(arr, arr + 5, bind(output, 5, _1));
        return 0;
    }
    

    输出:

    5, 1
    5, 2
    5, 3
    5, 4
    5, 5