【问题标题】:C++: Arbitrary function as argument of functionC++:任意函数作为函数的参数
【发布时间】:2018-07-10 22:28:03
【问题描述】:

假设我想编写一个通用的数值积分脚本,它接受一个用户定义的函数并对变量int x 进行积分。进一步假设该函数可以调用任意数量的数据列表;例如假设我希望集成商 f_integrator 能够集成以下任何内容:

integrand(x)=f(x)

integrand(x)=f(x)*g(x)

integrand(x)=(f(x)+g(x)/h(x))

integrand(x)=pow(f(x),2)*k(x)

那么看来我们需要它能够调用只是一个定义明确的函数,而不需要指定函数需要多少参数(也许我们需要指定其中的一部分,例如函数必须有一个int x)。如果是这样,那么我们该如何实施呢?如果我们应该用另一种方式来做,怎么做?

【问题讨论】:

  • 使用向量或诸如此类的东西,可能是字典(地图)向函数传递参数列表。
  • 我不明白关于“函数需要多少参数”的部分。您所有的示例似乎都是采用一个参数的函数。此外,您不能对定义域只能具有整数值的函数进行数值积分。
  • f_integrator([f,g,h] (int x) { return (f(x)+g(x))/h(x); });?
  • 我不明白你是如何得出结论的without specifying how many arguments the function takes。我认为您需要阐明您想要实现的目标,而不是告诉我们您认为应该如何解决它。
  • 如果你不知道你的函数有多少参数,你就不能用它做任何事情。所以也许你需要更多地考虑你想要达到的目标。

标签: c++ function variadic-functions


【解决方案1】:

如果您需要传递未知数量的参数,您可以为 f_integrator 使用可变参数模板

template<typename F, typename... Args >
double f_integrator(F integrand, std::tuple<Args...> const &bounds){
// integrate
} 

允许它处理采用任意参数类型的函数(假设积分的类型为double,如果需要,还可以为返回类型添加另一个模板参数)。模板参数F 扮演函数类型的角色。然后您可以直接在函数上调用f_integrator,例如像 lambda 一样

 double integral = f_integrate([](double x){return f(x)*g(x);},
                               std::make_tuple(1.0,2.0));

请注意,您可以将任何可调用对象传递给f_integrate,因为可调用对象返回您可以集成的内容。

使用std::tuple 允许以在函数体中可以处理的方式传递集成区域的边界。当然,如果考虑非平凡的集成区域,事情会变得更复杂,但您仍然可以通过Args 的数组表示的网格将集成区域的信息传递给f_integrator

如何执行积分本身是另一回事,但对一个又一个参数进行迭代积分并不是很有效,如果您想要进行高维积分,蒙特卡洛积分可能是一个不错的方法。

这是一个非常通用的解决方案,并且给出一些温和的假设,有更方便的方法来实现它(编写积分器的主体对于可变参数模板来说并不是很简单)。如果被积函数的所有参数都属于同一类型,我们可以将边界作为法线向量传递,例如

template<typename F, typename T>
double f_integrate(F integrand, std::vector<T> const &bounds){
  // integrate, much more convenient
}

现在,您提供的示例只需要一个参数,因此,如果您可以很好地集成一维函数,则可以更简单一些。如果您只传递带有单个参数的函数,则不需要可变参数模板,只需

template<typename F, typename T=double>
double f_integrate(F integrand, T const& lower_bound, T const& upper_bound){
   // integrate
}

可能,第二个参数甚至不是必需的,因为您可能只对实数进行积分(请注意,整数上的积分只是离散和,因此在这种情况下无需进行数值积分)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 2015-04-15
    相关资源
    最近更新 更多