将指针传递给非静态成员函数
Passing pointer to non-static member function
我有一个 class:
的非静态成员函数
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, ....)
哪个立方体不接受。然后我考虑使用 lambda,但我读到我只能转换非捕获 lambda,因此我无法捕获 band_obj.
我知道,有人问过这个问题的变体,我试过了,但没有一个似乎有效。
您可以使用 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
语句来清理代码。
好吧,那是行不通的。
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);
}
在 Cubator 中它说:
The FDATA argument of F is equal to the FDATA argument passed to
hcubature—this can be used by the caller to pass any additional
information through to F as needed
所以你可以创建一个静态代理函数:
static int Band::overlap_static(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval)
{
((Band *)fdata)->overlap(ndim, x, fdim, fval);
}
然后您可以使用当前 Band
指针作为第三个参数并使用 Band::operlap_static
作为函数指针来调用 hcubature
。当然,你给管理 *data
不同。
你不能。
Cubature 是一个 C 函数,需要一个 C 函数指针作为参数。
C++ 中绝对没有任何东西可以从成员函数、std::mem_fn
、std::function
、lambda 或除plain non-member extern "C"
函数指针.
你可以编写一个简单的 non-member extern "C"
函数,并使用 Band*
值作为 `void*.
传递给它
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++ 包装器模板。
问题
我们希望 f
成为指向 non-static 成员函数的指针 和 作为常规函数调用 - 没有 this
指针。 std::function
、lambda
和所有这些解决方案都行不通 - 我们仍然需要以某种方式传递他们的 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);
}
然后用this
参数调用hcubature
作为fdata
:
hcubature(1, f, static_cast<void*>(band),
3, xmin, xmax, 0, 0, 1e-4, ERROR_INDIVIDUAL, &val, &err);
我有一个 class:
的非静态成员函数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, ....)
哪个立方体不接受。然后我考虑使用 lambda,但我读到我只能转换非捕获 lambda,因此我无法捕获 band_obj.
我知道,有人问过这个问题的变体,我试过了,但没有一个似乎有效。
您可以使用 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
语句来清理代码。
好吧,那是行不通的。
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);
}
在 Cubator 中它说:
The FDATA argument of F is equal to the FDATA argument passed to hcubature—this can be used by the caller to pass any additional information through to F as needed
所以你可以创建一个静态代理函数:
static int Band::overlap_static(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval)
{
((Band *)fdata)->overlap(ndim, x, fdim, fval);
}
然后您可以使用当前 Band
指针作为第三个参数并使用 Band::operlap_static
作为函数指针来调用 hcubature
。当然,你给管理 *data
不同。
你不能。
Cubature 是一个 C 函数,需要一个 C 函数指针作为参数。
C++ 中绝对没有任何东西可以从成员函数、std::mem_fn
、std::function
、lambda 或除plain non-member extern "C"
函数指针.
你可以编写一个简单的 non-member extern "C"
函数,并使用 Band*
值作为 `void*.
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++ 包装器模板。
问题
我们希望 f
成为指向 non-static 成员函数的指针 和 作为常规函数调用 - 没有 this
指针。 std::function
、lambda
和所有这些解决方案都行不通 - 我们仍然需要以某种方式传递他们的 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);
}
然后用this
参数调用hcubature
作为fdata
:
hcubature(1, f, static_cast<void*>(band),
3, xmin, xmax, 0, 0, 1e-4, ERROR_INDIVIDUAL, &val, &err);