I have two classes B, C with pure virtual f,g functions respectively:
class B {
public:
virtual void f() = 0;
};
class C {
public:
virtual void g() = 0;
};
I want to create a child class A which conditionally inherits B or C. I know how to inherit from a different base class based on template parameter (let's say non-type bool template parameter):
template<bool test>
class A : public std::conditional<test, B, C>::type {
...
};
How to conditionally override f or g with respect to template parameter? Something like:
template<bool test>
class A : public std::conditional<test, B, C>::type {
public:
if constexpr (test) {
void f() override;
}
else {
void g() override;
}
}
Bonus question: is this even a good design? Should I avoid conditional inheritance? My application is far too big to use composition or some other design pattern, it would require drastic refactoring.
What you ask for is questionable design. Suppose you get what you ask for, then all code using A also needs to branch on depending whether A has a method called f or a method called g. I am sure there is a better way to solve your actual issue. However, you don't tell us why you want A to conditionally inherit so I will turn to your question as stated...
You cannot do this directly. You can however place the conditional at a different level:
struct AB : B {
void f() override;
}
struct AC : C {
void g() override;
}
template <bool test>
using A = std::conditional<test, AB, AC>::type;
Alternatively specialize the whole class A for test==true and for test==false.
Why one templated class rather than two classes (like above) ?
because I have common code (bunch of private functions) which is used inside the class. If I instantiate two plain classes
A_trueA_falsei need to copy/paste all of the private functions and have duplicate code.
No. You do not have to copy any code. Just move the common code elsewhere:
struct A_common { /* ... */ };
struct AB : B, A_common {
void f() override;
}
struct AC : C, A_common {
void g() override;
}
The same can be done when specializing a template class A. Generally you want to have all methods not depending on a template parameter outside of the template.
I would use old fashioned way of class specialization:
template<bool test>
class A : public B {
void f() override;
};
template<>
class A<false> : public C {
void g() override;
};
Pros:
it is simple and clean
will work with quite old C++ standard
Cons:
There is even simpler, solution. Just drop override keyword and let compiler create none virtual member function if there is no virtual equivalent in parent class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With