views:

849

answers:

6

ok 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 static class method

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 varribles, and Id rather not make the class instance global...eg

Render(MainMenu->Render);

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

+2  A: 

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);
  ...
}
mweerden
+12  A: 

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));
David Joyner
+1  A: 

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)

cjanssen
+1  A: 
Tom Martin
+2  A: 

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

Marcin Gil
A: 

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.

Nick Gebbie