Question

Say I have:

void Render(void(*Call)())
{
    D3dDevice->BeginScene();
    Call();
    D3dDevice->EndScene();
    D3dDevice->Present(0,0,0,0);
}

This is fine as long as the function I want to use to render is a function or a static member function:

Render(MainMenuRender);
Render(MainMenu::Render);

However, I really want to be able to use a class method as well since in most cases the rendering function will want to access member variables, and Id rather not make the class instance global, e.g.

Render(MainMenu->Render);

However I really have no idea how to do this, and still allow functions and static member functions to be used.

Was it helpful?

Solution

There are a lot of ways to skin this cat, including templates. My favorite is Boost.function as I've found it to be the most flexible in the long run. Also read up on Boost.bind for binding to member functions as well as many other tricks.

It would look like this:

#include <boost/bind.hpp>
#include <boost/function.hpp>

void Render(boost::function0<void> Call)
{
    // as before...
}

Render(boost::bind(&MainMenu::Render, myMainMenuInstance));

OTHER TIPS

You can make a wrapper function void Wrap(T *t) that just calls t->Call() and have Render take such a function together with an object. That is:

void Wrap(T *t)
{
  t->Call();
}

void Render(void (*f)(T *), T *t)
{
  ...
  f(t);
  ...
}

What about what C++ FAQ: Pointers to members says?

I did so once by defining a global function "Call" which accepts a pointer to your intance as member

void CallRender(myclass *Instance)
{
  Instance->Render();
}

So render becomes:

void Render(void (*Call)(myclass*), myclass* Instance)
{
  ...
  Call(Instance);
  ...
}

And your call to render is:

Render(CallRender, &MainMenu);

I know it's ugly, but worked for me (I was using pthreads)

You can't call a member function from a pointer unless you have a reference to the object as well. For example:

((object).*(ptrToMember))

So you won't be able to acheive this without changing the signature of your render method. This article explains why this is generally a bad idea.

A better way might be to define a "Renderer" interface which your classes that have render methods can implement and have that be the parameter type of your main Render method. You could then write a "StaticCaller" implementation to support the calling of your static methods by reference.

eg (My C++ is really rusty, I haven't compiled this either).



void Render(IRenderer *Renderer)
{
    D3dDevice->BeginScene();
    Renderer->Render();
    D3dDevice->EndScene();
    D3dDevice->Present(0,0,0,0);
}

// The "interface"
public class IRenderer 
{
public:
    virtual void Render();
};

public class StaticCaller: public IRenderer
{
    void (*Call)();
public:

    StaticCaller((*Call)())
    {
        this->Call = Call;
    }

    void Render()
    {
        Call();
    }
};

All this is pretty boilerplate but it should make for more readability.

You can declare a function pointer to a member function of class T using:

typedef void (T::*FUNCTIONPOINTERTYPE)(args..)
FUNCTIONPOINTERTYPE function;

And invoke it as:

T* t;
FUNCTIONPOINTERTYPE function;
(t->*function)(args..);

Extrapolating this into useful currying system with variable arguments, types, return values, etc, is monotonous and annoying. I've heard good things about the aforementioned boost library, so I'd recommend looking into that before doing anything drastic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top