Reputation: 611
How can I extend an abstract base class using templates for the extensions when I also wish to conditionally compile the overrides for the pure virtual functions?
Example: Given the base class
class AbstractBase {
public:
virtual void func() = 0;
};
I thought of extending with something like
enum class Opts{FOO, BAR};
template<Opts opt>
class Derived : public AbstractBase {
public:
template<Opts op = opt>
typename std::enable_if<op == Opts::FOO, void>::type func() {
std::cout << "Foo" << "\n";
}
template<Opts op = opt>
typename std::enable_if<op == Opts::BAR, void>::type func() {
std::cout << "BAR" << "\n";
}
};
My idea is that when one of the func get to compile in the extended class, then everything's good. However, I can't get it to work.
Derived<Opts::FOO> obj;
Will not compile because the derived class is is still abstract. I'm using templates because I want the compiler to pick only one member function to compile.
Thanks.
Upvotes: 0
Views: 541
Reputation:
You may specialize the function instead:
#include <iostream>
class AbstractBase
{
public:
// You should have a virtual destructor:
virtual ~AbstractBase() {}
virtual void func() = 0;
};
enum class Opts
{
FOO, BAR
};
template<Opts opt>
class Derived: public AbstractBase
{
public:
void func() override;
};
template<>
void Derived<Opts::FOO>::func()
{
std::cout << "Foo" << "\n";
}
template<>
void Derived<Opts::BAR>::func()
{
std::cout << "BAR" << "\n";
}
int main()
{
Derived<Opts::FOO> foo;
AbstractBase& bfoo = foo;
bfoo.func();
Derived<Opts::BAR> bar;
AbstractBase& bbar = bar;
bbar.func();
}
However, I consider mixing dynamic polymorphism (virtual) and static polymorphism (templates) a bad design (there might be exemptions).
Upvotes: 1
Reputation: 145239
Just specialize the class template for each to-be-treated-specially enum value, e.g.,
enum class Opts{foo, bar};
template<Opts opt>
class Derived;
template<>
class Derived<Opts::foo>
: public AbstractBase
{
public:
void func() override
{
std::cout << "Foo" << "\n";
}
};
template<>
class Derived<Opts::bar>
: public AbstractBase
{
public:
void func() override
{
std::cout << "bar" << "\n";
}
};
Where you want some general common stuff that's not in AbstractBase
, you can either inherit it in, or add it in via CRTP in a most derived class.
Disclaimer: off the cuff code, not compiled.
Upvotes: 1