Reputation: 556
For the upcoming coursework I am trying to avoid virtuals to see if I can squeeze more performance/memory efficiency out. The problem started when I wanted to implement a StateManager (coursework prototype is a small game).
To make that possible I have a template to "statify" the member function call of the current State.
An example state would be this:
struct TestState {
bool update(float delta) {
return true;
}
};
Now the State manager should be able to take any State-Class and bind the update function. It was easy to achieve this with boost::bind and boost::function, but there is a performance decrease compared to virtuals, so I wanted to have a look if it is possible without boost.
In theory it would be easy if the State is a class/struct only containing static functions, but that also adds inflexibility and even more static initialization mess.
The StateManager current revision is this:
class StateManager
{
public:
template <typename S> static void set(S* state)
{
#define UPDATE_ID 0
StateFunctionHandler<UPDATE_ID, S, bool, float>::bind(std::mem_fun1(&S::update), state);
m_funcUpdate = StateFunctionHandler<UPDATE_ID, S, bool, float>::exec;
}
static bool update(float delta)
{
return m_funcUpdate(delta);
}
typedef bool (*funcUpdate)(float);
private:
static funcUpdate m_funcUpdate;
};
The StateFunctionHandler is the template that is responsible for wrapping the member function in a static member of StateFunctionHandler. The first parameter of the template is an ID to force multiple templates for functions with the same return type and argument.
In code it looks like this:
template <int ID, typename S, typename R, typename A>
struct StateFunctionHandler
{
static void bind(std::mem_fun1_t<R, S, A> f, S* s)
{
func = f;
pState = s;
}
static R exec(A arg)
{
return func(pState, arg);
}
static std::mem_fun1_t<R, S, A> func;
static S* pState;
};
The problem now is to initialise the templated static members of StateFunctionHandler for the used cases, since we need to force the compiler to initialise them.
In the associated cpp file to these classes the static members get initialised:
template <int ID, typename S, typename R, typename A> std::mem_fun1_t<R, S, A> StateFunctionHandler<ID, S, R, A>::func;
template <int ID, typename S, typename R, typename A> S* StateFunctionHandler<ID, S, R, A>::pState = NULL;
StateManager::funcUpdate StateManager::m_funcUpdate = NULL;
But I get a link error (LNK2001) for StateFunctionHandler::func and ::pState, so the compiler seems to not have initialised the static members of the StateFunctionHandler.
The use case:
TestState* t = new TestState();
StateManager::set(t);
StateManager::update(0.1f);
Again to make it clear, I don't want to use boost, this is an experiment to see if I can avoid virtual function in this use case and have a performance as well.
Upvotes: 1
Views: 180
Reputation: 8604
You should move initialization of static template class members into the header file.
It should be visible in every translation unit which instantiates the template, the same as non-static template class members.
Upvotes: 1