通过引用传递函数的问题与打字
Passing function by reference problem with typing
我正在尝试使用 GSL 对一些棘手的积分进行数值计算,我希望实现将被积函数与 GSL 实现分开,以使我的代码更具可读性(和可调试性)。这些是实际评估我的模型的函数,其中的内容并不重要:
double Integrand1(double *k, size_t dim, void *params) {
double result = k[0]*k[1]*k[2];
return result;
}
double Integrand2(double *k, size_t dim, void *params) {
double result = k[0]-k[1]-k[2];
return result;
}
这就是我 运行 遇到麻烦的地方,试图抽象化对 GSL 的调用。请注意 gsl_monte_function G
:
的类型约束
void EvalIntegral(double &func, int_info ¶ms,double *xl,double *xu,size_t dim,
double &result,double &error){
const gsl_rng_type *T;
gsl_rng *r;
gsl_monte_function G;
G.f = &func; //This must be double (*)(double *,size_t,void *)
G.dim = dim; //This must be size_t
G.params = ¶ms; //This is a struct holding some variables
size_t calls = 5e5;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc(T);
gsl_monte_vegas_state *s = gsl_monte_vegas_alloc(dim);
gsl_monte_vegas_integrate(&G,xl,xu,dim,1e5,r,s, &result,&error);
gsl_monte_vegas_free (s);
gsl_rng_free (r);
}
我设置上面的函数是为了减少另一个函数中的一些混乱:
void Evaluate(double x, double y){
int_info params;
params.x = x;
params.y = y;
//Lower limits to the variables
double xl[3] = {0.,-100.,0.};
//Upper limits to the variables
double xu[3] = {100.,100.,1.};
double result1, result2, error1, error2;
EvalIntegral(&Integrand1,¶ms,xl,xu,3,&result1,&error1);
EvalIntegral(&Integrand2,¶ms,xl,xu,3,&result2,&error2);
}
不过,当我编译时,它似乎拒绝我传递被积函数:
error: cannot convert ‘double*’ to ‘double (*)(double*, size_t, void*)’ {aka ‘double (*)(double*, long unsigned int, void*)’} in assignment
G.f = &func;
^~~~
我有点困惑,当我将 EvalIntegral
的内容复制到 Evaluate
两次并将 func
替换为 Integrand1
和 [= 时,所有这些都有效19=]。我怎样才能让编译器相信 func
是一个具有正确原型的函数?
编译器给你答案:你需要一个函数指针类型而不是double&
:
void EvalIntegral(double (*func)(double*, std::size_t, void*), ...)
我正在尝试使用 GSL 对一些棘手的积分进行数值计算,我希望实现将被积函数与 GSL 实现分开,以使我的代码更具可读性(和可调试性)。这些是实际评估我的模型的函数,其中的内容并不重要:
double Integrand1(double *k, size_t dim, void *params) {
double result = k[0]*k[1]*k[2];
return result;
}
double Integrand2(double *k, size_t dim, void *params) {
double result = k[0]-k[1]-k[2];
return result;
}
这就是我 运行 遇到麻烦的地方,试图抽象化对 GSL 的调用。请注意 gsl_monte_function G
:
void EvalIntegral(double &func, int_info ¶ms,double *xl,double *xu,size_t dim,
double &result,double &error){
const gsl_rng_type *T;
gsl_rng *r;
gsl_monte_function G;
G.f = &func; //This must be double (*)(double *,size_t,void *)
G.dim = dim; //This must be size_t
G.params = ¶ms; //This is a struct holding some variables
size_t calls = 5e5;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc(T);
gsl_monte_vegas_state *s = gsl_monte_vegas_alloc(dim);
gsl_monte_vegas_integrate(&G,xl,xu,dim,1e5,r,s, &result,&error);
gsl_monte_vegas_free (s);
gsl_rng_free (r);
}
我设置上面的函数是为了减少另一个函数中的一些混乱:
void Evaluate(double x, double y){
int_info params;
params.x = x;
params.y = y;
//Lower limits to the variables
double xl[3] = {0.,-100.,0.};
//Upper limits to the variables
double xu[3] = {100.,100.,1.};
double result1, result2, error1, error2;
EvalIntegral(&Integrand1,¶ms,xl,xu,3,&result1,&error1);
EvalIntegral(&Integrand2,¶ms,xl,xu,3,&result2,&error2);
}
不过,当我编译时,它似乎拒绝我传递被积函数:
error: cannot convert ‘double*’ to ‘double (*)(double*, size_t, void*)’ {aka ‘double (*)(double*, long unsigned int, void*)’} in assignment
G.f = &func;
^~~~
我有点困惑,当我将 EvalIntegral
的内容复制到 Evaluate
两次并将 func
替换为 Integrand1
和 [= 时,所有这些都有效19=]。我怎样才能让编译器相信 func
是一个具有正确原型的函数?
编译器给你答案:你需要一个函数指针类型而不是double&
:
void EvalIntegral(double (*func)(double*, std::size_t, void*), ...)