c++templatesfunction-pointerspointer-to-membervirtual-inheritance

pass non-static member function with neither virtual inheritance nor templates


How do I pass the non-static member function eval of object Problem1 obj to the object Solver solver ?

#include<iostream>
#include<functional>

// non-templated class
struct Solver{
    std::function<void(double&, double&)>* f;
    double solve(){
        double y,x=1;
        for(long int i=0;i<10000;++i){
            (*f)(y,x); (*f)(x,y);
        }
        return y;
    }
};

// non-static class; unknown at implementation time of Solver
struct Problem1{
    double p;
    void eval(double& y, double& x){
        y = x*x - p;
    }
};

int main(){
    Problem1    obj;
    Solver      solver;
    solver.f = &(obj.eval); // pass non-static member function
    solver.solve();
}

Since one solver shall be used to solve very many different instances of various problem classes, I do not want to use templates. Since the solution of one problem object may require very many calls of eval, I am shy to use virtual inheritance from a VirtualProblem class due to the overhead and slow reputation of virtual classes in c++. Does this matter here? What should I do?


Solution

  • That's not how std::function works.

    First of all it should not be a pointer. You can't assign a pointer to a non-static member function to it (and especially not its pointer). And you can't use non-static member function that way.

    To solve your problem first lets make f a non-pointer object:

    struct Solver{
        std::function<void(double&, double&)> f;
        double solve(){
            double y,x=1;
            for(long int i=0;i<10000;++i){
                f(y,x); f(x,y);
            }
            return y;
        }
    };
    

    Then we can use a lambda to call the correct function on the correct object:

    solver.f = [&obj](double& a, double& b)
    {
        obj.eval(a, b);
    };
    

    On another note, if you want to return a value from a function, actually return a value. Please don't abuse reference arguments when it's not really needed.