std::tr1::函数和std::tr1::bind 我在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);
我需要自己提供一个std::tr1::函数和std::tr1::bind 我在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);,c++,c++11,tr1,C++,C++11,Tr1,我需要自己提供一个被积函数类型的空函数,adapt_integral将计算n维积分。如果func是独立函数,则calcTripleIntegral(以下)中的代码作为独立函数工作。 我想传递一个(非静态的!)类成员函数作为被积函数,因为这很容易重载等等 class myIntegrator { public: double calcTripleIntegral( double x, double Q2, std::tr1::function<integrand> &f
被积函数类型的空函数,adapt_integral将计算n维积分。如果func
是独立函数,则calcTripleIntegral
(以下)中的代码作为独立函数工作。
我想传递一个(非静态的!)类成员函数作为被积函数,因为这很容易重载等等
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);
}
}
类myIntegrator
{
公众:
双calcTripleIntegral(双x,双Q2,标准::tr1::函数和函数)常数
{
//…声明val、err、xMin、xMax和输入(x,Q2)//
自适应_积分(1,函数,输入,
3,xMin,xMax,
0,0,1e-4,
&val和err);
返回val;
}
double integrandF2(无符号ndim,常数double*x,void*,//无论内部是什么
无符号fdim,double*fval)const;//如果它不是类成员,则符合被积函数的条件
双getValue(双x,双Q2)常量
{
std::tr1::function func(std::tr1::bind(&myIntegrator::integrandF2,*this);
返回calcTripleIntegral(x,Q2,func);
}
}
在GCC 4.4.5(预发行版)中,这给了我:
错误:变量“std::tr1::function func”具有初始值设定项,但类型不完整
编辑:我的代码中有什么错误?我现在尝试使用GCC 4.4、4.5和4.6进行编译,所有这些都导致了相同的错误。要么没有对此做任何工作,要么我做错了什么/EDIT
非常感谢!如果我不够清楚,我很乐意详细说明
PS:我可以在没有tr1的情况下,通过使用指向myIntegrator.cpp中某个地方定义的函数的函数指针来解决这个问题吗
<强>最后更新< /强>:好吧,我错误地认为Tr1提供了一个/两个线的解决方案。BuMME。我正在“转换”我的类到命名空间和复制函数声明。我只需要一个基类和一个子类重新实现接口。C函数指针+ C++类=坏消息对我来说。
感谢所有的答案,你给我展示了一些C++的暗角;
< P>我想把一个(非静态的)类成员函数传递成整合式…< /P>
你不能。如果您搜索使用成员函数作为回调函数,您一定会找到有用的信息,包括您正在尝试做的事情,不管怎样,直接方法是不可能的
编辑:顺便说一句,代码中的一个问题(当然还有更多的问题,因为您试图做的是根本不可能的)是您向函数传递了一个函数指针类型,而它期望的是一个签名。函数模板的实现方式如下:
template < typename Signature >
struct function;
// for each possible number of arguments:
template < typename R, typename Arg1, typename Arg2 >
struct function<R(Arg1,Arg2)>
{
... body ...
};
模板
结构功能;
//对于每个可能的参数数:
模板
结构函数
{
…身体。。。
};
正如您所看到的,传递一个函数指针到这类事情是编译器无法理解的。它将尝试实例化forward声明,但却一无所获。这当然是你得到的编译器错误意味着什么,但它并没有解决你的根本问题,那就是你所做的永远不会起作用
在一个完全C++0x编译器中,这可以以不同的方式完成,但是boost::function和MSVC必须是这样的。此外,C++0x版本将遇到与您当前面临的问题相同的问题。该错误消息听起来好像您缺少所涉及类型之一的包含。至少尝试再次检查您的被积函数
和tr1
包含?绑定
的工作原理与您认为的有点不同。您需要为每个参数提供一个值或占位符
对于您的示例,这归结为(带占位符)
std::tr1::function func(std::tr1::bind(&myIntegrator::integrandF2,*this,_1,_2,_3,_4,_5));
由于绑定的是一个成员函数,因此有一个额外的(隐式)参数,即调用成员函数的对象,因此有六个
对于第一个绑定this
对象,对于其他参数,只需传递占位符
另一方面,您的成员函数返回double,而函数声明返回void
(作为记录,我仍在使用一个较旧的编译器,几乎不支持tr1,因此我只有bind
和function
使用boost的经验,tr1可能会有一些变化…您有三个问题。。。首先,您需要一个std::tr1::function
,但您的可以归结为std::tr1::function
——因此您需要两个typedef:
typedef void (integrand) (unsigned ndim, const double *x, void *,
unsigned fdim, double *fval);
typedef integrand* integrand_ptr;
。。。因此,第一个允许您使用可编译的函数
<代码>自适应\u集成
必须相应地固定:
int adapt_integrate(unsigned fdim, integrand_ptr f, ...);
接下来,您的bind
语法处于禁用状态,它应该是:
std::tr1::bind(&myIntegrator::integrandF2, *this, _1, _2, _3, _4, _5);
剩下的问题是tr1::function
不能转换为函数指针,因此您必须遍历包装函数,使用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, ...);
由于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;
};
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;
};
类myIntegrator
{
公众:
双getValue(双x,双Q2)常量
{
返回calcTripleIntegral(x,Q2,std::tr1::bind(&Integrator::integrandF2,this));
}
双计算积分(双x,双Q2,con
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;
};
#include <iostream>
#include <tr1/functional>
typedef void (*callback_function_t)(void *input, int arg);
struct data_type {
int x;
};
struct context_type {
std::tr1::function<void(data_type const &, int)> func;
data_type data;
};
void callback(data_type const&data, int x) {
std::cout << data.x << ", " << x << std::endl;
}
void callback_relay(void *context, int x) {
context_type const *ctxt = reinterpret_cast<context_type const*>(context);
ctxt->func(ctxt->data, x);
}
void call_callback(callback_function_t func, void *context, int x) {
func(context, x);
}
int main() {
context_type ctxt = { callback, { 1 } };
call_callback(callback_relay, &ctxt, 2);
}
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;
};