首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::tr1::function和std::tr1::bind

std::tr1::function和std::tr1::bind
EN

Stack Overflow用户
提问于 2010-07-15 20:20:55
回答 6查看 11.5K关注 0票数 4

我在C++类中使用一个非常复杂的C函数有问题(重写C函数不是一个选项)。C职能:

代码语言:javascript
复制
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,因为它很容易被重载等等。

代码语言:javascript
复制
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++的一些黑暗角落;)

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-07-16 14:29:33

如果您只是试图将一个成员函数传递给一个c样式的回调,您可以使用std::t1::bindstd::tr1::function完成这一任务。

代码语言:javascript
复制
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;
};
票数 3
EN

Stack Overflow用户

发布于 2010-07-15 22:22:54

你有三个问题。首先,您想要一个std::tr1::function<R (Args..)>,但您的需要归结为std::tr1::function<R (*)(Args...)> -所以您需要两种类型:

代码语言:javascript
复制
typedef void (integrand) (unsigned ndim, const double *x, void *,
                       unsigned fdim, double *fval);
typedef integrand* integrand_ptr;

..。因此,第一个允许您进行可编译的function<integrand>。必须相应地修正adapt_integrate

代码语言:javascript
复制
int adapt_integrate(unsigned fdim, integrand_ptr f, ...);

接下来,您的bind语法将关闭,它应该是:

代码语言:javascript
复制
std::tr1::bind(&myIntegrator::integrandF2, *this, _1, _2, _3, _4, _5);

剩下的问题是,tr1::function<T>不能转换为函数指针,因此您必须使用void* fdata参数来传递上下文,从而遍历包装函数。例如,类似:

代码语言:javascript
复制
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作为上下文参数:

代码语言:javascript
复制
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, ...);
票数 3
EN

Stack Overflow用户

发布于 2010-07-15 22:34:09

由于std::tr1::bind和c-样式的函数指针不合拍,所以请尝试以下操作。它将工作,只是myIntegrator::getValue不再是线程安全的。如果将calcTripleIntegral从接口中删除,这将更加简单,并且不需要使用std::tr1::bindstd::tr1::function

代码语言:javascript
复制
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;
};
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3259686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档