C函数指针与C++ 11 lambdas

Uld*_*isK 6 c++ gsl c++11

所以我正在尝试编写一个与c ++ 11 lambdas一起使用的Integration函数.代码看起来像这样:

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*)&params;
  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});
}
Run Code Online (Sandbox Code Playgroud)

试图编译它,编译器说:

error: cannot convert ‘std::function<double(double, void*)>’ to ‘double (*)(double, void*)’ in assignment
Run Code Online (Sandbox Code Playgroud)

关于线

F.function =func;
Run Code Online (Sandbox Code Playgroud)

但如果我写:

F.function =[](double a,void* param)
   {
   return ((std::vector<double> *)param)->at(0)*a+((std::vector<double> *)param)->at(1);
   };
Run Code Online (Sandbox Code Playgroud)

它编译并正常工作.我该怎么解决这个问题?

sel*_*tze 4

使用 void* 是典型的 C 回调接口,用于将某些“状态”传递给函数。然而, 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;
    :::
}
Run Code Online (Sandbox Code Playgroud)

并将参数向量的引用存储为函子的一部分,该函子将封装在 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);
    :::
}
Run Code Online (Sandbox Code Playgroud)

然而,该解决方案将使用相当多的间接方法。GSL 将调用您的 lambda。您的 lambda 会调用 std::function<>::operator() ,而 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;
    :::
}
Run Code Online (Sandbox Code Playgroud)

我想我更喜欢这个而不是 std::function 解决方案。