我正在使用gsl来集成一个函数。该函数构建在lambda函数中,该函数具有double和void *作为输入,并且输出为double。 现在,如果我使用没有任何变量捕获的lambda,一切正常。但如果我做变量捕获,它就不再起作用了。
有人可以解释我为什么这样吗?
以下是我用来解释我的问题的两段代码:
这个很好用:
int main(int argc, char **argv)
{
double beg = 0;
double end = 10;
auto f = [] (double x, void * p) {return 2.0;};
gsl_integration_workspace * w = gsl_integration_workspace_alloc (GSL_INTEGRATION_WORKSPACE_SIZE);
double result;
double error;
gsl_function F;
F.function = f;
F.params = NULL;
gsl_integration_qags (&F, beg, end, 0, GSL_INTEGRATION_RELATIVE_PRECISION, GSL_INTEGRATION_WORKSPACE_SIZE, w, &result, &error);
cout<<result<<endl;
}
虽然这个
int main(int argc, char **argv)
{
double beg = 0;
double end = 10;
double p = 2.0;
auto f = [&] (double x, void * p) {return p;};
gsl_integration_workspace * w = gsl_integration_workspace_alloc (GSL_INTEGRATION_WORKSPACE_SIZE);
double result;
double error;
gsl_function F;
F.function = f;
F.params = NULL;
gsl_integration_qags (&F, beg, end, 0, GSL_INTEGRATION_RELATIVE_PRECISION, GSL_INTEGRATION_WORKSPACE_SIZE, w, &result, &error);
cout<<result<<endl;
}
生产线
F.function = f;
以下错误:
Assigning to 'double (*)(double, void *)' from incompatible type '<lambda at /[omissis]/main.cpp>'
答案 0 :(得分:3)
@ user657267给出的答案是正确的。这就是为什么需要一个小包装器来将带有捕获的lambas转换为gsl_function。
Here is the wrapper for the f gsl_function和Here is the wrapper for the fdf gsl_function
在使用这两个答案中提出的包装器之后,您可以将lambda函数转换为gsl_function(我没有用std :: function发明版本,这是一个众所周知的答案。模板版本I在我的回答之前没见过)。
// std::function version
double a = 1;
gsl_function_pp Fp([=](double x)->double{return a*x;});
gsl_function *F = static_cast<gsl_function*>(&Fp);
//template version
double a = 1;
auto ptr = [=](double x)->double{return a*x;};
gsl_function_pp<decltype(ptr)> Fp(ptr);
gsl_function *F = static_cast<gsl_function*>(&Fp);
答案 1 :(得分:2)
只有没有捕获的lambda才能转换为函数指针。
[expr.prim.lambda]
6具有 no的非泛型lambda表达式的闭包类型 lambda-capture 具有公共非虚拟非显式const 转换 函数指向函数与C ++语言链接(7.5)有 与闭包类型的函数相同的参数和返回类型 呼叫运营商。
基本上这意味着
[] (double, void*) {return 2.0;};
就像定义为
一样class Lambda
{
public:
double operator()(double, void*);
operator double(*)(double, void*)() const;
};
如果lambda有捕获但是没有定义转换函数,并且lambda不能转换为常规函数指针。