我在C++类中使用一个非常复杂的C函数有问题(重写C函数不是一个选项)。C职能:
typedef void (*integrand) (unsigned ndim, const double* x, void* fdata,
unsigned fdim, double* fval);
// This one:
int adapt_integrate(unsigned fdim, integrand f, void* fdata,
unsigned dim, const double* xmin, const double* xmax,
unsigned maxEval, double reqAbsError, double reqRelError,
double* val, double* err);我需要自己提供一个integrand型的空函数,adapt_integrate将计算n维积分。如果calcTripleIntegral是独立函数的话,func中的代码(下面)作为独立函数工作。我想通过一个(非静态的!)类成员函数作为integrand,因为它很容易被重载等等。
class myIntegrator
{
public:
double calcTripleIntegral( double x, double Q2, std::tr1::function<integrand> &func ) const
{
//...declare val, err, xMin, xMax and input(x,Q2) ...//
adapt_integrate( 1, func, input,
3, xMin, xMax,
0, 0, 1e-4,
&val, &err);
return val;
}
double integrandF2( unsigned ndim, const double *x, void *, // no matter what's inside
unsigned fdim, double *fval) const; // this qualifies as an integrand if it were not a class member
double getValue( double x, double Q2 ) const
{
std::tr1::function<integrand> func(std::tr1::bind(&myIntegrator::integrandF2, *this);
return calcTripleIntegral(x,Q2,func);
}
}关于GCC 4.4.5 (预录),这给了我:
错误:变量‘std::tr1::func’具有初始化程序,但类型不完整
编辑:我的代码中的错误是什么?我现在试着用GCC 4.4,4.5和4.6编译,都导致了同样的错误。要么没有在这方面做任何工作,要么我做错了/EDIT
非常感谢!如果我说得不够清楚,我很乐意详细说明。
PS:我可以通过使用指向在tr1中某个地方定义的函数的函数指针来解决这个问题而不使用myIntegrator.cpp内容吗?
最终更新:好的,我错误地认为TR1提供了一个一/两行的解决方案。真扫兴。我正在将类“转换”到名称空间,并复制函数声明。我只需要一个基类和一个子类来重新实现接口。C函数指针+ C++类=坏消息。谢谢你所有的答案,你给我看了C++的一些黑暗角落;)
发布于 2010-07-16 14:29:33
如果您只是试图将一个成员函数传递给一个c样式的回调,您可以使用std::t1::bind或std::tr1::function完成这一任务。
class myIntegrator
{
public:
// getValue is no longer const. but integrandF2 wasn't changed
double getValue( double x, double Q2 )
{
m_x = x;
m_Q2 = Q2;
// these could be members if they need to change
const double xMin[3] = {0.0};
const double xMax[3] = {1.0,1.0,1.0};
const unsigned maxEval = 0;
double reqAbsError = 0.0;
double reqRelError = 1e-4;
double val;
adapt_integrate( 1, &myIntegrator::fancy_integrand,
reinterpret_cast<void*>(this),
3, xMin, xMax,
maxEval, reqAbsError, reqRelError,
&val, &m_err);
return val;
}
double get_error()
{ return m_error; }
private:
// use m_x and m_Q2 internally
// I removed the unused void* parameter
double integrandF2( unsigned ndim, const double *x,
unsigned fdim, double *fval) const;
static double fancy_integrand( unsigned ndim, const double* x, void* this_ptr,
unsigned fdim, double* fval)
{
myIntegrator& self = reinterpret_cast<myIntegrator*>(this_ptr);
self.integrateF2(ndim,x,fdim,fval);
}
double m_x
double m_Q2;
double m_err;
};发布于 2010-07-15 22:22:54
你有三个问题。首先,您想要一个std::tr1::function<R (Args..)>,但您的需要归结为std::tr1::function<R (*)(Args...)> -所以您需要两种类型:
typedef void (integrand) (unsigned ndim, const double *x, void *,
unsigned fdim, double *fval);
typedef integrand* integrand_ptr;..。因此,第一个允许您进行可编译的function<integrand>。必须相应地修正adapt_integrate:
int adapt_integrate(unsigned fdim, integrand_ptr f, ...);接下来,您的bind语法将关闭,它应该是:
std::tr1::bind(&myIntegrator::integrandF2, *this, _1, _2, _3, _4, _5);剩下的问题是,tr1::function<T>不能转换为函数指针,因此您必须使用void* fdata参数来传递上下文,从而遍历包装函数。例如,类似:
extern "C" void integrand_helper (unsigned ndim, const double *x, void* data,
unsigned fdim, double *fval)
{
typedef std::tr1::function<integrand> Functor;
Functor& f = *static_cast<Functor*>(data);
f(ndim, x, data, fdim, fval);
}
// ...
adapt_integrate(1, &integrand_helper, &func, ...);当然,这是假定void*参数被传递到函数中,如果不是,它就会变得丑陋。
另一方面,如果void* fdata允许传递上下文,那么所有tr1::function内容都是不必要的,您可以直接通过蹦床函数传递this作为上下文参数:
extern "C" void integrand_helper (unsigned ndim, const double *x, void* data,
unsigned fdim, double *fval)
{
static_cast<myIntegrator*>(data)->integrandF2(ndim, ...);
}
// ...
adapt_integrate(1, &integrand_helper, this, ...);发布于 2010-07-15 22:34:09
由于std::tr1::bind和c-样式的函数指针不合拍,所以请尝试以下操作。它将工作,只是myIntegrator::getValue不再是线程安全的。如果将calcTripleIntegral从接口中删除,这将更加简单,并且不需要使用std::tr1::bind或std::tr1::function。
class myIntegrator
{
public:
double getValue( double x, double Q2 ) const
{
return calcTripleIntegral(x,Q2,std::tr1::bind(&Integrator::integrandF2,this));
}
double calcTripleIntegral( double x, double Q2, const std::tr1::function<integrand>& func ) const
{
assert( s_integrator == NULL );
s_integrator = this;
m_integrand = func;
//...declare val, err, xMin, xMax and input(x,Q2) ...//
adapt_integrate( 1, &myIntegrator::fancy_integrand, input,
3, xMin, xMax,
0, 0, 1e-4,
&val, &err);
assert( s_integrator == this);
s_integrator = NULL;
return val;
}
private:
double integrandF2( unsigned ndim, const double *x, void *,
unsigned fdim, double *fval) const;
static double fancy_integrand( unsigned ndim, const double* x, void* input,
unsigned fdim, double* fval)
{
s_integrator->integrateF2(ndim,x,input,fdim,fval);
}
std::tr1::function<integrand> m_integrand;
static const myIntegrator* s_integrator;
};https://stackoverflow.com/questions/3259686
复制相似问题