Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么这个boost-bind非静态成员函数会失败?_C++_Boost_Boost Bind - Fatal编程技术网

C++ 为什么这个boost-bind非静态成员函数会失败?

C++ 为什么这个boost-bind非静态成员函数会失败?,c++,boost,boost-bind,C++,Boost,Boost Bind,为什么会进行以下编译,即将自由函数作为具有正确签名的参数传递: inline double free_adapter_f(unsigned n, const double *x, double *grad, void *d) { return 0.0; } nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size()); opt.set_min_objective(free_adapter_f, NULL); template<class Spac

为什么会进行以下编译,即将自由函数作为具有正确签名的参数传递:

inline double free_adapter_f(unsigned n, const double *x, double *grad, void *d) {
    return 0.0;
}

nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size());
opt.set_min_objective(free_adapter_f, NULL);
template<class Space, class Solution, class Oracle>
inline double NelderMead<Space, Solution, Oracle>::adapter_f(unsigned n, const double *x, double *grad, void *d) {
    return 0.0;
}

nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size());      
opt.set_min_objective(boost::bind(&NelderMead::adapter_f, this, ::_1, ::_2, ::_3, ::_4), NULL);
而另一个则不编译,即传递boost::bind的结果,并使用相同的签名绑定一个类成员函数:

inline double free_adapter_f(unsigned n, const double *x, double *grad, void *d) {
    return 0.0;
}

nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size());
opt.set_min_objective(free_adapter_f, NULL);
template<class Space, class Solution, class Oracle>
inline double NelderMead<Space, Solution, Oracle>::adapter_f(unsigned n, const double *x, double *grad, void *d) {
    return 0.0;
}

nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size());      
opt.set_min_objective(boost::bind(&NelderMead::adapter_f, this, ::_1, ::_2, ::_3, ::_4), NULL);

您需要定义set_min_objective,它接受boost::function作为第一个参数:

 typedef boost::function<double (unsigned n, const double *x, double *grad, void *f_data)> func_t;
 ...
 void set_min_objective(func_t, void*);
 ...
另一件事-最好不要使用NULL,set_min_objective的两个重载都期望函数指针作为第一个参数,但是boost::bind返回的对象不是函数指针,而是函数对象


bind返回一个存储目标函数和任何绑定参数的函数对象,它不会合成函数并返回指向它的指针,也不会神奇地将指向成员函数的指针变成指向函数的指针。这会很神奇。

下面是一个简单的示例,它演示了您的问题:

#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>

namespace g
{
  typedef int (*func)(int a, int b, int c);

  void bar(func f)
  {
    std::cout << "g::bar:: called" << (*f)(10, 20, 30) << std::endl;
  }

  // Disable the over load below and you will get the same error
  void bar(boost::function<int(int, int, int)> f)
  {
    std::cout << "g::bar:: called" << f(10, 20, 30) << std::endl;
  } 
}

template <typename A, typename B, typename C>
class foo
{

public:

  int bar(int a, int b, int c) const
  { return a + b + c; }

  void call()
  {
    g::bar(boost::bind(&foo::bar, this, ::_1, ::_2, ::_3));
  }
};

int main(void)
{
  foo<int, double, int> f;
  f.call();
  return 0;
}
那么你是不可知论者,当然纯粹主义者会有其他的观点

注意:boost::function的一个优点是,只要签名匹配,就可以在其中存储非成员函数指针。因此,实际上,您只需要一个接受正确boost::function的函数版本,它将在具有boost::bind的成员函数和非成员函数的两种情况下工作

EDIT2:好的,根据附加信息,您必须求助于以下机制,您需要拥有类的非成员函数,然后该函数将委托给成员函数,例如:

<>
class NelderMead
{

static double delegate_f(unsigned n, const double *x, double *grad, void *f_data)
{
  // I'm assuming here the frame work passed you whatever you gave in f_data
  NelderMead* inst = reinterpret_cast<NelderMead*>(f_data);
  return inst->adapter_f(n, x, grad);
}

double adapter_f(unsigned n, const double *x, double *grad)
{
}

void set()
{
  nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size());      
  opt.set_min_objective(delegate_f, this); //<-- here pass the instance as the additional data
}

};

这是第三方库所采用的典型模式,对用户代码来说是不可知的。

那么set_min_objective的可用重载是什么呢?啊哈,好吧,你说过同样的话,+1,我将保留我的答案,因为它有SSCCE来证明这一点。我不能这样做,因为set_min_objective属于我不愿意修改的第三方库。事实上,这段代码试图使我的优化器框架的签名适应这个第三方库NLOpt。@GiovanniAzua在这种情况下,您唯一能做的就是定义一个函数来适应您的NelderMead::adapter\u f。这是丑陋的,但有效:内尔德米德的例子;double nelder_mead_adapter_funn,const double*x,double*grad,void*d{return instance.adapter_fn,x,grad,d;}所以你可以把这个自由函数传递给NLOpt接口。正是因为如此,我不能使用静态单例实例。我需要能够在实例级别处理它。boost::bind不会返回boost::function,因此boost::function与任何事情的关系都不是很明显。如果您解释了boost::function的正确专门化可以存储boost::bind返回的对象以及其他可能有用的东西。@JonathanWakely,yip,editing…+1,感谢您解释什么是SSCCEset_min_objective属于第三方库NLopt,我不想修改它。事实上,我正在尝试调整两个不同的优化oracle函数接口,以便使用我的框架并能够插入这个外部库。
<>
class NelderMead
{

static double delegate_f(unsigned n, const double *x, double *grad, void *f_data)
{
  // I'm assuming here the frame work passed you whatever you gave in f_data
  NelderMead* inst = reinterpret_cast<NelderMead*>(f_data);
  return inst->adapter_f(n, x, grad);
}

double adapter_f(unsigned n, const double *x, double *grad)
{
}

void set()
{
  nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size());      
  opt.set_min_objective(delegate_f, this); //<-- here pass the instance as the additional data
}

};