pointers to member functions

G

giulianodammando

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.
 
V

Victor Bazarov

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
 
A

Alf P. Steinbach

* (e-mail address removed):
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 );
}
};
 
G

giulianodammando

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
 
A

Alf P. Steinbach

* (e-mail address removed):
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.
 
G

giulianodammando

Alf said:
* (e-mail address removed):

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

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top