C++ 将'std::function'转换为'double(*)(double)'

C++ 将'std::function'转换为'double(*)(double)',c++,C++,我试图将一个自定义lambda传递给一个函数,该函数期望函数指针更精确地表示零函数 我的想法是使用参数创建lambda一次,然后在这个函数中的几个值x处对其求值 我尝试了其中的步骤,但没有成功,并且我得到了一个错误,参数4从'Function{aka std::Function}'到'double*double'的转换未知。据我所知,编译器不知道如何从这两种类型转换 这个错误有解决方法吗?如果不需要对库进行任何修改,并且可以在我的程序中解决,那就更好了。下面是一段代码来说明这个问题 # incl

我试图将一个自定义lambda传递给一个函数,该函数期望函数指针更精确地表示零函数

我的想法是使用参数创建lambda一次,然后在这个函数中的几个值x处对其求值

我尝试了其中的步骤,但没有成功,并且我得到了一个错误,参数4从'Function{aka std::Function}'到'double*double'的转换未知。据我所知,编译器不知道如何从这两种类型转换

这个错误有解决方法吗?如果不需要对库进行任何修改,并且可以在我的程序中解决,那就更好了。下面是一段代码来说明这个问题

# include <functional>
# include "brent.hpp"

using namespace brent;

typedef std::function<double(double)> Function;

Function function_builder (double a, double b)
{
    return [a,b](double x) {
        return ( a * x + b );
    };
}

int main ( )

{
  Function func = function_builder ( 2.0, -1.0 );
  double z = zero (0, 1, 0.001, func ); //func should be a function pointer of type double (*)(double)

  return 0;
}

如果没有像使用一个全局对象将std::函数传递给double*double这样丑陋的hack,您将不会有太多的运气。关键的区别在于函数指针实际上只包含抽象的无状态函数,而带有非空捕获的std::function或lambda函数包含状态

但是,特别是对于提到的布伦特图书馆,有一种方法!该库实际上并不采用函数指针,而是按照func_基对象进行移动。您可以通过一个简单的适配器获得其中一个:

struct brent_fun: func_base {
    std::function<double(double)> fun;
    template <typename Fun>
    explicit brent_fun(Fun&& fun): fun(std::move(fun)) {}
    double operator()(double value) override { return this->fun(value); }
};

如果没有像使用一个全局对象将std::函数传递给double*double这样丑陋的hack,您将不会有太多的运气。关键的区别在于函数指针实际上只包含抽象的无状态函数,而带有非空捕获的std::function或lambda函数包含状态

但是,特别是对于提到的布伦特图书馆,有一种方法!该库实际上并不采用函数指针,而是按照func_基对象进行移动。您可以通过一个简单的适配器获得其中一个:

struct brent_fun: func_base {
    std::function<double(double)> fun;
    template <typename Fun>
    explicit brent_fun(Fun&& fun): fun(std::move(fun)) {}
    double operator()(double value) override { return this->fun(value); }
};

在您的例子中,lambda函数具有状态-捕获的a、b变量。无法将有状态lambda转换为指向函数的指针,但是

不需要指向函数的指针。zero函数声明为:

double zero ( double a, double b, double t, func_base& f )
并且具有定义为以下内容的重载:

// This is the overload you asked about, but....
double zero ( double a, double b, double t, double f ( double x ) ){
  func_wrapper foo(f);
  return zero(a, b, t, foo);
}
但您应该根据自己的需要使用第一种变体,它期望:

class func_base{
 public:
   virtual double operator() (double) = 0;
};
这是一个好消息,因为您只需从func_基派生,并在其中放入lambda:

template <class Lambda>
class FunctionWithState : public func_base, public Lambda {
  public:
     FunctionWithState(const Lambda & lambda): Lambda(lambda) {}
     double operator()(double x) override 
     { return Lambda::operator()(x); }
};

template<class Lambda>
auto function_builder_base (Lambda lambda)
{
    return FunctionWithState<decltype(lambda)>(lambda);
}

auto function_builder(double a, double b)
{
    return function_builder_base([a,b](double x) {
        return ( a * x + b );
    });
}
当然,可以完全去掉lambda函数,并管理非模板对象内部的状态。但另一方面,从lambda继承可以轻松定义许多其他函数生成器,例如:

auto function_builder3(double a, double b, double c)
{
  return function_builder_base([a,b,c](double x) {
       return ( a*x*x + b*x + c  );
  });
}

事实上,您可以在任何地方直接使用函数生成器库,无需函数生成器中间人

在您的示例中,lambda函数具有状态-捕获的a、b变量。无法将有状态lambda转换为指向函数的指针,但是

不需要指向函数的指针。zero函数声明为:

double zero ( double a, double b, double t, func_base& f )
并且具有定义为以下内容的重载:

// This is the overload you asked about, but....
double zero ( double a, double b, double t, double f ( double x ) ){
  func_wrapper foo(f);
  return zero(a, b, t, foo);
}
但您应该根据自己的需要使用第一种变体,它期望:

class func_base{
 public:
   virtual double operator() (double) = 0;
};
这是一个好消息,因为您只需从func_基派生,并在其中放入lambda:

template <class Lambda>
class FunctionWithState : public func_base, public Lambda {
  public:
     FunctionWithState(const Lambda & lambda): Lambda(lambda) {}
     double operator()(double x) override 
     { return Lambda::operator()(x); }
};

template<class Lambda>
auto function_builder_base (Lambda lambda)
{
    return FunctionWithState<decltype(lambda)>(lambda);
}

auto function_builder(double a, double b)
{
    return function_builder_base([a,b](double x) {
        return ( a * x + b );
    });
}
当然,可以完全去掉lambda函数,并管理非模板对象内部的状态。但另一方面,从lambda继承可以轻松定义许多其他函数生成器,例如:

auto function_builder3(double a, double b, double c)
{
  return function_builder_base([a,b,c](double x) {
       return ( a*x*x + b*x + c  );
  });
}

事实上,您可以在任何地方直接使用函数生成器库,无需函数生成器中间人

你不能直接转换。生成一个全局/静态std::函数,并生成一个调用它的常规函数或无状态lambda。然后将正则函数作为函数指针传递,链接库显式支持C++函子,但手工滚动。参见类func_base{public:virtualdouble操作符double=0;};你从这个问题中尝试过什么样的解决方案,它是如何不起作用的?你只是问了一个重复的问题,说重复的答案不适合你,这不足以提供答案。您需要提供更多信息。无法直接转换。生成一个全局/静态std::函数,并生成一个调用它的常规函数或无状态lambda。然后将正则函数作为函数指针传递,链接库显式支持C++函子,但手工滚动。参见类func_base{public:virtualdouble操作符double=0;};你从这个问题中尝试过什么样的解决方案,它是如何不起作用的?你只是问了一个重复的问题,说重复的答案不适合你,这不足以提供答案。你需要提供更多的信息。