pointers to member functions

Discussion in 'C++' started by giulianodammando@libero.it, Jul 17, 2006.

  1. Guest

    Hi to everybody here at the newsgroup. I've a class:


    class CrossSection {
    public:
    // ctor(), dtor()
    double getValue(double E);
    double integrate(double a, double b); // <-- i'd like to
    implement this
    private:
    // private data members used by getValue()
    };

    what i need is to numerically integrate the cross section (whose value
    is returned by the function
    getValue) with respect to the energy. This should be accomplished by a
    member function integrate()
    (see the prototype in the class declaration) that in turn should rely
    on a set of C routines (various integration algorithms) of the form:

    typedef double (*f_ptr)(double )

    int integrate_gauss (f_ptr, double a, double b, double *result, double
    *erel)
    int integrate_gauss_legendre (f_ptr, double a, double b, double
    *result, double *erel)
    int integrate_adapt_step (f_ptr, double a, double b, double *result,
    double *erel, size_t maxiter)
    etc..


    i've tried something like:

    double integrate(double a, double b) {
    double erel = 1e-8;
    double result;
    integrate_gauss(&getValue, a,b,&result,&erel);
    return result;
    }

    that obviously does not compile because integrate_xyz functions expect
    a
    "normal" poiter to a global function and not a pointer to a class
    member func.
    Sad but true.

    Obviously i'd like to use a member integrate() function in order to
    access to private
    data of the class. in fact I've an array (better, a 2D matrix) of
    CrossSection objects, each one with different values of internal
    parameters. So the use of static class member functions is not
    possible, at the moment, because it should be of the form:

    static double staticGetValue(CrossSection *, double E)

    wich obviously doesn't fit with the prototype needed by *integrate_xyz*
    funcs. Anyway I probably need to use the same integration routines in
    other parts of the code, i.e. with other classes.

    I think this should be a well known issue in interfacing C code with
    C++, but i haven't been able to find a decent solution by myself. I ask
    to the more expert (i'm not very confident with c++ at the moment, but
    I think that a solution must exist, eventually adding one more level of
    deference somewere, that shoul be acceptable for now) people here in
    the newsgroup, hoping in the meantime
    in an illumination. anyway thanks a lot for reading this message, i
    hope i've explained clearly the point. bye

    giuliano.
     
    , Jul 17, 2006
    #1
    1. Advertising

  2. wrote:
    > Hi to everybody here at the newsgroup. I've a class:
    >
    >
    > class CrossSection {
    > public:
    > // ctor(), dtor()
    > double getValue(double E);
    > double integrate(double a, double b); // <-- i'd like to
    > implement this
    > private:
    > // private data members used by getValue()
    > };
    >
    > what i need is to numerically integrate the cross section (whose value
    > is returned by the function
    > getValue) with respect to the energy. This should be accomplished by a
    > member function integrate()
    > (see the prototype in the class declaration) that in turn should rely
    > on a set of C routines (various integration algorithms) of the form:
    >
    > typedef double (*f_ptr)(double )
    >
    > int integrate_gauss (f_ptr, double a, double b, double *result, double
    > *erel)
    > int integrate_gauss_legendre (f_ptr, double a, double b, double
    > *result, double *erel)
    > int integrate_adapt_step (f_ptr, double a, double b, double *result,
    > double *erel, size_t maxiter)
    > etc..
    >
    >
    > i've tried something like:
    >
    > double integrate(double a, double b) {
    > double erel = 1e-8;
    > double result;
    > integrate_gauss(&getValue, a,b,&result,&erel);
    > return result;
    > }
    >
    > that obviously does not compile because integrate_xyz functions expect
    > a
    > "normal" poiter to a global function and not a pointer to a class
    > member func.
    > Sad but true.
    >
    > Obviously i'd like to use a member integrate() function in order to
    > access to private
    > data of the class. in fact I've an array (better, a 2D matrix) of
    > CrossSection objects, each one with different values of internal
    > parameters. So the use of static class member functions is not
    > possible, at the moment, because it should be of the form:
    >
    > static double staticGetValue(CrossSection *, double E)
    >
    > wich obviously doesn't fit with the prototype needed by
    > *integrate_xyz* funcs. Anyway I probably need to use the same
    > integration routines in other parts of the code, i.e. with other
    > classes.
    >
    > I think this should be a well known issue in interfacing C code with
    > C++, but i haven't been able to find a decent solution by myself. I
    > ask to the more expert (i'm not very confident with c++ at the
    > moment, but I think that a solution must exist, eventually adding one
    > more level of deference somewere, that shoul be acceptable for now)
    > people here in the newsgroup, hoping in the meantime
    > in an illumination. anyway thanks a lot for reading this message, i
    > hope i've explained clearly the point. bye


    If you're not concerned with threading for a moment, a simple static
    (class-wide) variable designating the object for which you will integrate
    might help:

    class CrossSection {
    static CrossSection* to_integrate;
    ...
    };

    Set it right before you integrate for a particular object:

    CrossSection::to_integrate = &blah; // 'blah' is your object

    and then use your static function (as you wanted). Inside that static
    function use the 'to_integrate' variable:

    class CrossSection {
    static CrossSection* to_integrate;
    static double staticGetValue(double E) {
    if (to_integrate) return to_integrate->getValue(E);
    else return 0; // or something else
    }
    ...
    };

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jul 17, 2006
    #2
    1. Advertising

  3. * :
    > Hi to everybody here at the newsgroup. I've a class:
    >
    >
    > class CrossSection {
    > public:
    > // ctor(), dtor()
    > double getValue(double E);
    > double integrate(double a, double b); // <-- i'd like to
    > implement this
    > private:
    > // private data members used by getValue()
    > };
    >
    > what i need is to numerically integrate the cross section (whose value
    > is returned by the function
    > getValue) with respect to the energy. This should be accomplished by a
    > member function integrate()
    > (see the prototype in the class declaration) that in turn should rely
    > on a set of C routines (various integration algorithms) of the form:
    >
    > typedef double (*f_ptr)(double )
    >
    > int integrate_gauss (f_ptr, double a, double b, double *result, double
    > *erel)
    > int integrate_gauss_legendre (f_ptr, double a, double b, double
    > *result, double *erel)
    > int integrate_adapt_step (f_ptr, double a, double b, double *result,
    > double *erel, size_t maxiter)
    > etc..
    >
    >
    > i've tried something like:
    >
    > double integrate(double a, double b) {
    > double erel = 1e-8;
    > double result;
    > integrate_gauss(&getValue, a,b,&result,&erel);
    > return result;
    > }
    >
    > that obviously does not compile because integrate_xyz functions expect
    > a
    > "normal" poiter to a global function and not a pointer to a class
    > member func.
    > Sad but true.
    >
    > Obviously i'd like to use a member integrate() function in order to
    > access to private
    > data of the class. in fact I've an array (better, a 2D matrix) of
    > CrossSection objects, each one with different values of internal
    > parameters. So the use of static class member functions is not
    > possible, at the moment, because it should be of the form:
    >
    > static double staticGetValue(CrossSection *, double E)
    >
    > wich obviously doesn't fit with the prototype needed by *integrate_xyz*
    > funcs. Anyway I probably need to use the same integration routines in
    > other parts of the code, i.e. with other classes.
    >
    > I think this should be a well known issue in interfacing C code with
    > C++, but i haven't been able to find a decent solution by myself. I ask
    > to the more expert (i'm not very confident with c++ at the moment, but
    > I think that a solution must exist, eventually adding one more level of
    > deference somewere, that shoul be acceptable for now) people here in
    > the newsgroup, hoping in the meantime
    > in an illumination. anyway thanks a lot for reading this message, i
    > hope i've explained clearly the point. bye
    >
    > giuliano.


    class CrossSection
    {
    public:
    double valueAt( double x ) const { ... }
    double integrate(double a, double b) const
    {
    theCurrentObjectRef() = this;
    return someCIntegrationFunction( &theValueAt, a, b );
    }
    private:
    static CrossSection const*& theCurrentObjectRef()
    {
    static CrossSection const* theCurrentObject = 0;
    return theCurrentObject;
    }

    static theValueAt( double x )
    {
    return theCurrentObjectRef()->valueAt( x );
    }
    };

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 17, 2006
    #3
  4. Guest

    Thanks a lot Victor and Alf. In the meantime i've found the following
    solution.
    It works, but I don't know exactly how and why.

    I've defined two auxiliary classes:

    class func {
    public:
    func() {};
    virtual ~func() {};
    virtual const T_float operator() (const T_float x) = 0;
    /*virtual const array_1* operator() (const array_1 &vx) = 0;*/
    };

    // Wrapper for class functions

    template <class T>
    class Regular_func : public func {
    public:
    typedef T_double (T::*func_ptr)(double);
    //
    Regular_func() {}
    explicit Regular_func(T *t, func_ptr fun) { T_pointer=t; f = fun;}
    const T_float operator() (const T_float x) { return
    (T_pointer->*f)(x); }
    private:
    T *T_pointer;
    func_ptr f;
    };

    and in my CrossSection class i do this:

    class CrossSection {
    public:
    // ctor(), dtor()
    double getValue(double x) { /* code */ }
    T_float integrate(double a, double b) {
    double result, error;
    Regular_func<X> f(this,&X::getValue);
    integration_adapt1 (&f,a, b,&result,&error);
    if(error<=1e-10)
    return result;
    else
    HANDLE_ERROR("not converged",
    E_NOT_CONV); <-stupid macro that abort()
    }
    private:
    // data
    };

    and obviously i've changed all the declarations of the C functions so
    that they accept
    pointers to the base class func. The syntax inside the C functions does
    not change, neither
    internal calls to integration subfunctions.

    So this work, but for now i've not idea about efficiency issues. How
    many times a pointer to
    class func get deferenced before the actual value calculation?

    *f(x) -> operator()(x) -> T_pointer->getValue(x) -> body of the real
    function

    it should be 3 times? or more ?
    Thanks a lot
     
    , Jul 17, 2006
    #4
  5. * :
    > Thanks a lot Victor and Alf. In the meantime i've found the following
    > solution.
    > It works, but I don't know exactly how and why.


    No-one can tell you unless you post the code.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 17, 2006
    #5
  6. Guest

    Alf P. Steinbach wrote:
    > * :
    > > Thanks a lot Victor and Alf. In the meantime i've found the following
    > > solution.
    > > It works, but I don't know exactly how and why.

    >
    > No-one can tell you unless you post the code.
    >
    > --
    > A: Because it messes up the order in which people normally read text.
    > Q: Why is it such a bad thing?
    > A: Top-posting.
    > Q: What is the most annoying thing on usenet and in e-mail?


    This is what i meant (should compile cleanly). Obviously this solution
    is far from general
    because one needs to recompile the C numerical integration library
    library (in my case a few files), but I have not modified them
    internally. So this serves my purpose. With a precompiled library I
    think this method cannot be applied.

    Best Regards
    Giuliano


    // abstract class
    class func {
    public:
    func() {};
    virtual ~func() {};
    virtual const double operator() (const double x) = 0;
    /*virtual const array_1* operator() (const array_1 &vx) = 0;*/
    };

    // Wrapper for regular functions
    template <class T>
    class Regular_func : public func {
    public:
    typedef double (T::*func_ptr)(double);
    Regular_func() {}
    explicit Regular_func(T *t, func_ptr fun) { T_pointer=t; f = fun;}
    const double operator() (const double x) { return (T_pointer->*f)(x);
    }
    /* const array_1* operator() (const array_1 &vx){ <-- commented (i use
    external Array class)
    // returns array of values
    array_1 *y = new array_1;
    y->resize(vx.size());
    for(int i= vx.lbound(0); i < vx.ubound(0); i++){
    (*y)(i) = (T_pointer->*f)(vx(i));
    }
    return y;
    }*/
    private:
    T *T_pointer;
    func_ptr f;
    };



    /*
    typedef double (*fptr)(double);

    int integration_simple (fptr *f,
    double a, double b,
    double * result, double * abserr); */

    int integration_simple (func *f,
    double a, double b,
    double * result, double * abserr);


    int integration_simple (func *f,
    double a, double b,
    double * result, double * abserr)
    {
    double result1,result2;
    double half = (b-a)/2;
    /* very simple trapezoidal rule */
    result1 = ((*f)(a)+(*f)(b))/2*(b-a);
    result2 = ((*f)(a)+(*f)(half))/2*half + ((*f)(half)+(*f)(b))/2*half;
    *abserr = result2-result1;
    *result = result2;
    return 0;
    }


    class CrossSection {
    public:
    CrossSection() : k(5.0) {};
    double Y(double x) { return k*x; }
    double integrate(double a,double b) {
    double result,abserr;
    Regular_func<CrossSection> f(this,&CrossSection::Y);
    integration_simple (&f,a, b,&result, &abserr);
    return result;
    }
    private:
    double k;
    };

    #include <iostream>
    using std::cout;
    using std::endl;
    using std::cin;

    int main() {

    double result;
    char dummy;

    CrossSection aCrossSection;

    result = aCrossSection.integrate(0.0,1.0);

    std::cout << result << std::endl;
    cin >> dummy;
    }
     
    , Jul 18, 2006
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Hamish
    Replies:
    3
    Views:
    590
    Alf P. Steinbach
    Jan 25, 2008
  2. Hicham Mouline
    Replies:
    0
    Views:
    441
    Hicham Mouline
    Apr 23, 2009
  3. Hicham Mouline
    Replies:
    1
    Views:
    423
    Michael DOUBEZ
    Apr 24, 2009
  4. paul
    Replies:
    8
    Views:
    726
    Alf P. Steinbach
    Apr 30, 2009
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    694
Loading...

Share This Page