Jump to content
  • Advertisement
Sign in to follow this  
daniel_i_l

Functor question

This topic is 3319 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Let's say that I have a class Simulation that contains a pointer to an integrator of type Integrator. The integrator class has a function "integrate" which takes a state and a function that can calculate the derivative of the state and returns the new state. The obvious way to implement this is with function pointers like this:
class Simulation
{
...
    Integrator *integrator;
    float[] GetDerivatives(float[] state, float dt);
    void Update(float dt);
};
void Simulation :: Update(float dt)
{
    integrator.integrate(..., &GetDerivatives);
}
class Integrator
{
...
    float[] integrate(float[] state, float t0, float t1, 
                      float[] (*GetDxDt)(float[] state, float dt));
};



But is there any more "c++" way of doing it such as functors? The problem is that the GetDerivatives function has to use other functions and information that're contained in "Simulation" (bodies,forces...). So if I made a "GetDerivatives" functor it'd have to hold a pointer to Simulation - and in that case I could just give "Integrator" a pointer to "Simulation" and let it use the function directly. It just seems like bad design to have objects point to each other. Are there better ways of implementing this? Thanks.

Share this post


Link to post
Share on other sites
Advertisement
I don't know if this is the best way to do it, but you could use boost::function to define a function object that supports the GetDerivatives function signature and then use boost::bind to bind the GetDerivatives member function to the function object.

So your code would look something like:



// Create a typedef of the function object
typedef boost::function<float[](float[] state, float dt)> derivativeFunction;

class Simulation
{
...
Integrator *integrator;
float[] GetDerivatives(float[] state, float dt);
void Update(float dt);
};
void Simulation :: Update(float dt)
{
// create the function object and bind it to the GetDerivatives member function
derivativeFunction derivFunction = boost::bind(&Simulation::GetDerivatives, this, _1, _2 );
integrator.integrate(..., derivFunction);
}

class Integrator
{
...
float[] integrate(float[] state, float t0, float t1, derivativeFunction derivFunction);
};

float[] Integrator::integrate(float[] state, float t0, float t1, derivativeFunction derivFunction)
{
...
float[] newState;

// Call the function object
state = derivFunction(...);
}






I think that would work. I've only used boost::function and boost::bind a little bit.

Share this post


Link to post
Share on other sites
I am not sure I understand all the issues involved in your situation, but this sounds to me like a place for the "curiously recursive template pattern":
template <class SIM>
class Integrator {
// ...
public:
void integrate(...) {
// ...
derivatives = get_derivatives(...);
// ...
}
};

class Simulation : public Integrator<Simulation> {
float [] get_derivatives(...);
// ...
};





If that's not clear enough (it can be confusing at first), I can try to write a complete example for a trivial case.

EDIT: I don't even think I got it right in the very incomplete code above. I'll post something when I have it working. Unfortunately, I have to go to work now.

Share this post


Link to post
Share on other sites
What language is that supposed to be?
Because this is definately not C++. "float[] state" is not a valid declaration.

Also, I don't understand why boost::function was recommended. You don't need type erasure here, you can just use functors directly using templates.

Share this post


Link to post
Share on other sites
loufoque is right. You just need to use a regular functor. This is an example of how to define the integrator:

#include <iostream>

template <class Time, class Point, class Vector, class DerivativeFunction>
class EulerIntegrator {
DerivativeFunction derivative;

public:
EulerIntegrator(DerivativeFunction const &derivative) : derivative(derivative) {
}

// I am trying to be clear, not to avoid making copies.
// Perhaps there is room for optimizations here.
Point step(Point const &position, Time dt) {
Vector velocity = derivative(position);
Point result = position + dt * velocity;
return result;
}
};

class Proportional {
float scale;

public:
Proportional(float scale) : scale(scale) {
}

float operator()(float x) {
return scale*x;
}
};

int main() {
Proportional identity(1.0f);
EulerIntegrator<float, float, float, Proportional> integrator(identity);

float x=1.0f;
for(int i=0;i<10;++i) {
x = integrator.step(x, 0.1f);
std::cout << x << '\n';
}
}


Share this post


Link to post
Share on other sites
Thanks for the help. I have one question though.
In my case the "DerivativeFunction" needs to use information from "Simulation" such as forces. So would the functor need to hold a pointer to "Simulation"? Is there a way to design it so that it won't have to?
Thanks.

Share this post


Link to post
Share on other sites
Why not keep it simple and pass the class along using the this pointer.

float[] GetDerivatives(Simulation *sim, float[] state, float dt);

and then do

functionPointer(this, state, dt));

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!