gpt4 book ai didi

C++:传递具有任意数量参数的函数作为参数

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:12:57 25 4
gpt4 key购买 nike

长时间的浏览器,第一次在这里提问。我已经编写了许多用于执行各种一维数值积分方法的脚本,并将它们编译到一个库中。我希望该库在集成能力方面尽可能灵活。

这里我包括一个示例:一个非常简单的梯形规则示例,我将指针传递给要集成的函数。

// Numerically integrate (*f) from a to b
// using the trapezoidal rule.
double trap(double (*f)(double), double a, double b) {
int N = 10000;
double step = (b-a)/N;
double s = 0;
for (int i=0; i<=N; i++) {
double xi = a + i*step;
if (i == 0 || i == N) { s += (*f)(xi); }
else { s += 2*(*f)(xi); }
}
s *= (b-a)/(2*N);
return s;
}

这对于只接受一个参数的简单函数非常有用。示例:

double a = trap(sin,0,1);

但是,有时我可能想要集成具有更多参数的东西,例如二次多项式。在此示例中,系数将在积分之前由用户定义。示例代码:

// arbitrary quadratic polynomial
double quad(double A, double B, double C, double x) {
return (A*pow(x,2) + B*x + C);
}

理想情况下,我可以做这样的事情来集成它:

double b = trap(quad(1,2,3),0,1);

但这显然行不通。我通过定义一个类来解决这个问题,该类将系数作为成员并将感兴趣的函数作为成员函数:

class Model {
double A,B,C;
public:
Model() { A = 0; B = 0; C = 0; }
Model(double x, double y, double z) { A = x; B = y; C = z; }
double func(double x) { return (A*pow(x,2)+B*x+C); }
};

但是,我的集成函数需要更改为将对象而不是函数指针作为输入:

// Numerically integrate model.func from a to b
// using the trapezoidal rule.
double trap(Model poly, double a, double b) {
int N = 10000;
double step = (b-a)/N;
double s = 0;
for (int i=0; i<=N; i++) {
double xi = a + i*step;
if (i == 0 || i == N) { s += poly.func(xi); }
else { s += 2*poly.func(xi); }
}
s *= (b-a)/(2*N);
return s;
}

这很好用,但是生成的库不是很独立,因为它需要在某处定义类模型。此外,理想情况下,模型应该能够从用户更改为用户,所以我不想在头文件中修复它。我曾尝试使用函数模板和仿函数来实现它,但它不是很独立,因为模板应该在头文件中定义(除非你想显式实例化,我不这样做)。

因此,总结一下:有什么方法可以让我的积分函数接受输入参数数量可变的任意一维函数,同时仍然保持足够的独立性,以便将它们编译成独立的库?预先感谢您的建议。

最佳答案

您需要的是模板和 std::bind()(或者它的 boost::bind() 对应物,如果您买不起 C++11) .例如,这就是您的 trap() 函数将变成的样子:

template<typename F>
double trap(F&& f, double a, double b) {
int N = 10000;
double step = (b-a)/N;
double s = 0;
for (int i=0; i<=N; i++) {
double xi = a + i*step;
if (i == 0 || i == N) { s += f(xi); }
// ^
else { s += 2* f(xi); }
// ^
}
s *= (b-a)/(2*N);
return s;
}

请注意,我们从函数指针泛化并允许传入任何类型的可调用对象(例如,包括 C++11 lambda)。因此,调用用户提供的函数不是 *f(param)(仅适用于函数指针),而只是 f(param)

关于灵 active ,让我们考虑两个硬编码函数(并假装它们有意义):

double foo(double x)
{
return x * 2;
}

double bar(double x, double y, double z, double t)
{
return x + y * (z - t);
}

您现在可以在 trap() 的输入中直接提供第一个函数,或者将第二个函数的最后三个参数绑定(bind)到某个特定值的结果(您可以自由选择要绑定(bind)的参数):

#include <functional>

int main()
{
trap(foo, 0, 42);
trap(std::bind(bar, std::placeholders::_1, 42, 1729, 0), 0, 42);
}

当然,您可以使用 lambda 获得更大的灵 active :

#include <functional>
#include <iostream>

int main()
{
trap(foo, 0, 42);
trap(std::bind(bar, std::placeholders::_1, 42, 1729, 0), 0, 42);

int x = 1729; // Or the result of some computation...
int y = 42; // Or some particular state information...
trap([&] (double d) -> double
{
x += 42 * d; // Or some meaningful computation...
y = 1; // Or some meaningful operation...
return x;
}, 0, 42);

std::cout << y; // Prints 1
}

您还可以传递自己的有状态仿函数 tp trap(),或一些包装在 std::function 对象(或 boost: :function 如果你买不起 C++11)。选择范围很广。

这是一个live example .

关于C++:传递具有任意数量参数的函数作为参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56090256/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com