c++ - 'std::function<double(double)>’ 到 ‘double (*)(double)’ 之间的转换

标签 c++

我正在尝试将自定义 lambda 传递给需要函数指针的函数(更准确地说是 zero 中的 Brent library 函数)。

我的想法是,我将使用参数创建一次 lambda,然后用多个值对其求值 x在这个函数里面。

我已经尝试了这个 thread 中的步骤没有成功,我收到错误 no known conversion for argument 4 from ‘Function {aka std::function<double(double)>}’ to ‘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;
}

最佳答案

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

Brent library不期望指向函数的指针。 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_base 派生,并在其中放置一个 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 );
    });
}

实现细节有点难看,但用法是合理的:

main ( )
{
  // func must be "auto" because the type depends on lambda, whose type is unknown.
  auto func = function_builder ( 2.0, -1.0 );
  double z = zero (0, 1, 0.001, func );
  return 0;
}

当然,可以完全摆脱 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  );
  });
}

事实上,你可以在任何地方直接使用function_builder_base,省去了function_builder中间人。

关于c++ - 'std::function<double(double)>’ 到 ‘double (*)(double)’ 之间的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51931479/

相关文章:

c++ - 二叉搜索树分析

c++ - 排序优化

c++ - QTableWidget 显示滚动条

c++ - 如何在 qtoolbar 中的 qaction 上设置 auto=repeat?

c++ - 从 C++ 中的抽象类派生的类中没有销毁阶段

c++ - 我可以使用 C++11 大括号初始化语法来避免为简单聚合声明琐碎的构造函数吗?

c++ - recvfrom 函数返回 -1,没有错误

c++ - cpack deb 生成器组件输出名称

c++ - iostream.h 是否被编译?

c++ - 哪个更好,指向其他类的指针或从该类继承