I have a class similar to the following:
class SomeClass
{
public:
template<typename... Args>
void doSomething(Args && ... args);
//... other methods etc.
};
However, what I really want is to have two different kinds of SomeClass
. Ideally, I would be able to derive from a common interface to make SomeOtherClass
, but I need to have a different implementation of doSomething
and templated methods cannot be virtual. I could make a templated class, but then every method that takes one of these (and there are many) would themselves have to be templates etc.
The best I've been able to come up with is to implement both types of doSomething
in the base class and have that method call a virtual method to determine which to use at runtime.
Is there a better solution?
Further explanation
I have many methods that look similar to this:
void foo(SomeClass * obj);
foo
calls obj->doSomething
and this all works fine, however I've since realized that I need a different kind of SomeClass
but want it to work with these same methods, for example:
class SomeClass
{
public:
// This won't work
template<typename... Args>
virtual void doSomething(Args && ... args) = 0;
// ... other common methods
};
class TheFirstType
{
public:
template<typename... Args>
void doSomething(Args && ... args);
// ... other specific methods
};
class TheSecondType
{
public:
template<typename... Args>
void doSomething(Args && ... args);
// ... other specific methods
};
The above would be ideal, if it were legal, but virtual methods cannot be templated. I've thus far gotten around this limitation by only having doSomething
defined in the base class, but with both the implementation for TheFirstType
and TheSecondType
separated by an if statement that checks on what type the instance actually is:
template<typename... Args>
void SomeClass::doSomething(Args && ... args)
{
if (this->type() == FIRST_TYPE) {
// ... the implementation that should rightfully be part of TheFirstType
} else if (this->type() == SECOND_TYPE) {
// ... the implementation that should be part of TheSecondType
}
}
This seems messy, however, so I was wondering if there is a better way.