C函数指针与C ++ 11 lambdas [英] C function pointers with C++11 lambdas
问题描述
所以我试图写一个Integration函数与c ++ 11 lambdas一起使用。代码看起来像这样:
So i'm trying to write an Integration function to be used with c++11 lambdas. The code looks something like this:
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});
}
尝试编译这个,编译器说:
Trying to compile this, compiler says:
error: cannot convert ‘std::function<double(double, void*)>’ to ‘double (*)(double, void*)’ in assignment
$ b
about line
F.function =func;
但如果我写:
F.function =[](double a,void* param)
{
return ((std::vector<double> *)param)->at(0)*a+((std::vector<double> *)param)->at(1);
};
它编译和工作正常。我应该如何解决这个问题?
It compiles and works fine. How should I solve this?
推荐答案
使用void *是典型的C回调接口向函数传递一些状态。但是,std :: function不需要这个,因为std :: function支持有状态的函数。因此,您可以执行这样的操作:
Using a void* is typical of C callback interfaces to pass some "state" to the function. However, std::function does not need this because std::function supports "stateful functions". So, you could do something like this:
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;
:::
}
并存储对参数向量的引用部分函数将被封装在std :: function对象中,或者做这样的事情:
and store a reference to the parameter vector as part of the functor that will be encapsulated in the std::function object or do something like this:
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(),它反过来会唤醒某种虚拟函数,用于类型擦除,反过来调用实际的计算。
However, this solution would use rather many indirections. GSL would invoke your lambda. Your lambda would invoke the std::function<>::operator() which in turn would inwoke some kind of virtual function that is used for type erasure which would in turn invoke the actual computation.
所以,如果你关心性能,你可以去掉一些层,特别是std :: function。这里是另一种具有函数模板的方法:
So, if you care about performance, you could get rid of a couple of layers there, specifically std::function. Here's a another approach with a function template:
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 solution。
I guess I would prefer this over the std::function solution.
这篇关于C函数指针与C ++ 11 lambdas的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!