所以我正在尝试编写一个与 C++11 lambdas 一起使用的集成函数。代码看起来像这样:
double Integrate(std::function<double(double,void*)> func, double a,double b,std::vector<double> & params)
{
gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
gsl_function F;
F.function =func;
F.params = (void*)¶ms;
double error,result;
gsl_integration_qag (&F, a, b, 0, 1e-7, 1000,GSL_INTEG_GAUSS61,w, &result, &error);
gsl_integration_workspace_free (w);
return result;
}
void Another_function()
{
//...
Integrate([](double a,void* param)
{
return ((vector<double> *)params)->at(0)*a+((vector<double> *)params)->at(1);
}
,0,3,{2,3});
}
试图编译这个,编译器说:
error: cannot convert ‘std::function<double(double, void*)>’ to ‘double (*)(double, void*)’ in assignment
关于行
F.function =func;
但是如果我写:
F.function =[](double a,void* param)
{
return ((std::vector<double> *)param)->at(0)*a+((std::vector<double> *)param)->at(1);
};
它编译并运行良好。我应该如何解决这个问题?
最佳答案
使用 void* 是典型的 C 回调接口(interface),用于将一些“状态”传递给函数。但是,std::function 不需要这个,因为 std::function 支持“有状态函数”。所以,您可以做这样的事情:
double Integrate(
std::function<double(double)> func,
double a, double b)
{
typedef std::function<double(double)> fun_type;
:::
F.function = [](double x, void* p){
return (*static_cast<fun_type*>(p))(x);
};
F.params = &func;
:::
}
并将对参数 vector 的引用存储为将封装在 std::function 对象中的仿函数的一部分或执行如下操作:
void Another_function()
{
double m = 2;
double b = 3;
auto func = [&](double x){return m*x+b};
auto r1 = Integrate(func,0,3);
:::
}
但是,此解决方案将使用相当多的间接寻址。 GSL 会调用您的 lambda。您的 lambda 将调用 std::function<>::operator() ,这反过来又会唤醒某种用于类型删除的虚函数,这又会调用实际的计算。
所以,如果你关心性能,你可以去掉几个层,特别是 std::function。这是另一种使用函数模板的方法:
template<class Func>
double Integrate(
Func func,
double a, double b)
{
:::
F.function = [](double x, void* p)->double{
return (*static_cast<Func*>(p))(x);
};
F.params = &func;
:::
}
我想我更喜欢这个而不是 std::function 解决方案。
关于c++ - 带有 C++11 lambda 的 C 函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13289311/