Monday, August 28

A POD polymorphic object

Impossible, you cry: POD is POD and virtual functions are virtual functions and nary the twain shall meet! More sophisticated readers among you might assume this is a rehash of static polymorphism, but this is not so. I have a POD struct that can be used nonhomegenously in a container, and support run-time polymorphism. Without further ado, here is the code..



simple.h





enum eEngineObjectKind
{
eMeshObject = 0,
eSkeletonObject,
nEngineObjectKinds
};

typedef float t_TRANSFORM[16];


typedef void (*UpdateFunctionPtr)(float time_delta);

extern UpdateFunctionPtr update_jump_table[nEngineObjectKinds];

template <typename T> class EngineObject
{
private:
T* object_data;
enum eEngineObjectKind kind;

public:
void init_object()
{
kind = T::object_kind;
update_jump_table[kind] = T::object_update_fn;
object_data = new T(); // or T::allocate_object
};

void update_object(float time_delta)
{
update_jump_table[kind](time_delta);
}
};

template <> class EngineObject<void>
{
private:
void *object_data;
eEngineObjectKind kind;

public:
void *getData()
{
return object_data;
}

eEngineObjectKind getKind()
{
return kind;
}

void update_object(float time_delta)
{
update_jump_table[kind](time_delta);
}

};

class EngineMeshData
{
public:
static eEngineObjectKind object_kind;
static UpdateFunctionPtr object_update_fn;

static void UpdateMesh(float time_delta);

};

class EngineSkeletonData
{
public:
static eEngineObjectKind object_kind;
static UpdateFunctionPtr object_update_fn;

static void UpdateSkeleton(float time_delta);

};

typedef EngineObject<EngineMeshData> EngineMeshObject;
typedef EngineObject<EngineSkeletonData> EngineSkeletonObject;




simple.cpp





#include <iostream>
#include "simple.h"

/**
* pseudo - vtable !
*/

UpdateFunctionPtr update_jump_table[nEngineObjectKinds];

/**
* skeleton defintions
*/

enum eEngineObjectKind EngineSkeletonData::object_kind = eSkeletonObject;

void EngineSkeletonData::UpdateSkeleton(float time_delta)
{
std::cout << "Update Skeleton\n";
}

UpdateFunctionPtr EngineSkeletonData::object_update_fn = EngineSkeletonData::UpdateSkeleton;

/**
* mesh defintions
*/

enum eEngineObjectKind EngineMeshData::object_kind = eMeshObject;

void EngineMeshData::UpdateMesh(float time_delta)
{
std::cout << "Update Mesh\n";
}

UpdateFunctionPtr EngineMeshData::object_update_fn = EngineMeshData::UpdateMesh;




EngineObject<void> world[2];

int main (int argc, char *argv[])
{
EngineSkeletonObject *skeleton = new(world) EngineSkeletonObject();
skeleton->init_object();

EngineMeshObject *mesh = new(world+1) EngineMeshObject();
mesh->init_object();

world[0].update_object(1.0f);
world[1].update_object(1.0f);

};

No comments: