passing member function pointers to a function

Discussion in 'C++' started by tbringley@gmail.com, Feb 23, 2007.

  1. Guest

    I am a c++ newbie, so please excuse the ignorance of this question.

    I am interested in a way of having a class call a general member
    function of another class.

    Specifically, I am trying to write an ordinary differential equation
    class that would solve a general equation in the form:
    dx/dt = f(x,t).

    The ode class shouldn't know anything about f, except how to call it.

    My first thought was to have a data member that stores a pointer to
    the function f like:
    double (*f) (double, double);

    However, I learned that f could not point to a non-static member
    function of a different class. This is bad for me, because I need to
    use the solver for functions that are complicated to evaluate and
    depend on many parameters. A simple example:

    class my_f{ public:
    double a;
    double f(double x, double t){ return t+x*a;}
    };

    my_f foo; foo.a = 7;

    I would like the ode solver to call foo.f(x,t). I could make

    double (my_f::* f)(double, double);

    a member of the ode solver, but then I would have to write a new ode
    solver for every new class of functions to be used for f or to have
    all these derive from some kind of base class, which I would prefer to
    avoid.

    My question is: is there a simple and elegant way to do this? I would
    think that similar issues have been encountered many times before.
    Thanks.
     
    , Feb 23, 2007
    #1
    1. Advertising

  2. Piyo Guest

    wrote:

    >
    > My question is: is there a simple and elegant way to do this? I would
    > think that similar issues have been encountered many times before.
    > Thanks.
    >

    This can help give you an idea how to approach this problem.

    -----------------------------------------------

    // Use boost/function and functors
    #include <boost/function.hpp>

    // create a functor
    class my_f
    {
    public:
    my_f( double a ) : m_a(a) {}
    double operator()(double x, double t){ return t+x*m_a;}
    private:
    double m_a;
    };

    // this is another functor
    class my_y
    {
    public:
    my_y( double a ) : m_a(a) {}
    double operator()(double x, double t) { return t+x*m_a;}
    private:
    double m_a;
    };

    class ODE
    {
    public:
    void solve( boost::function<double (double, double)> f)
    {
    // call f here
    double result = f( 1.0, 1.0 );
    }
    };

    int
    main()
    {
    ODE solver;
    solver.solve( my_f(20.0) );
    solver.solve( my_y(100.0) );
    }
     
    Piyo, Feb 23, 2007
    #2
    1. Advertising

  3. roy axenov Guest

    Please note that my C++ is so rusty it squeaks when I walk.

    On Feb 23, 10:36 pm, wrote:
    > I am interested in a way of having a class call a general
    > member function of another class.
    >
    > Specifically, I am trying to write an ordinary
    > differential equation class that would solve a general
    > equation in the form: dx/dt = f(x,t).


    I believe you're making a conceptual mistake here. In the
    design you're describing f(x,t) is not represented by a
    method of a class, but by the class itself, and f a (x,t) -
    by an instance of the class representing f(x,t) functions.
    That's why you probably shouldn't try passing a pointer to
    a method, pass a reference to the object instead. If you
    have more general questions about all of this, you probably
    should follow-up to comp.object.

    > The ode class shouldn't know anything about f, except how
    > to call it.


    That's pretty much a textbook description of an interface.

    [...]

    > a member of the ode solver, but then I would have to
    > write a new ode solver for every new class of functions
    > to be used for f or to have all these derive from some
    > kind of base class, which I would prefer to avoid.


    That kinda defeats the purpose of OOD, doesn't it?

    > My question is: is there a simple and elegant way to do
    > this? I would think that similar issues have been
    > encountered many times before.


    I'm not sure if this will work for you, but consider this
    bare-bones implementation:

    #include <iostream>

    class interface_function
    {
    public :
    virtual double operator ( )
    ( double x , double t ) const = 0 ;
    } ;

    class ode
    {
    public :
    static void solve ( const interface_function & f ) ;
    } ;

    void ode :: solve ( const interface_function & f )
    {
    std :: cout <<
    f
    (
    static_cast < double > ( 1 ) ,
    static_cast < double > ( 1 )
    ) ;
    std :: cout << std :: endl ;
    }

    class f : public interface_function
    {
    public :
    double a_ ;
    f ( ) : a_ ( 1 ) { }
    virtual double operator ( )
    ( double x , double t ) const ;
    } ;

    double f :: operator ( )
    ( double x , double t ) const
    {
    return t + x * a_ ;
    }

    class g : public interface_function
    {
    public :
    double a_ ;
    g ( ) : a_ ( 1 ) { }
    virtual double operator ( )
    ( double x , double t ) const ;
    } ;

    double g :: operator ( )
    ( double x , double t ) const
    {
    return t - x * a_ ;
    }

    int main ( )
    {
    f f1 ;
    g g1 ;
    ode :: solve ( f1 ) ;
    ode :: solve ( g1 ) ;
    f1 . a_ = 5 ;
    g1 . a_ = 5 ;
    ode :: solve ( f1 ) ;
    ode :: solve ( g1 ) ;
    }

    --
    roy axenov
     
    roy axenov, Feb 23, 2007
    #3
  4. Mark P Guest

    wrote:
    > I am a c++ newbie, so please excuse the ignorance of this question.
    >
    > I am interested in a way of having a class call a general member
    > function of another class.
    >
    > Specifically, I am trying to write an ordinary differential equation
    > class that would solve a general equation in the form:
    > dx/dt = f(x,t).
    >
    > The ode class shouldn't know anything about f, except how to call it.
    >
    > My first thought was to have a data member that stores a pointer to
    > the function f like:
    > double (*f) (double, double);
    >
    > However, I learned that f could not point to a non-static member
    > function of a different class. This is bad for me, because I need to
    > use the solver for functions that are complicated to evaluate and
    > depend on many parameters. A simple example:
    >
    > class my_f{ public:
    > double a;
    > double f(double x, double t){ return t+x*a;}
    > };
    >
    > my_f foo; foo.a = 7;
    >
    > I would like the ode solver to call foo.f(x,t). I could make
    >
    > double (my_f::* f)(double, double);
    >
    > a member of the ode solver, but then I would have to write a new ode
    > solver for every new class of functions to be used for f or to have
    > all these derive from some kind of base class, which I would prefer to
    > avoid.
    >
    > My question is: is there a simple and elegant way to do this? I would
    > think that similar issues have been encountered many times before.
    > Thanks.
    >


    How are you passing the function object to the solver in the first
    place? Or perhaps this is really the root of your question? The two
    most direct approaches would be to use either inheritance or templates.
    In the former, you would have some abstract base class like:

    class TwoArgFcn
    {
    public:
    virtual double evaluate( double x, double t) = 0;
    };

    Then a derived class defines evaluate() as appropriate and your solver
    takes an object of type TwoArgFcn& or something similar.

    If you use templates, then you solver is templated on the type of the
    function object:

    template <typename FcnClass>
    class Solver
    {
    public:
    Solver( FcnClass& input_fcn) : input_fcn( input_fcn) {}

    private:
    void solve() { /* use input_fcn.f() */ }

    FcnClass& input_fcn;
    };

    Here you assume that the template class FcnClass defines some function f
    (which will be verified when the template is instatiated).

    -Mark
     
    Mark P, Feb 23, 2007
    #4
  5. Guest

    Thanks for the suggestions everyone. I guess what I had in mind was
    something along the lines of:

    class ode_solver{
    ...
    double (*f) (double,double);
    void solve();
    ...
    };

    ode_solver s;
    s.f = & arbitraryclass.arbitraryfunction;
    s.solve();

    This would work perfectly fine if f pointed to a non-member function
    -- and this idea is used a lot in C.

    I will be needing to use the ode_solver with an extremely general set
    of functions f that might come from all different kinds of classes.
    It is not an option to guarantee that f is a member of a particular
    class or has a particular name (i.e. f or operator(double,double)). I
    would much prefer if I didn't have to modify the code of
    arbitraryclass, if that's possible.

    So, there is no way to do something like this in C++ with member
    functions?

    I could make "every" class in my library derive from

    class its_a_class{
    // empty
    };

    class my_class : public its_a_class{
    double f1(double x, double t);
    double f2(double x, double t);
    ....
    // lots of data/functions that f1 and f2 need to know about/call
    ....
    };

    class ode_solver : public its_a_class{
    double (its_a_class:: *f)(double, double);
    ....
    };

    my_class foo;
    ode_solver s;
    ....
    s.f = & foo.f1;
    s.solve;
    ....
    s.f = &foo.f2;
    s.solve;

    etc.

    Would this work? But, it's ridiculous, right? There's not a better
    way?

    It seems like the suggestions are along the lines of that f should be
    itself a class. So...

    class ode_solver{
    TwoArgFunc f;
    };

    but then...

    class my_class{
    TwoArgFunc f1;
    ....
    };

    s.f = foo.f1;

    is no good, because f1 needs to know about the data of my_class and to
    call other functions in my_class to evaluate itself (like a member
    function does).

    Thanks again.




    On Feb 23, 5:04 pm, Mark P <>
    wrote:
    > wrote:
    > > I am a c++ newbie, so please excuse the ignorance of this question.

    >
    > > I am interested in a way of having a class call a general member
    > > function of another class.

    >
    > > Specifically, I am trying to write an ordinary differential equation
    > > class that would solve a general equation in the form:
    > > dx/dt = f(x,t).

    >
    > > The ode class shouldn't know anything about f, except how to call it.

    >
    > > My first thought was to have a data member that stores a pointer to
    > > the function f like:
    > > double (*f) (double, double);

    >
    > > However, I learned that f could not point to a non-static member
    > > function of a different class. This is bad for me, because I need to
    > > use the solver for functions that are complicated to evaluate and
    > > depend on many parameters. A simple example:

    >
    > > class my_f{ public:
    > > double a;
    > > double f(double x, double t){ return t+x*a;}
    > > };

    >
    > > my_f foo; foo.a = 7;

    >
    > > I would like the ode solver to call foo.f(x,t). I could make

    >
    > > double (my_f::* f)(double, double);

    >
    > > a member of the ode solver, but then I would have to write a new ode
    > > solver for every new class of functions to be used for f or to have
    > > all these derive from some kind of base class, which I would prefer to
    > > avoid.

    >
    > > My question is: is there a simple and elegant way to do this? I would
    > > think that similar issues have been encountered many times before.
    > > Thanks.

    >
    > How are you passing the function object to the solver in the first
    > place? Or perhaps this is really the root of your question? The two
    > most direct approaches would be to use either inheritance or templates.
    > In the former, you would have some abstract base class like:
    >
    > class TwoArgFcn
    > {
    > public:
    > virtual double evaluate( double x, double t) = 0;
    >
    > };
    >
    > Then a derived class defines evaluate() as appropriate and your solver
    > takes an object of type TwoArgFcn& or something similar.
    >
    > If you use templates, then you solver is templated on the type of the
    > function object:
    >
    > template <typename FcnClass>
    > class Solver
    > {
    > public:
    > Solver( FcnClass& input_fcn) : input_fcn( input_fcn) {}
    >
    > private:
    > void solve() { /* use input_fcn.f() */ }
    >
    > FcnClass& input_fcn;
    >
    > };
    >
    > Here you assume that the template class FcnClass defines some function f
    > (which will be verified when the template is instatiated).
    >
    > -Mark
     
    , Feb 23, 2007
    #5
  6. Guest

    Thanks for the suggestions everyone. I guess what I had in mind was
    something along the lines of:

    class ode_solver{
    ...
    double (*f) (double,double);
    void solve();
    ...
    };

    ode_solver s;
    s.f = & arbitraryclass.arbitraryfunction;
    s.solve();

    This would work perfectly fine if f pointed to a non-member function
    -- and this idea is used a lot in C.

    I will be needing to use the ode_solver with an extremely general set
    of functions f that might come from all different kinds of classes.
    It is not an option to guarantee that f is a member of a particular
    class or has a particular name (i.e. f or operator(double,double)). I
    would much prefer if I didn't have to modify the code of
    arbitraryclass, if that's possible.

    So, there is no way to do something like this in C++ with member
    functions?

    I could make "every" class in my library derive from

    class its_a_class{
    // empty
    };

    class my_class : public its_a_class{
    double f1(double x, double t);
    double f2(double x, double t);
    ....
    // lots of data/functions that f1 and f2 need to know about/call
    ....
    };

    class ode_solver : public its_a_class{
    double (its_a_class:: *f)(double, double);
    ....
    };

    my_class foo;
    ode_solver s;
    ....
    s.f = & foo.f1;
    s.solve;
    ....
    s.f = &foo.f2;
    s.solve;

    etc.

    Would this work? But, it's ridiculous, right? There's not a better
    way?

    It seems like the suggestions are along the lines of that f should be
    itself a class. So...

    class ode_solver{
    TwoArgFunc f;
    };

    but then...

    class my_class{
    TwoArgFunc f1;
    ....
    };

    s.f = foo.f1;

    is no good, because f1 needs to know about the data of my_class and to
    call other functions in my_class to evaluate itself (like a member
    function does).

    Thanks again.




    On Feb 23, 5:04 pm, Mark P <>
    wrote:
    > wrote:
    > > I am a c++ newbie, so please excuse the ignorance of this question.

    >
    > > I am interested in a way of having a class call a general member
    > > function of another class.

    >
    > > Specifically, I am trying to write an ordinary differential equation
    > > class that would solve a general equation in the form:
    > > dx/dt = f(x,t).

    >
    > > The ode class shouldn't know anything about f, except how to call it.

    >
    > > My first thought was to have a data member that stores a pointer to
    > > the function f like:
    > > double (*f) (double, double);

    >
    > > However, I learned that f could not point to a non-static member
    > > function of a different class. This is bad for me, because I need to
    > > use the solver for functions that are complicated to evaluate and
    > > depend on many parameters. A simple example:

    >
    > > class my_f{ public:
    > > double a;
    > > double f(double x, double t){ return t+x*a;}
    > > };

    >
    > > my_f foo; foo.a = 7;

    >
    > > I would like the ode solver to call foo.f(x,t). I could make

    >
    > > double (my_f::* f)(double, double);

    >
    > > a member of the ode solver, but then I would have to write a new ode
    > > solver for every new class of functions to be used for f or to have
    > > all these derive from some kind of base class, which I would prefer to
    > > avoid.

    >
    > > My question is: is there a simple and elegant way to do this? I would
    > > think that similar issues have been encountered many times before.
    > > Thanks.

    >
    > How are you passing the function object to the solver in the first
    > place? Or perhaps this is really the root of your question? The two
    > most direct approaches would be to use either inheritance or templates.
    > In the former, you would have some abstract base class like:
    >
    > class TwoArgFcn
    > {
    > public:
    > virtual double evaluate( double x, double t) = 0;
    >
    > };
    >
    > Then a derived class defines evaluate() as appropriate and your solver
    > takes an object of type TwoArgFcn& or something similar.
    >
    > If you use templates, then you solver is templated on the type of the
    > function object:
    >
    > template <typename FcnClass>
    > class Solver
    > {
    > public:
    > Solver( FcnClass& input_fcn) : input_fcn( input_fcn) {}
    >
    > private:
    > void solve() { /* use input_fcn.f() */ }
    >
    > FcnClass& input_fcn;
    >
    > };
    >
    > Here you assume that the template class FcnClass defines some function f
    > (which will be verified when the template is instatiated).
    >
    > -Mark
     
    , Feb 23, 2007
    #6
  7. Piyo Guest

    >
    > class my_class : public its_a_class{
    > double f1(double x, double t);
    > double f2(double x, double t);
    > ...
    > // lots of data/functions that f1 and f2 need to know about/call
    > ...
    > };
    >
    > class ode_solver : public its_a_class{
    > double (its_a_class:: *f)(double, double);
    > ...
    > };
    >
    > my_class foo;
    > ode_solver s;
    > ...
    > s.f = & foo.f1;
    > s.solve;
    > ...
    > s.f = &foo.f2;
    > s.solve;
    >
    > etc.
    >
    > Would this work? But, it's ridiculous, right? There's not a better
    > way?
    >

    Hi, instead of us trying to determine your program requirements and
    write example code that will fit it properly, I think it is better to
    just teach you about calling a pointer to a member function because it
    is possible to do so.

    Here is a guide to doing that:

    http://www.parashift.com/c -faq-lite/pointers-to-members.html

    Good Luck with that :)
     
    Piyo, Feb 23, 2007
    #7
  8. Grizlyk Guest

    wrote:
    >
    > My first thought was to have a data member that stores a pointer to
    > the function f like:
    > double (*f) (double, double);
    >
    > but then I would have to write a new ode
    > solver for every new class of functions to be used for f or to have
    > all these derive from some kind of base class


    Pointer is no needed here, use ordinary member

    template<class T>
    class
    {
    T obj;

    public:
    double f(double x, double t){ return obj.f(x, t);}
    };

    The main OO design rule is: "find all that can be changed and encapsulate
    it". Incapsulator is function or class. You have said, that you will change
    implementation of concrete function - see design pattern "strategy".

    At design stage to find design patterns without external help do not speak
    implementations details (as "pointer") language, do not take the details as
    predefined invariants, describe what you want in design terms: interface,
    message and implementation, method.

    --
    Maksim A. Polyanin
    http://grizlyk1.narod.ru/cpp_new

    "In thi world of fairy tales rolls are liked olso"
    /Gnume/
     
    Grizlyk, Feb 23, 2007
    #8
  9. Guest

    I am aware that it is possible to have a pointer to a member
    function. However, such a pointer must know the name of the class
    that contains the member function to which it points. This is what I
    am trying to circumvent.

    Please do not write example code for me if you don't want to. I just
    included sample code and details of my project to give make more
    concrete what I am trying to do. In the simplest terms, I would just
    like to know if there is a way for class A to call a member function
    of class B without class A knowing that the function it is calling is
    a member of class B.

    Thanks.




    On Feb 23, 6:32 pm, Piyo <> wrote:
    > > class my_class : public its_a_class{
    > > double f1(double x, double t);
    > > double f2(double x, double t);
    > > ...
    > > // lots of data/functions that f1 and f2 need to know about/call
    > > ...
    > > };

    >
    > > class ode_solver : public its_a_class{
    > > double (its_a_class:: *f)(double, double);
    > > ...
    > > };

    >
    > > my_class foo;
    > > ode_solver s;
    > > ...
    > > s.f = & foo.f1;
    > > s.solve;
    > > ...
    > > s.f = &foo.f2;
    > > s.solve;

    >
    > > etc.

    >
    > > Would this work? But, it's ridiculous, right? There's not a better
    > > way?

    >
    > Hi, instead of us trying to determine your program requirements and
    > write example code that will fit it properly, I think it is better to
    > just teach you about calling a pointer to a member function because it
    > is possible to do so.
    >
    > Here is a guide to doing that:
    >
    > http://www.parashift.com/c -faq-lite/pointers-to-members.html
    >
    > Good Luck with that :)
     
    , Feb 23, 2007
    #9
  10. Guest

    I am aware that it is possible to have a pointer to a member
    function. However, such a pointer must know the name of the class
    that contains the member function to which it points. This is what I
    am trying to circumvent.

    Please do not write example code for me if you don't want to. I just
    included sample code and details of my project to give make more
    concrete what I am trying to do. In the simplest terms, I would just
    like to know if there is a way for class A to call a member function
    of class B without class A knowing that the function it is calling is
    a member of class B.

    Thanks.




    On Feb 23, 6:32 pm, Piyo <> wrote:
    > > class my_class : public its_a_class{
    > > double f1(double x, double t);
    > > double f2(double x, double t);
    > > ...
    > > // lots of data/functions that f1 and f2 need to know about/call
    > > ...
    > > };

    >
    > > class ode_solver : public its_a_class{
    > > double (its_a_class:: *f)(double, double);
    > > ...
    > > };

    >
    > > my_class foo;
    > > ode_solver s;
    > > ...
    > > s.f = & foo.f1;
    > > s.solve;
    > > ...
    > > s.f = &foo.f2;
    > > s.solve;

    >
    > > etc.

    >
    > > Would this work? But, it's ridiculous, right? There's not a better
    > > way?

    >
    > Hi, instead of us trying to determine your program requirements and
    > write example code that will fit it properly, I think it is better to
    > just teach you about calling a pointer to a member function because it
    > is possible to do so.
    >
    > Here is a guide to doing that:
    >
    > http://www.parashift.com/c -faq-lite/pointers-to-members.html
    >
    > Good Luck with that :)
     
    , Feb 23, 2007
    #10
  11. Lionel B Guest

    On Fri, 23 Feb 2007 12:36:07 -0800, tbringley wrote:

    > I am a c++ newbie, so please excuse the ignorance of this question.
    >
    > I am interested in a way of having a class call a general member
    > function of another class.
    >
    > Specifically, I am trying to write an ordinary differential equation
    > class that would solve a general equation in the form:
    > dx/dt = f(x,t).
    >
    > The ode class shouldn't know anything about f, except how to call it.
    >
    > My first thought was to have a data member that stores a pointer to
    > the function f like:
    > double (*f) (double, double);
    >
    > However, I learned that f could not point to a non-static member
    > function of a different class. This is bad for me, because I need to
    > use the solver for functions that are complicated to evaluate and
    > depend on many parameters. A simple example:
    >
    > class my_f{ public:
    > double a;
    > double f(double x, double t){ return t+x*a;}
    > };
    >
    > my_f foo; foo.a = 7;
    >
    > I would like the ode solver to call foo.f(x,t). I could make
    >
    > double (my_f::* f)(double, double);
    >
    > a member of the ode solver, but then I would have to write a new ode
    > solver for every new class of functions to be used for f or to have
    > all these derive from some kind of base class, which I would prefer to
    > avoid.
    >
    > My question is: is there a simple and elegant way to do this? I would
    > think that similar issues have been encountered many times before.
    > Thanks.


    How about something like this?

    #include <iostream>

    class Aclass
    {
    double a,b;
    public:
    Aclass(double a_, double b_) : a(a_), b(b_)
    {
    }

    double func1(double x, double t)
    {
    return a*x+b*t;
    }

    double func2(double x, double t)
    {
    return a*x*x+b*t;
    }
    };

    template<typename T> double solver(T& obj, double (T::*func)(double,double))
    {
    double y = (obj.*func)(2.0,3.0);
    return y;
    }

    int main()
    {
    Aclass aclass(3.0, 4.0);

    double y1 = solver(aclass, &Aclass::func1);

    std::cout << "y1 = " << y1 << '\n';

    double y2 = solver(aclass, &Aclass::func2);

    std::cout << "y2 = " << y2 << '\n';
    }

    Output:
    y1 = 18
    y2 = 24



    --
    Lionel B
     
    Lionel B, Feb 24, 2007
    #11
  12. Lionel B Guest

    On Sat, 24 Feb 2007 00:04:12 +0000, Lionel B wrote:

    > On Fri, 23 Feb 2007 12:36:07 -0800, tbringley wrote:
    >
    >> I am a c++ newbie, so please excuse the ignorance of this question.
    >>
    >> I am interested in a way of having a class call a general member
    >> function of another class.
    >>
    >> Specifically, I am trying to write an ordinary differential equation
    >> class that would solve a general equation in the form:
    >> dx/dt = f(x,t).
    >>
    >> The ode class shouldn't know anything about f, except how to call it.
    >>
    >> My first thought was to have a data member that stores a pointer to
    >> the function f like:
    >> double (*f) (double, double);
    >>
    >> However, I learned that f could not point to a non-static member
    >> function of a different class. This is bad for me, because I need to
    >> use the solver for functions that are complicated to evaluate and
    >> depend on many parameters. A simple example:
    >>
    >> class my_f{ public:
    >> double a;
    >> double f(double x, double t){ return t+x*a;}
    >> };
    >>
    >> my_f foo; foo.a = 7;
    >>
    >> I would like the ode solver to call foo.f(x,t). I could make
    >>
    >> double (my_f::* f)(double, double);
    >>
    >> a member of the ode solver, but then I would have to write a new ode
    >> solver for every new class of functions to be used for f or to have
    >> all these derive from some kind of base class, which I would prefer to
    >> avoid.
    >>
    >> My question is: is there a simple and elegant way to do this? I would
    >> think that similar issues have been encountered many times before.
    >> Thanks.

    >
    > How about something like this?


    [snip]

    Sorry, you wanted your solver to be a class... try something
    along these lines:

    #include <iostream>

    class Aclass
    {
    double a,b;

    public:
    Aclass(double a_, double b_) : a(a_), b(b_)
    {
    }

    double func1(double x, double t)
    {
    return a*x+b*t;
    }

    double func2(double x, double t)
    {
    return a*x*x+b*t;
    }
    };

    class Solver
    {
    double c,d;

    public:
    Solver(double c_, double d_) : c(c_), d(d_)
    {
    }

    template<typename T> double solve(T& obj, double (T::*func)(double,double))
    {
    double y = (obj.*func)(c,d);
    return y;
    }
    };

    int main()
    {
    Solver solver(2.0,3.0);

    Aclass aclass(3.0, 4.0);

    double y1 = solver.solve(aclass, &Aclass::func1);

    std::cout << "y1 = " << y1 << '\n';

    double y2 = solver.solve(aclass, &Aclass::func2);

    std::cout << "y2 = " << y2 << '\n';
    }

    Output:
    y1 = 18
    y2 = 24

    --
    Lionel B
     
    Lionel B, Feb 24, 2007
    #12
  13. Guest

    Thanks Lionel! That's brilliant.

    On Feb 23, 7:14 pm, Lionel B <> wrote:
    > On Sat, 24 Feb 2007 00:04:12 +0000, Lionel B wrote:
    > > On Fri, 23 Feb 2007 12:36:07 -0800, tbringley wrote:

    >
    > >> I am a c++ newbie, so please excuse the ignorance of this question.

    >
    > >> I am interested in a way of having a class call a general member
    > >> function of another class.

    >
    > >> Specifically, I am trying to write an ordinary differential equation
    > >> class that would solve a general equation in the form:
    > >> dx/dt = f(x,t).

    >
    > >> The ode class shouldn't know anything about f, except how to call it.

    >
    > >> My first thought was to have a data member that stores a pointer to
    > >> the function f like:
    > >> double (*f) (double, double);

    >
    > >> However, I learned that f could not point to a non-static member
    > >> function of a different class. This is bad for me, because I need to
    > >> use the solver for functions that are complicated to evaluate and
    > >> depend on many parameters. A simple example:

    >
    > >> class my_f{ public:
    > >> double a;
    > >> double f(double x, double t){ return t+x*a;}
    > >> };

    >
    > >> my_f foo; foo.a = 7;

    >
    > >> I would like the ode solver to call foo.f(x,t). I could make

    >
    > >> double (my_f::* f)(double, double);

    >
    > >> a member of the ode solver, but then I would have to write a new ode
    > >> solver for every new class of functions to be used for f or to have
    > >> all these derive from some kind of base class, which I would prefer to
    > >> avoid.

    >
    > >> My question is: is there a simple and elegant way to do this? I would
    > >> think that similar issues have been encountered many times before.
    > >> Thanks.

    >
    > > How about something like this?

    >
    > [snip]
    >
    > Sorry, you wanted your solver to be a class... try something
    > along these lines:
    >
    > #include <iostream>
    >
    > class Aclass
    > {
    > double a,b;
    >
    > public:
    > Aclass(double a_, double b_) : a(a_), b(b_)
    > {
    > }
    >
    > double func1(double x, double t)
    > {
    > return a*x+b*t;
    > }
    >
    > double func2(double x, double t)
    > {
    > return a*x*x+b*t;
    > }
    >
    > };
    >
    > class Solver
    > {
    > double c,d;
    >
    > public:
    > Solver(double c_, double d_) : c(c_), d(d_)
    > {
    > }
    >
    > template<typename T> double solve(T& obj, double (T::*func)(double,double))
    > {
    > double y = (obj.*func)(c,d);
    > return y;
    > }
    >
    > };
    >
    > int main()
    > {
    > Solver solver(2.0,3.0);
    >
    > Aclass aclass(3.0, 4.0);
    >
    > double y1 = solver.solve(aclass, &Aclass::func1);
    >
    > std::cout << "y1 = " << y1 << '\n';
    >
    > double y2 = solver.solve(aclass, &Aclass::func2);
    >
    > std::cout << "y2 = " << y2 << '\n';
    >
    > }
    >
    > Output:
    > y1 = 18
    > y2 = 24
    >
    > --
    > Lionel B
     
    , Feb 24, 2007
    #13
  14. Guest

    Thanks Lionel! That's brilliant.

    On Feb 23, 7:14 pm, Lionel B <> wrote:
    > On Sat, 24 Feb 2007 00:04:12 +0000, Lionel B wrote:
    > > On Fri, 23 Feb 2007 12:36:07 -0800, tbringley wrote:

    >
    > >> I am a c++ newbie, so please excuse the ignorance of this question.

    >
    > >> I am interested in a way of having a class call a general member
    > >> function of another class.

    >
    > >> Specifically, I am trying to write an ordinary differential equation
    > >> class that would solve a general equation in the form:
    > >> dx/dt = f(x,t).

    >
    > >> The ode class shouldn't know anything about f, except how to call it.

    >
    > >> My first thought was to have a data member that stores a pointer to
    > >> the function f like:
    > >> double (*f) (double, double);

    >
    > >> However, I learned that f could not point to a non-static member
    > >> function of a different class. This is bad for me, because I need to
    > >> use the solver for functions that are complicated to evaluate and
    > >> depend on many parameters. A simple example:

    >
    > >> class my_f{ public:
    > >> double a;
    > >> double f(double x, double t){ return t+x*a;}
    > >> };

    >
    > >> my_f foo; foo.a = 7;

    >
    > >> I would like the ode solver to call foo.f(x,t). I could make

    >
    > >> double (my_f::* f)(double, double);

    >
    > >> a member of the ode solver, but then I would have to write a new ode
    > >> solver for every new class of functions to be used for f or to have
    > >> all these derive from some kind of base class, which I would prefer to
    > >> avoid.

    >
    > >> My question is: is there a simple and elegant way to do this? I would
    > >> think that similar issues have been encountered many times before.
    > >> Thanks.

    >
    > > How about something like this?

    >
    > [snip]
    >
    > Sorry, you wanted your solver to be a class... try something
    > along these lines:
    >
    > #include <iostream>
    >
    > class Aclass
    > {
    > double a,b;
    >
    > public:
    > Aclass(double a_, double b_) : a(a_), b(b_)
    > {
    > }
    >
    > double func1(double x, double t)
    > {
    > return a*x+b*t;
    > }
    >
    > double func2(double x, double t)
    > {
    > return a*x*x+b*t;
    > }
    >
    > };
    >
    > class Solver
    > {
    > double c,d;
    >
    > public:
    > Solver(double c_, double d_) : c(c_), d(d_)
    > {
    > }
    >
    > template<typename T> double solve(T& obj, double (T::*func)(double,double))
    > {
    > double y = (obj.*func)(c,d);
    > return y;
    > }
    >
    > };
    >
    > int main()
    > {
    > Solver solver(2.0,3.0);
    >
    > Aclass aclass(3.0, 4.0);
    >
    > double y1 = solver.solve(aclass, &Aclass::func1);
    >
    > std::cout << "y1 = " << y1 << '\n';
    >
    > double y2 = solver.solve(aclass, &Aclass::func2);
    >
    > std::cout << "y2 = " << y2 << '\n';
    >
    > }
    >
    > Output:
    > y1 = 18
    > y2 = 24
    >
    > --
    > Lionel B
     
    , Feb 24, 2007
    #14
  15. Mark P Guest

    wrote:

    First things first. You're top-posting (i.e., posting above the text to
    which you're replying rather than below or inline) and you seem to be
    double posting as well. Both of things will make others less inclined
    to help you. (To your credit, you've composed clear and thoughtful
    questions, which is always appreciated.)

    > Thanks for the suggestions everyone. I guess what I had in mind was
    > something along the lines of:
    >
    > class ode_solver{
    > ...
    > double (*f) (double,double);
    > void solve();
    > ...
    > };
    >
    > ode_solver s;
    > s.f = & arbitraryclass.arbitraryfunction;
    > s.solve();
    >
    > This would work perfectly fine if f pointed to a non-member function
    > -- and this idea is used a lot in C.


    Indeed, but think about why this won't work for a member function.
    Conceptually when you call member function A::f( x, t), you're really
    making a call along the lines of f( A*, x, t) where A* is the "this"
    pointer. As you suggested in your original post, f needs to have some
    sort of local state and there's no way to make all of that local state
    available to some other function if you only give it a function pointer.

    >
    > I will be needing to use the ode_solver with an extremely general set
    > of functions f that might come from all different kinds of classes.
    > It is not an option to guarantee that f is a member of a particular
    > class or has a particular name (i.e. f or operator(double,double)). I
    > would much prefer if I didn't have to modify the code of
    > arbitraryclass, if that's possible.


    Well that's understandable. In that case you might want to consider
    some sort of adapter class that makes an arbitrary third party class
    compatible with your solver. Again you can do this via templates or
    inheritance, but basically you need wrap a reference to the third party
    class inside of some standardized function object and specialize the
    function object to call the third party class function. This may
    involve some fairly gnarly syntax so I won't embarrass myself by trying
    to write sample code on the spot :)

    >
    >
    > It seems like the suggestions are along the lines of that f should be
    > itself a class. So...
    >
    > class ode_solver{
    > TwoArgFunc f;
    > };
    >
    > but then...
    >
    > class my_class{
    > TwoArgFunc f1;
    > ...
    > };


    No, my suggestion was that my_class derive from TwoArgFunc, not that it
    contain such a function. But if you don't have access to the other
    classes then this becomes a moot issue.

    -Mark
     
    Mark P, Feb 24, 2007
    #15
  16. Mark P Guest

    Mark P wrote:

    > Well that's understandable. In that case you might want to consider
    > some sort of adapter class that makes an arbitrary third party class
    > compatible with your solver. Again you can do this via templates or
    > inheritance, but basically you need wrap a reference to the third party
    > class inside of some standardized function object and specialize the
    > function object to call the third party class function. This may
    > involve some fairly gnarly syntax so I won't embarrass myself by trying
    > to write sample code on the spot :)


    Okay, I was intrigued enough to try this myself. It actually works very
    nicely:

    #include <iostream>

    using namespace std;

    // class FcnAdapter: bridges arbitrary function class to Solver

    template< typename T>
    class FcnAdapter
    {
    public:
    FcnAdapter( T& fcn) : fcn( fcn) {}

    double eval( double x, double y);

    private:
    T& fcn;
    };





    // class Fcn1

    struct Fcn1
    {
    public:
    Fcn1( double d) : d( d) {}

    double run( double x, double y) { return x * y / d;}

    double d;
    };



    // specialize eval for Fcn1

    template<>
    double FcnAdapter<Fcn1>::eval( double x, double y)
    {
    return fcn.run( x, y);
    }





    // class Fcn2

    struct Fcn2
    {
    public:
    Fcn2( double d) : d( d) {}

    double execute( double x, double y) { return (x + y) / d;}

    double d;
    };



    // specialize eval for Fcn2

    template<>
    double FcnAdapter<Fcn2>::eval( double x, double y)
    {
    return fcn.execute( x, y);
    }




    // class Solver

    template< typename F>
    class Solver
    {
    public:
    Solver( F& f) : f( f) {}

    void execute()
    {
    for( int i = 0; i < 3; ++i)
    for( int j = 0; j < 3; ++j)
    cout << f.eval( i, j) << endl;
    }

    private:
    F& f; // F is a FcnAdapter
    };


    // helper fcn for arbitrary base function class.

    template< typename T>
    void runSolver( T& base)
    {
    FcnAdapter< T> adapter( base);
    Solver< FcnAdapter< T> > solver( adapter);
    solver.execute();
    }

    // main

    int main()
    {
    Fcn1 f1( 2.1);
    Fcn2 f2( 3.5);

    cout << "runSolver( f1)" << endl;
    runSolver( f1);

    cout << endl << "runSolver( f2)" << endl;
    runSolver( f2);
    }

    All you have to do is specialize the FcnAdapter eval function for any
    particular function class you have and the rest is handled
    automatically. Note the use of a templated function (runSolver) to
    automate the template argument deduction (since no deduction is
    performed for class templates).

    Hope that helps,
    Mark
     
    Mark P, Feb 24, 2007
    #16
  17. roy axenov Guest

    Note that top-posting and double-posting is generally
    considered rude on the Usenet. The fact that your problem
    is interesting (at least for me) overweights the (probably
    unintended) rudeness.

    On Feb 24, 1:05 am, wrote:
    > Thanks for the suggestions everyone. I guess what I had
    > in mind was something along the lines of:
    >
    > class ode_solver{
    > ...
    > double (*f) (double,double);
    > void solve();
    > ...
    >
    > };
    >
    > ode_solver s;
    > s.f = & arbitraryclass.arbitraryfunction;
    > s.solve();
    >
    > I will be needing to use the ode_solver with an extremely
    > general set of functions f that might come from all
    > different kinds of classes.


    So basically what you need is ode_solver class you can
    stuff pretty much anything that could be representing an
    f(x,t) into and f(x,t) implementations that are blissfully
    unaware of ode_solver's desires. Sounds like it's time for
    Captain Genericity! An adapter template class exposing a
    simple interface to ode_solver and hiding the grisly
    details of calling the various f(x,t) implementations would
    fit the bill, I believe.

    The details will vary depending on those f(x,t)
    implementations, but consider the following code:

    #include <iostream>

    // f(x,t) implementations. Blissfully ignorant.
    class foo
    { public :
    double a_ ;
    foo ( ) : a_ ( 1 ) { }
    double warble ( double x , double t ) const
    { return t + x * a_ ; } } ;

    class bar
    { public :
    double a_ ;
    bar ( ) : a_ ( 1 ) { }
    double goonglify ( double x , double t ) const
    { return t - x * a_ ; } } ;

    class xyzzy
    { public :
    double a_ ;
    mutable double t_ ;
    xyzzy ( ) : a_ ( 1 ) , t_ ( 1 ) { }
    void t ( double t ) const { t_ = t ; }
    double fooble ( double x ) const
    { return t_ - x * a_ ; } } ;

    // The generic f(x,t) interface.
    class interface_f_x_t
    { public :
    virtual double operator ( )
    ( double x , double t ) const = 0 ; } ;

    // ode solver. Blissfully ignorant.
    class ode
    { public :
    static void solve ( const interface_f_x_t & f )
    { std :: cout << f ( 1.0 , 1.0 ) << std :: endl ; }
    } ;

    // That's the rug we'll be hiding our dirty little secrets
    // under.
    template < typename T , typename F >
    class f_x_t : public interface_f_x_t
    { public :
    f_x_t ( const T & obj , F f ) :
    obj_ ( obj ) , f_ ( f ) { }
    virtual double operator ( )
    ( double x , double t ) const = 0 ;
    private :
    const T & obj_ ;
    F f_ ; } ;

    template < typename T >
    class f_x_t
    < T , double ( T :: * ) ( double , double ) const > :
    public interface_f_x_t
    { public :
    typedef
    double ( T :: * f_ptr ) ( double , double ) const ;
    f_x_t ( const T & obj , f_ptr f ) :
    obj_ ( obj ) , f_ ( f ) { }
    virtual double operator ( )
    ( double x , double t ) const ;
    private :
    const T & obj_ ;
    f_ptr f_ ; } ;

    template < typename T >
    double
    f_x_t < T , double ( T :: * ) ( double , double ) const >
    :: operator ( ) ( double x , double t ) const
    { return ( obj_ .* f_ ) ( x , t ) ; }

    template < typename T >
    class f_x_t
    < T , double ( T :: * ) ( double ) const > :
    public interface_f_x_t
    { public :
    typedef double ( T :: * f_ptr ) ( double ) const ;
    typedef void ( T :: * s_ptr ) ( double ) const ;
    f_x_t ( const T & obj , f_ptr f , s_ptr s ) :
    obj_ ( obj ) , f_ ( f ) , s_ ( s ) { }
    virtual double operator ( )
    ( double x , double t ) const ;
    private :
    const T & obj_ ;
    f_ptr f_ ;
    s_ptr s_ ; } ;

    template < typename T >
    double
    f_x_t < T , double ( T :: * ) ( double ) const >
    :: operator ( ) ( double x , double t ) const
    { ( obj_ .* s_ ) ( t ) ; return ( obj_ .* f_ ) ( x ) ; }

    // Let's see if it all comes together...
    int main ( )
    { foo foo1 ;
    bar bar1 ;
    xyzzy xyzzy1 ;

    f_x_t
    < foo , double ( foo :: * ) ( double , double ) const >
    f1 ( foo1 , & foo :: warble ) ;
    f_x_t
    < bar , double ( bar :: * ) ( double , double ) const >
    g1 ( bar1 , & bar :: goonglify ) ;
    f_x_t
    <xyzzy , double ( xyzzy :: * ) ( double ) const >
    h1 ( xyzzy1 , & xyzzy :: fooble , & xyzzy :: t ) ;

    ode :: solve ( f1 ) ;
    ode :: solve ( g1 ) ;
    ode :: solve ( h1 ) ;

    foo1 . a_ = 5 ;
    bar1 . a_ = 5 ;
    xyzzy1 . a_ = 5 ;

    ode :: solve ( f1 ) ;
    ode :: solve ( g1 ) ;
    ode :: solve ( h1 ) ; }

    Hope this helps a bit.

    --
    roy axenov
     
    roy axenov, Feb 24, 2007
    #17
  18. Guest

    Thanks Mark and Roy. Apologies for the top posting and double
    posting. I am not knowledgeable in the ways of usenet.

    Those are great ideas, and it seems like I'll be able to get exactly
    the functionality I want. Particuarly nice is the idea of a function
    interface class that hides all the templating syntax and can be reused
    whenever this situation arises (I can think of 3 or 4 examples off the
    top of my head just for the ode solver).

    I'm beginning to get an idea of the power of templating in c++. And I
    was just happy that I didn't have to write separate code for int and
    double...

    Thanks again to everyone who put time and thought into helping out.

    Tom
     
    , Feb 24, 2007
    #18
  19. On Feb 24, 3:47 pm, wrote:
    > Thanks Mark and Roy. Apologies for the top posting and double
    > posting. I am not knowledgeable in the ways of usenet.
    >
    > Those are great ideas, and it seems like I'll be able to get exactly
    > the functionality I want. Particuarly nice is the idea of a function
    > interface class that hides all the templating syntax and can be reused
    > whenever this situation arises (I can think of 3 or 4 examples off the
    > top of my head just for the ode solver).
    >
    > I'm beginning to get an idea of the power of templating in c++. And I
    > was just happy that I didn't have to write separate code for int and
    > double...
    >
    > Thanks again to everyone who put time and thought into helping out.
    >
    > Tom


    if you don't need tigher coupling, consider taking a look at Command
    Pattern

    Diego
     
    Diego Martins, Feb 26, 2007
    #19
    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. Newsgroup - Ann
    Replies:
    5
    Views:
    610
    John Carson
    Jul 30, 2003
  2. Replies:
    8
    Views:
    556
    PJP of NYC
    May 24, 2005
  3. n2xssvv g02gfr12930

    Smart pointers and member function pointers

    n2xssvv g02gfr12930, Nov 26, 2005, in forum: C++
    Replies:
    3
    Views:
    472
    n2xssvv g02gfr12930
    Nov 27, 2005
  4. Azdo
    Replies:
    2
    Views:
    435
  5. Hamish
    Replies:
    3
    Views:
    579
    Alf P. Steinbach
    Jan 25, 2008
Loading...

Share This Page