将指针传递给非静态成员函数

时间:2017-01-22 21:25:56

标签: c++ function-pointers member-function-pointers

我有一个类的非静态成员函数:

int Band::overlap(unsigned dim, const double *x, void *data_p, unsigned fdim,
        double *retval){

    int *data = (int*) data_p;
    // data[0] = m; data[1] = n; data[2] = k_ind; data[3] = b
    cmplx result = (this->U(x[0], x[1], x[2], data[2], data[0])).adjoint()
                 *  this->U(x[0], x[1], x[2], data[2] + data[3], data[1]);
    retval[0] = result.real();
    retval[1] = result.imag();
    return 0;
}

我希望将其传递给cubature,这要求它具有以下形式:

int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval)

我考虑使用std::mem_fn,但如果我使用:

auto bla = std::mem_fn(&Band::overlap);

我的电话会是:

bla(band_obj, ....)

哪个cubature不接受。然后我考虑使用lambdas,但我读到我只能转换非捕获lambda,因此我无法捕获band_obj。

我意识到,这个问题的变化已被提出,我试过它们,而不是它们似乎有效。

5 个答案:

答案 0 :(得分:1)

在Cubator中它说:

  

F的FDATA参数等于传递给的FDATA参数   hcubature - 调用者可以使用它来传递任何其他内容   根据需要通过F的信息

所以你可以创建一个静态代理函数:

static int Band::overlap_static(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval) 
{
  ((Band *)fdata)->overlap(ndim, x, fdim, fval);
}

然后,您可以使用当前hcubature指针作为第三个参数调用Band,并使用Band::operlap_static作为函数指针。当然,您以不同的方式管理*data

答案 1 :(得分:1)

你做不到。

Cubature是一个C函数,它需要一个C函数指针作为参数。

C ++中绝对没有任何内容可以从成员函数,std::mem_fnstd::function,lambda或除了普通非成员之外的任何其他内容创建C兼容函数指针extern "C"函数指针。

您可以编写一个简单的非成员extern "C"函数,并使其作为“void *”传递给它的Band*值。

Band* band;
hcubature_v(fdim, overlap_adapter, static_cast<void*>(band), ...);

extern "C" int overlap_adapter(unsigned ndim, unsigned npts, 
                               const double *x, void *fdata,
                               unsigned fdim, double *fval) 
{
    Band* band = static_cast<Band*>(fdata);
    ... band->overlap(...) ...
}

当然,首先要做的是围绕hcubature_v编写一个接受任何C ++可调用对象的C ++包装器模板。

答案 2 :(得分:1)

问题

我们希望f成为指向非静态成员函数的指针,作为常规函数调用 - 没有this指针。 std::functionlambda并且所有这些解决方案都无效 - 我们仍然需要以某种方式传递this

解决方案

Cubature提供fdata参数将其传递给您的函数,我们可以使用它来传递this指针:

int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval) {
    Band *band = static_cast<Band*>(fdata);
    return band->overlap(ndim, x, fdim, fval);
}

然后使用hcubature参数this调用fdata

hcubature(1, f, static_cast<void*>(band), 
          3, xmin, xmax, 0, 0, 1e-4, ERROR_INDIVIDUAL, &val, &err);

答案 3 :(得分:0)

嗯,那不行。

void *data_p是传递状态的参数的一部分,但Band::overlap同时使用void *data_p Band* this

解决方案:

/*static*/ int Band::overlap(
      unsigned dim, const double *x, void *data_p, unsigned fdim, double *retval)
{
    return static_cast<Band*>(data_p)->overlap(dim,x,fdim, retval);
}

答案 4 :(得分:-1)

您可以使用std::function

using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::placeholders::_4;
using std::placeholders::_5;

using fn_signiture = int(unsigned, const double*, void*, unsigned, double*)

std::function<fn_signiture> pointer = std::bind(&Band::overlap,this,_1, _2, _3, _4, _5);
//"this" can be replaced with a pointer to a specific instance of a Band.

我选择使用一些using语句来清理代码。