Reputation: 9376
Suppose I have these classes:
class A
{
// virtual methods
};
template<typename T>
class B : public A
{
void ANewMethodSpecificOfClassB(...){...};
}
I would like to add a subset of B classes into a container and from there, call ANewMethodSpecificOfClassB
.
For example, given:
B<instanciation1> south_park;
B<instanciatoin2> family_guy;
suppose I want to put B<instanciation1>
and B<instanciation2>
in the same container (for example a vector): I cannot declare a std::vector<B>
because B
is not a real class, only B<instanciation1>
and B<instanciation2>
are.
Then I thought to define a vector using a (shared) pointer to the base class. However, doing so gives error when calling ANewMethodSpecificOfClassB
because the method is not defined in the base class (and no, I can't modify the base class adding the method there).
Is there a way create a container with two different instances of a template classes and call a method that all of the instantiated classes have but not the parent class of the template class?
Upvotes: 0
Views: 123
Reputation: 10880
There are (at least) two ways around this:
AWithSpecificMethod
:class AWithSpecificMethod {
protected:
virtual ANewMethodSpecificOfClassB() const = 0;
};
Then have B<>
descend either from A
or from AWithSpecificMethod
. You can do that using std::conditional<>
, std::is_same<>
et. al.
However, this way of solving it, at some point, creates several interfaces and immediate classes which are not true abstractions, just a notation of existence of method. Also, it's virtual => likely very slow.
std::variant<B<T1>, B<T2>, ...>
and reconsider even if A
is necessary as an interface class. This works if you know the possible types T1, T2, ... that you intend to work with (practically almost always). You can visit a variant
using std::visit
, which you usually pass a lambda and the variant:std::variant<B<int>, B<char>> var;
std::visit([&](auto const& actual) {
// here actual is the concrete type
// either B<int> const& or B<char>&
}, var);
Upvotes: 2