c++ - 带有 C++11 lambda 的 C 函数指针

标签 c++ c++11 gsl

所以我正在尝试编写一个与 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*)&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});
}

试图编译这个,编译器说:

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/

相关文章:

c++ - 在类构造函数 C++ 中零初始化多维数组

c++ - C++11 目标构造函数是否允许我从模板构造函数安全地初始化派生类?

c# - 如何在 C# 项目中使用 Clang?

C++ 内存泄漏与 STL vector

c++ - 在 Windows DLL 中通过它的签名查找函数

c++ - 确定数据类型

C++:不同类型模板函数(方法)的自定义返回值

android - dlopen 失败 : cannot locate symbol "cblas_sdsdot" referenced by "libgsl.so"

c - 使用 gsl 编写 Runge-Kutta ODE 求解器

通过 M<N 的 GSL 计算矩阵的零空间会产生错误