首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“std::function<double(Double)>”到“double(*)(Double)”之间的转换

“std::function<double(Double)>”到“double(*)(Double)”之间的转换
EN

Stack Overflow用户
提问于 2018-08-20 13:09:04
回答 2查看 1.3K关注 0票数 1

我正在尝试将一个定制的lambda传递给一个函数,该函数需要一个函数指针(更准确地说,是zero函数在布伦特图书馆中)。

其思想是,我将创建一个带有参数的lambda,然后在这个函数中的几个值x中对它进行计算。

我已经尝试了这个线程中的步骤,但没有成功,而且我得到了一个no known conversion for argument 4 from ‘Function {aka std::function<double(double)>}’ to ‘double (*)(double)’错误。据我所知,编译器不知道如何从这2种类型中进行转换。

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

代码语言:javascript
复制
# 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;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-20 14:22:35

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

布伦特图书馆不期望一个指针起作用。zero函数声明为:

代码语言:javascript
复制
double zero ( double a, double b, double t, func_base& f )

并且重载定义为:

代码语言:javascript
复制
// 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);
}

但是,您应该使用第一个变体来满足您的需求,这意味着:

代码语言:javascript
复制
class func_base{
 public:
   virtual double operator() (double) = 0;
};

这是个好消息,因为您只需从func_base派生,并在其中放置一个lambda:

代码语言:javascript
复制
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 );
    });
}

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

代码语言:javascript
复制
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继承可以很容易地定义许多其他函数构建器,例如:

代码语言:javascript
复制
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中间人的需求。

票数 3
EN

Stack Overflow用户

发布于 2018-08-20 13:21:57

如果没有将std::function<double(double)>传递给double(*)(double)的丑陋攻击(比如使用全局对象),就不会有什么好运气了。关键的区别在于函数指针真正只抽象无状态函数,而非空捕获包含状态的std::function<double(double)>或lambda函数。

专门为布伦特图书馆提到的,但是,有一个方法!库并不真正接受函数指针,而是以func_base对象的形式运行。您可以通过一个简单的适配器获得其中的一个:

代码语言:javascript
复制
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); }
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51931479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档