function call missing argument list

1.7k views Asked by At

I'm trying to use odeint (i.e. library for solving differential equations) inside a class but I couldn't. I really need to put it inside a class so that I can have control over my project. This is the error I'm getting error C3867: 'robot::sys': function call missing argument list; use '&robot::sys' to create a pointer to member

and this is my code

#include <iostream>
#include <boost/numeric/odeint.hpp>

using namespace std;
using namespace boost::numeric::odeint;

/* The type of container used to hold the state vector */
typedef std::vector< double > state_type;

class robot
{
    double g, dt, t;
    runge_kutta_dopri5<state_type> stepper;

public:
    state_type x;

    robot() : x(2)
    {
        x[0] = 1.0;
        x[1] = 0.0;
        t = 0;
        g = 0.15;
        dt = 0.1;
    }

    void move();
    void sys(const state_type &x, state_type &dx,  double t);
};


void robot::move()
{
    stepper.do_step(sys , x , t, dt );
    t += dt;
}


void robot::sys( const state_type &x , state_type &dx ,  double t )
{
    dx[0] =  x[1];
    dx[1] = -x[0] - g*x[1];
}



int main(int argc, char **argv)
{
   robot Robo;

   for ( size_t i(0); i < 100; ++i){
       Robo.move();
   }


    return 0;
}

When I try the solution that is suggested in the error message, I'm getting another error which is

....\odeint\stepper\base\explicit_error_stepper_fsal_base.hpp(279): error C2064: term does not evaluate to a function taking 3 arguments

2

There are 2 answers

1
T.C. On BEST ANSWER

sys is a non-static member function; they do not behave like normal functions because they have an implicit this parameter.

Possible fixes are:

(1) Use a C++11 lambda in place of sys:

void robot::move()
{
    stepper.do_step([this](const state_type &x, state_type &dx, double t){
        dx[0] =  x[1];
        dx[1] = -x[0] - g*x[1];
    }, x , t, dt );
    t += dt;
}

(2) Keep sys and use std::bind or boost::bind:

void robot::move()
{
    using namespace std::placeholders;
    stepper.do_step(std::bind(&robot::sys, this, _1, _2, _3), x , t, dt );
    t += dt;
}

(3) Use a custom-written functor instead of sys:

struct System {
    double g;
    explicit System(double g) : g(g) {}
    void operator()( const state_type &x , state_type &dx ,  double t )
    {
        dx[0] =  x[1];
        dx[1] = -x[0] - g*x[1];
    }
};

void robot::move()
{
    stepper.do_step(System(g), x , t, dt );
    t += dt;
}

Note that in this case you can have your class store a System object instead of storing g and constructing it on each call to move.

2
pdeschain On

Your move function is passing sys as argument and the compiler suggests correct syntax for that. You can swap sys for appropriate lambda expression in the move function or use bind.

http://en.cppreference.com/w/cpp/utility/functional/bind

http://www.cprogramming.com/c++11/c++11-lambda-closures.html