Simplified I have the following class hierarchy:
class BaseVec {
public:
BaseVec() {};
virtual ~BaseVec() {};
virtual double get_double(int i) con
First of all, don't use reinterpret_cast
while converting to/from pointer to polymorphic class. You can write a simple pointer wrapper which allow you to use safe casting operator static_cast
:
template
class PointerWrapper
{
public:
PointerWrapper(Type* object);
PointerWrapper& operator=(Type* object);
Type* operator->();
protected:
Type* object;
};
template
PointerWrapper::PointerWrapper(Type* object) :
object(object)
{
}
template
PointerWrapper& PointerWrapper::operator=(Type* object)
{
this->object = object;
}
template
Type* PointerWrapper::operator->()
{
return object;
}
Now you can write:
typedef PointerWrapper BaseVecPointer;
template
double foo(void* p) {
BaseVecPointer* vp = static_cast(p);
// ...
// ... = (*vp)->get_double(...);
// ...
return result;
}
In this code polymorphism capabilities were used, i.e. function get_double
was called instead of calling get
.
But if you want to call just get
, not get_double
, i.e. you want to call template functions with different template arguments depending on the value of run-time variable, you can use the following method:
enum FooTypes
{
NoFooType = -1,
DoubleFooType = 0,
IntegerFooType = 1,
// ...
FooTypesCount
};
template
struct ChooseType
{
static
const FooTypes value = NoFooType;
typedef void Type;
};
template<>
struct ChooseType
{
static
const FooTypes value = DoubleFooType;
typedef double Type;
};
template<>
struct ChooseType
{
static
const FooTypes value = IntegerFooType;
typedef int Type;
};
Here you should write specializations of the class template ChooseType
for all possible values of type
variable.
Following code describes the function ChooseFoo
which selects what specialization of foo_template
function template should be called:
typedef double (*FooFunction)(void*);
template
FooFunction ChooseFooImpl(int type)
{
if (type == fooType)
{
if (ChooseType::value != NoFooType)
{
return foo_template::Type>;
}
else
{
return NULL;
}
}
else
{
return ChooseFooImpl<(FooTypes)(fooType - 1)>(type);
}
}
template<>
FooFunction ChooseFooImpl(int type)
{
return NULL;
}
FooFunction ChooseFoo(int type)
{
return ChooseFooImpl(type);
}
And this is foo
function implementation:
double foo(void* p, int type)
{
FooFunction fooFunction = ChooseFoo(type);
if (fooFunction != NULL)
{
return fooFunction(p);
}
else
{
//unsupported type
// ...
}
}