Search code examples
c++c++11tr1

std::tr1::function and std::tr1::bind


I have a problem using a very complicated C function in a C++ class (rewriting the C function is not an option). C function:

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);

I need to supply a void function of type integrand myself, and adapt_integrate will calculate the n-dimensional integral. The code in calcTripleIntegral (below) works as a standalone function if func is a standalone function). I want to pass a (non-static!) class member function as the integrand, as this can be easily overloaded etc...

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);
    }
}

On GCC 4.4.5 (prerelease), this gives me:

error: variable 'std::tr1::function func' has initializer but incomplete type

EDIT:What is the error in my code? I have now tried compiling with GCC 4.4, 4.5 and 4.6, all resulting in the same error. Either no work has been done on this, or I did something wrong /EDIT

Thanks very much! If I'm not clear enough, I'll gladly elaborate.

PS: Could I work around this without tr1 stuff by using a function pointer to a function defined somewhere in myIntegrator.cpp?

FINAL UPDATE: ok, I was mistaken in thinking TR1 provided a one/two-line solution for this. Bummer. I'm "converting" my classes to namespaces and copypasting the function declarations. I only need one base class and one subclass which reimplemented the interface. C function pointer + C++ class = bad news for me. Thanks anyways for all the answers, you've shown me some dark corners of C++ ;)


Solution

  • If you are just trying to pass a member function into a c-style callback, you can do that with out using std::t1::bind or 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;
    };